cfsa-antigravity 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,851 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: logging-best-practices
|
|
3
|
+
description: Implement structured logging with JSON formats, log levels (DEBUG, INFO, WARN, ERROR), contextual logging, PII handling, and centralized logging. Use for logging, observability, log levels, structured logs, or debugging.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Logging Best Practices
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Comprehensive guide to implementing structured, secure, and performant logging across applications. Covers log levels, structured logging formats, contextual information, PII protection, and centralized logging systems.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
- Setting up application logging infrastructure
|
|
15
|
+
- Implementing structured logging
|
|
16
|
+
- Configuring log levels for different environments
|
|
17
|
+
- Managing sensitive data in logs
|
|
18
|
+
- Setting up centralized logging
|
|
19
|
+
- Implementing distributed tracing
|
|
20
|
+
- Debugging production issues
|
|
21
|
+
- Compliance with logging regulations
|
|
22
|
+
|
|
23
|
+
## Instructions
|
|
24
|
+
|
|
25
|
+
### 1. **Log Levels**
|
|
26
|
+
|
|
27
|
+
#### Standard Log Levels
|
|
28
|
+
```typescript
|
|
29
|
+
// logger.ts
|
|
30
|
+
enum LogLevel {
|
|
31
|
+
DEBUG = 0, // Detailed information for debugging
|
|
32
|
+
INFO = 1, // General informational messages
|
|
33
|
+
WARN = 2, // Warning messages, potentially harmful
|
|
34
|
+
ERROR = 3, // Error messages, application can continue
|
|
35
|
+
FATAL = 4 // Critical errors, application must stop
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class Logger {
|
|
39
|
+
constructor(private minLevel: LogLevel = LogLevel.INFO) {}
|
|
40
|
+
|
|
41
|
+
debug(message: string, context?: object) {
|
|
42
|
+
if (this.minLevel <= LogLevel.DEBUG) {
|
|
43
|
+
this.log(LogLevel.DEBUG, message, context);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
info(message: string, context?: object) {
|
|
48
|
+
if (this.minLevel <= LogLevel.INFO) {
|
|
49
|
+
this.log(LogLevel.INFO, message, context);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
warn(message: string, context?: object) {
|
|
54
|
+
if (this.minLevel <= LogLevel.WARN) {
|
|
55
|
+
this.log(LogLevel.WARN, message, context);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
error(message: string, error?: Error, context?: object) {
|
|
60
|
+
if (this.minLevel <= LogLevel.ERROR) {
|
|
61
|
+
this.log(LogLevel.ERROR, message, {
|
|
62
|
+
...context,
|
|
63
|
+
error: {
|
|
64
|
+
message: error?.message,
|
|
65
|
+
stack: error?.stack,
|
|
66
|
+
name: error?.name
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
fatal(message: string, error?: Error, context?: object) {
|
|
73
|
+
this.log(LogLevel.FATAL, message, {
|
|
74
|
+
...context,
|
|
75
|
+
error: {
|
|
76
|
+
message: error?.message,
|
|
77
|
+
stack: error?.stack,
|
|
78
|
+
name: error?.name
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private log(level: LogLevel, message: string, context?: object) {
|
|
85
|
+
const logEntry = {
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
level: LogLevel[level],
|
|
88
|
+
message,
|
|
89
|
+
...context
|
|
90
|
+
};
|
|
91
|
+
console.log(JSON.stringify(logEntry));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Usage
|
|
96
|
+
const logger = new Logger(
|
|
97
|
+
process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
logger.debug('Processing request', { userId: '123', requestId: 'abc' });
|
|
101
|
+
logger.info('User logged in', { userId: '123' });
|
|
102
|
+
logger.warn('Rate limit approaching', { userId: '123', count: 95 });
|
|
103
|
+
logger.error('Database connection failed', dbError, { query: 'SELECT ...' });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. **Structured Logging (JSON)**
|
|
107
|
+
|
|
108
|
+
#### Node.js with Winston
|
|
109
|
+
```typescript
|
|
110
|
+
// winston-logger.ts
|
|
111
|
+
import winston from 'winston';
|
|
112
|
+
|
|
113
|
+
const logger = winston.createLogger({
|
|
114
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
115
|
+
format: winston.format.combine(
|
|
116
|
+
winston.format.timestamp(),
|
|
117
|
+
winston.format.errors({ stack: true }),
|
|
118
|
+
winston.format.json()
|
|
119
|
+
),
|
|
120
|
+
defaultMeta: {
|
|
121
|
+
service: 'user-service',
|
|
122
|
+
environment: process.env.NODE_ENV
|
|
123
|
+
},
|
|
124
|
+
transports: [
|
|
125
|
+
// Write to console
|
|
126
|
+
new winston.transports.Console({
|
|
127
|
+
format: winston.format.combine(
|
|
128
|
+
winston.format.colorize(),
|
|
129
|
+
winston.format.simple()
|
|
130
|
+
)
|
|
131
|
+
}),
|
|
132
|
+
// Write to file
|
|
133
|
+
new winston.transports.File({
|
|
134
|
+
filename: 'logs/error.log',
|
|
135
|
+
level: 'error',
|
|
136
|
+
maxsize: 5242880, // 5MB
|
|
137
|
+
maxFiles: 5
|
|
138
|
+
}),
|
|
139
|
+
new winston.transports.File({
|
|
140
|
+
filename: 'logs/combined.log',
|
|
141
|
+
maxsize: 5242880,
|
|
142
|
+
maxFiles: 5
|
|
143
|
+
})
|
|
144
|
+
]
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Usage
|
|
148
|
+
logger.info('User created', {
|
|
149
|
+
userId: user.id,
|
|
150
|
+
email: user.email,
|
|
151
|
+
requestId: req.id
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
logger.error('Payment processing failed', {
|
|
155
|
+
error: error.message,
|
|
156
|
+
stack: error.stack,
|
|
157
|
+
orderId: order.id,
|
|
158
|
+
amount: order.total,
|
|
159
|
+
userId: user.id
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### Python with structlog
|
|
164
|
+
```python
|
|
165
|
+
# logger.py
|
|
166
|
+
import structlog
|
|
167
|
+
import logging
|
|
168
|
+
|
|
169
|
+
# Configure structlog
|
|
170
|
+
structlog.configure(
|
|
171
|
+
processors=[
|
|
172
|
+
structlog.stdlib.filter_by_level,
|
|
173
|
+
structlog.stdlib.add_logger_name,
|
|
174
|
+
structlog.stdlib.add_log_level,
|
|
175
|
+
structlog.stdlib.PositionalArgumentsFormatter(),
|
|
176
|
+
structlog.processors.TimeStamper(fmt="iso"),
|
|
177
|
+
structlog.processors.StackInfoRenderer(),
|
|
178
|
+
structlog.processors.format_exc_info,
|
|
179
|
+
structlog.processors.UnicodeDecoder(),
|
|
180
|
+
structlog.processors.JSONRenderer()
|
|
181
|
+
],
|
|
182
|
+
context_class=dict,
|
|
183
|
+
logger_factory=structlog.stdlib.LoggerFactory(),
|
|
184
|
+
cache_logger_on_first_use=True,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
logger = structlog.get_logger()
|
|
188
|
+
|
|
189
|
+
# Usage
|
|
190
|
+
logger.info("user_created",
|
|
191
|
+
user_id=user.id,
|
|
192
|
+
email=user.email,
|
|
193
|
+
request_id=request.id
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
logger.error("payment_failed",
|
|
197
|
+
error=str(error),
|
|
198
|
+
order_id=order.id,
|
|
199
|
+
amount=order.total,
|
|
200
|
+
user_id=user.id
|
|
201
|
+
)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Go with zap
|
|
205
|
+
```go
|
|
206
|
+
// logger.go
|
|
207
|
+
package main
|
|
208
|
+
|
|
209
|
+
import (
|
|
210
|
+
"go.uber.org/zap"
|
|
211
|
+
"go.uber.org/zap"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
func main() {
|
|
215
|
+
// Production config (JSON)
|
|
216
|
+
logger, _ := zap.NewProduction()
|
|
217
|
+
defer logger.Sync()
|
|
218
|
+
|
|
219
|
+
// Development config (human-readable)
|
|
220
|
+
// logger, _ := zap.NewDevelopment()
|
|
221
|
+
|
|
222
|
+
logger.Info("User created",
|
|
223
|
+
zap.String("userId", user.ID),
|
|
224
|
+
zap.String("email", user.Email),
|
|
225
|
+
zap.String("requestId", req.ID),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
logger.Error("Payment processing failed",
|
|
229
|
+
zap.Error(err),
|
|
230
|
+
zap.String("orderId", order.ID),
|
|
231
|
+
zap.Float64("amount", order.Total),
|
|
232
|
+
zap.String("userId", user.ID),
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
// Sugared logger for less structured logs
|
|
236
|
+
sugar := logger.Sugar()
|
|
237
|
+
sugar.Infow("User login",
|
|
238
|
+
"userId", user.ID,
|
|
239
|
+
"ip", req.IP,
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 3. **Contextual Logging**
|
|
245
|
+
|
|
246
|
+
#### Request Context Middleware
|
|
247
|
+
```typescript
|
|
248
|
+
// request-logger.ts
|
|
249
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
250
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
251
|
+
|
|
252
|
+
const asyncLocalStorage = new AsyncLocalStorage();
|
|
253
|
+
|
|
254
|
+
// Middleware to add request context
|
|
255
|
+
export function requestLogger(req, res, next) {
|
|
256
|
+
const requestId = req.headers['x-request-id'] || uuidv4();
|
|
257
|
+
const context = {
|
|
258
|
+
requestId,
|
|
259
|
+
method: req.method,
|
|
260
|
+
path: req.path,
|
|
261
|
+
ip: req.ip,
|
|
262
|
+
userAgent: req.headers['user-agent'],
|
|
263
|
+
userId: req.user?.id
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
asyncLocalStorage.run(context, () => {
|
|
267
|
+
logger.info('Request started', context);
|
|
268
|
+
|
|
269
|
+
// Log response when finished
|
|
270
|
+
res.on('finish', () => {
|
|
271
|
+
logger.info('Request completed', {
|
|
272
|
+
...context,
|
|
273
|
+
statusCode: res.statusCode,
|
|
274
|
+
duration: Date.now() - req.startTime
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
req.startTime = Date.now();
|
|
279
|
+
next();
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Logger wrapper that includes context
|
|
284
|
+
export function getLogger() {
|
|
285
|
+
const context = asyncLocalStorage.getStore();
|
|
286
|
+
return {
|
|
287
|
+
info: (message: string, meta?: object) =>
|
|
288
|
+
logger.info(message, { ...context, ...meta }),
|
|
289
|
+
error: (message: string, error: Error, meta?: object) =>
|
|
290
|
+
logger.error(message, { ...context, error, ...meta }),
|
|
291
|
+
warn: (message: string, meta?: object) =>
|
|
292
|
+
logger.warn(message, { ...context, ...meta }),
|
|
293
|
+
debug: (message: string, meta?: object) =>
|
|
294
|
+
logger.debug(message, { ...context, ...meta })
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Usage in route handler
|
|
299
|
+
app.get('/api/users/:id', async (req, res) => {
|
|
300
|
+
const log = getLogger();
|
|
301
|
+
|
|
302
|
+
log.info('Fetching user', { userId: req.params.id });
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
const user = await userService.findById(req.params.id);
|
|
306
|
+
log.info('User found', { userId: user.id });
|
|
307
|
+
res.json(user);
|
|
308
|
+
} catch (error) {
|
|
309
|
+
log.error('Failed to fetch user', error, { userId: req.params.id });
|
|
310
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### Correlation IDs
|
|
316
|
+
```typescript
|
|
317
|
+
// correlation-id.ts
|
|
318
|
+
export class CorrelationIdManager {
|
|
319
|
+
private static storage = new AsyncLocalStorage<string>();
|
|
320
|
+
|
|
321
|
+
static run<T>(correlationId: string, callback: () => T): T {
|
|
322
|
+
return this.storage.run(correlationId, callback);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
static get(): string | undefined {
|
|
326
|
+
return this.storage.getStore();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Middleware
|
|
331
|
+
app.use((req, res, next) => {
|
|
332
|
+
const correlationId = req.headers['x-correlation-id'] || uuidv4();
|
|
333
|
+
res.setHeader('x-correlation-id', correlationId);
|
|
334
|
+
|
|
335
|
+
CorrelationIdManager.run(correlationId, () => {
|
|
336
|
+
next();
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Enhanced logger
|
|
341
|
+
const enhancedLogger = {
|
|
342
|
+
info: (message: string, meta?: object) =>
|
|
343
|
+
logger.info(message, {
|
|
344
|
+
correlationId: CorrelationIdManager.get(),
|
|
345
|
+
...meta
|
|
346
|
+
})
|
|
347
|
+
};
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 4. **PII and Sensitive Data Handling**
|
|
351
|
+
|
|
352
|
+
#### Data Sanitization
|
|
353
|
+
```typescript
|
|
354
|
+
// sanitizer.ts
|
|
355
|
+
const SENSITIVE_FIELDS = [
|
|
356
|
+
'password',
|
|
357
|
+
'token',
|
|
358
|
+
'apiKey',
|
|
359
|
+
'ssn',
|
|
360
|
+
'creditCard',
|
|
361
|
+
'email', // depending on regulations
|
|
362
|
+
'phone' // depending on regulations
|
|
363
|
+
];
|
|
364
|
+
|
|
365
|
+
function sanitize(obj: any): any {
|
|
366
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
367
|
+
return obj;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (Array.isArray(obj)) {
|
|
371
|
+
return obj.map(sanitize);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const sanitized = {};
|
|
375
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
376
|
+
if (SENSITIVE_FIELDS.some(field =>
|
|
377
|
+
key.toLowerCase().includes(field.toLowerCase())
|
|
378
|
+
)) {
|
|
379
|
+
sanitized[key] = '[REDACTED]';
|
|
380
|
+
} else if (typeof value === 'object') {
|
|
381
|
+
sanitized[key] = sanitize(value);
|
|
382
|
+
} else {
|
|
383
|
+
sanitized[key] = value;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return sanitized;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Usage
|
|
390
|
+
logger.info('User data', sanitize({
|
|
391
|
+
userId: '123',
|
|
392
|
+
email: 'user@example.com', // Will be redacted
|
|
393
|
+
password: 'secret123', // Will be redacted
|
|
394
|
+
name: 'John Doe' // Will be logged
|
|
395
|
+
}));
|
|
396
|
+
|
|
397
|
+
// Output:
|
|
398
|
+
// {
|
|
399
|
+
// "userId": "123",
|
|
400
|
+
// "email": "[REDACTED]",
|
|
401
|
+
// "password": "[REDACTED]",
|
|
402
|
+
// "name": "John Doe"
|
|
403
|
+
// }
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
#### Email/PII Masking
|
|
407
|
+
```typescript
|
|
408
|
+
// masking.ts
|
|
409
|
+
function maskEmail(email: string): string {
|
|
410
|
+
const [local, domain] = email.split('@');
|
|
411
|
+
const maskedLocal = local[0] + '*'.repeat(local.length - 2) + local[local.length - 1];
|
|
412
|
+
return `${maskedLocal}@${domain}`;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function maskPhone(phone: string): string {
|
|
416
|
+
return phone.replace(/\d(?=\d{4})/g, '*');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function maskCreditCard(cc: string): string {
|
|
420
|
+
return cc.replace(/\d(?=\d{4})/g, '*');
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Usage
|
|
424
|
+
logger.info('User registered', {
|
|
425
|
+
userId: user.id,
|
|
426
|
+
email: maskEmail(user.email), // u***r@example.com
|
|
427
|
+
phone: maskPhone(user.phone), // ******1234
|
|
428
|
+
creditCard: maskCreditCard(user.card) // ************1234
|
|
429
|
+
});
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### 5. **Performance Logging**
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
// performance-logger.ts
|
|
436
|
+
class PerformanceLogger {
|
|
437
|
+
private timers = new Map<string, number>();
|
|
438
|
+
|
|
439
|
+
start(operation: string) {
|
|
440
|
+
this.timers.set(operation, Date.now());
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
end(operation: string, metadata?: object) {
|
|
444
|
+
const startTime = this.timers.get(operation);
|
|
445
|
+
if (!startTime) return;
|
|
446
|
+
|
|
447
|
+
const duration = Date.now() - startTime;
|
|
448
|
+
this.timers.delete(operation);
|
|
449
|
+
|
|
450
|
+
logger.info(`Performance: ${operation}`, {
|
|
451
|
+
operation,
|
|
452
|
+
duration,
|
|
453
|
+
durationMs: duration,
|
|
454
|
+
...metadata
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// Alert if slow
|
|
458
|
+
if (duration > 1000) {
|
|
459
|
+
logger.warn(`Slow operation: ${operation}`, {
|
|
460
|
+
operation,
|
|
461
|
+
duration,
|
|
462
|
+
threshold: 1000,
|
|
463
|
+
...metadata
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async measure<T>(operation: string, fn: () => Promise<T>, metadata?: object): Promise<T> {
|
|
469
|
+
this.start(operation);
|
|
470
|
+
try {
|
|
471
|
+
return await fn();
|
|
472
|
+
} finally {
|
|
473
|
+
this.end(operation, metadata);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Usage
|
|
479
|
+
const perfLogger = new PerformanceLogger();
|
|
480
|
+
|
|
481
|
+
// Manual timing
|
|
482
|
+
perfLogger.start('database-query');
|
|
483
|
+
const users = await db.query('SELECT * FROM users');
|
|
484
|
+
perfLogger.end('database-query', { count: users.length });
|
|
485
|
+
|
|
486
|
+
// Automatic timing
|
|
487
|
+
const result = await perfLogger.measure(
|
|
488
|
+
'complex-operation',
|
|
489
|
+
async () => await processData(),
|
|
490
|
+
{ userId: '123' }
|
|
491
|
+
);
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### 6. **Centralized Logging**
|
|
495
|
+
|
|
496
|
+
#### ELK Stack (Elasticsearch, Logstash, Kibana)
|
|
497
|
+
```yaml
|
|
498
|
+
# docker-compose.yml
|
|
499
|
+
version: '3'
|
|
500
|
+
services:
|
|
501
|
+
elasticsearch:
|
|
502
|
+
image: elasticsearch:8.0.0
|
|
503
|
+
environment:
|
|
504
|
+
- discovery.type=single-node
|
|
505
|
+
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
|
506
|
+
ports:
|
|
507
|
+
- "9200:9200"
|
|
508
|
+
|
|
509
|
+
logstash:
|
|
510
|
+
image: logstash:8.0.0
|
|
511
|
+
volumes:
|
|
512
|
+
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
|
|
513
|
+
ports:
|
|
514
|
+
- "5000:5000"
|
|
515
|
+
depends_on:
|
|
516
|
+
- elasticsearch
|
|
517
|
+
|
|
518
|
+
kibana:
|
|
519
|
+
image: kibana:8.0.0
|
|
520
|
+
ports:
|
|
521
|
+
- "5601:5601"
|
|
522
|
+
depends_on:
|
|
523
|
+
- elasticsearch
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
```conf
|
|
527
|
+
# logstash.conf
|
|
528
|
+
input {
|
|
529
|
+
tcp {
|
|
530
|
+
port => 5000
|
|
531
|
+
codec => json
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
filter {
|
|
536
|
+
# Parse timestamp
|
|
537
|
+
date {
|
|
538
|
+
match => ["timestamp", "ISO8601"]
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
# Add geo-location if IP present
|
|
542
|
+
if [ip] {
|
|
543
|
+
geoip {
|
|
544
|
+
source => "ip"
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
output {
|
|
550
|
+
elasticsearch {
|
|
551
|
+
hosts => ["elasticsearch:9200"]
|
|
552
|
+
index => "app-logs-%{+YYYY.MM.dd}"
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
#### Ship Logs to ELK
|
|
558
|
+
```typescript
|
|
559
|
+
// winston-elk.ts
|
|
560
|
+
import winston from 'winston';
|
|
561
|
+
import 'winston-logstash';
|
|
562
|
+
|
|
563
|
+
const logger = winston.createLogger({
|
|
564
|
+
transports: [
|
|
565
|
+
new winston.transports.Logstash({
|
|
566
|
+
port: 5000,
|
|
567
|
+
host: 'logstash',
|
|
568
|
+
node_name: 'user-service',
|
|
569
|
+
max_connect_retries: -1
|
|
570
|
+
})
|
|
571
|
+
]
|
|
572
|
+
});
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
#### AWS CloudWatch Logs
|
|
576
|
+
```typescript
|
|
577
|
+
// cloudwatch-logger.ts
|
|
578
|
+
import winston from 'winston';
|
|
579
|
+
import WinstonCloudWatch from 'winston-cloudwatch';
|
|
580
|
+
|
|
581
|
+
const logger = winston.createLogger({
|
|
582
|
+
transports: [
|
|
583
|
+
new WinstonCloudWatch({
|
|
584
|
+
logGroupName: '/aws/lambda/user-service',
|
|
585
|
+
logStreamName: () => {
|
|
586
|
+
const date = new Date().toISOString().split('T')[0];
|
|
587
|
+
return `${date}-${process.env.LAMBDA_VERSION}`;
|
|
588
|
+
},
|
|
589
|
+
awsRegion: 'us-east-1',
|
|
590
|
+
jsonMessage: true
|
|
591
|
+
})
|
|
592
|
+
]
|
|
593
|
+
});
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### 7. **Distributed Tracing**
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
// tracing.ts
|
|
600
|
+
import opentelemetry from '@opentelemetry/api';
|
|
601
|
+
import { NodeTracerProvider } from '@opentelemetry/node';
|
|
602
|
+
import { SimpleSpanProcessor } from '@opentelemetry/tracing';
|
|
603
|
+
import { JaegerExporter } from '@opentelemetry/exporter-jaeger';
|
|
604
|
+
|
|
605
|
+
// Setup tracer
|
|
606
|
+
const provider = new NodeTracerProvider();
|
|
607
|
+
provider.addSpanProcessor(
|
|
608
|
+
new SimpleSpanProcessor(
|
|
609
|
+
new JaegerExporter({
|
|
610
|
+
serviceName: 'user-service',
|
|
611
|
+
endpoint: 'http://jaeger:14268/api/traces'
|
|
612
|
+
})
|
|
613
|
+
)
|
|
614
|
+
);
|
|
615
|
+
provider.register();
|
|
616
|
+
|
|
617
|
+
const tracer = opentelemetry.trace.getTracer('user-service');
|
|
618
|
+
|
|
619
|
+
// Usage in application
|
|
620
|
+
app.get('/api/users/:id', async (req, res) => {
|
|
621
|
+
const span = tracer.startSpan('get-user', {
|
|
622
|
+
attributes: {
|
|
623
|
+
'http.method': req.method,
|
|
624
|
+
'http.url': req.url,
|
|
625
|
+
'user.id': req.params.id
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
try {
|
|
630
|
+
const user = await fetchUser(req.params.id, span);
|
|
631
|
+
span.setStatus({ code: opentelemetry.SpanStatusCode.OK });
|
|
632
|
+
res.json(user);
|
|
633
|
+
} catch (error) {
|
|
634
|
+
span.setStatus({
|
|
635
|
+
code: opentelemetry.SpanStatusCode.ERROR,
|
|
636
|
+
message: error.message
|
|
637
|
+
});
|
|
638
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
639
|
+
} finally {
|
|
640
|
+
span.end();
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
async function fetchUser(userId: string, parentSpan: Span) {
|
|
645
|
+
const span = tracer.startSpan('database-query', {
|
|
646
|
+
parent: parentSpan,
|
|
647
|
+
attributes: { 'db.statement': 'SELECT * FROM users WHERE id = ?' }
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
try {
|
|
651
|
+
const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
|
|
652
|
+
return user;
|
|
653
|
+
} finally {
|
|
654
|
+
span.end();
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### 8. **Log Sampling (High-Volume Services)**
|
|
660
|
+
|
|
661
|
+
```typescript
|
|
662
|
+
// log-sampler.ts
|
|
663
|
+
class SamplingLogger {
|
|
664
|
+
constructor(
|
|
665
|
+
private logger: Logger,
|
|
666
|
+
private sampleRate: number = 0.1 // 10% sampling
|
|
667
|
+
) {}
|
|
668
|
+
|
|
669
|
+
info(message: string, meta?: object) {
|
|
670
|
+
if (this.shouldSample()) {
|
|
671
|
+
this.logger.info(message, meta);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Always log warnings and errors
|
|
676
|
+
warn(message: string, meta?: object) {
|
|
677
|
+
this.logger.warn(message, meta);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
error(message: string, error: Error, meta?: object) {
|
|
681
|
+
this.logger.error(message, error, meta);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
private shouldSample(): boolean {
|
|
685
|
+
return Math.random() < this.sampleRate;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Sample based on user ID (consistent sampling)
|
|
689
|
+
infoSampled(userId: string, message: string, meta?: object) {
|
|
690
|
+
const hash = this.hashUserId(userId);
|
|
691
|
+
if (hash % 100 < this.sampleRate * 100) {
|
|
692
|
+
this.logger.info(message, { ...meta, sampled: true });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
private hashUserId(userId: string): number {
|
|
697
|
+
let hash = 0;
|
|
698
|
+
for (let i = 0; i < userId.length; i++) {
|
|
699
|
+
hash = ((hash << 5) - hash) + userId.charCodeAt(i);
|
|
700
|
+
hash |= 0;
|
|
701
|
+
}
|
|
702
|
+
return Math.abs(hash);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
## Best Practices
|
|
708
|
+
|
|
709
|
+
### ✅ DO
|
|
710
|
+
- Use structured logging (JSON) in production
|
|
711
|
+
- Include correlation/request IDs in all logs
|
|
712
|
+
- Log at appropriate levels (don't overuse DEBUG)
|
|
713
|
+
- Redact sensitive data (PII, passwords, tokens)
|
|
714
|
+
- Include context (userId, requestId, etc.)
|
|
715
|
+
- Log errors with full stack traces
|
|
716
|
+
- Use centralized logging in distributed systems
|
|
717
|
+
- Set up log rotation to manage disk space
|
|
718
|
+
- Monitor log volume and costs
|
|
719
|
+
- Use async logging for performance
|
|
720
|
+
- Include timestamps in ISO 8601 format
|
|
721
|
+
- Log business events (user actions, transactions)
|
|
722
|
+
- Set up alerts for error patterns
|
|
723
|
+
|
|
724
|
+
### ❌ DON'T
|
|
725
|
+
- Log passwords, tokens, or sensitive data
|
|
726
|
+
- Use console.log in production
|
|
727
|
+
- Log at DEBUG level in production by default
|
|
728
|
+
- Log inside tight loops (use sampling)
|
|
729
|
+
- Include PII without anonymization
|
|
730
|
+
- Ignore log rotation (disk will fill up)
|
|
731
|
+
- Use synchronous logging in hot paths
|
|
732
|
+
- Log to multiple transports without need
|
|
733
|
+
- Forget to include error stack traces
|
|
734
|
+
- Log binary data or large objects
|
|
735
|
+
- Use string concatenation (use structured fields)
|
|
736
|
+
- Log every single request in high-volume APIs
|
|
737
|
+
|
|
738
|
+
## Common Patterns
|
|
739
|
+
|
|
740
|
+
### Pattern 1: Error Boundary Logging
|
|
741
|
+
```typescript
|
|
742
|
+
class ErrorBoundary {
|
|
743
|
+
static async handle(fn: () => Promise<void>) {
|
|
744
|
+
try {
|
|
745
|
+
await fn();
|
|
746
|
+
} catch (error) {
|
|
747
|
+
logger.error('Unhandled error', error, {
|
|
748
|
+
function: fn.name,
|
|
749
|
+
stack: error.stack
|
|
750
|
+
});
|
|
751
|
+
throw error;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### Pattern 2: Audit Logging
|
|
758
|
+
```typescript
|
|
759
|
+
function auditLog(action: string, resource: string) {
|
|
760
|
+
return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
761
|
+
const originalMethod = descriptor.value;
|
|
762
|
+
|
|
763
|
+
descriptor.value = async function(...args: any[]) {
|
|
764
|
+
const result = await originalMethod.apply(this, args);
|
|
765
|
+
|
|
766
|
+
logger.info('Audit', {
|
|
767
|
+
action,
|
|
768
|
+
resource,
|
|
769
|
+
userId: this.userId,
|
|
770
|
+
timestamp: new Date().toISOString(),
|
|
771
|
+
result: sanitize(result)
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
return result;
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
return descriptor;
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Usage
|
|
782
|
+
class UserService {
|
|
783
|
+
@auditLog('DELETE', 'user')
|
|
784
|
+
async deleteUser(userId: string) {
|
|
785
|
+
// ...
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
## Tools & Resources
|
|
791
|
+
|
|
792
|
+
- **Winston**: Versatile Node.js logger
|
|
793
|
+
- **Pino**: Fast JSON logger for Node.js
|
|
794
|
+
- **structlog**: Structured logging for Python
|
|
795
|
+
- **zap**: Fast structured logging for Go
|
|
796
|
+
- **Logback**: Java logging framework
|
|
797
|
+
- **ELK Stack**: Elasticsearch, Logstash, Kibana
|
|
798
|
+
- **Splunk**: Enterprise log management
|
|
799
|
+
- **Datadog**: Cloud monitoring and logging
|
|
800
|
+
- **CloudWatch**: AWS log management
|
|
801
|
+
- **Jaeger**: Distributed tracing
|
|
802
|
+
|
|
803
|
+
## Observability Architecture Interview
|
|
804
|
+
|
|
805
|
+
This interview runs during `/create-prd-security` §7.5. All 5 decisions must be confirmed before the security section is complete.
|
|
806
|
+
|
|
807
|
+
### Decision 1 — Logging Strategy
|
|
808
|
+
|
|
809
|
+
- **Logging library name** — the specific library (e.g., Pino, Winston, structlog, zap).
|
|
810
|
+
- **Structured JSON in production** — yes or no.
|
|
811
|
+
- **Log levels per environment** — dev: debug, staging: info, prod: warn.
|
|
812
|
+
- **PII field names that are never logged** — enumerate explicitly (e.g., `password`, `ssn`, `creditCard`, `token`).
|
|
813
|
+
- **Log destination** — stdout, file, cloud service — name it.
|
|
814
|
+
|
|
815
|
+
**Bootstrap fire:** When logging is confirmed, always fire `/bootstrap-agents OBSERVABILITY=structured-logging` first to provision baseline logging guidance. If the confirmed library or stack maps to an additional observability tool (e.g., Datadog, OpenTelemetry, Pino), also fire `/bootstrap-agents OBSERVABILITY=[tool-specific value]`.
|
|
816
|
+
|
|
817
|
+
### Decision 2 — Tracing Strategy
|
|
818
|
+
|
|
819
|
+
- **Which service boundaries are traced** — name the services or layers where trace spans are created.
|
|
820
|
+
- **Sampling rate per environment** — e.g., dev: 100%, staging: 50%, prod: 10%.
|
|
821
|
+
- **Trace ID propagation to API clients** — header name used to propagate trace IDs (e.g., `X-Trace-Id`, `traceparent`).
|
|
822
|
+
|
|
823
|
+
**Bootstrap fire:** If a specific tracing tool is confirmed, invoke `/bootstrap-agents OBSERVABILITY=[confirmed value]`.
|
|
824
|
+
|
|
825
|
+
### Decision 3 — Alerting Thresholds
|
|
826
|
+
|
|
827
|
+
- **Error rate percentage that triggers alert** — e.g., 5% of requests returning 5xx in a 5-minute window.
|
|
828
|
+
- **Latency threshold (ms) + duration before alert** — e.g., p95 > 500ms for 3 consecutive minutes.
|
|
829
|
+
- **Queue depth warning level** — e.g., background job queue exceeds 1000 items.
|
|
830
|
+
- **Delivery mechanism** — PagerDuty, Slack, email — name it.
|
|
831
|
+
|
|
832
|
+
**Bootstrap fire:** If a specific monitoring tool is confirmed, invoke `/bootstrap-agents MONITORING=[confirmed value]`.
|
|
833
|
+
|
|
834
|
+
### Decision 4 — Launch Dashboards
|
|
835
|
+
|
|
836
|
+
- **Minimum required panels** — name each panel (e.g., request rate, error rate, p50/p95/p99 latency, active connections, queue depth, CPU/memory utilization).
|
|
837
|
+
- **Tool** — Grafana, Datadog, CloudWatch — name it.
|
|
838
|
+
- **Dashboard owner** — role, not person (e.g., "on-call engineer", "platform team lead").
|
|
839
|
+
|
|
840
|
+
### Decision 5 — Retention
|
|
841
|
+
|
|
842
|
+
- **Log retention duration** — e.g., 30 days hot, 90 days cold.
|
|
843
|
+
- **Trace retention duration** — e.g., 7 days.
|
|
844
|
+
- **Compliance alignment** — if applicable (e.g., SOC2 requires 1 year of audit logs).
|
|
845
|
+
|
|
846
|
+
### User Presentation Prompts
|
|
847
|
+
|
|
848
|
+
Present these two questions to the user for confirmation:
|
|
849
|
+
|
|
850
|
+
1. "Are these logging levels and PII exclusions correct for your compliance requirements?"
|
|
851
|
+
2. "Are the alerting thresholds appropriate for your expected traffic?"
|