agent-skill-kit 3.9.135
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/.agent/global.d.ts +80 -0
- package/.agent/rules/GEMINI.md +210 -0
- package/.agent/rules/autopilot.md +287 -0
- package/.agent/rules/code-rules.md +227 -0
- package/.agent/scripts/audit_workflows.ts +23 -0
- package/.agent/scripts/auto_preview.ts +170 -0
- package/.agent/scripts/checklist.ts +180 -0
- package/.agent/scripts/compile-agents.ts +237 -0
- package/.agent/scripts/fix_skills.ts +49 -0
- package/.agent/scripts/session_manager.ts +222 -0
- package/.agent/scripts/skill-audit.ts +255 -0
- package/.agent/scripts/sync_workflows.ts +54 -0
- package/.agent/scripts/utils/colors.ts +58 -0
- package/.agent/scripts/utils/process-manager.ts +131 -0
- package/.agent/scripts/utils/reporter.ts +192 -0
- package/.agent/scripts/utils/runner.ts +128 -0
- package/.agent/scripts/verify_all.ts +243 -0
- package/.agent/scripts/version-sync.ts +256 -0
- package/.agent/skills/SKILL_INDEX.md +129 -0
- package/.agent/skills/agent-browser/AGENTS.md +728 -0
- package/.agent/skills/agent-browser/SKILL.md +193 -0
- package/.agent/skills/agent-browser/rules/_sections.md +15 -0
- package/.agent/skills/agent-browser/rules/_template.md +32 -0
- package/.agent/skills/agent-browser/rules/engineering-spec.md +528 -0
- package/.agent/skills/agent-browser/scripts/browser_cli.ts +52 -0
- package/.agent/skills/agent-browser/scripts/session_manager.ts +166 -0
- package/.agent/skills/ai-artist/AGENTS.md +1082 -0
- package/.agent/skills/ai-artist/SKILL.md +186 -0
- package/.agent/skills/ai-artist/rules/_sections.md +30 -0
- package/.agent/skills/ai-artist/rules/_template.md +32 -0
- package/.agent/skills/ai-artist/rules/domain-code.md +118 -0
- package/.agent/skills/ai-artist/rules/domain-marketing.md +105 -0
- package/.agent/skills/ai-artist/rules/engineering-spec.md +519 -0
- package/.agent/skills/ai-artist/rules/image-prompts.md +195 -0
- package/.agent/skills/ai-artist/rules/model-syntax.md +115 -0
- package/.agent/skills/ai-artist/scripts/prompt_compiler.ts +72 -0
- package/.agent/skills/ai-artist/templates/image-core.txt +1 -0
- package/.agent/skills/ai-artist/templates/llm-core.txt +6 -0
- package/.agent/skills/api-architect/AGENTS.md +1896 -0
- package/.agent/skills/api-architect/SKILL.md +173 -0
- package/.agent/skills/api-architect/rules/_sections.md +35 -0
- package/.agent/skills/api-architect/rules/_template.md +32 -0
- package/.agent/skills/api-architect/rules/api-style.md +115 -0
- package/.agent/skills/api-architect/rules/auth.md +134 -0
- package/.agent/skills/api-architect/rules/documentation.md +131 -0
- package/.agent/skills/api-architect/rules/engineering-spec.md +505 -0
- package/.agent/skills/api-architect/rules/graphql.md +154 -0
- package/.agent/skills/api-architect/rules/rate-limiting.md +76 -0
- package/.agent/skills/api-architect/rules/response.md +138 -0
- package/.agent/skills/api-architect/rules/rest.md +113 -0
- package/.agent/skills/api-architect/rules/security-testing.md +146 -0
- package/.agent/skills/api-architect/rules/trpc.md +129 -0
- package/.agent/skills/api-architect/rules/versioning.md +100 -0
- package/.agent/skills/api-architect/scripts/api_validator.ts +413 -0
- package/.agent/skills/auth-patterns/AGENTS.md +1830 -0
- package/.agent/skills/auth-patterns/SKILL.md +163 -0
- package/.agent/skills/auth-patterns/rules/_sections.md +30 -0
- package/.agent/skills/auth-patterns/rules/_template.md +32 -0
- package/.agent/skills/auth-patterns/rules/engineering-spec.md +515 -0
- package/.agent/skills/auth-patterns/rules/jwt-deep.md +196 -0
- package/.agent/skills/auth-patterns/rules/mfa.md +174 -0
- package/.agent/skills/auth-patterns/rules/oauth2.md +134 -0
- package/.agent/skills/auth-patterns/rules/passkey.md +243 -0
- package/.agent/skills/auth-patterns/rules/rbac-abac.md +206 -0
- package/.agent/skills/auth-patterns/rules/session.md +183 -0
- package/.agent/skills/auth-patterns/scripts/auth_validator.ts +121 -0
- package/.agent/skills/chrome-devtools/AGENTS.md +952 -0
- package/.agent/skills/chrome-devtools/SKILL.md +160 -0
- package/.agent/skills/chrome-devtools/rules/_sections.md +25 -0
- package/.agent/skills/chrome-devtools/rules/_template.md +32 -0
- package/.agent/skills/chrome-devtools/rules/aria-snapshot.md +95 -0
- package/.agent/skills/chrome-devtools/rules/engineering-spec.md +510 -0
- package/.agent/skills/chrome-devtools/rules/scripts-guide.md +174 -0
- package/.agent/skills/chrome-devtools/scripts/aria-snapshot.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/click.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/console.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/core_cli.ts +79 -0
- package/.agent/skills/chrome-devtools/scripts/evaluate.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/fill.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/navigate.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/network.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/performance.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/screenshot.ts +3 -0
- package/.agent/skills/chrome-devtools/scripts/select-ref.ts +3 -0
- package/.agent/skills/cicd-pipeline/AGENTS.md +809 -0
- package/.agent/skills/cicd-pipeline/SKILL.md +164 -0
- package/.agent/skills/cicd-pipeline/rules/_sections.md +15 -0
- package/.agent/skills/cicd-pipeline/rules/_template.md +32 -0
- package/.agent/skills/cicd-pipeline/rules/engineering-spec.md +477 -0
- package/.agent/skills/cicd-pipeline/scripts/flag-manager.ts +253 -0
- package/.agent/skills/cicd-pipeline/scripts/pipeline_validator.ts +133 -0
- package/.agent/skills/code-constitution/AGENTS.md +597 -0
- package/.agent/skills/code-constitution/CHANGELOG.md +216 -0
- package/.agent/skills/code-constitution/SKILL.md +191 -0
- package/.agent/skills/code-constitution/VERSION +3 -0
- package/.agent/skills/code-constitution/examples/violation-backend-mutation/after.tsx +59 -0
- package/.agent/skills/code-constitution/examples/violation-backend-mutation/before.tsx +42 -0
- package/.agent/skills/code-constitution/examples/violation-backend-mutation/explanation.md +91 -0
- package/.agent/skills/code-constitution/examples/violation-chart-injection/after.tsx +99 -0
- package/.agent/skills/code-constitution/examples/violation-chart-injection/before.tsx +57 -0
- package/.agent/skills/code-constitution/examples/violation-chart-injection/explanation.md +120 -0
- package/.agent/skills/code-constitution/knowledge/lessons-learned.yaml +3 -0
- package/.agent/skills/code-constitution/metadata/precedence.yaml +117 -0
- package/.agent/skills/code-constitution/metadata/scope-map.yaml +156 -0
- package/.agent/skills/code-constitution/proposals/v1.1-change-proposal-template.md +201 -0
- package/.agent/skills/code-constitution/resources/AUTHORITY_MODEL.md +115 -0
- package/.agent/skills/code-constitution/resources/ENFORCEMENT_GUIDE.md +246 -0
- package/.agent/skills/code-constitution/resources/LOAD_ORDER.md +86 -0
- package/.agent/skills/code-constitution/rules/_sections.md +15 -0
- package/.agent/skills/code-constitution/rules/_template.md +32 -0
- package/.agent/skills/code-constitution/rules/constitution/master-constitution.md +210 -0
- package/.agent/skills/code-constitution/rules/doctrines/architecture/architecture-doctrine.md +188 -0
- package/.agent/skills/code-constitution/rules/doctrines/backend/backend-data-engine-doctrine.md +218 -0
- package/.agent/skills/code-constitution/rules/doctrines/commercial/commercial-guardrails-doctrine.md +196 -0
- package/.agent/skills/code-constitution/rules/doctrines/data/data-integrity-doctrine.md +202 -0
- package/.agent/skills/code-constitution/rules/doctrines/frontend/frontend-mobile-doctrine.md +169 -0
- package/.agent/skills/code-constitution/rules/doctrines/frontend/interaction-patterns-doctrine.md +176 -0
- package/.agent/skills/code-constitution/rules/doctrines/learning/learning-engine-doctrine.md +192 -0
- package/.agent/skills/code-constitution/rules/doctrines/performance/performance-doctrine.md +180 -0
- package/.agent/skills/code-constitution/rules/doctrines/review/code-review-doctrine.md +174 -0
- package/.agent/skills/code-constitution/rules/enforcement/agents/agent-enforcement-protocol.md +218 -0
- package/.agent/skills/code-constitution/rules/enforcement/agents/agent-system-prompt.md +196 -0
- package/.agent/skills/code-constitution/rules/enforcement/checklists/backend-api-review-checklist.md +131 -0
- package/.agent/skills/code-constitution/rules/enforcement/checklists/chart-component-review-checklist.md +147 -0
- package/.agent/skills/code-constitution/rules/enforcement/checklists/frontend-review-checklist.md +194 -0
- package/.agent/skills/code-constitution/rules/enforcement/playbooks/doctrine-violation-playbook.md +236 -0
- package/.agent/skills/code-constitution/rules/engineering-spec.md +561 -0
- package/.agent/skills/code-constitution/scripts/audit_pr.ts +219 -0
- package/.agent/skills/code-constitution/scripts/check_boundaries.ts +134 -0
- package/.agent/skills/code-constitution/scripts/learn.ts +202 -0
- package/.agent/skills/code-constitution/scripts/validate_doctrine.ts +287 -0
- package/.agent/skills/code-craft/AGENTS.md +803 -0
- package/.agent/skills/code-craft/SKILL.md +170 -0
- package/.agent/skills/code-craft/rules/_sections.md +20 -0
- package/.agent/skills/code-craft/rules/_template.md +32 -0
- package/.agent/skills/code-craft/rules/engineering-spec.md +447 -0
- package/.agent/skills/code-craft/rules/verification-scripts.md +83 -0
- package/.agent/skills/code-craft/scripts/code_quality_checker.ts +193 -0
- package/.agent/skills/code-review/AGENTS.md +1664 -0
- package/.agent/skills/code-review/SKILL.md +152 -0
- package/.agent/skills/code-review/rules/_sections.md +15 -0
- package/.agent/skills/code-review/rules/_template.md +32 -0
- package/.agent/skills/code-review/rules/engineering-spec.md +466 -0
- package/.agent/skills/code-review/scripts/lint_runner.ts +213 -0
- package/.agent/skills/code-review/scripts/type_coverage.ts +118 -0
- package/.agent/skills/context-engineering/AGENTS.md +499 -0
- package/.agent/skills/context-engineering/SKILL.md +147 -0
- package/.agent/skills/context-engineering/rules/_sections.md +15 -0
- package/.agent/skills/context-engineering/rules/_template.md +32 -0
- package/.agent/skills/context-engineering/rules/engineering-spec.md +463 -0
- package/.agent/skills/context-engineering/scripts/context_analyzer.ts +127 -0
- package/.agent/skills/copywriting/AGENTS.md +501 -0
- package/.agent/skills/copywriting/SKILL.md +188 -0
- package/.agent/skills/copywriting/rules/_sections.md +15 -0
- package/.agent/skills/copywriting/rules/_template.md +32 -0
- package/.agent/skills/copywriting/rules/engineering-spec.md +465 -0
- package/.agent/skills/copywriting/scripts/copy_validator.ts +185 -0
- package/.agent/skills/data-modeler/AGENTS.md +814 -0
- package/.agent/skills/data-modeler/SKILL.md +195 -0
- package/.agent/skills/data-modeler/rules/_sections.md +15 -0
- package/.agent/skills/data-modeler/rules/_template.md +32 -0
- package/.agent/skills/data-modeler/rules/database-selection.md +124 -0
- package/.agent/skills/data-modeler/rules/engineering-spec.md +479 -0
- package/.agent/skills/data-modeler/rules/indexing.md +166 -0
- package/.agent/skills/data-modeler/rules/migrations.md +176 -0
- package/.agent/skills/data-modeler/rules/optimization.md +161 -0
- package/.agent/skills/data-modeler/rules/orm-selection.md +155 -0
- package/.agent/skills/data-modeler/rules/schema-design.md +162 -0
- package/.agent/skills/data-modeler/scripts/schema_validator.ts +357 -0
- package/.agent/skills/debug-pro/AGENTS.md +798 -0
- package/.agent/skills/debug-pro/SKILL.md +193 -0
- package/.agent/skills/debug-pro/defense-in-depth/SKILL.md +148 -0
- package/.agent/skills/debug-pro/root-cause-tracing/SKILL.md +196 -0
- package/.agent/skills/debug-pro/root-cause-tracing/find-polluter.sh +63 -0
- package/.agent/skills/debug-pro/rules/_sections.md +15 -0
- package/.agent/skills/debug-pro/rules/_template.md +32 -0
- package/.agent/skills/debug-pro/rules/engineering-spec.md +491 -0
- package/.agent/skills/debug-pro/scripts/debug_verifier.ts +148 -0
- package/.agent/skills/debug-pro/verification-before-completion/SKILL.md +160 -0
- package/.agent/skills/design-system/AGENTS.md +4216 -0
- package/.agent/skills/design-system/SKILL.md +186 -0
- package/.agent/skills/design-system/rules/_sections.md +65 -0
- package/.agent/skills/design-system/rules/_template.md +32 -0
- package/.agent/skills/design-system/rules/animation-guide.md +355 -0
- package/.agent/skills/design-system/rules/color-system.md +335 -0
- package/.agent/skills/design-system/rules/color-systems.md +133 -0
- package/.agent/skills/design-system/rules/decision-trees.md +442 -0
- package/.agent/skills/design-system/rules/design-extraction.md +152 -0
- package/.agent/skills/design-system/rules/engineering-spec.md +484 -0
- package/.agent/skills/design-system/rules/motion-design.md +161 -0
- package/.agent/skills/design-system/rules/motion-graphics.md +330 -0
- package/.agent/skills/design-system/rules/spatial-composition.md +184 -0
- package/.agent/skills/design-system/rules/typography-system.md +369 -0
- package/.agent/skills/design-system/rules/typography.md +124 -0
- package/.agent/skills/design-system/rules/ux-psychology.md +565 -0
- package/.agent/skills/design-system/rules/visual-effects.md +407 -0
- package/.agent/skills/design-system/scripts/accessibility_checker.ts +292 -0
- package/.agent/skills/design-system/scripts/ux_audit.ts +356 -0
- package/.agent/skills/doc-templates/AGENTS.md +820 -0
- package/.agent/skills/doc-templates/SKILL.md +260 -0
- package/.agent/skills/doc-templates/rules/_sections.md +20 -0
- package/.agent/skills/doc-templates/rules/_template.md +32 -0
- package/.agent/skills/doc-templates/rules/doc.md +355 -0
- package/.agent/skills/doc-templates/rules/engineering-spec.md +422 -0
- package/.agent/skills/doc-templates/scripts/editor-server.ts +162 -0
- package/.agent/skills/doc-templates/scripts/inject_otel.ts +22 -0
- package/.agent/skills/doc-templates/scripts/kanban-server.ts +171 -0
- package/.agent/skills/doc-templates/scripts/markdown-server.ts +185 -0
- package/.agent/skills/e2e-automation/AGENTS.md +882 -0
- package/.agent/skills/e2e-automation/SKILL.md +175 -0
- package/.agent/skills/e2e-automation/rules/_sections.md +20 -0
- package/.agent/skills/e2e-automation/rules/_template.md +32 -0
- package/.agent/skills/e2e-automation/rules/aria-snapshot.md +185 -0
- package/.agent/skills/e2e-automation/rules/engineering-spec.md +501 -0
- package/.agent/skills/e2e-automation/scripts/playwright_runner.ts +208 -0
- package/.agent/skills/execution-reporter/AGENTS.md +419 -0
- package/.agent/skills/execution-reporter/SKILL.md +152 -0
- package/.agent/skills/execution-reporter/rules/_sections.md +15 -0
- package/.agent/skills/execution-reporter/rules/_template.md +32 -0
- package/.agent/skills/execution-reporter/rules/engineering-spec.md +389 -0
- package/.agent/skills/game-development/2d-games/SKILL.md +140 -0
- package/.agent/skills/game-development/3d-games/SKILL.md +156 -0
- package/.agent/skills/game-development/AGENTS.md +783 -0
- package/.agent/skills/game-development/SKILL.md +178 -0
- package/.agent/skills/game-development/game-art/SKILL.md +207 -0
- package/.agent/skills/game-development/game-audio/SKILL.md +211 -0
- package/.agent/skills/game-development/game-design/SKILL.md +151 -0
- package/.agent/skills/game-development/mobile-games/SKILL.md +130 -0
- package/.agent/skills/game-development/multiplayer/SKILL.md +154 -0
- package/.agent/skills/game-development/pc-games/SKILL.md +167 -0
- package/.agent/skills/game-development/rules/_sections.md +15 -0
- package/.agent/skills/game-development/rules/_template.md +32 -0
- package/.agent/skills/game-development/rules/engineering-spec.md +480 -0
- package/.agent/skills/game-development/vr-ar/SKILL.md +144 -0
- package/.agent/skills/game-development/web-games/SKILL.md +173 -0
- package/.agent/skills/git-workflow/AGENTS.md +554 -0
- package/.agent/skills/git-workflow/SKILL.md +181 -0
- package/.agent/skills/git-workflow/rules/_sections.md +15 -0
- package/.agent/skills/git-workflow/rules/_template.md +32 -0
- package/.agent/skills/git-workflow/rules/engineering-spec.md +518 -0
- package/.agent/skills/gitops/AGENTS.md +921 -0
- package/.agent/skills/gitops/SKILL.md +163 -0
- package/.agent/skills/gitops/rules/_sections.md +25 -0
- package/.agent/skills/gitops/rules/_template.md +32 -0
- package/.agent/skills/gitops/rules/argocd-setup.md +148 -0
- package/.agent/skills/gitops/rules/engineering-spec.md +450 -0
- package/.agent/skills/gitops/rules/sync-policies.md +145 -0
- package/.agent/skills/google-adk-python/AGENTS.md +1054 -0
- package/.agent/skills/google-adk-python/SKILL.md +168 -0
- package/.agent/skills/google-adk-python/rules/_sections.md +25 -0
- package/.agent/skills/google-adk-python/rules/_template.md +32 -0
- package/.agent/skills/google-adk-python/rules/deployment.md +138 -0
- package/.agent/skills/google-adk-python/rules/engineering-spec.md +451 -0
- package/.agent/skills/google-adk-python/rules/multi-agent.md +146 -0
- package/.agent/skills/google-adk-python/rules/tools.md +131 -0
- package/.agent/skills/idea-storm/AGENTS.md +995 -0
- package/.agent/skills/idea-storm/SKILL.md +160 -0
- package/.agent/skills/idea-storm/rules/_sections.md +25 -0
- package/.agent/skills/idea-storm/rules/_template.md +32 -0
- package/.agent/skills/idea-storm/rules/architecture-debate.md +122 -0
- package/.agent/skills/idea-storm/rules/dynamic-questioning.md +374 -0
- package/.agent/skills/idea-storm/rules/engineering-spec.md +466 -0
- package/.agent/skills/knowledge-compiler/SKILL.md +320 -0
- package/.agent/skills/knowledge-graph/AGENTS.md +762 -0
- package/.agent/skills/knowledge-graph/SKILL.md +157 -0
- package/.agent/skills/knowledge-graph/rules/_sections.md +15 -0
- package/.agent/skills/knowledge-graph/rules/_template.md +32 -0
- package/.agent/skills/knowledge-graph/rules/engineering-spec.md +439 -0
- package/.agent/skills/knowledge-linter/SKILL.md +217 -0
- package/.agent/skills/lifecycle-orchestrator/AGENTS.md +989 -0
- package/.agent/skills/lifecycle-orchestrator/SKILL.md +169 -0
- package/.agent/skills/lifecycle-orchestrator/rules/_sections.md +15 -0
- package/.agent/skills/lifecycle-orchestrator/rules/_template.md +32 -0
- package/.agent/skills/lifecycle-orchestrator/rules/engineering-spec.md +525 -0
- package/.agent/skills/lifecycle-orchestrator/scripts/state_manager.ts +189 -0
- package/.agent/skills/mcp-builder/AGENTS.md +1653 -0
- package/.agent/skills/mcp-builder/SKILL.md +166 -0
- package/.agent/skills/mcp-builder/rules/_sections.md +40 -0
- package/.agent/skills/mcp-builder/rules/_template.md +32 -0
- package/.agent/skills/mcp-builder/rules/best-practices.md +157 -0
- package/.agent/skills/mcp-builder/rules/design-principles.md +105 -0
- package/.agent/skills/mcp-builder/rules/engineering-spec.md +473 -0
- package/.agent/skills/mcp-builder/rules/evaluation.md +103 -0
- package/.agent/skills/mcp-builder/rules/python-implementation.md +249 -0
- package/.agent/skills/mcp-builder/rules/quickstart.md +111 -0
- package/.agent/skills/mcp-builder/rules/typescript-implementation.md +280 -0
- package/.agent/skills/mcp-management/AGENTS.md +837 -0
- package/.agent/skills/mcp-management/SKILL.md +164 -0
- package/.agent/skills/mcp-management/rules/_sections.md +25 -0
- package/.agent/skills/mcp-management/rules/_template.md +32 -0
- package/.agent/skills/mcp-management/rules/cli-usage.md +146 -0
- package/.agent/skills/mcp-management/rules/engineering-spec.md +501 -0
- package/.agent/skills/mcp-management/rules/protocol.md +159 -0
- package/.agent/skills/media-processing/AGENTS.md +479 -0
- package/.agent/skills/media-processing/SKILL.md +176 -0
- package/.agent/skills/media-processing/rules/_sections.md +15 -0
- package/.agent/skills/media-processing/rules/_template.md +32 -0
- package/.agent/skills/media-processing/rules/engineering-spec.md +452 -0
- package/.agent/skills/media-processing/scripts/convert-video.ts +155 -0
- package/.agent/skills/media-processing/scripts/optimize-image.ts +127 -0
- package/.agent/skills/mobile-design/AGENTS.md +6531 -0
- package/.agent/skills/mobile-design/SKILL.md +165 -0
- package/.agent/skills/mobile-design/rules/_sections.md +45 -0
- package/.agent/skills/mobile-design/rules/_template.md +32 -0
- package/.agent/skills/mobile-design/rules/decision-trees.md +540 -0
- package/.agent/skills/mobile-design/rules/engineering-spec.md +467 -0
- package/.agent/skills/mobile-design/rules/mobile-backend.md +516 -0
- package/.agent/skills/mobile-design/rules/mobile-color-system.md +436 -0
- package/.agent/skills/mobile-design/rules/mobile-debugging.md +146 -0
- package/.agent/skills/mobile-design/rules/mobile-design-thinking.md +381 -0
- package/.agent/skills/mobile-design/rules/mobile-navigation.md +474 -0
- package/.agent/skills/mobile-design/rules/mobile-performance.md +783 -0
- package/.agent/skills/mobile-design/rules/mobile-testing.md +380 -0
- package/.agent/skills/mobile-design/rules/mobile-typography.md +449 -0
- package/.agent/skills/mobile-design/rules/platform-android.md +682 -0
- package/.agent/skills/mobile-design/rules/platform-ios.md +577 -0
- package/.agent/skills/mobile-design/rules/touch-psychology.md +553 -0
- package/.agent/skills/mobile-design/scripts/mobile_audit.ts +309 -0
- package/.agent/skills/mobile-developer/AGENTS.md +904 -0
- package/.agent/skills/mobile-developer/SKILL.md +194 -0
- package/.agent/skills/mobile-developer/rules/_sections.md +75 -0
- package/.agent/skills/mobile-developer/rules/_template.md +32 -0
- package/.agent/skills/mobile-developer/rules/anti-patterns.md +70 -0
- package/.agent/skills/mobile-developer/rules/app-store-optimization.md +319 -0
- package/.agent/skills/mobile-developer/rules/decision-trees.md +545 -0
- package/.agent/skills/mobile-developer/rules/deep-linking.md +441 -0
- package/.agent/skills/mobile-developer/rules/engineering-spec.md +477 -0
- package/.agent/skills/mobile-developer/rules/flutter.md +475 -0
- package/.agent/skills/mobile-developer/rules/mobile-backend.md +516 -0
- package/.agent/skills/mobile-developer/rules/mobile-color-system.md +444 -0
- package/.agent/skills/mobile-developer/rules/mobile-debugging.md +428 -0
- package/.agent/skills/mobile-developer/rules/mobile-design-thinking.md +367 -0
- package/.agent/skills/mobile-developer/rules/mobile-navigation.md +483 -0
- package/.agent/skills/mobile-developer/rules/mobile-performance.md +778 -0
- package/.agent/skills/mobile-developer/rules/mobile-testing.md +382 -0
- package/.agent/skills/mobile-developer/rules/mobile-typography.md +457 -0
- package/.agent/skills/mobile-developer/rules/native.md +572 -0
- package/.agent/skills/mobile-developer/rules/platform-android.md +676 -0
- package/.agent/skills/mobile-developer/rules/platform-ios.md +571 -0
- package/.agent/skills/mobile-developer/rules/push-notifications.md +599 -0
- package/.agent/skills/mobile-developer/rules/react-native.md +422 -0
- package/.agent/skills/mobile-developer/rules/touch-psychology.md +547 -0
- package/.agent/skills/mobile-developer/scripts/mobile_audit.ts +701 -0
- package/.agent/skills/nextjs-pro/AGENTS.md +3932 -0
- package/.agent/skills/nextjs-pro/SKILL.md +171 -0
- package/.agent/skills/nextjs-pro/rules/_sections.md +50 -0
- package/.agent/skills/nextjs-pro/rules/_template.md +32 -0
- package/.agent/skills/nextjs-pro/rules/advanced-event-handler-refs.md +59 -0
- package/.agent/skills/nextjs-pro/rules/advanced-init-once.md +46 -0
- package/.agent/skills/nextjs-pro/rules/advanced-use-latest.md +43 -0
- package/.agent/skills/nextjs-pro/rules/async-api-routes.md +42 -0
- package/.agent/skills/nextjs-pro/rules/async-defer-await.md +84 -0
- package/.agent/skills/nextjs-pro/rules/async-dependencies.md +55 -0
- package/.agent/skills/nextjs-pro/rules/async-parallel.md +32 -0
- package/.agent/skills/nextjs-pro/rules/async-suspense-boundaries.md +103 -0
- package/.agent/skills/nextjs-pro/rules/bundle-barrel-imports.md +63 -0
- package/.agent/skills/nextjs-pro/rules/bundle-conditional.md +35 -0
- package/.agent/skills/nextjs-pro/rules/bundle-defer-third-party.md +53 -0
- package/.agent/skills/nextjs-pro/rules/bundle-dynamic-imports.md +39 -0
- package/.agent/skills/nextjs-pro/rules/bundle-preload.md +54 -0
- package/.agent/skills/nextjs-pro/rules/client-event-listeners.md +78 -0
- package/.agent/skills/nextjs-pro/rules/client-localstorage-schema.md +75 -0
- package/.agent/skills/nextjs-pro/rules/client-passive-event-listeners.md +52 -0
- package/.agent/skills/nextjs-pro/rules/client-swr-dedup.md +60 -0
- package/.agent/skills/nextjs-pro/rules/engineering-spec.md +440 -0
- package/.agent/skills/nextjs-pro/rules/js-batch-dom-css.md +111 -0
- package/.agent/skills/nextjs-pro/rules/js-cache-function-results.md +84 -0
- package/.agent/skills/nextjs-pro/rules/js-cache-property-access.md +32 -0
- package/.agent/skills/nextjs-pro/rules/js-cache-storage.md +74 -0
- package/.agent/skills/nextjs-pro/rules/js-combine-iterations.md +36 -0
- package/.agent/skills/nextjs-pro/rules/js-early-exit.md +54 -0
- package/.agent/skills/nextjs-pro/rules/js-hoist-regexp.md +49 -0
- package/.agent/skills/nextjs-pro/rules/js-index-maps.md +41 -0
- package/.agent/skills/nextjs-pro/rules/js-length-check-first.md +53 -0
- package/.agent/skills/nextjs-pro/rules/js-min-max-loop.md +86 -0
- package/.agent/skills/nextjs-pro/rules/js-set-map-lookups.md +28 -0
- package/.agent/skills/nextjs-pro/rules/js-tosorted-immutable.md +61 -0
- package/.agent/skills/nextjs-pro/rules/rendering-activity.md +30 -0
- package/.agent/skills/nextjs-pro/rules/rendering-animate-svg-wrapper.md +51 -0
- package/.agent/skills/nextjs-pro/rules/rendering-conditional-render.md +44 -0
- package/.agent/skills/nextjs-pro/rules/rendering-content-visibility.md +42 -0
- package/.agent/skills/nextjs-pro/rules/rendering-hoist-jsx.md +50 -0
- package/.agent/skills/nextjs-pro/rules/rendering-hydration-no-flicker.md +86 -0
- package/.agent/skills/nextjs-pro/rules/rendering-hydration-suppress-warning.md +34 -0
- package/.agent/skills/nextjs-pro/rules/rendering-svg-precision.md +32 -0
- package/.agent/skills/nextjs-pro/rules/rendering-usetransition-loading.md +79 -0
- package/.agent/skills/nextjs-pro/rules/rerender-defer-reads.md +43 -0
- package/.agent/skills/nextjs-pro/rules/rerender-dependencies.md +49 -0
- package/.agent/skills/nextjs-pro/rules/rerender-derived-state-no-effect.md +44 -0
- package/.agent/skills/nextjs-pro/rules/rerender-derived-state.md +33 -0
- package/.agent/skills/nextjs-pro/rules/rerender-functional-setstate.md +78 -0
- package/.agent/skills/nextjs-pro/rules/rerender-lazy-state-init.md +62 -0
- package/.agent/skills/nextjs-pro/rules/rerender-memo-with-default-value.md +42 -0
- package/.agent/skills/nextjs-pro/rules/rerender-memo.md +48 -0
- package/.agent/skills/nextjs-pro/rules/rerender-move-effect-to-event.md +49 -0
- package/.agent/skills/nextjs-pro/rules/rerender-simple-expression-in-memo.md +39 -0
- package/.agent/skills/nextjs-pro/rules/rerender-transitions.md +44 -0
- package/.agent/skills/nextjs-pro/rules/rerender-use-ref-transient-values.md +77 -0
- package/.agent/skills/nextjs-pro/rules/schema.json +34 -0
- package/.agent/skills/nextjs-pro/rules/server-after-nonblocking.md +77 -0
- package/.agent/skills/nextjs-pro/rules/server-auth-actions.md +100 -0
- package/.agent/skills/nextjs-pro/rules/server-cache-lru.md +45 -0
- package/.agent/skills/nextjs-pro/rules/server-cache-react.md +80 -0
- package/.agent/skills/nextjs-pro/rules/server-dedup-props.md +69 -0
- package/.agent/skills/nextjs-pro/rules/server-parallel-fetching.md +87 -0
- package/.agent/skills/nextjs-pro/rules/server-serialization.md +42 -0
- package/.agent/skills/nodejs-pro/AGENTS.md +866 -0
- package/.agent/skills/nodejs-pro/SKILL.md +172 -0
- package/.agent/skills/nodejs-pro/rules/_sections.md +50 -0
- package/.agent/skills/nodejs-pro/rules/_template.md +32 -0
- package/.agent/skills/nodejs-pro/rules/architecture-patterns.md +229 -0
- package/.agent/skills/nodejs-pro/rules/async-patterns.md +246 -0
- package/.agent/skills/nodejs-pro/rules/engineering-spec.md +438 -0
- package/.agent/skills/nodejs-pro/rules/error-handling.md +257 -0
- package/.agent/skills/nodejs-pro/rules/framework-selection.md +220 -0
- package/.agent/skills/nodejs-pro/rules/runtime-modules.md +176 -0
- package/.agent/skills/nodejs-pro/rules/testing-strategy.md +266 -0
- package/.agent/skills/nodejs-pro/rules/validation-security.md +205 -0
- package/.agent/skills/observability/AGENTS.md +607 -0
- package/.agent/skills/observability/SKILL.md +178 -0
- package/.agent/skills/observability/rules/_sections.md +15 -0
- package/.agent/skills/observability/rules/_template.md +32 -0
- package/.agent/skills/observability/rules/engineering-spec.md +440 -0
- package/.agent/skills/offensive-sec/AGENTS.md +849 -0
- package/.agent/skills/offensive-sec/SKILL.md +191 -0
- package/.agent/skills/offensive-sec/rules/_sections.md +15 -0
- package/.agent/skills/offensive-sec/rules/_template.md +32 -0
- package/.agent/skills/offensive-sec/rules/engineering-spec.md +470 -0
- package/.agent/skills/perf-optimizer/AGENTS.md +870 -0
- package/.agent/skills/perf-optimizer/SKILL.md +189 -0
- package/.agent/skills/perf-optimizer/rules/_sections.md +15 -0
- package/.agent/skills/perf-optimizer/rules/_template.md +32 -0
- package/.agent/skills/perf-optimizer/rules/backend-patterns.md +312 -0
- package/.agent/skills/perf-optimizer/rules/engineering-spec.md +428 -0
- package/.agent/skills/perf-optimizer/scripts/lighthouse_audit.ts +201 -0
- package/.agent/skills/problem-checker/AGENTS.md +519 -0
- package/.agent/skills/problem-checker/SKILL.md +189 -0
- package/.agent/skills/problem-checker/rules/_sections.md +15 -0
- package/.agent/skills/problem-checker/rules/_template.md +32 -0
- package/.agent/skills/problem-checker/rules/engineering-spec.md +483 -0
- package/.agent/skills/problem-checker/scripts/check_problems.ts +396 -0
- package/.agent/skills/project-planner/AGENTS.md +2698 -0
- package/.agent/skills/project-planner/SKILL.md +166 -0
- package/.agent/skills/project-planner/rules/_sections.md +15 -0
- package/.agent/skills/project-planner/rules/_template.md +32 -0
- package/.agent/skills/project-planner/rules/engineering-spec.md +420 -0
- package/.agent/skills/python-pro/AGENTS.md +1871 -0
- package/.agent/skills/python-pro/SKILL.md +182 -0
- package/.agent/skills/python-pro/rules/_sections.md +50 -0
- package/.agent/skills/python-pro/rules/_template.md +32 -0
- package/.agent/skills/python-pro/rules/async-patterns.md +168 -0
- package/.agent/skills/python-pro/rules/django-patterns.md +194 -0
- package/.agent/skills/python-pro/rules/engineering-spec.md +442 -0
- package/.agent/skills/python-pro/rules/fastapi-patterns.md +179 -0
- package/.agent/skills/python-pro/rules/framework-selection.md +167 -0
- package/.agent/skills/python-pro/rules/project-structure.md +181 -0
- package/.agent/skills/python-pro/rules/testing-patterns.md +212 -0
- package/.agent/skills/python-pro/rules/type-hints.md +159 -0
- package/.agent/skills/react-pro/AGENTS.md +963 -0
- package/.agent/skills/react-pro/SKILL.md +232 -0
- package/.agent/skills/react-pro/rules/_sections.md +40 -0
- package/.agent/skills/react-pro/rules/_template.md +32 -0
- package/.agent/skills/react-pro/rules/component-patterns.md +145 -0
- package/.agent/skills/react-pro/rules/composition-compound.md +82 -0
- package/.agent/skills/react-pro/rules/data-fetching.md +133 -0
- package/.agent/skills/react-pro/rules/engineering-spec.md +453 -0
- package/.agent/skills/react-pro/rules/error-boundary.md +61 -0
- package/.agent/skills/react-pro/rules/file-organization.md +158 -0
- package/.agent/skills/react-pro/rules/hooks-custom.md +61 -0
- package/.agent/skills/react-pro/rules/mui-styling.md +138 -0
- package/.agent/skills/react-pro/rules/patterns.md +24 -0
- package/.agent/skills/react-pro/rules/performance-optimization.md +65 -0
- package/.agent/skills/react-pro/rules/performance.md +137 -0
- package/.agent/skills/react-pro/rules/react19-hooks.md +85 -0
- package/.agent/skills/react-pro/rules/state-management.md +90 -0
- package/.agent/skills/react-pro/rules/testing-patterns.md +52 -0
- package/.agent/skills/registry.json +1251 -0
- package/.agent/skills/security-scanner/AGENTS.md +851 -0
- package/.agent/skills/security-scanner/SKILL.md +182 -0
- package/.agent/skills/security-scanner/rules/_sections.md +15 -0
- package/.agent/skills/security-scanner/rules/_template.md +32 -0
- package/.agent/skills/security-scanner/rules/auth-patterns.md +281 -0
- package/.agent/skills/security-scanner/rules/checklists.md +186 -0
- package/.agent/skills/security-scanner/rules/engineering-spec.md +440 -0
- package/.agent/skills/security-scanner/scripts/security_scan.ts +513 -0
- package/.agent/skills/seo-optimizer/AGENTS.md +839 -0
- package/.agent/skills/seo-optimizer/SKILL.md +180 -0
- package/.agent/skills/seo-optimizer/rules/_sections.md +15 -0
- package/.agent/skills/seo-optimizer/rules/_template.md +32 -0
- package/.agent/skills/seo-optimizer/rules/engineering-spec.md +433 -0
- package/.agent/skills/seo-optimizer/scripts/geo_checker.ts +109 -0
- package/.agent/skills/seo-optimizer/scripts/seo_checker.ts +308 -0
- package/.agent/skills/server-ops/AGENTS.md +643 -0
- package/.agent/skills/server-ops/SKILL.md +194 -0
- package/.agent/skills/server-ops/rules/_sections.md +15 -0
- package/.agent/skills/server-ops/rules/_template.md +32 -0
- package/.agent/skills/server-ops/rules/engineering-spec.md +450 -0
- package/.agent/skills/shell-script/AGENTS.md +499 -0
- package/.agent/skills/shell-script/SKILL.md +205 -0
- package/.agent/skills/shell-script/rules/_sections.md +15 -0
- package/.agent/skills/shell-script/rules/_template.md +32 -0
- package/.agent/skills/shell-script/rules/engineering-spec.md +463 -0
- package/.agent/skills/skill-generator/SKILL.md +147 -0
- package/.agent/skills/smart-router/SKILL.md +95 -0
- package/.agent/skills/studio/AGENTS.md +636 -0
- package/.agent/skills/studio/SKILL.md +178 -0
- package/.agent/skills/studio/data/charts.csv +26 -0
- package/.agent/skills/studio/data/colors.csv +97 -0
- package/.agent/skills/studio/data/icons.csv +101 -0
- package/.agent/skills/studio/data/landing.csv +31 -0
- package/.agent/skills/studio/data/products.csv +97 -0
- package/.agent/skills/studio/data/prompts.csv +24 -0
- package/.agent/skills/studio/data/react-performance.csv +45 -0
- package/.agent/skills/studio/data/stacks/flutter.csv +52 -0
- package/.agent/skills/studio/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/studio/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/skills/studio/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/studio/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/skills/studio/data/stacks/nuxtjs.csv +59 -0
- package/.agent/skills/studio/data/stacks/react-native.csv +52 -0
- package/.agent/skills/studio/data/stacks/react.csv +54 -0
- package/.agent/skills/studio/data/stacks/shadcn.csv +61 -0
- package/.agent/skills/studio/data/stacks/svelte.csv +54 -0
- package/.agent/skills/studio/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/studio/data/stacks/vue.csv +50 -0
- package/.agent/skills/studio/data/styles.csv +59 -0
- package/.agent/skills/studio/data/typography.csv +58 -0
- package/.agent/skills/studio/data/ui-reasoning.csv +101 -0
- package/.agent/skills/studio/data/ux-guidelines.csv +100 -0
- package/.agent/skills/studio/data/web-interface.csv +31 -0
- package/.agent/skills/studio/rules/_sections.md +15 -0
- package/.agent/skills/studio/rules/_template.md +32 -0
- package/.agent/skills/studio/rules/engineering-spec.md +455 -0
- package/.agent/skills/studio/scripts/core.ts +345 -0
- package/.agent/skills/studio/scripts/design_system.ts +953 -0
- package/.agent/skills/studio/scripts/search.ts +197 -0
- package/.agent/skills/studio/scripts/types.ts +147 -0
- package/.agent/skills/studio/scripts/utils/component-specs.ts +154 -0
- package/.agent/skills/studio/scripts/utils/config-loader.ts +165 -0
- package/.agent/skills/studio/scripts/utils/css-templates.ts +169 -0
- package/.agent/skills/studio/scripts/utils/css-validator.ts +95 -0
- package/.agent/skills/studio/scripts/utils/csv-loader.ts +52 -0
- package/.agent/skills/studio/scripts/utils/intelligent-overrides.ts +129 -0
- package/.agent/skills/studio/scripts/utils/page-override-formatter.ts +143 -0
- package/.agent/skills/studio/scripts/utils/page-type-detector.ts +124 -0
- package/.agent/skills/studio/scripts/utils/search-cache.ts +165 -0
- package/.agent/skills/studio/scripts/utils/text-utils.ts +44 -0
- package/.agent/skills/system-design/AGENTS.md +597 -0
- package/.agent/skills/system-design/SKILL.md +153 -0
- package/.agent/skills/system-design/rules/_sections.md +15 -0
- package/.agent/skills/system-design/rules/_template.md +32 -0
- package/.agent/skills/system-design/rules/context-discovery.md +117 -0
- package/.agent/skills/system-design/rules/engineering-spec.md +437 -0
- package/.agent/skills/system-design/rules/examples.md +180 -0
- package/.agent/skills/system-design/rules/pattern-selection.md +130 -0
- package/.agent/skills/system-design/rules/patterns-reference.md +110 -0
- package/.agent/skills/system-design/rules/trade-off-analysis.md +169 -0
- package/.agent/skills/tailwind-kit/AGENTS.md +1135 -0
- package/.agent/skills/tailwind-kit/SKILL.md +171 -0
- package/.agent/skills/tailwind-kit/rules/_sections.md +20 -0
- package/.agent/skills/tailwind-kit/rules/_template.md +32 -0
- package/.agent/skills/tailwind-kit/rules/components.md +232 -0
- package/.agent/skills/tailwind-kit/rules/engineering-spec.md +435 -0
- package/.agent/skills/tailwind-kit/rules/responsive.md +221 -0
- package/.agent/skills/tailwind-kit/rules/v4-config.md +72 -0
- package/.agent/skills/test-architect/AGENTS.md +851 -0
- package/.agent/skills/test-architect/SKILL.md +176 -0
- package/.agent/skills/test-architect/rules/_sections.md +15 -0
- package/.agent/skills/test-architect/rules/_template.md +32 -0
- package/.agent/skills/test-architect/rules/engineering-spec.md +434 -0
- package/.agent/skills/test-architect/scripts/test_runner.ts +265 -0
- package/.agent/skills/typescript-expert/AGENTS.md +1045 -0
- package/.agent/skills/typescript-expert/SKILL.md +200 -0
- package/.agent/skills/typescript-expert/rules/_sections.md +20 -0
- package/.agent/skills/typescript-expert/rules/_template.md +32 -0
- package/.agent/skills/typescript-expert/rules/engineering-spec.md +433 -0
- package/.agent/skills/typescript-expert/rules/tsconfig-strict.json +92 -0
- package/.agent/skills/typescript-expert/rules/typescript-cheatsheet.md +407 -0
- package/.agent/skills/typescript-expert/rules/utility-types.ts +264 -0
- package/.agent/skills/typescript-expert/scripts/ts_diagnostic.ts +321 -0
- package/.agent/skills/vercel-deploy/AGENTS.md +490 -0
- package/.agent/skills/vercel-deploy/SKILL.md +175 -0
- package/.agent/skills/vercel-deploy/rules/_sections.md +15 -0
- package/.agent/skills/vercel-deploy/rules/_template.md +32 -0
- package/.agent/skills/vercel-deploy/rules/engineering-spec.md +463 -0
- package/.agent/skills/vercel-deploy/scripts/deploy.sh +310 -0
- package/.agent/workflows/api.md +377 -0
- package/.agent/workflows/autopilot.md +344 -0
- package/.agent/workflows/build.md +338 -0
- package/.agent/workflows/chronicle.md +279 -0
- package/.agent/workflows/cook.md +217 -0
- package/.agent/workflows/diagnose.md +302 -0
- package/.agent/workflows/fix.md +253 -0
- package/.agent/workflows/game.md +329 -0
- package/.agent/workflows/inspect.md +276 -0
- package/.agent/workflows/knowledge.md +212 -0
- package/.agent/workflows/launch.md +345 -0
- package/.agent/workflows/mobile.md +354 -0
- package/.agent/workflows/monitor.md +239 -0
- package/.agent/workflows/optimize.md +269 -0
- package/.agent/workflows/plan.md +278 -0
- package/.agent/workflows/stage.md +286 -0
- package/.agent/workflows/studio.md +276 -0
- package/.agent/workflows/think.md +262 -0
- package/.agent/workflows/validate.md +289 -0
- package/.agentignore +161 -0
- package/.gitattributes +16 -0
- package/CHANGELOG.md +198 -0
- package/LICENSE +40 -0
- package/README.md +173 -0
- package/docs/SKILL_DESIGN_GUIDE.md +561 -0
- package/docs/The-Complete-Guide-to-Building-Skills-for-Claude.md +1207 -0
- package/docs/WORKFLOW_DESIGN_GUIDE.md +325 -0
- package/package.json +33 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,1830 @@
|
|
|
1
|
+
# auth-patterns
|
|
2
|
+
|
|
3
|
+
**Version 1.0.0**
|
|
4
|
+
Engineering
|
|
5
|
+
March 2026
|
|
6
|
+
|
|
7
|
+
> **Note:**
|
|
8
|
+
> This document is for agents and LLMs to follow when working on auth-patterns domain.
|
|
9
|
+
> Optimized for automation and consistency by AI-assisted workflows.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Auth Patterns
|
|
14
|
+
|
|
15
|
+
> Authentication & authorization decisions for production applications. Fail closed. Defense in depth.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
**Required:** None — Auth Patterns is a knowledge-based skill with no external dependencies.
|
|
22
|
+
|
|
23
|
+
**Optional:**
|
|
24
|
+
- `security-scanner` skill (for implementation validation)
|
|
25
|
+
- `offensive-sec` skill (for attack vector analysis)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## When to Use
|
|
30
|
+
|
|
31
|
+
| Situation | Reference |
|
|
32
|
+
|-----------|-----------|
|
|
33
|
+
| Choosing auth strategy | Decision tree below |
|
|
34
|
+
| OAuth2 / SSO / OIDC | `rules/oauth2.md` |
|
|
35
|
+
| JWT signing, rotation, refresh | `rules/jwt-deep.md` |
|
|
36
|
+
| Permission system (RBAC/ABAC) | `rules/rbac-abac.md` |
|
|
37
|
+
| Multi-factor authentication | `rules/mfa.md` |
|
|
38
|
+
| Session management | `rules/session.md` |
|
|
39
|
+
| Passwordless / Passkeys | `rules/passkey.md` |
|
|
40
|
+
| Architecture review, contracts | `rules/engineering-spec.md` |
|
|
41
|
+
|
|
42
|
+
**Selective Reading Rule:** Read ONLY the file matching the current request.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## System Boundaries
|
|
47
|
+
|
|
48
|
+
| Owned by This Skill | NOT Owned |
|
|
49
|
+
|---------------------|-----------|
|
|
50
|
+
| Auth strategy selection (JWT/Session/OAuth/Passkey) | Auth library implementation |
|
|
51
|
+
| Token lifecycle design (TTL, rotation, revocation) | Secret/key generation |
|
|
52
|
+
| Permission model architecture (RBAC/ABAC) | Users/roles DB schema (→ data-modeler) |
|
|
53
|
+
| MFA strategy selection (TOTP/WebAuthn) | MFA provider integration |
|
|
54
|
+
| Session config (cookie, store, invalidation) | Session store provisioning (→ server-ops) |
|
|
55
|
+
|
|
56
|
+
**Pure decision skill:** Produces security guidance. Zero network calls, zero credential handling, zero side effects.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Core Principles
|
|
61
|
+
|
|
62
|
+
| Principle | Enforcement |
|
|
63
|
+
|-----------|-------------|
|
|
64
|
+
| **Fail Closed** | Auth error or ambiguity → deny access. Never implicit allow. |
|
|
65
|
+
| **Defense in Depth** | Every recommendation includes ≥ 3 controls: auth + authz + rate limit + monitoring |
|
|
66
|
+
| **Least Privilege** | Grant minimum permissions; default to no-access |
|
|
67
|
+
| **Token Hygiene** | Access token ≤ 15 min. Refresh token rotated on use. httpOnly storage. |
|
|
68
|
+
| **Zero Trust** | Verify every request. No implicit trust for internal services. |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Auth Strategy Decision Tree
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
What type of application?
|
|
76
|
+
├── SPA / Mobile App
|
|
77
|
+
│ ├── First-party only → JWT (≤15min access) + Refresh Token (httpOnly cookie)
|
|
78
|
+
│ └── Third-party login → OAuth 2.0 + PKCE (mandatory for public clients)
|
|
79
|
+
├── Traditional Web (SSR)
|
|
80
|
+
│ └── Session-based (httpOnly secure cookies, SameSite=Strict)
|
|
81
|
+
├── API / Microservices
|
|
82
|
+
│ ├── Service-to-service → mTLS or API Keys + HMAC
|
|
83
|
+
│ └── User-facing → JWT with gateway validation
|
|
84
|
+
├── Enterprise / B2B
|
|
85
|
+
│ └── SAML 2.0 or OIDC (SSO)
|
|
86
|
+
└── Modern Passwordless
|
|
87
|
+
└── Passkeys (WebAuthn/FIDO2)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Error Taxonomy
|
|
93
|
+
|
|
94
|
+
| Code | Recoverable | Trigger |
|
|
95
|
+
|------|-------------|---------|
|
|
96
|
+
| `ERR_INVALID_REQUEST_TYPE` | No | Request type not one of the 8 supported types |
|
|
97
|
+
| `ERR_MISSING_CONTEXT` | Yes | Required context field is null or empty |
|
|
98
|
+
| `ERR_CONSTRAINT_CONFLICT` | Yes | Contradictory constraints |
|
|
99
|
+
| `ERR_INVALID_APP_TYPE` | No | App type not recognized |
|
|
100
|
+
| `ERR_INVALID_SENSITIVITY` | No | Sensitivity not one of: low, medium, high, critical |
|
|
101
|
+
| `ERR_REFERENCE_NOT_FOUND` | No | Reference file missing |
|
|
102
|
+
| `ERR_UNSUPPORTED_COMPLIANCE` | Yes | Compliance standard combination not covered |
|
|
103
|
+
|
|
104
|
+
**Zero internal retries.** Deterministic output; same context = same recommendation.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Decision Checklist
|
|
109
|
+
|
|
110
|
+
- [ ] **Auth strategy chosen for THIS app type?** (JWT / Session / OAuth / Passkey)
|
|
111
|
+
- [ ] **Token storage decided?** (httpOnly secure cookie — NOT localStorage)
|
|
112
|
+
- [ ] **Access token TTL ≤ 15 minutes?**
|
|
113
|
+
- [ ] **Refresh token rotation configured?** (rotate on every use)
|
|
114
|
+
- [ ] **Permission model chosen?** (RBAC / ABAC / hybrid)
|
|
115
|
+
- [ ] **MFA required for sensitive operations?** (high/critical sensitivity)
|
|
116
|
+
- [ ] **Session invalidation on password change?**
|
|
117
|
+
- [ ] **Rate limiting on auth endpoints?**
|
|
118
|
+
- [ ] **PKCE enabled for all public clients?** (SPA, mobile)
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Anti-Patterns
|
|
123
|
+
|
|
124
|
+
| ❌ Don't | ✅ Do |
|
|
125
|
+
|---------|-------|
|
|
126
|
+
| Store JWT in localStorage | Use httpOnly secure cookies |
|
|
127
|
+
| Access tokens with 24h+ expiry | Access token ≤ 15 min + refresh token |
|
|
128
|
+
| Roll your own crypto | Use battle-tested libraries (jose, passport) |
|
|
129
|
+
| Same signing key for all services | Per-service signing keys |
|
|
130
|
+
| Skip PKCE for public clients | PKCE mandatory for SPA/mobile OAuth |
|
|
131
|
+
| Hardcode roles in application code | Store permissions in database |
|
|
132
|
+
| Implicit trust for internal services | Zero trust: verify every request |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📑 Content Map
|
|
137
|
+
|
|
138
|
+
| File | Description | When to Read |
|
|
139
|
+
|------|-------------|--------------|
|
|
140
|
+
| [oauth2.md](rules/oauth2.md) | OAuth 2.0 + OIDC flows, PKCE, scopes, providers | Third-party login, SSO |
|
|
141
|
+
| [jwt-deep.md](rules/jwt-deep.md) | JWT signing, rotation, claims, refresh patterns | Token-based auth |
|
|
142
|
+
| [rbac-abac.md](rules/rbac-abac.md) | Role-Based + Attribute-Based access control | Permission systems |
|
|
143
|
+
| [mfa.md](rules/mfa.md) | TOTP, WebAuthn, backup codes, recovery | Multi-factor auth |
|
|
144
|
+
| [session.md](rules/session.md) | Cookie sessions, Redis store, stateless vs stateful | Session design |
|
|
145
|
+
| [passkey.md](rules/passkey.md) | WebAuthn/FIDO2 implementation guide | Passwordless auth |
|
|
146
|
+
| [engineering-spec.md](rules/engineering-spec.md) | Full engineering spec: contracts, security model, scalability | Architecture review |
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 🔗 Related
|
|
151
|
+
|
|
152
|
+
| Item | Type | Purpose |
|
|
153
|
+
|------|------|---------|
|
|
154
|
+
| `api-architect` | Skill | API auth integration patterns |
|
|
155
|
+
| `security-scanner` | Skill | Auth vulnerability scanning |
|
|
156
|
+
| `data-modeler` | Skill | Users/roles schema design |
|
|
157
|
+
| `offensive-sec` | Skill | Auth attack vectors and pen testing |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Detailed Rules
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### Rule: engineering-spec
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
title: Auth Patterns — Engineering Specification
|
|
174
|
+
impact: MEDIUM
|
|
175
|
+
tags: auth-patterns
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
# Auth Patterns — Engineering Specification
|
|
179
|
+
|
|
180
|
+
> Production-grade specification for authentication and authorization pattern selection at FAANG scale.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 1. Overview
|
|
185
|
+
|
|
186
|
+
Auth Patterns provides structured decision frameworks for authentication and authorization in production applications. The skill covers OAuth2/OIDC, JWT lifecycle, RBAC/ABAC permission models, MFA, Passkeys (WebAuthn/FIDO2), and session management. It operates as a security-focused expert knowledge base that produces architectural decisions and implementation guidance, not runtime auth code.
|
|
187
|
+
|
|
188
|
+
The skill enforces a "fail closed" design philosophy: ambiguous or missing auth configuration must result in access denial, never access grant.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 2. Problem Statement
|
|
193
|
+
|
|
194
|
+
Authentication and authorization at scale present four quantified problems:
|
|
195
|
+
|
|
196
|
+
| Problem | Measurement | Impact |
|
|
197
|
+
|---------|-------------|--------|
|
|
198
|
+
| Wrong auth strategy selection | JWT in localStorage in 45%+ of SPAs | XSS-exploitable token theft |
|
|
199
|
+
| Long-lived access tokens | Access tokens with 24h+ expiry in 30% of APIs | Extended attack window on token compromise |
|
|
200
|
+
| Flat permission models | Binary admin/user roles in 60% of applications | Over-privileged users, compliance violations |
|
|
201
|
+
| Missing MFA | < 20% of B2B apps enforce MFA for sensitive operations | Account takeover vulnerability |
|
|
202
|
+
|
|
203
|
+
Auth Patterns eliminates these by providing context-aware decision trees that produce security-vetted auth architectures.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 3. Design Goals
|
|
208
|
+
|
|
209
|
+
| ID | Goal | Measurable Constraint |
|
|
210
|
+
|----|------|-----------------------|
|
|
211
|
+
| G1 | Context-aware auth selection | Decision tree produces one of JWT/Session/OAuth/Passkey based on ≤ 4 input criteria |
|
|
212
|
+
| G2 | Fail-closed defaults | Every pattern defaults to deny-access on ambiguity; no implicit allow |
|
|
213
|
+
| G3 | Token hygiene enforcement | All JWT patterns specify ≤ 15-minute access token lifetime |
|
|
214
|
+
| G4 | Defense in depth | Every auth recommendation includes ≥ 3 complementary controls (auth + authz + rate limit + monitoring) |
|
|
215
|
+
| G5 | Decision traceability | Every recommendation includes security rationale and threat model reference |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 4. Non-Goals
|
|
220
|
+
|
|
221
|
+
| ID | Excluded | Rationale |
|
|
222
|
+
|----|----------|-----------|
|
|
223
|
+
| NG1 | Auth library implementation | This skill produces design decisions; code is the implementing agent's responsibility |
|
|
224
|
+
| NG2 | Credential storage | No secrets, keys, or tokens are stored by this skill |
|
|
225
|
+
| NG3 | Runtime token validation | Validation logic is part of application code, not design guidance |
|
|
226
|
+
| NG4 | User database schema | Owned by `data-modeler` skill |
|
|
227
|
+
| NG5 | API endpoint design | Owned by `api-architect` skill |
|
|
228
|
+
| NG6 | Penetration testing | Owned by `security-scanner` and `offensive-sec` skills |
|
|
229
|
+
| NG7 | Compliance certification (SOC2, HIPAA) | This skill aligns with security principles but does not produce compliance artifacts |
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 5. System Boundaries
|
|
234
|
+
|
|
235
|
+
| Boundary | Owned | Not Owned |
|
|
236
|
+
|----------|-------|-----------|
|
|
237
|
+
| Auth strategy selection | JWT/Session/OAuth/Passkey decision tree | Auth library selection |
|
|
238
|
+
| Token lifecycle design | Expiry, rotation, revocation patterns | Token signing key generation |
|
|
239
|
+
| Permission model design | RBAC/ABAC/hybrid architecture | Permission database schema (→ data-modeler) |
|
|
240
|
+
| MFA strategy | TOTP/WebAuthn/backup code patterns | MFA provider integration |
|
|
241
|
+
| Session management | Cookie config, store selection, invalidation | Session store provisioning (→ server-ops) |
|
|
242
|
+
| Passkey architecture | WebAuthn/FIDO2 flow design | Browser API implementation |
|
|
243
|
+
|
|
244
|
+
**Side-effect boundary:** Auth Patterns produces design documents and security guidance. It does not generate secrets, create keys, modify configurations, or make network requests.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 6. Integration Model
|
|
249
|
+
|
|
250
|
+
### 6.1 Agent Contract
|
|
251
|
+
|
|
252
|
+
#### Input Schema
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
Request_Type: string # One of: "strategy-selection" | "jwt-design" | "oauth-flow" |
|
|
256
|
+
# "permission-model" | "mfa-strategy" | "session-design" |
|
|
257
|
+
# "passkey-architecture" | "security-review"
|
|
258
|
+
Context: {
|
|
259
|
+
app_type: string # "spa" | "ssr" | "mobile" | "api" | "microservice" | "b2b-enterprise"
|
|
260
|
+
auth_consumers: Array<string> # ["first-party", "third-party", "service-to-service"]
|
|
261
|
+
sensitivity: string # "low" | "medium" | "high" | "critical"
|
|
262
|
+
compliance: Array<string> | null # ["soc2", "hipaa", "gdpr", "pci-dss"]
|
|
263
|
+
existing_auth: string | null # Current auth system if migrating
|
|
264
|
+
constraints: Array<string> | null # ["no-cookies", "must-use-oauth", "stateless-only"]
|
|
265
|
+
}
|
|
266
|
+
contract_version: string # "2.0.0"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Output Schema
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
Status: "success" | "error"
|
|
273
|
+
Data: {
|
|
274
|
+
strategy: string # Selected auth pattern
|
|
275
|
+
rationale: string # Security-focused justification
|
|
276
|
+
threat_model: Array<string> # Threats this pattern mitigates
|
|
277
|
+
controls: {
|
|
278
|
+
primary: string # Main auth mechanism
|
|
279
|
+
secondary: string # Complementary control (e.g., MFA)
|
|
280
|
+
rate_limiting: string # Auth endpoint protection
|
|
281
|
+
monitoring: string # Anomaly detection recommendation
|
|
282
|
+
}
|
|
283
|
+
token_config: { # For JWT/token-based strategies
|
|
284
|
+
access_ttl: string # e.g., "15 minutes"
|
|
285
|
+
refresh_ttl: string # e.g., "7 days"
|
|
286
|
+
storage: string # "httpOnly-secure-cookie" | "secure-storage"
|
|
287
|
+
rotation: string # "on-use" | "on-expiry"
|
|
288
|
+
} | null
|
|
289
|
+
permission_model: { # For permission-related requests
|
|
290
|
+
type: string # "rbac" | "abac" | "hybrid"
|
|
291
|
+
granularity: string # "role" | "permission" | "attribute"
|
|
292
|
+
} | null
|
|
293
|
+
reference_file: string # Path to detailed reference document
|
|
294
|
+
checklist: Array<string> # Security action items
|
|
295
|
+
anti_patterns: Array<string> # Context-specific security mistakes to avoid
|
|
296
|
+
metadata: {
|
|
297
|
+
version: string
|
|
298
|
+
context_hash: string
|
|
299
|
+
sensitivity_level: string
|
|
300
|
+
contract_version: string # "2.0.0"
|
|
301
|
+
backward_compatibility: string # "breaking"
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
Error: ErrorSchema | null
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Contract Version:** 2.0.0
|
|
308
|
+
**Backward Compatibility:** breaking (first hardened version)
|
|
309
|
+
**Breaking Changes:** None — new spec for first hardening
|
|
310
|
+
|
|
311
|
+
#### Error Schema
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
Code: string # From Error Taxonomy (Section 11)
|
|
315
|
+
Message: string # Human-readable, single line
|
|
316
|
+
Request_Type: string
|
|
317
|
+
Recoverable: boolean
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Deterministic Guarantees
|
|
321
|
+
|
|
322
|
+
- Same `Request_Type` + `Context` = identical `strategy` + `rationale` output.
|
|
323
|
+
- Decision tree evaluation order: app_type → auth_consumers → sensitivity → compliance → constraints.
|
|
324
|
+
- Token configuration values are fixed per strategy (access TTL = 15 min for JWT, never variable).
|
|
325
|
+
- No randomization, no A/B selection, no heuristic weighting.
|
|
326
|
+
|
|
327
|
+
#### What Agents May Assume
|
|
328
|
+
|
|
329
|
+
- Output `strategy` follows current industry security standards (OWASP, NIST).
|
|
330
|
+
- `token_config` values enforce secure defaults (short-lived access, httpOnly storage).
|
|
331
|
+
- `anti_patterns` are specific to the chosen strategy and project context.
|
|
332
|
+
- The skill is stateless; no prior invocation affects current output.
|
|
333
|
+
|
|
334
|
+
#### What Agents Must NOT Assume
|
|
335
|
+
|
|
336
|
+
- The recommendation constitutes a security audit (it provides patterns, not certification).
|
|
337
|
+
- Token configuration is universally correct (sensitivity and compliance context may require adjustments).
|
|
338
|
+
- Implementation details are included (this skill produces architecture, not code).
|
|
339
|
+
- The skill verifies that the recommendation was correctly implemented.
|
|
340
|
+
|
|
341
|
+
#### Side-Effect Boundaries
|
|
342
|
+
|
|
343
|
+
| Operation | Side Effects |
|
|
344
|
+
|-----------|-------------|
|
|
345
|
+
| Strategy selection | None; pure decision output |
|
|
346
|
+
| Token config generation | None; fixed value lookup |
|
|
347
|
+
| Permission model design | None; architecture output |
|
|
348
|
+
| Security review | None; checklist output |
|
|
349
|
+
| Reference file lookup | Read-only access to `rules/` |
|
|
350
|
+
|
|
351
|
+
### 6.2 Workflow Contract
|
|
352
|
+
|
|
353
|
+
#### Invocation Pattern
|
|
354
|
+
|
|
355
|
+
```
|
|
356
|
+
1. Define app context (type, consumers, sensitivity, compliance)
|
|
357
|
+
2. Select request type (strategy-selection → token/session design → permission model → MFA)
|
|
358
|
+
3. Receive recommendation with rationale, threat model, and checklist
|
|
359
|
+
4. Review and implement (caller's responsibility)
|
|
360
|
+
5. Run security-scanner for implementation validation (separate skill)
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**Recommended ordering:** strategy-selection → jwt-design or session-design → permission-model → mfa-strategy → security-review.
|
|
364
|
+
|
|
365
|
+
#### Execution Guarantees
|
|
366
|
+
|
|
367
|
+
- Each invocation produces a complete, self-contained recommendation.
|
|
368
|
+
- No background processes, no deferred execution.
|
|
369
|
+
- Output includes all necessary context for implementation without re-invoking.
|
|
370
|
+
|
|
371
|
+
#### Failure Propagation Model
|
|
372
|
+
|
|
373
|
+
| Failure Severity | Propagation | Workflow Action |
|
|
374
|
+
|-----------------|-------------|-----------------|
|
|
375
|
+
| Invalid request type | Return error to caller | Use supported request type |
|
|
376
|
+
| Missing context field | Return error to caller | Supply missing context |
|
|
377
|
+
| Conflicting constraints | Return error to caller | Resolve constraint conflict |
|
|
378
|
+
| Reference file missing | Return error to caller | Verify skill installation |
|
|
379
|
+
|
|
380
|
+
Failures are isolated to the current invocation. No state carries between invocations.
|
|
381
|
+
|
|
382
|
+
#### Retry Boundaries
|
|
383
|
+
|
|
384
|
+
- Zero internal retries. Deterministic output makes retrying identical inputs meaningless.
|
|
385
|
+
- Callers should modify `Context` between invocations to explore alternative strategies.
|
|
386
|
+
|
|
387
|
+
#### Isolation Model
|
|
388
|
+
|
|
389
|
+
- Each invocation is stateless and independent.
|
|
390
|
+
- No shared state between invocations, sessions, or agents.
|
|
391
|
+
- Reference files in `rules/` are read-only resources.
|
|
392
|
+
|
|
393
|
+
#### Idempotency Expectations
|
|
394
|
+
|
|
395
|
+
| Operation | Idempotent | Notes |
|
|
396
|
+
|-----------|-----------|-------|
|
|
397
|
+
| Strategy selection | Yes | Same context = same strategy |
|
|
398
|
+
| Token config | Yes | Fixed values per strategy |
|
|
399
|
+
| Permission model design | Yes | Deterministic per context |
|
|
400
|
+
| Reference lookup | Yes | Read-only, no mutation |
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## 7. Execution Model
|
|
405
|
+
|
|
406
|
+
### 4-Phase Lifecycle
|
|
407
|
+
|
|
408
|
+
| Phase | Action | Output |
|
|
409
|
+
|-------|--------|--------|
|
|
410
|
+
| **Classify** | Validate request type and security context | Validated input or error |
|
|
411
|
+
| **Evaluate** | Traverse auth decision tree | Selected strategy with threat model |
|
|
412
|
+
| **Harden** | Apply defense-in-depth controls, token config, anti-patterns | Complete security recommendation |
|
|
413
|
+
| **Emit** | Return structured output with metadata | Complete output schema |
|
|
414
|
+
|
|
415
|
+
All phases execute synchronously in a single invocation. No async pipeline.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## 8. Deterministic Design Principles
|
|
420
|
+
|
|
421
|
+
| Principle | Enforcement |
|
|
422
|
+
|-----------|-------------|
|
|
423
|
+
| Fixed decision tree ordering | app_type → auth_consumers → sensitivity → compliance → constraints |
|
|
424
|
+
| Fail-closed defaults | Ambiguous context → most restrictive recommendation |
|
|
425
|
+
| No external calls | Decisions use only local reference files and input context |
|
|
426
|
+
| No ambient state | Each invocation operates solely on explicit inputs |
|
|
427
|
+
| Fixed token values | Access TTL, refresh TTL, storage method are constants per strategy |
|
|
428
|
+
| No randomization | Decision trees are deterministic if-then-else chains |
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## 9. State & Idempotency Model
|
|
433
|
+
|
|
434
|
+
### State Machine
|
|
435
|
+
|
|
436
|
+
```
|
|
437
|
+
States: IDLE (single state — skill is stateless)
|
|
438
|
+
Transitions: None — each invocation is independent
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Auth Patterns maintains zero persistent state. Every invocation starts from a clean state. Invoking N times with identical inputs produces N identical outputs.
|
|
442
|
+
|
|
443
|
+
### Reference Versioning
|
|
444
|
+
|
|
445
|
+
- Reference files are versioned via `metadata.version` in SKILL.md frontmatter.
|
|
446
|
+
- Security recommendation changes require a version bump.
|
|
447
|
+
- Callers can reference specific versions for audit trail purposes.
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## 10. Failure Handling Strategy
|
|
452
|
+
|
|
453
|
+
| Failure Class | Behavior | Caller Recovery |
|
|
454
|
+
|---------------|----------|-----------------|
|
|
455
|
+
| Unknown request type | Return `ERR_INVALID_REQUEST_TYPE` | Use supported request type |
|
|
456
|
+
| Missing context field | Return `ERR_MISSING_CONTEXT` with field name | Supply missing field |
|
|
457
|
+
| Conflicting constraints | Return `ERR_CONSTRAINT_CONFLICT` | Resolve conflict |
|
|
458
|
+
| Invalid app type | Return `ERR_INVALID_APP_TYPE` | Use supported app type |
|
|
459
|
+
| Invalid sensitivity level | Return `ERR_INVALID_SENSITIVITY` | Use: low, medium, high, critical |
|
|
460
|
+
| Reference file missing | Return `ERR_REFERENCE_NOT_FOUND` | Verify skill installation |
|
|
461
|
+
| Unsupported compliance combo | Return `ERR_UNSUPPORTED_COMPLIANCE` | Check supported compliance standards |
|
|
462
|
+
|
|
463
|
+
**Invariant:** Every failure returns a structured error. No invocation fails silently. On ambiguous input, the most restrictive recommendation is produced (fail-closed).
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## 11. Error Taxonomy
|
|
468
|
+
|
|
469
|
+
| Code | Category | Recoverable | Description |
|
|
470
|
+
|------|----------|-------------|-------------|
|
|
471
|
+
| `ERR_INVALID_REQUEST_TYPE` | Validation | No | Request type not one of the 8 supported types |
|
|
472
|
+
| `ERR_MISSING_CONTEXT` | Validation | Yes | Required context field is null or empty |
|
|
473
|
+
| `ERR_CONSTRAINT_CONFLICT` | Validation | Yes | Constraints contradict each other |
|
|
474
|
+
| `ERR_INVALID_APP_TYPE` | Validation | No | App type not recognized |
|
|
475
|
+
| `ERR_INVALID_SENSITIVITY` | Validation | No | Sensitivity not one of: low, medium, high, critical |
|
|
476
|
+
| `ERR_REFERENCE_NOT_FOUND` | Infrastructure | No | Reference file missing from rules/ directory |
|
|
477
|
+
| `ERR_UNSUPPORTED_COMPLIANCE` | Validation | Yes | Compliance standard combination not covered |
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## 12. Timeout & Retry Policy
|
|
482
|
+
|
|
483
|
+
| Parameter | Value | Rationale |
|
|
484
|
+
|-----------|-------|-----------|
|
|
485
|
+
| Decision generation timeout | N/A | Synchronous decision tree traversal; completes in < 50ms |
|
|
486
|
+
| Internal retries | Zero | Deterministic output makes retries meaningless |
|
|
487
|
+
| Reference file read timeout | 1,000 ms | Local filesystem; fail immediately if inaccessible |
|
|
488
|
+
|
|
489
|
+
**Retry policy:** Zero internal retries. Callers should modify context inputs to explore alternative auth strategies.
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## 13. Observability & Logging Schema
|
|
494
|
+
|
|
495
|
+
### Log Entry Format
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{
|
|
499
|
+
"trace_id": "uuid",
|
|
500
|
+
"skill_name": "auth-patterns",
|
|
501
|
+
"contract_version": "2.0.0",
|
|
502
|
+
"execution_id": "uuid",
|
|
503
|
+
"timestamp": "ISO-8601",
|
|
504
|
+
"request_type": "string",
|
|
505
|
+
"strategy": "string",
|
|
506
|
+
"app_type": "string",
|
|
507
|
+
"sensitivity": "string",
|
|
508
|
+
"context_hash": "string",
|
|
509
|
+
"status": "success|error",
|
|
510
|
+
"error_code": "string|null",
|
|
511
|
+
"reference_files_read": ["string"],
|
|
512
|
+
"duration_ms": "number"
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Required Log Points
|
|
517
|
+
|
|
518
|
+
| Event | Log Level | Fields |
|
|
519
|
+
|-------|-----------|--------|
|
|
520
|
+
| Recommendation generated | INFO | All fields |
|
|
521
|
+
| Recommendation failed | ERROR | All fields + error_code |
|
|
522
|
+
| Reference file read | DEBUG | file path, read duration |
|
|
523
|
+
| Fail-closed fallback applied | WARN | original context, fallback strategy |
|
|
524
|
+
| High-sensitivity request | INFO | invocation_id, sensitivity, strategy |
|
|
525
|
+
|
|
526
|
+
### Metrics
|
|
527
|
+
|
|
528
|
+
| Metric | Type | Unit |
|
|
529
|
+
|--------|------|------|
|
|
530
|
+
| `auth.decision.duration` | Histogram | ms |
|
|
531
|
+
| `auth.decision.error_rate` | Counter | per error_code |
|
|
532
|
+
| `auth.request_type.usage` | Counter | per request_type |
|
|
533
|
+
| `auth.strategy.selected` | Counter | per strategy |
|
|
534
|
+
| `auth.sensitivity.distribution` | Counter | per sensitivity level |
|
|
535
|
+
| `auth.compliance.requested` | Counter | per compliance standard |
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## 14. Security & Trust Model
|
|
540
|
+
|
|
541
|
+
### Fail-Closed Design
|
|
542
|
+
|
|
543
|
+
- Every decision tree branch terminates in an explicit recommendation; no branch returns "no recommendation."
|
|
544
|
+
- Ambiguous or under-specified context triggers the most restrictive strategy for the given app type.
|
|
545
|
+
- The skill never returns guidance that weakens security below baseline (e.g., no long-lived tokens, no localStorage for JWTs).
|
|
546
|
+
|
|
547
|
+
### Credential Handling
|
|
548
|
+
|
|
549
|
+
- Auth Patterns does not store, process, or transmit any credentials, secrets, or tokens.
|
|
550
|
+
- Token configuration values are architectural parameters (TTLs, storage locations), not actual secrets.
|
|
551
|
+
- Secret management guidance references patterns; it does not generate or rotate secrets.
|
|
552
|
+
|
|
553
|
+
### Reference Integrity
|
|
554
|
+
|
|
555
|
+
- Reference files in `rules/` are read-only, security-reviewed resources.
|
|
556
|
+
- Changes to reference files require a version bump and security review.
|
|
557
|
+
- No runtime injection; references are static markdown files.
|
|
558
|
+
|
|
559
|
+
### Input Sanitization
|
|
560
|
+
|
|
561
|
+
- Context parameters are used for decision tree traversal, not code execution.
|
|
562
|
+
- No eval, no template injection, no dynamic code generation from inputs.
|
|
563
|
+
|
|
564
|
+
### Multi-Tenant Boundaries
|
|
565
|
+
|
|
566
|
+
- Each invocation is stateless; no data persists between invocations.
|
|
567
|
+
- No invocation can access context or outputs from another invocation.
|
|
568
|
+
- Sensitivity level does not cross invocation boundaries.
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## 15. Scalability Model
|
|
573
|
+
|
|
574
|
+
| Dimension | Constraint | Mitigation |
|
|
575
|
+
|-----------|-----------|------------|
|
|
576
|
+
| Throughput | CPU-bound decision tree traversal | Completes in < 50ms; scales linearly |
|
|
577
|
+
| Concurrency | Stateless invocations | Unlimited parallel invocations |
|
|
578
|
+
| Reference storage | 6 reference files (~12 KB total) | Static files; no growth concern |
|
|
579
|
+
| Memory per invocation | < 1 MB | No accumulation |
|
|
580
|
+
| Network | Zero network calls | No external dependency |
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
## 16. Concurrency Model
|
|
585
|
+
|
|
586
|
+
| Scope | Model | Behavior |
|
|
587
|
+
|-------|-------|----------|
|
|
588
|
+
| Within invocation | Sequential | Classify → Evaluate → Harden → Emit |
|
|
589
|
+
| Across invocations | Fully parallel | No shared state, no coordination |
|
|
590
|
+
| Reference access | Read-only shared | Multiple concurrent reads safe |
|
|
591
|
+
|
|
592
|
+
**No undefined behavior:** Stateless skill with read-only resource access; any concurrency level is safe.
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## 17. Resource Lifecycle Management
|
|
597
|
+
|
|
598
|
+
| Resource | Created By | Destroyed By | Max Lifetime |
|
|
599
|
+
|----------|-----------|-------------|--------------|
|
|
600
|
+
| Decision output | Emit phase | Caller (after consumption) | Invocation scope |
|
|
601
|
+
| Reference file handle | Evaluate phase | Auto-close after read | < 10 ms |
|
|
602
|
+
| Input context | Caller | Invocation completion | Invocation scope |
|
|
603
|
+
|
|
604
|
+
**Leak prevention:** All resources scoped to single invocation. No persistent handles, connections, or buffers.
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## 18. Performance Constraints
|
|
609
|
+
|
|
610
|
+
| Operation | P50 Target | P99 Target | Hard Limit |
|
|
611
|
+
|-----------|-----------|-----------|------------|
|
|
612
|
+
| Strategy selection | < 5 ms | < 20 ms | 50 ms |
|
|
613
|
+
| Full recommendation (with controls) | < 10 ms | < 30 ms | 100 ms |
|
|
614
|
+
| Reference file read | < 1 ms | < 5 ms | 1,000 ms |
|
|
615
|
+
| Output size | ≤ 800 chars | ≤ 2,000 chars | 5,000 chars |
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## 19. Operational Risks
|
|
620
|
+
|
|
621
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
622
|
+
|------|-----------|--------|------------|
|
|
623
|
+
| Outdated security recommendations | Medium | Vulnerable auth architecture | Version-bumped references; periodic review cycle aligned with OWASP updates |
|
|
624
|
+
| Over-application of restrictive defaults | Low | Friction for low-sensitivity apps | Sensitivity input controls restriction level; low = relaxed, critical = maximum |
|
|
625
|
+
| Missing compliance standard | Medium | Incomplete guidance for regulated industries | `ERR_UNSUPPORTED_COMPLIANCE` returned; manual review required |
|
|
626
|
+
| Context under-specification | High | Generic recommendation | Fail-closed: produces most restrictive recommendation for app type |
|
|
627
|
+
| Decision tree staleness for new auth methods | Low | Missing new auth approaches (e.g., device-bound sessions) | Version bump process; references updated on new standard adoption |
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## 20. Compliance with skill-design-guide.md
|
|
632
|
+
|
|
633
|
+
| Requirement | Status | Evidence |
|
|
634
|
+
|-------------|--------|----------|
|
|
635
|
+
| YAML frontmatter complete | ✅ | name, description, metadata with category, version, triggers, coordinates_with, success_metrics |
|
|
636
|
+
| SKILL.md < 200 lines | ✅ | Entry point under 200 lines; details in rules/ |
|
|
637
|
+
| Prerequisites documented | ✅ | No external dependencies required |
|
|
638
|
+
| When to Use section | ✅ | Auth domain decision matrix |
|
|
639
|
+
| Quick Reference | ✅ | Decision tree and checklist |
|
|
640
|
+
| Core content matches skill type | ✅ | Expert type: decision trees, security principles |
|
|
641
|
+
| Troubleshooting section | ✅ | Anti-patterns table |
|
|
642
|
+
| Related section | ✅ | Cross-links to api-architect, security-scanner, data-modeler, offensive-sec |
|
|
643
|
+
| Content Map for multi-file | ✅ | Links to 6 reference files + engineering-spec.md |
|
|
644
|
+
| Contract versioning | ✅ | contract_version, backward_compatibility, breaking_changes |
|
|
645
|
+
| Compliance matrix structured | ✅ | This table with ✅/❌ + evidence |
|
|
646
|
+
|
|
647
|
+
---
|
|
648
|
+
|
|
649
|
+
## 21. Production Readiness Checklist
|
|
650
|
+
|
|
651
|
+
| Category | Check | Status |
|
|
652
|
+
|----------|-------|--------|
|
|
653
|
+
| **Functionality** | 8 request types covering auth lifecycle | ✅ |
|
|
654
|
+
| **Functionality** | Decision tree for 6 app types | ✅ |
|
|
655
|
+
| **Functionality** | 6 reference files covering OAuth2, JWT, RBAC, MFA, Session, Passkey | ✅ |
|
|
656
|
+
| **Contracts** | Input/output/error schemas defined | ✅ |
|
|
657
|
+
| **Contracts** | Agent assumptions and non-assumptions documented | ✅ |
|
|
658
|
+
| **Contracts** | Workflow invocation pattern specified | ✅ |
|
|
659
|
+
| **Failure** | Error taxonomy with 7 categorized error codes | ✅ |
|
|
660
|
+
| **Failure** | No silent failures; fail-closed on ambiguity | ✅ |
|
|
661
|
+
| **Failure** | Retry policy: zero internal retries | ✅ |
|
|
662
|
+
| **Determinism** | Fixed decision tree ordering | ✅ |
|
|
663
|
+
| **Determinism** | Fixed token config values per strategy | ✅ |
|
|
664
|
+
| **Security** | Fail-closed design: ambiguity → most restrictive | ✅ |
|
|
665
|
+
| **Security** | No credential storage or processing | ✅ |
|
|
666
|
+
| **Security** | Anti-patterns: no localStorage JWTs, no long-lived tokens | ✅ |
|
|
667
|
+
| **Observability** | Structured log schema with 5 log points | ✅ |
|
|
668
|
+
| **Observability** | 6 metrics defined with types and units | ✅ |
|
|
669
|
+
| **Performance** | P50/P99 targets for all operations | ✅ |
|
|
670
|
+
| **Scalability** | Stateless; unlimited parallel invocations | ✅ |
|
|
671
|
+
| **Concurrency** | No shared state; read-only reference access | ✅ |
|
|
672
|
+
| **Resources** | All resources scoped to invocation lifetime | ✅ |
|
|
673
|
+
| **Idempotency** | Fully idempotent — all operations are pure functions | ✅ |
|
|
674
|
+
| **Compliance** | All skill-design-guide.md sections present | ✅ |
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
### Rule: jwt-deep
|
|
683
|
+
|
|
684
|
+
---
|
|
685
|
+
name: jwt-deep
|
|
686
|
+
description: JWT signing, rotation, claims, refresh token patterns, JWKS endpoint
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
# JWT Deep Dive
|
|
690
|
+
|
|
691
|
+
> Token design, signing, rotation, and refresh patterns.
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
## JWT Structure
|
|
696
|
+
|
|
697
|
+
```
|
|
698
|
+
Header.Payload.Signature
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
| Part | Contains | Example |
|
|
702
|
+
|------|----------|---------|
|
|
703
|
+
| Header | Algorithm, type | `{"alg": "RS256", "typ": "JWT"}` |
|
|
704
|
+
| Payload | Claims (data) | `{"sub": "user123", "exp": 1700000000}` |
|
|
705
|
+
| Signature | Verification | HMAC or RSA signature |
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
## Signing Algorithms
|
|
710
|
+
|
|
711
|
+
| Algorithm | Type | Best For |
|
|
712
|
+
|-----------|------|----------|
|
|
713
|
+
| `RS256` | Asymmetric (RSA) | Microservices (verify without secret) |
|
|
714
|
+
| `ES256` | Asymmetric (ECDSA) | Mobile, performance-sensitive |
|
|
715
|
+
| `HS256` | Symmetric (HMAC) | Monolith (single service) |
|
|
716
|
+
| `EdDSA` | Asymmetric (Ed25519) | Modern, fastest asymmetric |
|
|
717
|
+
|
|
718
|
+
> **Rule:** Use asymmetric for distributed systems. Symmetric only for single-service.
|
|
719
|
+
|
|
720
|
+
---
|
|
721
|
+
|
|
722
|
+
## Claims Best Practices
|
|
723
|
+
|
|
724
|
+
### Standard Claims (use these)
|
|
725
|
+
|
|
726
|
+
| Claim | Purpose | Required? |
|
|
727
|
+
|-------|---------|-----------|
|
|
728
|
+
| `sub` | Subject (user ID) | ✅ |
|
|
729
|
+
| `iss` | Issuer | ✅ |
|
|
730
|
+
| `aud` | Audience | ✅ |
|
|
731
|
+
| `exp` | Expiry (Unix timestamp) | ✅ |
|
|
732
|
+
| `iat` | Issued at | ✅ |
|
|
733
|
+
| `jti` | JWT ID (unique) | For revocation |
|
|
734
|
+
|
|
735
|
+
### Custom Claims
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
// ✅ Minimal claims
|
|
739
|
+
{
|
|
740
|
+
sub: "user_abc123",
|
|
741
|
+
role: "admin", // For quick authz checks
|
|
742
|
+
org: "org_xyz", // Multi-tenant
|
|
743
|
+
scope: "read write", // API permissions
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// ❌ Too much data
|
|
747
|
+
{
|
|
748
|
+
sub: "user_abc123",
|
|
749
|
+
email: "user@example.com", // PII in token
|
|
750
|
+
address: "...", // Never store PII
|
|
751
|
+
fullProfile: {...}, // Token too large
|
|
752
|
+
}
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
---
|
|
756
|
+
|
|
757
|
+
## Access + Refresh Token Pattern
|
|
758
|
+
|
|
759
|
+
```
|
|
760
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
761
|
+
│ Client │ │ Auth Server │ │ Resource │
|
|
762
|
+
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
|
|
763
|
+
│ Login │ │
|
|
764
|
+
│───────────────────>│ │
|
|
765
|
+
│ Access (15min) │ │
|
|
766
|
+
│ + Refresh (7d) │ │
|
|
767
|
+
│<───────────────────│ │
|
|
768
|
+
│ │ │
|
|
769
|
+
│ API call + Access Token │
|
|
770
|
+
│────────────────────────────────────────>│
|
|
771
|
+
│ Response │
|
|
772
|
+
│<────────────────────────────────────────│
|
|
773
|
+
│ │ │
|
|
774
|
+
│ (Access expired) │ │
|
|
775
|
+
│ Refresh request │ │
|
|
776
|
+
│───────────────────>│ │
|
|
777
|
+
│ New Access │ │
|
|
778
|
+
│ + New Refresh │ (rotation!) │
|
|
779
|
+
│<───────────────────│ │
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
### Implementation
|
|
783
|
+
|
|
784
|
+
```typescript
|
|
785
|
+
// Token generation
|
|
786
|
+
function generateTokenPair(userId: string) {
|
|
787
|
+
const accessToken = jwt.sign(
|
|
788
|
+
{ sub: userId, type: 'access' },
|
|
789
|
+
ACCESS_SECRET,
|
|
790
|
+
{ expiresIn: '15m', algorithm: 'RS256' }
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
const refreshToken = jwt.sign(
|
|
794
|
+
{ sub: userId, type: 'refresh', jti: crypto.randomUUID() },
|
|
795
|
+
REFRESH_SECRET,
|
|
796
|
+
{ expiresIn: '7d', algorithm: 'RS256' }
|
|
797
|
+
);
|
|
798
|
+
|
|
799
|
+
return { accessToken, refreshToken };
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Refresh endpoint
|
|
803
|
+
async function refreshTokens(oldRefreshToken: string) {
|
|
804
|
+
const payload = jwt.verify(oldRefreshToken, REFRESH_PUBLIC_KEY);
|
|
805
|
+
|
|
806
|
+
// Check if token was already used (rotation detection)
|
|
807
|
+
const isUsed = await redis.get(`used_refresh:${payload.jti}`);
|
|
808
|
+
if (isUsed) {
|
|
809
|
+
// Token reuse detected → compromise! Revoke all user sessions
|
|
810
|
+
await revokeAllSessions(payload.sub);
|
|
811
|
+
throw new SecurityError('Refresh token reuse detected');
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// Mark old token as used
|
|
815
|
+
await redis.setex(`used_refresh:${payload.jti}`, 7 * 86400, '1');
|
|
816
|
+
|
|
817
|
+
return generateTokenPair(payload.sub);
|
|
818
|
+
}
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
---
|
|
822
|
+
|
|
823
|
+
## Key Rotation
|
|
824
|
+
|
|
825
|
+
### Why Rotate
|
|
826
|
+
|
|
827
|
+
- Limit blast radius of key compromise
|
|
828
|
+
- Compliance requirements (SOC 2, PCI)
|
|
829
|
+
|
|
830
|
+
### JWKS Endpoint Pattern
|
|
831
|
+
|
|
832
|
+
```typescript
|
|
833
|
+
// /.well-known/jwks.json
|
|
834
|
+
{
|
|
835
|
+
"keys": [
|
|
836
|
+
{ "kid": "key-2025-01", "kty": "RSA", "use": "sig", ... }, // Current
|
|
837
|
+
{ "kid": "key-2024-07", "kty": "RSA", "use": "sig", ... } // Previous (grace period)
|
|
838
|
+
]
|
|
839
|
+
}
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
### Rotation Schedule
|
|
843
|
+
|
|
844
|
+
| Environment | Frequency | Grace Period |
|
|
845
|
+
|-------------|-----------|--------------|
|
|
846
|
+
| Production | Every 90 days | 30 days overlap |
|
|
847
|
+
| High security | Every 30 days | 14 days overlap |
|
|
848
|
+
|
|
849
|
+
---
|
|
850
|
+
|
|
851
|
+
## Anti-Patterns
|
|
852
|
+
|
|
853
|
+
| ❌ Don't | ✅ Do |
|
|
854
|
+
|---------|------|
|
|
855
|
+
| Store JWT in localStorage | httpOnly secure cookie |
|
|
856
|
+
| Long-lived access tokens | 15 min max + refresh |
|
|
857
|
+
| Put PII in claims | Minimal claims, lookup from DB |
|
|
858
|
+
| Same key for all environments | Per-env signing keys |
|
|
859
|
+
| Skip `exp` validation | Always check expiry |
|
|
860
|
+
| Trust JWT without signature check | Always verify signature |
|
|
861
|
+
|
|
862
|
+
---
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
|
|
868
|
+
## 🔗 Related
|
|
869
|
+
|
|
870
|
+
| File | When to Read |
|
|
871
|
+
|------|-------------|
|
|
872
|
+
| [oauth2.md](oauth2.md) | OAuth2 flows that issue JWTs |
|
|
873
|
+
| [session.md](session.md) | Stateful alternative to JWT |
|
|
874
|
+
| [rbac-abac.md](rbac-abac.md) | Permission claims in JWT |
|
|
875
|
+
| [SKILL.md](../SKILL.md) | Auth strategy decision tree |
|
|
876
|
+
|
|
877
|
+
---
|
|
878
|
+
|
|
879
|
+
### Rule: mfa
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
name: mfa
|
|
883
|
+
description: Multi-factor authentication — TOTP setup, backup codes, WebAuthn for MFA, recovery flows
|
|
884
|
+
---
|
|
885
|
+
|
|
886
|
+
# Multi-Factor Authentication (MFA)
|
|
887
|
+
|
|
888
|
+
> TOTP, WebAuthn, backup codes, and recovery flows.
|
|
889
|
+
> **See also:** `security-scanner/auth-patterns.md` for TOTP code pattern and account lockout.
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
## MFA Strategy Selection
|
|
894
|
+
|
|
895
|
+
| Method | Security | UX | Best For |
|
|
896
|
+
|--------|----------|-----|---------|
|
|
897
|
+
| TOTP (authenticator app) | ★★★★ | ★★★ | General purpose |
|
|
898
|
+
| WebAuthn / Passkey | ★★★★★ | ★★★★ | Modern apps |
|
|
899
|
+
| SMS OTP | ★★ | ★★★★ | Legacy, low-risk |
|
|
900
|
+
| Email OTP | ★★ | ★★★ | Fallback only |
|
|
901
|
+
| Hardware key (YubiKey) | ★★★★★ | ★★ | High security |
|
|
902
|
+
|
|
903
|
+
> ⚠️ **SMS OTP is vulnerable to SIM swapping.** Avoid for high-value targets.
|
|
904
|
+
|
|
905
|
+
---
|
|
906
|
+
|
|
907
|
+
## TOTP Implementation
|
|
908
|
+
|
|
909
|
+
> **Reference:** See `security-scanner/auth-patterns.md` for base TOTP code pattern.
|
|
910
|
+
|
|
911
|
+
### Enhanced Setup Flow
|
|
912
|
+
|
|
913
|
+
```typescript
|
|
914
|
+
import { authenticator } from 'otplib';
|
|
915
|
+
import qrcode from 'qrcode';
|
|
916
|
+
|
|
917
|
+
async function enableMFA(userId: string) {
|
|
918
|
+
// 1. Generate secret
|
|
919
|
+
const secret = authenticator.generateSecret();
|
|
920
|
+
|
|
921
|
+
// 2. Create otpauth URI
|
|
922
|
+
const otpauthUrl = authenticator.keyuri(
|
|
923
|
+
user.email,
|
|
924
|
+
'YourApp',
|
|
925
|
+
secret
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
// 3. Generate QR code
|
|
929
|
+
const qrDataUrl = await qrcode.toDataURL(otpauthUrl);
|
|
930
|
+
|
|
931
|
+
// 4. Store secret (encrypted) — NOT active yet
|
|
932
|
+
await db.user.update({
|
|
933
|
+
where: { id: userId },
|
|
934
|
+
data: { mfaSecret: encrypt(secret), mfaPending: true },
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
// 5. Generate backup codes
|
|
938
|
+
const backupCodes = generateBackupCodes(10);
|
|
939
|
+
await storeBackupCodes(userId, backupCodes);
|
|
940
|
+
|
|
941
|
+
return { qrDataUrl, backupCodes };
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// 6. Verify first code to activate
|
|
945
|
+
async function confirmMFA(userId: string, code: string) {
|
|
946
|
+
const secret = decrypt(user.mfaSecret);
|
|
947
|
+
const isValid = authenticator.verify({ token: code, secret });
|
|
948
|
+
|
|
949
|
+
if (!isValid) throw new InvalidCodeError();
|
|
950
|
+
|
|
951
|
+
await db.user.update({
|
|
952
|
+
where: { id: userId },
|
|
953
|
+
data: { mfaEnabled: true, mfaPending: false },
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
### Backup Codes
|
|
959
|
+
|
|
960
|
+
```typescript
|
|
961
|
+
function generateBackupCodes(count: number = 10): string[] {
|
|
962
|
+
return Array.from({ length: count }, () =>
|
|
963
|
+
crypto.randomBytes(4).toString('hex') // 8-char codes
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
async function storeBackupCodes(userId: string, codes: string[]) {
|
|
968
|
+
// Hash each code before storing
|
|
969
|
+
const hashed = codes.map(code => ({
|
|
970
|
+
userId,
|
|
971
|
+
codeHash: crypto.createHash('sha256').update(code).digest('hex'),
|
|
972
|
+
used: false,
|
|
973
|
+
}));
|
|
974
|
+
await db.backupCode.createMany({ data: hashed });
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
async function useBackupCode(userId: string, code: string): Promise<boolean> {
|
|
978
|
+
const hash = crypto.createHash('sha256').update(code).digest('hex');
|
|
979
|
+
const result = await db.backupCode.updateMany({
|
|
980
|
+
where: { userId, codeHash: hash, used: false },
|
|
981
|
+
data: { used: true, usedAt: new Date() },
|
|
982
|
+
});
|
|
983
|
+
return result.count > 0;
|
|
984
|
+
}
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
---
|
|
988
|
+
|
|
989
|
+
## WebAuthn / Passkey for MFA
|
|
990
|
+
|
|
991
|
+
```typescript
|
|
992
|
+
import { generateAuthenticationOptions, verifyAuthenticationResponse }
|
|
993
|
+
from '@simplewebauthn/server';
|
|
994
|
+
|
|
995
|
+
// Challenge generation (server)
|
|
996
|
+
const options = await generateAuthenticationOptions({
|
|
997
|
+
rpID: 'example.com',
|
|
998
|
+
allowCredentials: user.credentials.map(c => ({
|
|
999
|
+
id: c.credentialId,
|
|
1000
|
+
type: 'public-key',
|
|
1001
|
+
})),
|
|
1002
|
+
userVerification: 'required',
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
// Verify response (server)
|
|
1006
|
+
const verification = await verifyAuthenticationResponse({
|
|
1007
|
+
response: clientResponse,
|
|
1008
|
+
expectedChallenge: storedChallenge,
|
|
1009
|
+
expectedOrigin: 'https://example.com',
|
|
1010
|
+
expectedRPID: 'example.com',
|
|
1011
|
+
authenticator: storedCredential,
|
|
1012
|
+
});
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
---
|
|
1016
|
+
|
|
1017
|
+
## Recovery Flow
|
|
1018
|
+
|
|
1019
|
+
```
|
|
1020
|
+
User cannot access MFA device?
|
|
1021
|
+
├── Has backup codes → Enter backup code
|
|
1022
|
+
├── Has recovery email → Email verification + admin review
|
|
1023
|
+
├── Has trusted device → Device-based recovery
|
|
1024
|
+
└── None of above → Manual identity verification (support)
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
### Recovery Best Practices
|
|
1028
|
+
|
|
1029
|
+
| Practice | Why |
|
|
1030
|
+
|----------|-----|
|
|
1031
|
+
| Show backup codes ONCE at setup | Prevent later access |
|
|
1032
|
+
| Allow re-generating backup codes | When old ones run out |
|
|
1033
|
+
| Log all recovery events | Audit trail |
|
|
1034
|
+
| Rate limit recovery attempts | Prevent brute force |
|
|
1035
|
+
| Notify on MFA changes | Alert user to compromise |
|
|
1036
|
+
|
|
1037
|
+
---
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
---
|
|
1042
|
+
|
|
1043
|
+
## 🔗 Related
|
|
1044
|
+
|
|
1045
|
+
| File | When to Read |
|
|
1046
|
+
|------|-------------|
|
|
1047
|
+
| [passkey.md](passkey.md) | Passkeys as MFA or passwordless |
|
|
1048
|
+
| [jwt-deep.md](jwt-deep.md) | Token lifecycle after MFA |
|
|
1049
|
+
| [session.md](session.md) | Session management with MFA |
|
|
1050
|
+
| [SKILL.md](../SKILL.md) | Auth strategy decision tree |
|
|
1051
|
+
|
|
1052
|
+
---
|
|
1053
|
+
|
|
1054
|
+
### Rule: oauth2
|
|
1055
|
+
|
|
1056
|
+
---
|
|
1057
|
+
name: oauth2
|
|
1058
|
+
description: OAuth 2.0 + OpenID Connect flows, PKCE, scopes, provider integration
|
|
1059
|
+
---
|
|
1060
|
+
|
|
1061
|
+
# OAuth 2.0 & OpenID Connect
|
|
1062
|
+
|
|
1063
|
+
> Third-party login, SSO, and delegated authorization.
|
|
1064
|
+
|
|
1065
|
+
---
|
|
1066
|
+
|
|
1067
|
+
## OAuth 2.0 Flows
|
|
1068
|
+
|
|
1069
|
+
### Authorization Code + PKCE (Recommended for SPA/Mobile)
|
|
1070
|
+
|
|
1071
|
+
```
|
|
1072
|
+
1. Client generates code_verifier (random 43-128 chars)
|
|
1073
|
+
2. Client creates code_challenge = SHA256(code_verifier)
|
|
1074
|
+
3. Redirect to auth server with code_challenge
|
|
1075
|
+
4. User authenticates → redirect back with auth code
|
|
1076
|
+
5. Client exchanges code + code_verifier for tokens
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
```typescript
|
|
1080
|
+
import crypto from 'crypto';
|
|
1081
|
+
|
|
1082
|
+
// Generate PKCE pair
|
|
1083
|
+
const codeVerifier = crypto.randomBytes(32).toString('base64url');
|
|
1084
|
+
const codeChallenge = crypto
|
|
1085
|
+
.createHash('sha256')
|
|
1086
|
+
.update(codeVerifier)
|
|
1087
|
+
.digest('base64url');
|
|
1088
|
+
|
|
1089
|
+
// Authorization URL
|
|
1090
|
+
const authUrl = new URL('https://auth.example.com/authorize');
|
|
1091
|
+
authUrl.searchParams.set('response_type', 'code');
|
|
1092
|
+
authUrl.searchParams.set('client_id', CLIENT_ID);
|
|
1093
|
+
authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
|
|
1094
|
+
authUrl.searchParams.set('scope', 'openid profile email');
|
|
1095
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
1096
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
1097
|
+
authUrl.searchParams.set('state', crypto.randomBytes(16).toString('hex'));
|
|
1098
|
+
```
|
|
1099
|
+
|
|
1100
|
+
### Flow Selection Guide
|
|
1101
|
+
|
|
1102
|
+
| Flow | Best For | PKCE? |
|
|
1103
|
+
|------|----------|-------|
|
|
1104
|
+
| Authorization Code + PKCE | SPA, Mobile, Server | ✅ Always |
|
|
1105
|
+
| Client Credentials | Machine-to-machine | N/A |
|
|
1106
|
+
| Device Code | TV, CLI, IoT | N/A |
|
|
1107
|
+
| ~~Implicit~~ | **DEPRECATED** — never use | ❌ |
|
|
1108
|
+
| ~~Password~~ | **DEPRECATED** — never use | ❌ |
|
|
1109
|
+
|
|
1110
|
+
---
|
|
1111
|
+
|
|
1112
|
+
## OpenID Connect (OIDC)
|
|
1113
|
+
|
|
1114
|
+
OIDC = OAuth 2.0 + Identity Layer
|
|
1115
|
+
|
|
1116
|
+
### ID Token Claims
|
|
1117
|
+
|
|
1118
|
+
| Claim | Purpose |
|
|
1119
|
+
|-------|---------|
|
|
1120
|
+
| `sub` | Unique user identifier |
|
|
1121
|
+
| `iss` | Token issuer |
|
|
1122
|
+
| `aud` | Intended audience (your client_id) |
|
|
1123
|
+
| `exp` | Expiration time |
|
|
1124
|
+
| `iat` | Issued at |
|
|
1125
|
+
| `nonce` | Replay attack prevention |
|
|
1126
|
+
| `email` | User email (with scope) |
|
|
1127
|
+
| `name` | User display name (with scope) |
|
|
1128
|
+
|
|
1129
|
+
### Scopes
|
|
1130
|
+
|
|
1131
|
+
| Scope | Data Returned |
|
|
1132
|
+
|-------|---------------|
|
|
1133
|
+
| `openid` | Required — returns `sub` |
|
|
1134
|
+
| `profile` | name, picture, locale |
|
|
1135
|
+
| `email` | email, email_verified |
|
|
1136
|
+
| `offline_access` | Refresh token |
|
|
1137
|
+
|
|
1138
|
+
---
|
|
1139
|
+
|
|
1140
|
+
## Provider Integration
|
|
1141
|
+
|
|
1142
|
+
### Popular Providers
|
|
1143
|
+
|
|
1144
|
+
| Provider | Docs | Notes |
|
|
1145
|
+
|----------|------|-------|
|
|
1146
|
+
| Google | `accounts.google.com` | OIDC compliant |
|
|
1147
|
+
| GitHub | `github.com/login/oauth` | OAuth 2.0 only (no OIDC) |
|
|
1148
|
+
| Microsoft | `login.microsoftonline.com` | OIDC + Azure AD |
|
|
1149
|
+
| Apple | `appleid.apple.com` | Required for iOS apps |
|
|
1150
|
+
|
|
1151
|
+
### Auth Libraries (Node.js)
|
|
1152
|
+
|
|
1153
|
+
| Library | Use Case |
|
|
1154
|
+
|---------|----------|
|
|
1155
|
+
| `next-auth` / `Auth.js` | Next.js integration |
|
|
1156
|
+
| `passport` | Express middleware |
|
|
1157
|
+
| `arctic` | Lightweight OAuth 2.0 |
|
|
1158
|
+
| `lucia` | Session + OAuth (modern) |
|
|
1159
|
+
| `better-auth` | Full-featured (2025+) |
|
|
1160
|
+
|
|
1161
|
+
---
|
|
1162
|
+
|
|
1163
|
+
## Security Checklist
|
|
1164
|
+
|
|
1165
|
+
- [ ] Always use PKCE for public clients
|
|
1166
|
+
- [ ] Validate `state` parameter to prevent CSRF
|
|
1167
|
+
- [ ] Verify ID token signature and claims (`iss`, `aud`, `exp`)
|
|
1168
|
+
- [ ] Use `nonce` to prevent replay attacks
|
|
1169
|
+
- [ ] Store tokens in httpOnly cookies, not localStorage
|
|
1170
|
+
- [ ] Implement token refresh before expiry
|
|
1171
|
+
|
|
1172
|
+
---
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
---
|
|
1177
|
+
|
|
1178
|
+
## 🔗 Related
|
|
1179
|
+
|
|
1180
|
+
| File | When to Read |
|
|
1181
|
+
|------|-------------|
|
|
1182
|
+
| [jwt-deep.md](jwt-deep.md) | Token lifecycle after OAuth login |
|
|
1183
|
+
| [session.md](session.md) | Session-based alternative |
|
|
1184
|
+
| [passkey.md](passkey.md) | Passwordless alternative |
|
|
1185
|
+
| [SKILL.md](../SKILL.md) | Auth strategy decision tree |
|
|
1186
|
+
|
|
1187
|
+
---
|
|
1188
|
+
|
|
1189
|
+
### Rule: passkey
|
|
1190
|
+
|
|
1191
|
+
---
|
|
1192
|
+
name: passkey
|
|
1193
|
+
description: WebAuthn/FIDO2 passkeys — registration, authentication, browser + server implementation
|
|
1194
|
+
---
|
|
1195
|
+
|
|
1196
|
+
# Passkeys (WebAuthn / FIDO2)
|
|
1197
|
+
|
|
1198
|
+
> Passwordless authentication using public-key cryptography.
|
|
1199
|
+
|
|
1200
|
+
---
|
|
1201
|
+
|
|
1202
|
+
## What Are Passkeys?
|
|
1203
|
+
|
|
1204
|
+
| Aspect | Detail |
|
|
1205
|
+
|--------|--------|
|
|
1206
|
+
| Standard | WebAuthn (W3C) + FIDO2 (FIDO Alliance) |
|
|
1207
|
+
| Mechanism | Public-key cryptography (device holds private key) |
|
|
1208
|
+
| Phishing resistance | ✅ Origin-bound (can't be phished) |
|
|
1209
|
+
| UX | Biometric (fingerprint, Face ID) or PIN |
|
|
1210
|
+
| Syncing | iCloud Keychain, Google Password Manager, 1Password |
|
|
1211
|
+
|
|
1212
|
+
---
|
|
1213
|
+
|
|
1214
|
+
## Flow Overview
|
|
1215
|
+
|
|
1216
|
+
```
|
|
1217
|
+
Registration:
|
|
1218
|
+
1. Server sends challenge + user info
|
|
1219
|
+
2. Browser calls navigator.credentials.create()
|
|
1220
|
+
3. User authenticates locally (biometric/PIN)
|
|
1221
|
+
4. Browser returns public key + signed challenge
|
|
1222
|
+
5. Server stores public key
|
|
1223
|
+
|
|
1224
|
+
Authentication:
|
|
1225
|
+
1. Server sends challenge + allowed credential IDs
|
|
1226
|
+
2. Browser calls navigator.credentials.get()
|
|
1227
|
+
3. User authenticates locally
|
|
1228
|
+
4. Browser returns signed challenge
|
|
1229
|
+
5. Server verifies signature with stored public key
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
---
|
|
1233
|
+
|
|
1234
|
+
## Server Implementation
|
|
1235
|
+
|
|
1236
|
+
### Using @simplewebauthn/server
|
|
1237
|
+
|
|
1238
|
+
```bash
|
|
1239
|
+
npm install @simplewebauthn/server @simplewebauthn/browser
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1242
|
+
### Registration
|
|
1243
|
+
|
|
1244
|
+
```typescript
|
|
1245
|
+
import {
|
|
1246
|
+
generateRegistrationOptions,
|
|
1247
|
+
verifyRegistrationResponse,
|
|
1248
|
+
} from '@simplewebauthn/server';
|
|
1249
|
+
|
|
1250
|
+
const rpName = 'Your App';
|
|
1251
|
+
const rpID = 'example.com';
|
|
1252
|
+
const origin = 'https://example.com';
|
|
1253
|
+
|
|
1254
|
+
// Step 1: Generate options
|
|
1255
|
+
async function startRegistration(user: User) {
|
|
1256
|
+
const options = await generateRegistrationOptions({
|
|
1257
|
+
rpName,
|
|
1258
|
+
rpID,
|
|
1259
|
+
userID: user.id,
|
|
1260
|
+
userName: user.email,
|
|
1261
|
+
attestationType: 'none', // Don't need hardware attestation
|
|
1262
|
+
authenticatorSelection: {
|
|
1263
|
+
residentKey: 'preferred', // Discoverable credential (passkey)
|
|
1264
|
+
userVerification: 'required',
|
|
1265
|
+
},
|
|
1266
|
+
excludeCredentials: user.credentials.map(c => ({
|
|
1267
|
+
id: c.credentialId,
|
|
1268
|
+
type: 'public-key',
|
|
1269
|
+
})),
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1272
|
+
// Store challenge temporarily
|
|
1273
|
+
await redis.setex(`webauthn:${user.id}`, 300, options.challenge);
|
|
1274
|
+
|
|
1275
|
+
return options;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// Step 2: Verify response
|
|
1279
|
+
async function finishRegistration(user: User, response: RegistrationResponse) {
|
|
1280
|
+
const expectedChallenge = await redis.get(`webauthn:${user.id}`);
|
|
1281
|
+
|
|
1282
|
+
const verification = await verifyRegistrationResponse({
|
|
1283
|
+
response,
|
|
1284
|
+
expectedChallenge,
|
|
1285
|
+
expectedOrigin: origin,
|
|
1286
|
+
expectedRPID: rpID,
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
if (verification.verified && verification.registrationInfo) {
|
|
1290
|
+
const { credentialPublicKey, credentialID, counter } =
|
|
1291
|
+
verification.registrationInfo;
|
|
1292
|
+
|
|
1293
|
+
// Store credential
|
|
1294
|
+
await db.credential.create({
|
|
1295
|
+
data: {
|
|
1296
|
+
userId: user.id,
|
|
1297
|
+
credentialId: Buffer.from(credentialID),
|
|
1298
|
+
publicKey: Buffer.from(credentialPublicKey),
|
|
1299
|
+
counter,
|
|
1300
|
+
deviceType: verification.registrationInfo.credentialDeviceType,
|
|
1301
|
+
backedUp: verification.registrationInfo.credentialBackedUp,
|
|
1302
|
+
},
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
### Authentication
|
|
1309
|
+
|
|
1310
|
+
```typescript
|
|
1311
|
+
import {
|
|
1312
|
+
generateAuthenticationOptions,
|
|
1313
|
+
verifyAuthenticationResponse,
|
|
1314
|
+
} from '@simplewebauthn/server';
|
|
1315
|
+
|
|
1316
|
+
// Step 1: Generate challenge
|
|
1317
|
+
async function startAuth(user?: User) {
|
|
1318
|
+
const options = await generateAuthenticationOptions({
|
|
1319
|
+
rpID,
|
|
1320
|
+
userVerification: 'required',
|
|
1321
|
+
// If user known, limit to their credentials
|
|
1322
|
+
...(user && {
|
|
1323
|
+
allowCredentials: user.credentials.map(c => ({
|
|
1324
|
+
id: c.credentialId,
|
|
1325
|
+
type: 'public-key',
|
|
1326
|
+
})),
|
|
1327
|
+
}),
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
await redis.setex(`webauthn:auth:${options.challenge}`, 300, '1');
|
|
1331
|
+
return options;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// Step 2: Verify
|
|
1335
|
+
async function finishAuth(response: AuthenticationResponse) {
|
|
1336
|
+
const credential = await db.credential.findUnique({
|
|
1337
|
+
where: { credentialId: response.id },
|
|
1338
|
+
include: { user: true },
|
|
1339
|
+
});
|
|
1340
|
+
|
|
1341
|
+
if (!credential) throw new Error('Credential not found');
|
|
1342
|
+
|
|
1343
|
+
const verification = await verifyAuthenticationResponse({
|
|
1344
|
+
response,
|
|
1345
|
+
expectedChallenge: storedChallenge,
|
|
1346
|
+
expectedOrigin: origin,
|
|
1347
|
+
expectedRPID: rpID,
|
|
1348
|
+
authenticator: {
|
|
1349
|
+
credentialPublicKey: credential.publicKey,
|
|
1350
|
+
credentialID: credential.credentialId,
|
|
1351
|
+
counter: credential.counter,
|
|
1352
|
+
},
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
if (verification.verified) {
|
|
1356
|
+
// Update counter (replay protection)
|
|
1357
|
+
await db.credential.update({
|
|
1358
|
+
where: { id: credential.id },
|
|
1359
|
+
data: { counter: verification.authenticationInfo.newCounter },
|
|
1360
|
+
});
|
|
1361
|
+
|
|
1362
|
+
return credential.user;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
```
|
|
1366
|
+
|
|
1367
|
+
---
|
|
1368
|
+
|
|
1369
|
+
## Frontend (Browser)
|
|
1370
|
+
|
|
1371
|
+
```typescript
|
|
1372
|
+
import {
|
|
1373
|
+
startRegistration,
|
|
1374
|
+
startAuthentication,
|
|
1375
|
+
} from '@simplewebauthn/browser';
|
|
1376
|
+
|
|
1377
|
+
// Registration
|
|
1378
|
+
const regOptions = await fetch('/api/auth/passkey/register').then(r => r.json());
|
|
1379
|
+
const regResult = await startRegistration(regOptions);
|
|
1380
|
+
await fetch('/api/auth/passkey/register/verify', {
|
|
1381
|
+
method: 'POST',
|
|
1382
|
+
body: JSON.stringify(regResult),
|
|
1383
|
+
});
|
|
1384
|
+
|
|
1385
|
+
// Authentication
|
|
1386
|
+
const authOptions = await fetch('/api/auth/passkey/login').then(r => r.json());
|
|
1387
|
+
const authResult = await startAuthentication(authOptions);
|
|
1388
|
+
await fetch('/api/auth/passkey/login/verify', {
|
|
1389
|
+
method: 'POST',
|
|
1390
|
+
body: JSON.stringify(authResult),
|
|
1391
|
+
});
|
|
1392
|
+
```
|
|
1393
|
+
|
|
1394
|
+
---
|
|
1395
|
+
|
|
1396
|
+
## Adoption Strategy
|
|
1397
|
+
|
|
1398
|
+
| Phase | Action |
|
|
1399
|
+
|-------|--------|
|
|
1400
|
+
| 1 | Offer passkey as optional MFA |
|
|
1401
|
+
| 2 | Prompt existing users to add passkey |
|
|
1402
|
+
| 3 | Allow passkey-only login (passwordless) |
|
|
1403
|
+
| 4 | Keep password as fallback recovery |
|
|
1404
|
+
|
|
1405
|
+
---
|
|
1406
|
+
|
|
1407
|
+
## Browser Support (2025)
|
|
1408
|
+
|
|
1409
|
+
| Browser | Passkey Support |
|
|
1410
|
+
|---------|-----------------|
|
|
1411
|
+
| Chrome 108+ | ✅ Full |
|
|
1412
|
+
| Safari 16+ | ✅ Full |
|
|
1413
|
+
| Firefox 122+ | ✅ Full |
|
|
1414
|
+
| Edge 108+ | ✅ Full |
|
|
1415
|
+
|
|
1416
|
+
---
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
---
|
|
1421
|
+
|
|
1422
|
+
## 🔗 Related
|
|
1423
|
+
|
|
1424
|
+
| File | When to Read |
|
|
1425
|
+
|------|-------------|
|
|
1426
|
+
| [mfa.md](mfa.md) | MFA with passkeys as second factor |
|
|
1427
|
+
| [oauth2.md](oauth2.md) | OAuth alternative to passkeys |
|
|
1428
|
+
| [session.md](session.md) | Session after passkey auth |
|
|
1429
|
+
| [SKILL.md](../SKILL.md) | Auth strategy decision tree |
|
|
1430
|
+
|
|
1431
|
+
---
|
|
1432
|
+
|
|
1433
|
+
### Rule: rbac-abac
|
|
1434
|
+
|
|
1435
|
+
---
|
|
1436
|
+
name: rbac-abac
|
|
1437
|
+
description: Role-Based and Attribute-Based access control — Prisma schema, middleware, ABAC policy engine
|
|
1438
|
+
---
|
|
1439
|
+
|
|
1440
|
+
# RBAC & ABAC — Access Control
|
|
1441
|
+
|
|
1442
|
+
> Role-Based and Attribute-Based authorization patterns.
|
|
1443
|
+
|
|
1444
|
+
---
|
|
1445
|
+
|
|
1446
|
+
## Model Selection
|
|
1447
|
+
|
|
1448
|
+
```
|
|
1449
|
+
How complex are your permissions?
|
|
1450
|
+
├── Simple (admin/user/viewer)
|
|
1451
|
+
│ └── RBAC (Role-Based)
|
|
1452
|
+
├── Medium (roles + resource ownership)
|
|
1453
|
+
│ └── RBAC + ownership checks
|
|
1454
|
+
├── Complex (context-dependent rules)
|
|
1455
|
+
│ └── ABAC (Attribute-Based)
|
|
1456
|
+
└── Enterprise (multi-tenant + compliance)
|
|
1457
|
+
└── ABAC or hybrid RBAC+ABAC
|
|
1458
|
+
```
|
|
1459
|
+
|
|
1460
|
+
---
|
|
1461
|
+
|
|
1462
|
+
## RBAC (Role-Based Access Control)
|
|
1463
|
+
|
|
1464
|
+
### Schema Design
|
|
1465
|
+
|
|
1466
|
+
```typescript
|
|
1467
|
+
// Database models
|
|
1468
|
+
interface User {
|
|
1469
|
+
id: string;
|
|
1470
|
+
roles: Role[]; // Many-to-many
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
interface Role {
|
|
1474
|
+
id: string;
|
|
1475
|
+
name: string; // "admin", "editor", "viewer"
|
|
1476
|
+
permissions: Permission[]; // Many-to-many
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
interface Permission {
|
|
1480
|
+
id: string;
|
|
1481
|
+
resource: string; // "posts", "users", "billing"
|
|
1482
|
+
action: string; // "create", "read", "update", "delete"
|
|
1483
|
+
}
|
|
1484
|
+
```
|
|
1485
|
+
|
|
1486
|
+
### Prisma Schema
|
|
1487
|
+
|
|
1488
|
+
```prisma
|
|
1489
|
+
model User {
|
|
1490
|
+
id String @id @default(cuid())
|
|
1491
|
+
roles UserRole[]
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
model Role {
|
|
1495
|
+
id String @id @default(cuid())
|
|
1496
|
+
name String @unique
|
|
1497
|
+
permissions RolePermission[]
|
|
1498
|
+
users UserRole[]
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
model Permission {
|
|
1502
|
+
id String @id @default(cuid())
|
|
1503
|
+
resource String
|
|
1504
|
+
action String
|
|
1505
|
+
roles RolePermission[]
|
|
1506
|
+
@@unique([resource, action])
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
model UserRole {
|
|
1510
|
+
userId String
|
|
1511
|
+
roleId String
|
|
1512
|
+
user User @relation(fields: [userId], references: [id])
|
|
1513
|
+
role Role @relation(fields: [roleId], references: [id])
|
|
1514
|
+
@@id([userId, roleId])
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
model RolePermission {
|
|
1518
|
+
roleId String
|
|
1519
|
+
permissionId String
|
|
1520
|
+
role Role @relation(fields: [roleId], references: [id])
|
|
1521
|
+
permission Permission @relation(fields: [permissionId], references: [id])
|
|
1522
|
+
@@id([roleId, permissionId])
|
|
1523
|
+
}
|
|
1524
|
+
```
|
|
1525
|
+
|
|
1526
|
+
### Permission Check (Middleware)
|
|
1527
|
+
|
|
1528
|
+
```typescript
|
|
1529
|
+
function requirePermission(resource: string, action: string) {
|
|
1530
|
+
return async (req: Request, res: Response, next: NextFunction) => {
|
|
1531
|
+
const user = req.user;
|
|
1532
|
+
const hasPermission = user.roles.some(role =>
|
|
1533
|
+
role.permissions.some(p =>
|
|
1534
|
+
p.resource === resource && p.action === action
|
|
1535
|
+
)
|
|
1536
|
+
);
|
|
1537
|
+
|
|
1538
|
+
if (!hasPermission) {
|
|
1539
|
+
return res.status(403).json({ error: 'Insufficient permissions' });
|
|
1540
|
+
}
|
|
1541
|
+
next();
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// Usage
|
|
1546
|
+
app.delete('/api/posts/:id', requirePermission('posts', 'delete'), deletePost);
|
|
1547
|
+
```
|
|
1548
|
+
|
|
1549
|
+
---
|
|
1550
|
+
|
|
1551
|
+
## ABAC (Attribute-Based Access Control)
|
|
1552
|
+
|
|
1553
|
+
### When to Use
|
|
1554
|
+
|
|
1555
|
+
| Scenario | Example |
|
|
1556
|
+
|----------|---------|
|
|
1557
|
+
| Context-dependent | "Editors can only edit posts they authored" |
|
|
1558
|
+
| Time-based | "Access only during business hours" |
|
|
1559
|
+
| Location-based | "Only from corporate network" |
|
|
1560
|
+
| Multi-tenant | "Users can only see their organization's data" |
|
|
1561
|
+
|
|
1562
|
+
### Policy Pattern
|
|
1563
|
+
|
|
1564
|
+
```typescript
|
|
1565
|
+
interface PolicyContext {
|
|
1566
|
+
subject: { id: string; role: string; orgId: string; };
|
|
1567
|
+
resource: { type: string; ownerId: string; orgId: string; };
|
|
1568
|
+
action: string;
|
|
1569
|
+
environment: { time: Date; ip: string; };
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
function evaluatePolicy(ctx: PolicyContext): boolean {
|
|
1573
|
+
const policies: Policy[] = [
|
|
1574
|
+
// Owners can do anything to their resources
|
|
1575
|
+
{
|
|
1576
|
+
effect: 'allow',
|
|
1577
|
+
condition: (c) => c.subject.id === c.resource.ownerId,
|
|
1578
|
+
},
|
|
1579
|
+
// Admins can do anything in their org
|
|
1580
|
+
{
|
|
1581
|
+
effect: 'allow',
|
|
1582
|
+
condition: (c) =>
|
|
1583
|
+
c.subject.role === 'admin' &&
|
|
1584
|
+
c.subject.orgId === c.resource.orgId,
|
|
1585
|
+
},
|
|
1586
|
+
// Editors can read/update (not delete) in their org
|
|
1587
|
+
{
|
|
1588
|
+
effect: 'allow',
|
|
1589
|
+
condition: (c) =>
|
|
1590
|
+
c.subject.role === 'editor' &&
|
|
1591
|
+
c.subject.orgId === c.resource.orgId &&
|
|
1592
|
+
['read', 'update'].includes(c.action),
|
|
1593
|
+
},
|
|
1594
|
+
];
|
|
1595
|
+
|
|
1596
|
+
// Default deny — allow only if at least one policy matches
|
|
1597
|
+
return policies.some(p => p.effect === 'allow' && p.condition(ctx));
|
|
1598
|
+
}
|
|
1599
|
+
```
|
|
1600
|
+
|
|
1601
|
+
---
|
|
1602
|
+
|
|
1603
|
+
## Libraries & Services
|
|
1604
|
+
|
|
1605
|
+
| Solution | Type | Best For |
|
|
1606
|
+
|----------|------|----------|
|
|
1607
|
+
| CASL | Library (JS) | Frontend + backend RBAC/ABAC |
|
|
1608
|
+
| Casbin | Library (multi-lang) | Policy engine |
|
|
1609
|
+
| Oso | Library | Application-embedded authz |
|
|
1610
|
+
| Auth0 FGA | Service | Fine-grained authorization |
|
|
1611
|
+
| Permit.io | Service | Managed RBAC/ABAC |
|
|
1612
|
+
|
|
1613
|
+
---
|
|
1614
|
+
|
|
1615
|
+
## Anti-Patterns
|
|
1616
|
+
|
|
1617
|
+
| ❌ Don't | ✅ Do |
|
|
1618
|
+
|---------|------|
|
|
1619
|
+
| Hardcode roles in if/else | Use permission table |
|
|
1620
|
+
| Check role name in code | Check permission (resource + action) |
|
|
1621
|
+
| Forget resource ownership | Always check `ownerId` |
|
|
1622
|
+
| Skip multi-tenant isolation | Always scope queries by `orgId` |
|
|
1623
|
+
|
|
1624
|
+
---
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
---
|
|
1629
|
+
|
|
1630
|
+
## 🔗 Related
|
|
1631
|
+
|
|
1632
|
+
| File | When to Read |
|
|
1633
|
+
|------|-------------|
|
|
1634
|
+
| [jwt-deep.md](jwt-deep.md) | Role/permission claims in JWT |
|
|
1635
|
+
| [session.md](session.md) | Session-based permission checks |
|
|
1636
|
+
| [SKILL.md](../SKILL.md) | Auth strategy decision tree |
|
|
1637
|
+
|
|
1638
|
+
---
|
|
1639
|
+
|
|
1640
|
+
### Rule: session
|
|
1641
|
+
|
|
1642
|
+
---
|
|
1643
|
+
name: session
|
|
1644
|
+
description: Cookie sessions, Redis store, stateless vs stateful, session lifecycle and security
|
|
1645
|
+
---
|
|
1646
|
+
|
|
1647
|
+
# Session Management
|
|
1648
|
+
|
|
1649
|
+
> Cookie-based sessions, Redis store, stateless vs stateful trade-offs.
|
|
1650
|
+
|
|
1651
|
+
---
|
|
1652
|
+
|
|
1653
|
+
## Stateless vs Stateful
|
|
1654
|
+
|
|
1655
|
+
| Aspect | Stateless (JWT) | Stateful (Session) |
|
|
1656
|
+
|--------|-----------------|-------------------|
|
|
1657
|
+
| Storage | Token contains data | Server stores data |
|
|
1658
|
+
| Scalability | ✅ No shared state | ⚠️ Needs shared store |
|
|
1659
|
+
| Revocation | ❌ Hard (need blocklist) | ✅ Delete from store |
|
|
1660
|
+
| Size | Can grow large | Fixed session ID |
|
|
1661
|
+
| Best for | Microservices, API | Traditional web SSR |
|
|
1662
|
+
|
|
1663
|
+
### Hybrid Approach (Recommended)
|
|
1664
|
+
|
|
1665
|
+
```
|
|
1666
|
+
Use JWT for access (short-lived, stateless)
|
|
1667
|
+
+ Session-based refresh (stateful, revocable in Redis)
|
|
1668
|
+
```
|
|
1669
|
+
|
|
1670
|
+
---
|
|
1671
|
+
|
|
1672
|
+
## Cookie-Based Session
|
|
1673
|
+
|
|
1674
|
+
### Secure Cookie Configuration
|
|
1675
|
+
|
|
1676
|
+
```typescript
|
|
1677
|
+
app.use(session({
|
|
1678
|
+
name: '__session', // Avoid default 'connect.sid'
|
|
1679
|
+
secret: process.env.SESSION_SECRET,
|
|
1680
|
+
resave: false,
|
|
1681
|
+
saveUninitialized: false,
|
|
1682
|
+
cookie: {
|
|
1683
|
+
httpOnly: true, // No JS access
|
|
1684
|
+
secure: true, // HTTPS only
|
|
1685
|
+
sameSite: 'lax', // CSRF protection
|
|
1686
|
+
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
1687
|
+
domain: '.example.com', // Cross-subdomain if needed
|
|
1688
|
+
path: '/',
|
|
1689
|
+
},
|
|
1690
|
+
}));
|
|
1691
|
+
```
|
|
1692
|
+
|
|
1693
|
+
### Cookie Security Flags
|
|
1694
|
+
|
|
1695
|
+
| Flag | Purpose | Always Set? |
|
|
1696
|
+
|------|---------|-------------|
|
|
1697
|
+
| `httpOnly` | Prevent XSS token theft | ✅ |
|
|
1698
|
+
| `secure` | HTTPS only | ✅ (prod) |
|
|
1699
|
+
| `sameSite: lax` | Basic CSRF protection | ✅ |
|
|
1700
|
+
| `sameSite: strict` | Full CSRF protection | For sensitive ops |
|
|
1701
|
+
| `__Host-` prefix | Origin-bound | High security |
|
|
1702
|
+
|
|
1703
|
+
---
|
|
1704
|
+
|
|
1705
|
+
## Redis Session Store
|
|
1706
|
+
|
|
1707
|
+
### Why Redis
|
|
1708
|
+
|
|
1709
|
+
| Feature | Benefit |
|
|
1710
|
+
|---------|---------|
|
|
1711
|
+
| In-memory speed | < 1ms session lookup |
|
|
1712
|
+
| TTL support | Automatic expiry |
|
|
1713
|
+
| Cluster support | Horizontal scaling |
|
|
1714
|
+
| Pub/Sub | Session invalidation across nodes |
|
|
1715
|
+
|
|
1716
|
+
### Setup
|
|
1717
|
+
|
|
1718
|
+
```typescript
|
|
1719
|
+
import RedisStore from 'connect-redis';
|
|
1720
|
+
import { createClient } from 'redis';
|
|
1721
|
+
|
|
1722
|
+
const redisClient = createClient({ url: process.env.REDIS_URL });
|
|
1723
|
+
await redisClient.connect();
|
|
1724
|
+
|
|
1725
|
+
app.use(session({
|
|
1726
|
+
store: new RedisStore({ client: redisClient }),
|
|
1727
|
+
secret: process.env.SESSION_SECRET,
|
|
1728
|
+
resave: false,
|
|
1729
|
+
saveUninitialized: false,
|
|
1730
|
+
cookie: { httpOnly: true, secure: true, sameSite: 'lax' },
|
|
1731
|
+
}));
|
|
1732
|
+
```
|
|
1733
|
+
|
|
1734
|
+
### Session Data Structure
|
|
1735
|
+
|
|
1736
|
+
```typescript
|
|
1737
|
+
// Keep session data minimal
|
|
1738
|
+
interface SessionData {
|
|
1739
|
+
userId: string;
|
|
1740
|
+
role: string;
|
|
1741
|
+
orgId?: string;
|
|
1742
|
+
loginAt: number;
|
|
1743
|
+
lastActiveAt: number;
|
|
1744
|
+
// DON'T store: full user profile, preferences, cart items
|
|
1745
|
+
}
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
---
|
|
1749
|
+
|
|
1750
|
+
## Session Lifecycle
|
|
1751
|
+
|
|
1752
|
+
### Login
|
|
1753
|
+
|
|
1754
|
+
```typescript
|
|
1755
|
+
async function login(req: Request) {
|
|
1756
|
+
const user = await authenticate(req.body);
|
|
1757
|
+
|
|
1758
|
+
// Regenerate session ID (prevent fixation)
|
|
1759
|
+
req.session.regenerate(() => {
|
|
1760
|
+
req.session.userId = user.id;
|
|
1761
|
+
req.session.role = user.role;
|
|
1762
|
+
req.session.loginAt = Date.now();
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
```
|
|
1766
|
+
|
|
1767
|
+
### Logout
|
|
1768
|
+
|
|
1769
|
+
```typescript
|
|
1770
|
+
async function logout(req: Request) {
|
|
1771
|
+
const sessionId = req.sessionID;
|
|
1772
|
+
|
|
1773
|
+
// Destroy server-side session
|
|
1774
|
+
req.session.destroy(() => {
|
|
1775
|
+
// Clear cookie
|
|
1776
|
+
res.clearCookie('__session');
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
```
|
|
1780
|
+
|
|
1781
|
+
### Invalidate All Sessions (password change)
|
|
1782
|
+
|
|
1783
|
+
```typescript
|
|
1784
|
+
async function invalidateAllSessions(userId: string) {
|
|
1785
|
+
// Scan Redis for user's sessions
|
|
1786
|
+
const keys = await redis.keys(`sess:*`);
|
|
1787
|
+
for (const key of keys) {
|
|
1788
|
+
const data = await redis.get(key);
|
|
1789
|
+
if (data && JSON.parse(data).userId === userId) {
|
|
1790
|
+
await redis.del(key);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
```
|
|
1795
|
+
|
|
1796
|
+
---
|
|
1797
|
+
|
|
1798
|
+
## Session Security Checklist
|
|
1799
|
+
|
|
1800
|
+
- [ ] Regenerate session ID after login
|
|
1801
|
+
- [ ] Set `httpOnly`, `secure`, `sameSite` on cookies
|
|
1802
|
+
- [ ] Use Redis/Memcached for distributed sessions
|
|
1803
|
+
- [ ] Implement idle timeout (30 min) + absolute timeout (24h)
|
|
1804
|
+
- [ ] Invalidate sessions on password change
|
|
1805
|
+
- [ ] Log session creation/destruction for audit
|
|
1806
|
+
|
|
1807
|
+
---
|
|
1808
|
+
|
|
1809
|
+
|
|
1810
|
+
|
|
1811
|
+
---
|
|
1812
|
+
|
|
1813
|
+
## 🔗 Related
|
|
1814
|
+
|
|
1815
|
+
| File | When to Read |
|
|
1816
|
+
|------|-------------|
|
|
1817
|
+
| [jwt-deep.md](jwt-deep.md) | JWT as stateless alternative |
|
|
1818
|
+
| [oauth2.md](oauth2.md) | OAuth sessions |
|
|
1819
|
+
| [mfa.md](mfa.md) | MFA with sessions |
|
|
1820
|
+
| [SKILL.md](../SKILL.md) | Auth strategy decision tree |
|
|
1821
|
+
|
|
1822
|
+
---
|
|
1823
|
+
|
|
1824
|
+
⚡ ## Security Audit Logging (MANDATORY)
|
|
1825
|
+
|
|
1826
|
+
- EVERY sensitive auth event MUST be audited to SIEM with ip_address and imestamp.
|
|
1827
|
+
|
|
1828
|
+
---
|
|
1829
|
+
|
|
1830
|
+
PikaKit v3.9.134
|