@ketecode/loom 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +516 -2
- package/agents/accessibility-reviewer/AGENT.md +70 -0
- package/agents/accessibility-reviewer/evals/triggers.json +15 -0
- package/agents/agent-evaluator/AGENT.md +74 -0
- package/agents/agent-evaluator/evals/triggers.json +15 -0
- package/agents/architect/AGENT.md +82 -0
- package/agents/architect/evals/triggers.json +17 -0
- package/agents/billing-reviewer/AGENT.md +68 -0
- package/agents/billing-reviewer/evals/triggers.json +16 -0
- package/agents/code-reviewer/AGENT.md +51 -0
- package/agents/code-reviewer/evals/triggers.json +14 -0
- package/agents/code-simplifier/AGENT.md +74 -0
- package/agents/code-simplifier/evals/triggers.json +15 -0
- package/agents/cpp-build-resolver/AGENT.md +73 -0
- package/agents/cpp-build-resolver/evals/triggers.json +16 -0
- package/agents/cpp-reviewer/AGENT.md +59 -0
- package/agents/cpp-reviewer/evals/triggers.json +16 -0
- package/agents/csharp-build-resolver/AGENT.md +84 -0
- package/agents/csharp-build-resolver/evals/triggers.json +17 -0
- package/agents/csharp-reviewer/AGENT.md +88 -0
- package/agents/csharp-reviewer/evals/triggers.json +17 -0
- package/agents/dart-build-resolver/AGENT.md +80 -0
- package/agents/dart-build-resolver/evals/triggers.json +17 -0
- package/agents/dart-reviewer/AGENT.md +66 -0
- package/agents/dart-reviewer/evals/triggers.json +17 -0
- package/agents/database-reviewer/AGENT.md +72 -0
- package/agents/database-reviewer/evals/triggers.json +16 -0
- package/agents/django-reviewer/AGENT.md +61 -0
- package/agents/django-reviewer/evals/triggers.json +15 -0
- package/agents/doc-updater/AGENT.md +92 -0
- package/agents/doc-updater/evals/triggers.json +14 -0
- package/agents/e2e-runner/AGENT.md +88 -0
- package/agents/e2e-runner/evals/triggers.json +16 -0
- package/agents/fastapi-reviewer/AGENT.md +63 -0
- package/agents/fastapi-reviewer/evals/triggers.json +15 -0
- package/agents/flutter-reviewer/AGENT.md +70 -0
- package/agents/flutter-reviewer/evals/triggers.json +15 -0
- package/agents/fsharp-build-resolver/AGENT.md +81 -0
- package/agents/fsharp-build-resolver/evals/triggers.json +15 -0
- package/agents/fsharp-reviewer/AGENT.md +77 -0
- package/agents/fsharp-reviewer/evals/triggers.json +15 -0
- package/agents/go-build-resolver/AGENT.md +85 -0
- package/agents/go-build-resolver/evals/triggers.json +16 -0
- package/agents/go-reviewer/AGENT.md +66 -0
- package/agents/go-reviewer/evals/triggers.json +16 -0
- package/agents/healthcare-reviewer/AGENT.md +65 -0
- package/agents/healthcare-reviewer/evals/triggers.json +16 -0
- package/agents/i18n-reviewer/AGENT.md +64 -0
- package/agents/i18n-reviewer/evals/triggers.json +16 -0
- package/agents/infra-reviewer/AGENT.md +93 -0
- package/agents/infra-reviewer/evals/triggers.json +15 -0
- package/agents/java-build-resolver/AGENT.md +82 -0
- package/agents/java-build-resolver/evals/triggers.json +16 -0
- package/agents/java-reviewer/AGENT.md +64 -0
- package/agents/java-reviewer/evals/triggers.json +16 -0
- package/agents/kotlin-build-resolver/AGENT.md +89 -0
- package/agents/kotlin-build-resolver/evals/triggers.json +16 -0
- package/agents/kotlin-reviewer/AGENT.md +75 -0
- package/agents/kotlin-reviewer/evals/triggers.json +16 -0
- package/agents/mle-reviewer/AGENT.md +68 -0
- package/agents/mle-reviewer/evals/triggers.json +16 -0
- package/agents/network-config-reviewer/AGENT.md +68 -0
- package/agents/network-config-reviewer/evals/triggers.json +17 -0
- package/agents/payments-reviewer/AGENT.md +64 -0
- package/agents/payments-reviewer/evals/triggers.json +16 -0
- package/agents/performance-optimizer/AGENT.md +86 -0
- package/agents/performance-optimizer/evals/triggers.json +16 -0
- package/agents/perl-build-resolver/AGENT.md +84 -0
- package/agents/perl-build-resolver/evals/triggers.json +15 -0
- package/agents/perl-reviewer/AGENT.md +77 -0
- package/agents/perl-reviewer/evals/triggers.json +15 -0
- package/agents/php-build-resolver/AGENT.md +88 -0
- package/agents/php-build-resolver/evals/triggers.json +16 -0
- package/agents/php-reviewer/AGENT.md +61 -0
- package/agents/php-reviewer/evals/triggers.json +15 -0
- package/agents/planner/AGENT.md +75 -0
- package/agents/planner/evals/triggers.json +17 -0
- package/agents/pr-test-analyzer/AGENT.md +82 -0
- package/agents/pr-test-analyzer/evals/triggers.json +16 -0
- package/agents/python-build-resolver/AGENT.md +87 -0
- package/agents/python-build-resolver/evals/triggers.json +16 -0
- package/agents/python-reviewer/AGENT.md +63 -0
- package/agents/python-reviewer/evals/triggers.json +15 -0
- package/agents/rag-reviewer/AGENT.md +71 -0
- package/agents/rag-reviewer/evals/triggers.json +16 -0
- package/agents/react-reviewer/AGENT.md +70 -0
- package/agents/react-reviewer/evals/triggers.json +16 -0
- package/agents/refactor-cleaner/AGENT.md +82 -0
- package/agents/refactor-cleaner/evals/triggers.json +16 -0
- package/agents/ruby-build-resolver/AGENT.md +93 -0
- package/agents/ruby-build-resolver/evals/triggers.json +16 -0
- package/agents/ruby-reviewer/AGENT.md +62 -0
- package/agents/ruby-reviewer/evals/triggers.json +16 -0
- package/agents/rust-build-resolver/AGENT.md +98 -0
- package/agents/rust-build-resolver/evals/triggers.json +16 -0
- package/agents/rust-reviewer/AGENT.md +78 -0
- package/agents/rust-reviewer/evals/triggers.json +15 -0
- package/agents/security-reviewer/AGENT.md +84 -0
- package/agents/security-reviewer/evals/triggers.json +16 -0
- package/agents/silent-failure-hunter/AGENT.md +66 -0
- package/agents/silent-failure-hunter/evals/triggers.json +16 -0
- package/agents/solidity-reviewer/AGENT.md +70 -0
- package/agents/solidity-reviewer/evals/triggers.json +16 -0
- package/agents/swift-build-resolver/AGENT.md +85 -0
- package/agents/swift-build-resolver/evals/triggers.json +15 -0
- package/agents/swift-reviewer/AGENT.md +75 -0
- package/agents/swift-reviewer/evals/triggers.json +15 -0
- package/agents/typescript-build-resolver/AGENT.md +76 -0
- package/agents/typescript-build-resolver/evals/triggers.json +15 -0
- package/agents/typescript-reviewer/AGENT.md +76 -0
- package/agents/typescript-reviewer/evals/triggers.json +15 -0
- package/agents/vue-reviewer/AGENT.md +75 -0
- package/agents/vue-reviewer/evals/triggers.json +15 -0
- package/bin/kete-loom.js +683 -0
- package/commands/aside.md +19 -0
- package/commands/build-fix.md +26 -0
- package/commands/campaign.md +19 -0
- package/commands/changelog.md +36 -0
- package/commands/checkpoint.md +26 -0
- package/commands/codemap.md +25 -0
- package/commands/commit.md +26 -0
- package/commands/deps-audit.md +32 -0
- package/commands/epic-decompose.md +21 -0
- package/commands/explain.md +37 -0
- package/commands/feature-dev.md +22 -0
- package/commands/hookify.md +23 -0
- package/commands/i18n-check.md +39 -0
- package/commands/issue-sync.md +22 -0
- package/commands/jira.md +19 -0
- package/commands/learn.md +23 -0
- package/commands/loom.md +21 -0
- package/commands/loop.md +20 -0
- package/commands/model-route.md +27 -0
- package/commands/onboard.md +35 -0
- package/commands/orchestrate.md +21 -0
- package/commands/plan-feature.md +36 -0
- package/commands/postmortem.md +42 -0
- package/commands/pr-describe.md +39 -0
- package/commands/pr.md +22 -0
- package/commands/prd.md +41 -0
- package/commands/project-init.md +21 -0
- package/commands/refactor-clean.md +24 -0
- package/commands/resume-session.md +22 -0
- package/commands/review.md +35 -0
- package/commands/save-session.md +37 -0
- package/commands/security-scan.md +32 -0
- package/commands/sessions.md +21 -0
- package/commands/skill-create.md +21 -0
- package/commands/tdd.md +36 -0
- package/commands/test-coverage.md +24 -0
- package/commands/threat-model.md +36 -0
- package/commands/update-docs.md +25 -0
- package/commands/verify.md +21 -0
- package/hooks/block-dangerous-commands/HOOK.md +30 -0
- package/hooks/block-dangerous-commands/cases.json +50 -0
- package/hooks/block-dangerous-commands/hook.js +75 -0
- package/hooks/block-no-verify/HOOK.md +25 -0
- package/hooks/block-no-verify/cases.json +30 -0
- package/hooks/block-no-verify/hook.js +43 -0
- package/hooks/format-on-edit/HOOK.md +24 -0
- package/hooks/format-on-edit/hook.js +89 -0
- package/hooks/guard-secrets/HOOK.md +19 -0
- package/hooks/guard-secrets/cases.json +110 -0
- package/hooks/guard-secrets/hook.js +44 -0
- package/hooks/load-session-context/HOOK.md +20 -0
- package/hooks/load-session-context/hook.js +56 -0
- package/hooks/protect-files/HOOK.md +24 -0
- package/hooks/protect-files/cases.json +27 -0
- package/hooks/protect-files/hook.js +39 -0
- package/hooks/run.js +132 -0
- package/mcp/atlassian.json +11 -0
- package/mcp/chrome-devtools.json +18 -0
- package/mcp/cloudflare.json +11 -0
- package/mcp/context7.json +11 -0
- package/mcp/fetch.json +17 -0
- package/mcp/figma.json +11 -0
- package/mcp/git.json +17 -0
- package/mcp/github.json +11 -0
- package/mcp/linear.json +11 -0
- package/mcp/memory.json +18 -0
- package/mcp/notion.json +11 -0
- package/mcp/playwright.json +18 -0
- package/mcp/sentry.json +11 -0
- package/mcp/stripe.json +11 -0
- package/mcp/supabase.json +11 -0
- package/mcp/time.json +17 -0
- package/package.json +59 -4
- package/profiles.json +165 -0
- package/rules/common.md +21 -0
- package/rules/cpp.md +29 -0
- package/rules/csharp.md +25 -0
- package/rules/dart.md +29 -0
- package/rules/fsharp.md +28 -0
- package/rules/git.md +26 -0
- package/rules/go.md +29 -0
- package/rules/java.md +29 -0
- package/rules/kotlin.md +27 -0
- package/rules/perl.md +26 -0
- package/rules/php.md +28 -0
- package/rules/python.md +30 -0
- package/rules/ruby.md +27 -0
- package/rules/rust.md +26 -0
- package/rules/security.md +29 -0
- package/rules/swift.md +28 -0
- package/rules/testing.md +25 -0
- package/rules/typescript.md +29 -0
- package/schemas/skill-frontmatter.schema.json +52 -0
- package/scripts/lib/audit.js +96 -0
- package/scripts/lib/frontmatter.js +65 -0
- package/scripts/lib/hooks-install.js +292 -0
- package/scripts/lib/i18n.js +51 -0
- package/scripts/lib/inventory.js +85 -0
- package/scripts/lib/lint.js +158 -0
- package/scripts/lib/mcp-install.js +284 -0
- package/scripts/lib/profiles.js +128 -0
- package/scripts/lib/render.js +86 -0
- package/scripts/lib/rules-install.js +118 -0
- package/scripts/lib/skills.js +86 -0
- package/scripts/lib/targets.js +113 -0
- package/skills/accounting-api-integration/SKILL.md +81 -0
- package/skills/accounting-api-integration/evals/triggers.json +17 -0
- package/skills/accounting-api-integration/references/quickbooks.md +48 -0
- package/skills/accounting-api-integration/references/xero.md +45 -0
- package/skills/agent-harness-design/SKILL.md +125 -0
- package/skills/agent-harness-design/evals/triggers.json +21 -0
- package/skills/ai-media-generation/SKILL.md +89 -0
- package/skills/ai-media-generation/evals/triggers.json +16 -0
- package/skills/ai-media-generation/references/job-pipeline.md +76 -0
- package/skills/angular-patterns/SKILL.md +122 -0
- package/skills/angular-patterns/evals/triggers.json +16 -0
- package/skills/api-design/SKILL.md +96 -0
- package/skills/api-design/evals/triggers.json +18 -0
- package/skills/api-design/references/conventions.md +133 -0
- package/skills/architecture-decision-records/SKILL.md +98 -0
- package/skills/architecture-decision-records/evals/triggers.json +17 -0
- package/skills/article-writing/SKILL.md +108 -0
- package/skills/article-writing/evals/triggers.json +16 -0
- package/skills/aspnet-core-patterns/SKILL.md +149 -0
- package/skills/aspnet-core-patterns/evals/triggers.json +16 -0
- package/skills/auth-patterns/SKILL.md +104 -0
- package/skills/auth-patterns/evals/triggers.json +17 -0
- package/skills/auth-patterns/references/oauth-oidc.md +64 -0
- package/skills/autonomous-loops/SKILL.md +99 -0
- package/skills/autonomous-loops/evals/triggers.json +14 -0
- package/skills/aws-patterns/SKILL.md +91 -0
- package/skills/aws-patterns/evals/triggers.json +16 -0
- package/skills/azure-patterns/SKILL.md +86 -0
- package/skills/azure-patterns/evals/triggers.json +16 -0
- package/skills/benchmark-methodology/SKILL.md +88 -0
- package/skills/benchmark-methodology/evals/triggers.json +16 -0
- package/skills/benchmark-methodology/references/language-harnesses.md +130 -0
- package/skills/bgp-diagnostics/SKILL.md +84 -0
- package/skills/bgp-diagnostics/evals/triggers.json +18 -0
- package/skills/bgp-diagnostics/references/bgp-reference.md +81 -0
- package/skills/bioinformatics-workflows/SKILL.md +108 -0
- package/skills/bioinformatics-workflows/evals/triggers.json +16 -0
- package/skills/bioinformatics-workflows/references/commands.md +71 -0
- package/skills/bioinformatics-workflows/references/formats.md +24 -0
- package/skills/bioinformatics-workflows/references/workflow-managers.md +107 -0
- package/skills/brand-voice/SKILL.md +112 -0
- package/skills/brand-voice/evals/triggers.json +16 -0
- package/skills/browser-qa/SKILL.md +99 -0
- package/skills/browser-qa/evals/triggers.json +16 -0
- package/skills/bun-runtime/SKILL.md +93 -0
- package/skills/bun-runtime/evals/triggers.json +16 -0
- package/skills/cisco-ios-config/SKILL.md +101 -0
- package/skills/cisco-ios-config/evals/triggers.json +18 -0
- package/skills/cisco-ios-config/references/verification.md +63 -0
- package/skills/clickhouse-patterns/SKILL.md +101 -0
- package/skills/clickhouse-patterns/evals/triggers.json +18 -0
- package/skills/clickhouse-patterns/references/engines-and-views.md +138 -0
- package/skills/clinical-decision-support/SKILL.md +90 -0
- package/skills/clinical-decision-support/evals/triggers.json +16 -0
- package/skills/clinical-decision-support/references/cds-hooks.md +76 -0
- package/skills/clinical-decision-support/references/regulatory-boundaries.md +37 -0
- package/skills/code-tour/SKILL.md +97 -0
- package/skills/code-tour/evals/triggers.json +14 -0
- package/skills/codebase-onboarding/SKILL.md +112 -0
- package/skills/codebase-onboarding/evals/triggers.json +14 -0
- package/skills/cold-outreach-sequences/SKILL.md +90 -0
- package/skills/cold-outreach-sequences/evals/triggers.json +16 -0
- package/skills/content-repurposing/SKILL.md +82 -0
- package/skills/content-repurposing/evals/triggers.json +16 -0
- package/skills/context-budget/SKILL.md +84 -0
- package/skills/context-budget/evals/triggers.json +14 -0
- package/skills/conventional-commits/SKILL.md +144 -0
- package/skills/conventional-commits/evals/triggers.json +16 -0
- package/skills/cpp-patterns/SKILL.md +129 -0
- package/skills/cpp-patterns/evals/triggers.json +16 -0
- package/skills/cpp-patterns/references/cmake-and-tooling.md +88 -0
- package/skills/cpp-patterns/references/undefined-behaviour.md +75 -0
- package/skills/cpp-testing/SKILL.md +131 -0
- package/skills/cpp-testing/evals/triggers.json +16 -0
- package/skills/csharp-patterns/SKILL.md +110 -0
- package/skills/csharp-patterns/evals/triggers.json +17 -0
- package/skills/csharp-patterns/references/analyzers.md +59 -0
- package/skills/csharp-testing/SKILL.md +85 -0
- package/skills/csharp-testing/evals/triggers.json +17 -0
- package/skills/csharp-testing/references/integration-tests.md +77 -0
- package/skills/css-architecture/SKILL.md +143 -0
- package/skills/css-architecture/evals/triggers.json +16 -0
- package/skills/customs-trade-compliance/SKILL.md +95 -0
- package/skills/customs-trade-compliance/evals/triggers.json +16 -0
- package/skills/customs-trade-compliance/references/incoterms-2020.md +42 -0
- package/skills/dart-patterns/SKILL.md +157 -0
- package/skills/dart-patterns/evals/triggers.json +18 -0
- package/skills/dart-testing/SKILL.md +164 -0
- package/skills/dart-testing/evals/triggers.json +18 -0
- package/skills/data-analysis-notebooks/SKILL.md +113 -0
- package/skills/data-analysis-notebooks/evals/triggers.json +16 -0
- package/skills/data-analysis-notebooks/references/dataframe-pitfalls.md +49 -0
- package/skills/data-analysis-notebooks/references/statistics-pitfalls.md +24 -0
- package/skills/data-pipelines/SKILL.md +90 -0
- package/skills/data-pipelines/evals/triggers.json +16 -0
- package/skills/data-pipelines/references/orchestrators.md +64 -0
- package/skills/database-migrations/SKILL.md +102 -0
- package/skills/database-migrations/evals/triggers.json +16 -0
- package/skills/database-migrations/references/recipes.md +98 -0
- package/skills/database-migrations/references/tools.md +21 -0
- package/skills/dbt-patterns/SKILL.md +96 -0
- package/skills/dbt-patterns/evals/triggers.json +16 -0
- package/skills/dbt-patterns/references/yaml-examples.md +114 -0
- package/skills/deep-research/SKILL.md +107 -0
- package/skills/deep-research/evals/triggers.json +14 -0
- package/skills/dependency-audit/SKILL.md +103 -0
- package/skills/dependency-audit/evals/triggers.json +16 -0
- package/skills/dependency-audit/references/tools.md +124 -0
- package/skills/deployment-strategies/SKILL.md +108 -0
- package/skills/deployment-strategies/evals/triggers.json +16 -0
- package/skills/django-patterns/SKILL.md +123 -0
- package/skills/django-patterns/evals/triggers.json +16 -0
- package/skills/docker-patterns/SKILL.md +132 -0
- package/skills/docker-patterns/evals/triggers.json +16 -0
- package/skills/docker-patterns/references/dockerfiles.md +105 -0
- package/skills/e2e-testing-playwright/SKILL.md +94 -0
- package/skills/e2e-testing-playwright/evals/triggers.json +16 -0
- package/skills/e2e-testing-playwright/references/config-and-ci.md +129 -0
- package/skills/ef-core-patterns/SKILL.md +117 -0
- package/skills/ef-core-patterns/evals/triggers.json +16 -0
- package/skills/email-deliverability/SKILL.md +99 -0
- package/skills/email-deliverability/evals/triggers.json +17 -0
- package/skills/email-deliverability/references/dns-records.md +85 -0
- package/skills/error-handling-patterns/SKILL.md +112 -0
- package/skills/error-handling-patterns/evals/triggers.json +18 -0
- package/skills/error-handling-patterns/references/language-idioms.md +49 -0
- package/skills/estimation-and-scoping/SKILL.md +97 -0
- package/skills/estimation-and-scoping/evals/triggers.json +14 -0
- package/skills/evm-dapp-integration/SKILL.md +73 -0
- package/skills/evm-dapp-integration/evals/triggers.json +16 -0
- package/skills/fastapi-patterns/SKILL.md +127 -0
- package/skills/fastapi-patterns/evals/triggers.json +16 -0
- package/skills/ffmpeg-media-processing/SKILL.md +94 -0
- package/skills/ffmpeg-media-processing/evals/triggers.json +16 -0
- package/skills/ffmpeg-media-processing/references/recipes.md +112 -0
- package/skills/fhir-integration/SKILL.md +81 -0
- package/skills/fhir-integration/evals/triggers.json +16 -0
- package/skills/fhir-integration/references/search-and-bundles.md +73 -0
- package/skills/fhir-integration/references/smart-on-fhir.md +50 -0
- package/skills/flask-patterns/SKILL.md +132 -0
- package/skills/flask-patterns/evals/triggers.json +16 -0
- package/skills/flutter-patterns/SKILL.md +99 -0
- package/skills/flutter-patterns/evals/triggers.json +16 -0
- package/skills/flutterwave-integration/SKILL.md +75 -0
- package/skills/flutterwave-integration/evals/triggers.json +16 -0
- package/skills/flutterwave-integration/references/api.md +73 -0
- package/skills/flutterwave-integration/references/webhooks.md +49 -0
- package/skills/fsharp-patterns/SKILL.md +133 -0
- package/skills/fsharp-patterns/evals/triggers.json +16 -0
- package/skills/fsharp-testing/SKILL.md +136 -0
- package/skills/fsharp-testing/evals/triggers.json +16 -0
- package/skills/gcp-patterns/SKILL.md +86 -0
- package/skills/gcp-patterns/evals/triggers.json +16 -0
- package/skills/git-workflow/SKILL.md +114 -0
- package/skills/git-workflow/evals/triggers.json +16 -0
- package/skills/github-actions-ci/SKILL.md +117 -0
- package/skills/github-actions-ci/evals/triggers.json +16 -0
- package/skills/github-api-automation/SKILL.md +101 -0
- package/skills/github-api-automation/evals/triggers.json +17 -0
- package/skills/go-patterns/SKILL.md +118 -0
- package/skills/go-patterns/evals/triggers.json +17 -0
- package/skills/go-patterns/references/concurrency.md +162 -0
- package/skills/go-testing/SKILL.md +154 -0
- package/skills/go-testing/evals/triggers.json +17 -0
- package/skills/hexagonal-architecture/SKILL.md +89 -0
- package/skills/hexagonal-architecture/evals/triggers.json +17 -0
- package/skills/hipaa-compliance/SKILL.md +91 -0
- package/skills/hipaa-compliance/evals/triggers.json +18 -0
- package/skills/hipaa-compliance/references/safeguards.md +68 -0
- package/skills/hl7v2-integration/SKILL.md +69 -0
- package/skills/hl7v2-integration/evals/triggers.json +16 -0
- package/skills/hl7v2-integration/references/messages-and-ack.md +78 -0
- package/skills/homelab-network-setup/SKILL.md +125 -0
- package/skills/homelab-network-setup/evals/triggers.json +18 -0
- package/skills/homelab-network-setup/references/firewall-and-dns.md +45 -0
- package/skills/homelab-network-setup/references/wireguard.md +72 -0
- package/skills/hubtel-integration/SKILL.md +77 -0
- package/skills/hubtel-integration/evals/triggers.json +16 -0
- package/skills/hubtel-integration/references/api.md +92 -0
- package/skills/i18n-localization/SKILL.md +114 -0
- package/skills/i18n-localization/evals/triggers.json +16 -0
- package/skills/i18n-localization/references/libraries.md +52 -0
- package/skills/incident-postmortem/SKILL.md +118 -0
- package/skills/incident-postmortem/evals/triggers.json +14 -0
- package/skills/inventory-demand-planning/SKILL.md +89 -0
- package/skills/inventory-demand-planning/evals/triggers.json +16 -0
- package/skills/inventory-demand-planning/references/formulas.md +62 -0
- package/skills/investor-materials/SKILL.md +127 -0
- package/skills/investor-materials/evals/triggers.json +16 -0
- package/skills/investor-materials/references/templates.md +74 -0
- package/skills/invoicing-and-tax/SKILL.md +84 -0
- package/skills/invoicing-and-tax/evals/triggers.json +17 -0
- package/skills/invoicing-and-tax/references/e-invoicing.md +24 -0
- package/skills/invoicing-and-tax/references/invoice-fields.md +38 -0
- package/skills/invoicing-and-tax/references/rounding.md +26 -0
- package/skills/java-patterns/SKILL.md +141 -0
- package/skills/java-patterns/evals/triggers.json +17 -0
- package/skills/java-testing/SKILL.md +142 -0
- package/skills/java-testing/evals/triggers.json +16 -0
- package/skills/jetpack-compose-patterns/SKILL.md +88 -0
- package/skills/jetpack-compose-patterns/evals/triggers.json +16 -0
- package/skills/jira-integration/SKILL.md +92 -0
- package/skills/jira-integration/evals/triggers.json +17 -0
- package/skills/jpa-hibernate/SKILL.md +92 -0
- package/skills/jpa-hibernate/evals/triggers.json +18 -0
- package/skills/jpa-hibernate/references/mapping.md +99 -0
- package/skills/kotlin-multiplatform/SKILL.md +97 -0
- package/skills/kotlin-multiplatform/evals/triggers.json +16 -0
- package/skills/kotlin-patterns/SKILL.md +128 -0
- package/skills/kotlin-patterns/evals/triggers.json +16 -0
- package/skills/kotlin-testing/SKILL.md +117 -0
- package/skills/kotlin-testing/evals/triggers.json +16 -0
- package/skills/ktor-patterns/SKILL.md +135 -0
- package/skills/ktor-patterns/evals/triggers.json +18 -0
- package/skills/kubernetes-patterns/SKILL.md +106 -0
- package/skills/kubernetes-patterns/evals/triggers.json +16 -0
- package/skills/kubernetes-patterns/references/manifests.md +115 -0
- package/skills/laravel-patterns/SKILL.md +136 -0
- package/skills/laravel-patterns/evals/triggers.json +16 -0
- package/skills/linear-integration/SKILL.md +98 -0
- package/skills/linear-integration/evals/triggers.json +17 -0
- package/skills/literature-review/SKILL.md +109 -0
- package/skills/literature-review/evals/triggers.json +16 -0
- package/skills/literature-review/references/appraisal.md +41 -0
- package/skills/literature-review/references/search-sources.md +39 -0
- package/skills/llm-app-patterns/SKILL.md +97 -0
- package/skills/llm-app-patterns/evals/triggers.json +17 -0
- package/skills/llm-evals/SKILL.md +98 -0
- package/skills/llm-evals/evals/triggers.json +16 -0
- package/skills/llm-evals/references/graders.md +66 -0
- package/skills/logistics-exception-management/SKILL.md +90 -0
- package/skills/logistics-exception-management/evals/triggers.json +16 -0
- package/skills/manim-animations/SKILL.md +106 -0
- package/skills/manim-animations/evals/triggers.json +16 -0
- package/skills/market-research/SKILL.md +117 -0
- package/skills/market-research/evals/triggers.json +16 -0
- package/skills/marketing-campaign/SKILL.md +111 -0
- package/skills/marketing-campaign/evals/triggers.json +16 -0
- package/skills/mcp-server-patterns/SKILL.md +127 -0
- package/skills/mcp-server-patterns/evals/triggers.json +18 -0
- package/skills/mcp-server-patterns/references/protocol-notes.md +68 -0
- package/skills/metrics-dashboards/SKILL.md +113 -0
- package/skills/metrics-dashboards/evals/triggers.json +16 -0
- package/skills/ml-experiment-workflow/SKILL.md +125 -0
- package/skills/ml-experiment-workflow/evals/triggers.json +16 -0
- package/skills/mongodb-patterns/SKILL.md +115 -0
- package/skills/mongodb-patterns/evals/triggers.json +18 -0
- package/skills/mongodb-patterns/references/indexes-and-aggregation.md +94 -0
- package/skills/mpesa-daraja-integration/SKILL.md +70 -0
- package/skills/mpesa-daraja-integration/evals/triggers.json +16 -0
- package/skills/mpesa-daraja-integration/references/api.md +103 -0
- package/skills/mpesa-daraja-integration/references/callbacks.md +74 -0
- package/skills/mtn-momo-integration/SKILL.md +66 -0
- package/skills/mtn-momo-integration/evals/triggers.json +16 -0
- package/skills/mtn-momo-integration/references/api.md +153 -0
- package/skills/mtn-momo-integration/references/callbacks.md +92 -0
- package/skills/mtn-momo-integration/references/sandbox-and-go-live.md +51 -0
- package/skills/mtn-momo-integration/scripts/sandbox-setup.js +79 -0
- package/skills/mysql-patterns/SKILL.md +96 -0
- package/skills/mysql-patterns/evals/triggers.json +16 -0
- package/skills/mysql-patterns/references/explain.md +34 -0
- package/skills/mysql-patterns/references/online-ddl.md +41 -0
- package/skills/nestjs-patterns/SKILL.md +114 -0
- package/skills/nestjs-patterns/evals/triggers.json +16 -0
- package/skills/nestjs-patterns/references/testing.md +68 -0
- package/skills/network-automation/SKILL.md +107 -0
- package/skills/network-automation/evals/triggers.json +18 -0
- package/skills/network-automation/references/tool-snippets.md +153 -0
- package/skills/network-troubleshooting/SKILL.md +152 -0
- package/skills/network-troubleshooting/evals/triggers.json +18 -0
- package/skills/network-troubleshooting/references/commands.md +33 -0
- package/skills/nextjs-patterns/SKILL.md +150 -0
- package/skills/nextjs-patterns/evals/triggers.json +18 -0
- package/skills/nextjs-patterns/references/caching.md +87 -0
- package/skills/node-backend-patterns/SKILL.md +103 -0
- package/skills/node-backend-patterns/evals/triggers.json +16 -0
- package/skills/node-backend-patterns/references/templates.md +122 -0
- package/skills/nuxt-patterns/SKILL.md +103 -0
- package/skills/nuxt-patterns/evals/triggers.json +16 -0
- package/skills/parallel-agent-orchestration/SKILL.md +106 -0
- package/skills/parallel-agent-orchestration/evals/triggers.json +14 -0
- package/skills/paystack-integration/SKILL.md +59 -0
- package/skills/paystack-integration/evals/triggers.json +14 -0
- package/skills/paystack-integration/references/api.md +73 -0
- package/skills/paystack-integration/references/mobile-money.md +50 -0
- package/skills/paystack-integration/references/webhooks.md +80 -0
- package/skills/pci-dss-scope/SKILL.md +103 -0
- package/skills/pci-dss-scope/evals/triggers.json +18 -0
- package/skills/pci-dss-scope/references/saq-and-data.md +36 -0
- package/skills/perl-patterns/SKILL.md +135 -0
- package/skills/perl-patterns/evals/triggers.json +18 -0
- package/skills/perl-testing/SKILL.md +126 -0
- package/skills/perl-testing/evals/triggers.json +17 -0
- package/skills/php-patterns/SKILL.md +116 -0
- package/skills/php-patterns/evals/triggers.json +16 -0
- package/skills/php-testing/SKILL.md +123 -0
- package/skills/php-testing/evals/triggers.json +16 -0
- package/skills/postgres-patterns/SKILL.md +103 -0
- package/skills/postgres-patterns/evals/triggers.json +17 -0
- package/skills/postgres-patterns/references/explain.md +59 -0
- package/skills/postgres-patterns/references/locks.md +53 -0
- package/skills/prd-writing/SKILL.md +124 -0
- package/skills/prd-writing/evals/triggers.json +15 -0
- package/skills/prisma-patterns/SKILL.md +83 -0
- package/skills/prisma-patterns/evals/triggers.json +18 -0
- package/skills/prisma-patterns/references/prisma-8.md +46 -0
- package/skills/prisma-patterns/references/workflow.md +50 -0
- package/skills/privacy-compliance/SKILL.md +121 -0
- package/skills/privacy-compliance/evals/triggers.json +18 -0
- package/skills/privacy-compliance/references/jurisdictions.md +51 -0
- package/skills/production-scheduling/SKILL.md +98 -0
- package/skills/production-scheduling/evals/triggers.json +16 -0
- package/skills/prompt-engineering/SKILL.md +92 -0
- package/skills/prompt-engineering/evals/triggers.json +16 -0
- package/skills/python-patterns/SKILL.md +107 -0
- package/skills/python-patterns/evals/triggers.json +16 -0
- package/skills/python-patterns/references/tooling.md +101 -0
- package/skills/python-testing/SKILL.md +126 -0
- package/skills/python-testing/evals/triggers.json +16 -0
- package/skills/python-testing/references/mocking.md +71 -0
- package/skills/pytorch-patterns/SKILL.md +139 -0
- package/skills/pytorch-patterns/evals/triggers.json +16 -0
- package/skills/pytorch-patterns/references/debugging.md +39 -0
- package/skills/quarkus-patterns/SKILL.md +93 -0
- package/skills/quarkus-patterns/evals/triggers.json +18 -0
- package/skills/rag-pipeline-patterns/SKILL.md +117 -0
- package/skills/rag-pipeline-patterns/evals/triggers.json +18 -0
- package/skills/rag-pipeline-patterns/references/evaluation.md +37 -0
- package/skills/rag-pipeline-patterns/references/retrieval-recipes.md +78 -0
- package/skills/rails-patterns/SKILL.md +132 -0
- package/skills/rails-patterns/evals/triggers.json +16 -0
- package/skills/react-native-patterns/SKILL.md +101 -0
- package/skills/react-native-patterns/evals/triggers.json +16 -0
- package/skills/react-patterns/SKILL.md +140 -0
- package/skills/react-patterns/evals/triggers.json +18 -0
- package/skills/react-performance/SKILL.md +107 -0
- package/skills/react-performance/evals/triggers.json +18 -0
- package/skills/redis-patterns/SKILL.md +109 -0
- package/skills/redis-patterns/evals/triggers.json +18 -0
- package/skills/redis-patterns/references/operations.md +61 -0
- package/skills/refactoring-safely/SKILL.md +107 -0
- package/skills/refactoring-safely/evals/triggers.json +17 -0
- package/skills/release-management/SKILL.md +141 -0
- package/skills/release-management/evals/triggers.json +16 -0
- package/skills/remotion-video/SKILL.md +91 -0
- package/skills/remotion-video/evals/triggers.json +16 -0
- package/skills/remotion-video/references/lambda.md +66 -0
- package/skills/returns-reverse-logistics/SKILL.md +97 -0
- package/skills/returns-reverse-logistics/evals/triggers.json +16 -0
- package/skills/ruby-patterns/SKILL.md +127 -0
- package/skills/ruby-patterns/evals/triggers.json +18 -0
- package/skills/ruby-testing/SKILL.md +113 -0
- package/skills/ruby-testing/evals/triggers.json +18 -0
- package/skills/runbook-writing/SKILL.md +101 -0
- package/skills/runbook-writing/evals/triggers.json +14 -0
- package/skills/rust-patterns/SKILL.md +118 -0
- package/skills/rust-patterns/evals/triggers.json +16 -0
- package/skills/rust-patterns/references/cargo-and-clippy.md +105 -0
- package/skills/rust-patterns/references/errors-and-traits.md +97 -0
- package/skills/rust-testing/SKILL.md +148 -0
- package/skills/rust-testing/evals/triggers.json +16 -0
- package/skills/rust-testing/references/fakes-proptest-async.md +113 -0
- package/skills/search-first/SKILL.md +73 -0
- package/skills/search-first/evals/triggers.json +14 -0
- package/skills/security-review/SKILL.md +58 -0
- package/skills/security-review/evals/triggers.json +14 -0
- package/skills/security-review/references/checklist.md +54 -0
- package/skills/security-review/scripts/scan-secrets.js +79 -0
- package/skills/seo-audit/SKILL.md +111 -0
- package/skills/seo-audit/evals/triggers.json +16 -0
- package/skills/seo-audit/references/checks.md +65 -0
- package/skills/session-handoff/SKILL.md +101 -0
- package/skills/session-handoff/evals/triggers.json +14 -0
- package/skills/skill-authoring/SKILL.md +87 -0
- package/skills/skill-authoring/evals/triggers.json +14 -0
- package/skills/skill-authoring/references/frontmatter.md +40 -0
- package/skills/slack-app-integration/SKILL.md +108 -0
- package/skills/slack-app-integration/evals/triggers.json +17 -0
- package/skills/smart-contract-security/SKILL.md +110 -0
- package/skills/smart-contract-security/evals/triggers.json +16 -0
- package/skills/smart-contract-security/references/vulnerability-checklist.md +79 -0
- package/skills/social-media-publishing/SKILL.md +84 -0
- package/skills/social-media-publishing/evals/triggers.json +17 -0
- package/skills/social-media-publishing/references/platform-apis.md +116 -0
- package/skills/solidity-patterns/SKILL.md +95 -0
- package/skills/solidity-patterns/evals/triggers.json +16 -0
- package/skills/spring-boot-patterns/SKILL.md +128 -0
- package/skills/spring-boot-patterns/evals/triggers.json +18 -0
- package/skills/spring-boot-patterns/references/testing.md +72 -0
- package/skills/stripe-integration/SKILL.md +69 -0
- package/skills/stripe-integration/evals/triggers.json +16 -0
- package/skills/stripe-integration/references/api.md +71 -0
- package/skills/stripe-integration/references/billing.md +58 -0
- package/skills/stripe-integration/references/webhooks.md +76 -0
- package/skills/subscription-billing-ops/SKILL.md +118 -0
- package/skills/subscription-billing-ops/evals/triggers.json +17 -0
- package/skills/subscription-billing-ops/references/proration.md +47 -0
- package/skills/subscription-billing-ops/references/revenue-metrics.md +38 -0
- package/skills/svelte-patterns/SKILL.md +122 -0
- package/skills/svelte-patterns/evals/triggers.json +16 -0
- package/skills/swift-patterns/SKILL.md +113 -0
- package/skills/swift-patterns/evals/triggers.json +16 -0
- package/skills/swift-patterns/references/concurrency-migration.md +40 -0
- package/skills/swift-testing/SKILL.md +121 -0
- package/skills/swift-testing/evals/triggers.json +16 -0
- package/skills/swift-testing/references/swift-testing-cheatsheet.md +81 -0
- package/skills/swiftui-patterns/SKILL.md +102 -0
- package/skills/swiftui-patterns/evals/triggers.json +16 -0
- package/skills/tdd-workflow/SKILL.md +67 -0
- package/skills/tdd-workflow/evals/triggers.json +14 -0
- package/skills/technical-writing/SKILL.md +95 -0
- package/skills/technical-writing/evals/triggers.json +14 -0
- package/skills/terraform-patterns/SKILL.md +122 -0
- package/skills/terraform-patterns/evals/triggers.json +16 -0
- package/skills/terraform-patterns/references/backends.md +67 -0
- package/skills/test-coverage-improvement/SKILL.md +107 -0
- package/skills/test-coverage-improvement/evals/triggers.json +16 -0
- package/skills/threat-modeling/SKILL.md +113 -0
- package/skills/threat-modeling/evals/triggers.json +16 -0
- package/skills/typescript-patterns/SKILL.md +122 -0
- package/skills/typescript-patterns/evals/triggers.json +16 -0
- package/skills/typescript-testing/SKILL.md +101 -0
- package/skills/typescript-testing/evals/triggers.json +16 -0
- package/skills/verification-loop/SKILL.md +70 -0
- package/skills/verification-loop/evals/triggers.json +14 -0
- package/skills/verification-loop/scripts/detect-checks.js +102 -0
- package/skills/vite-patterns/SKILL.md +117 -0
- package/skills/vite-patterns/evals/triggers.json +16 -0
- package/skills/vue-patterns/SKILL.md +104 -0
- package/skills/vue-patterns/evals/triggers.json +16 -0
- package/skills/web-accessibility/SKILL.md +119 -0
- package/skills/web-accessibility/evals/triggers.json +16 -0
- package/skills/web-performance/SKILL.md +107 -0
- package/skills/web-performance/evals/triggers.json +16 -0
- package/skills/web-scraping/SKILL.md +80 -0
- package/skills/web-scraping/evals/triggers.json +16 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architecture-decision-records
|
|
3
|
+
description: Writes and maintains Architecture Decision Records (ADRs), deciding whether a choice deserves one, filling a short template (Nygard sections plus options considered) with context, the options weighed, the decision and its consequences, numbering and storing it next to the code, and superseding old records instead of rewriting them. Use when the user wants to record or document a technical decision, start an ADR log in a repo, or update the status of an earlier decision.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Writes Markdown files; git is optional.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: docs
|
|
9
|
+
kete-loom/risk: writes-files
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Architecture decision records
|
|
14
|
+
|
|
15
|
+
An ADR captures one decision, the reason for it, and what it costs, so a future reader can tell whether the reason still holds. It is short, dated and never silently edited.
|
|
16
|
+
|
|
17
|
+
## Does this need an ADR?
|
|
18
|
+
|
|
19
|
+
Write one when the decision is **hard to reverse, affects more than one module or team, or someone will later ask "why did we do it this way?"** Examples: choosing a database, message broker, auth provider, framework, API style, deployment model; adopting or dropping an architectural pattern; a deliberate trade-off against a stated quality (accepting eventual consistency, skipping multi-region).
|
|
20
|
+
|
|
21
|
+
Don't write one for: library patch upgrades, naming, formatting, decisions fully captured by a ticket, or anything trivially reversible. Say so and stop.
|
|
22
|
+
|
|
23
|
+
## Steps
|
|
24
|
+
|
|
25
|
+
1. **Find the log.** Search the repo for an existing ADR directory: `docs/adr/`, `doc/adr/` (the adr-tools default), `docs/decisions/`, `doc/architecture/decisions/`, `adr/`, or an `.adr-dir` file (adr-tools stores the chosen directory there). Use it and its template and numbering exactly. If none exists, propose `docs/adr/` and create `0001-record-architecture-decisions.md` first, then the user's ADR.
|
|
26
|
+
2. **Gather the facts.** You need: the problem and forces (constraints, requirements, deadlines), at least two real options (including "do nothing" when plausible), the chosen option, and who decided. **Stop and ask the user** for anything missing. Never invent the reasons, the alternatives considered or the people involved.
|
|
27
|
+
3. **Number and name.** Next free four-digit number, kebab-case title stating the decision: `0007-use-postgres-for-event-store.md`. Numbers are never reused.
|
|
28
|
+
4. **Write it** with the template below. Keep it to one or two screens. Link to longer analysis rather than pasting it.
|
|
29
|
+
5. **Set the status** (see lifecycle). New records start as `Proposed` unless the user says the decision is made.
|
|
30
|
+
6. **Supersede, don't rewrite.** When a decision changes, write a new ADR, set the old one's status to `Superseded by ADR-00NN` and add `Supersedes ADR-00MM` to the new one. Only typo fixes and status lines change in accepted ADRs.
|
|
31
|
+
7. **Index.** If the log has a README or index listing ADRs, add the new line.
|
|
32
|
+
|
|
33
|
+
## Template
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
# ADR-0007: Use Postgres for the event store
|
|
37
|
+
|
|
38
|
+
- Status: Proposed | Accepted | Rejected | Deprecated | Superseded by ADR-00NN
|
|
39
|
+
- Date: 2026-03-01
|
|
40
|
+
- Deciders: names or roles
|
|
41
|
+
- Supersedes: ADR-00MM (if any)
|
|
42
|
+
|
|
43
|
+
## Context
|
|
44
|
+
|
|
45
|
+
What problem forces a decision now. Constraints, requirements, quality
|
|
46
|
+
attributes that matter (cost, latency, team skills, compliance). Facts, not
|
|
47
|
+
the conclusion.
|
|
48
|
+
|
|
49
|
+
## Options considered
|
|
50
|
+
|
|
51
|
+
1. **Postgres with an append-only events table**: pros, cons.
|
|
52
|
+
2. **EventStoreDB**: pros, cons.
|
|
53
|
+
3. **Kafka as the system of record**: pros, cons.
|
|
54
|
+
|
|
55
|
+
## Decision
|
|
56
|
+
|
|
57
|
+
We will use option 1 because <the deciding reasons, tied to the context>.
|
|
58
|
+
|
|
59
|
+
## Consequences
|
|
60
|
+
|
|
61
|
+
- Positive: what gets easier.
|
|
62
|
+
- Negative: what gets harder or what we accept (the trade-off, stated plainly).
|
|
63
|
+
- Follow-ups: work this creates, and the signal that would make us revisit it.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Status lifecycle
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Proposed ──▶ Accepted ──▶ Deprecated
|
|
70
|
+
│ └──────▶ Superseded by ADR-NNNN
|
|
71
|
+
└──▶ Rejected
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- `Proposed`: under discussion, usually in a pull request.
|
|
75
|
+
- `Accepted`: merged and in force.
|
|
76
|
+
- `Rejected`: kept on purpose, so the option isn't re-litigated without new facts.
|
|
77
|
+
- `Deprecated`: no longer relevant (the system it governed is gone).
|
|
78
|
+
- `Superseded`: replaced by a newer ADR, linked both ways.
|
|
79
|
+
|
|
80
|
+
## Where to store them
|
|
81
|
+
|
|
82
|
+
- In the repo of the code they govern, as Markdown, reviewed in pull requests like code. Cross-cutting decisions go in a shared architecture repo, linked from each affected repo.
|
|
83
|
+
- If the team uses a tool (adr-tools, Log4brains), follow its file layout and commands instead of hand-numbering.
|
|
84
|
+
|
|
85
|
+
## Writing rules
|
|
86
|
+
|
|
87
|
+
- One decision per ADR. If you need "and" in the title, split it.
|
|
88
|
+
- The Consequences section must include at least one negative. A decision with no cost wasn't a decision.
|
|
89
|
+
- Write the context so a new hire understands it without the meeting.
|
|
90
|
+
- Dates are absolute (`2026-03-01`), never "last sprint".
|
|
91
|
+
|
|
92
|
+
## Report back
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
ADR: path/to/NNNN-title.md (status)
|
|
96
|
+
Updated: older ADRs whose status changed, index file
|
|
97
|
+
Missing facts: anything you left as a question for the user
|
|
98
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Write an ADR for our decision to move from RabbitMQ to Kafka",
|
|
4
|
+
"We agreed in the meeting to use Keycloak for auth, can you document that decision in the repo?",
|
|
5
|
+
"Set up an architecture decision log in this repo with the first record",
|
|
6
|
+
"ADR 0004 is outdated since we switched to DynamoDB, mark it superseded and write the new one",
|
|
7
|
+
"Record why we chose server-side rendering over a SPA so future devs understand it"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Should we use RabbitMQ or Kafka for order events? Weigh the options and recommend one",
|
|
11
|
+
"Write a README section explaining how to run the project locally",
|
|
12
|
+
"Draft the changelog and release notes for version 2.3.0",
|
|
13
|
+
"Design the pagination and versioning scheme for the public API",
|
|
14
|
+
"Write a commit message for these staged changes",
|
|
15
|
+
"Turn this feature request into a step-by-step implementation plan"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: article-writing
|
|
3
|
+
description: Long-form article and blog post writing, from choosing a sharp angle and outlining, through gathering evidence and drafting in plain prose, to a structured editing pass and a final headline, summary and meta description. Use when someone wants a blog post, essay, opinion piece, case study, newsletter feature or company announcement of roughly 800 words or more written, restructured or edited for clarity.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Web access helps when the article needs facts checked; otherwise works from the user's material.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: business
|
|
9
|
+
kete-loom/risk: read-only
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Article writing
|
|
14
|
+
|
|
15
|
+
Write a piece a busy reader finishes and remembers. One reader, one point, evidence for it, plain words.
|
|
16
|
+
|
|
17
|
+
## 0. Brief
|
|
18
|
+
|
|
19
|
+
Ask for what is missing, in one message:
|
|
20
|
+
|
|
21
|
+
1. **Reader**: who they are and what they already know.
|
|
22
|
+
2. **Purpose**: what the reader should think, feel or do afterwards.
|
|
23
|
+
3. **Format and length**: blog post, essay, case study, announcement; target word count.
|
|
24
|
+
4. **Where it runs**: company blog, newsletter, publication (and their style rules).
|
|
25
|
+
5. **Material**: notes, data, interviews, links, drafts, and the author's own experience.
|
|
26
|
+
6. **Voice**: a brand voice guide if one exists (apply it; the `brand-voice` skill covers defining one).
|
|
27
|
+
|
|
28
|
+
If the user says "just write it", state your assumptions in two lines at the top of the draft and proceed.
|
|
29
|
+
|
|
30
|
+
## 1. Angle
|
|
31
|
+
|
|
32
|
+
- Write the **one-sentence point** of the article. If you cannot, the topic is too broad; offer two or three sharper angles and let the user pick.
|
|
33
|
+
- Good angles are specific and arguable: "Why we stopped offering a free plan" beats "Thoughts on pricing".
|
|
34
|
+
- Check the angle against the reader: why would they care now?
|
|
35
|
+
|
|
36
|
+
## 2. Outline
|
|
37
|
+
|
|
38
|
+
Before drafting, show the user a short outline:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Working headline:
|
|
42
|
+
Point (one sentence):
|
|
43
|
+
Opening: <the hook: a scene, a surprising fact, a problem the reader has>
|
|
44
|
+
Section 1: <claim> - evidence:
|
|
45
|
+
Section 2: <claim> - evidence:
|
|
46
|
+
Section 3: <claim> - evidence:
|
|
47
|
+
Close: <what to do or think next>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Three to five sections is typical. Each section makes one claim that supports the point. For long or high-stakes pieces, **stop and get agreement** on the outline before drafting.
|
|
51
|
+
|
|
52
|
+
## 3. Evidence
|
|
53
|
+
|
|
54
|
+
- Back each claim with something concrete: data, an example, a quote, a story from the author's experience, a demo or code.
|
|
55
|
+
- Attribute facts and link to the source. Prefer primary sources.
|
|
56
|
+
- If a fact cannot be verified, cut it or flag it to the user as `[CHECK: ...]`. Never invent statistics, quotes, studies or customer stories.
|
|
57
|
+
- Mark the author's opinions as opinions.
|
|
58
|
+
|
|
59
|
+
## 4. Draft
|
|
60
|
+
|
|
61
|
+
- Open with the hook and state the point within the first few paragraphs. No throat-clearing ("In today's fast-paced world...").
|
|
62
|
+
- One idea per paragraph. Topic sentence first.
|
|
63
|
+
- Short, common words. Active voice. Concrete nouns and verbs.
|
|
64
|
+
- Subheadings that say something ("Free users cost us 30% of support time"), not labels ("Background").
|
|
65
|
+
- Explain jargon the reader may not know, or remove it.
|
|
66
|
+
- Use lists for steps or parallel items, prose for argument.
|
|
67
|
+
- End with a close that pays off the opening: a takeaway, a next step or a call to action. Do not just summarise.
|
|
68
|
+
|
|
69
|
+
## 5. Editing pass
|
|
70
|
+
|
|
71
|
+
Go through the draft in this order, one pass per item:
|
|
72
|
+
|
|
73
|
+
1. **Structure**: does every section support the point? Cut or move what doesn't.
|
|
74
|
+
2. **Opening**: would the reader keep going after three sentences?
|
|
75
|
+
3. **Cut**: remove repetition, filler (very, really, just, actually), hedges that add nothing, and sentences that restate the previous one. Aim to cut 10-20%.
|
|
76
|
+
4. **Clarity**: split sentences over about 25 words; replace abstractions with examples.
|
|
77
|
+
5. **Accuracy**: every number, name, quote and link checked against its source.
|
|
78
|
+
6. **Consistency**: terms, capitalisation, spelling variant (US or UK) and voice.
|
|
79
|
+
7. **Read aloud** test: flag anything awkward.
|
|
80
|
+
|
|
81
|
+
## 6. Headline, summary and metadata
|
|
82
|
+
|
|
83
|
+
- Offer three to five headline options: specific, honest, ideally with the benefit or the surprise. No clickbait the article does not deliver.
|
|
84
|
+
- A one- or two-sentence summary (standfirst or dek).
|
|
85
|
+
- A meta description for the web, and a suggested URL slug. Google sets no fixed length and truncates by display width, so keep the key point in the first 120 characters or so; about 150-160 characters is a common convention, not a rule.
|
|
86
|
+
- If the piece targets search, use the phrase readers would search for in the headline or first paragraph naturally; do not stuff keywords.
|
|
87
|
+
|
|
88
|
+
## Rules
|
|
89
|
+
|
|
90
|
+
- Never fabricate facts, quotes, sources or anecdotes, and never present the author as having done something they did not tell you about.
|
|
91
|
+
- Do not copy text from sources; quote briefly with attribution or paraphrase.
|
|
92
|
+
- Keep the author's voice when editing their draft; fix problems, do not rewrite their personality away.
|
|
93
|
+
- For technical docs (API references, READMEs, how-to guides inside a product) use the `technical-writing` skill instead.
|
|
94
|
+
|
|
95
|
+
## Output
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
# <Headline>
|
|
99
|
+
<Summary / standfirst>
|
|
100
|
+
|
|
101
|
+
<Article body>
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
Headline options: 1. ... 2. ... 3. ...
|
|
105
|
+
Meta description: <...> Slug: <...>
|
|
106
|
+
Word count: <n>
|
|
107
|
+
To check: <list of [CHECK] items and sources to confirm>
|
|
108
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Write a 1500-word blog post on why we rebuilt our checkout around mobile money",
|
|
4
|
+
"Here's my messy draft about remote hiring. Can you restructure and tighten it into a proper article?",
|
|
5
|
+
"I want an opinion piece arguing that small startups should skip microservices. Give me an angle and outline first.",
|
|
6
|
+
"Turn these interview notes into a customer case study for our blog",
|
|
7
|
+
"Give me a few headline options and a meta description for this finished essay"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Write the README and API reference for our Node SDK",
|
|
11
|
+
"Create a style guide describing our brand personality with do and don't examples",
|
|
12
|
+
"Write a short commit message for these staged changes",
|
|
13
|
+
"Plan the content calendar and paid budget for next quarter's campaign",
|
|
14
|
+
"Audit our blog for crawl and indexing problems"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aspnet-core-patterns
|
|
3
|
+
description: ASP.NET Core web API and app hosting decisions - choosing minimal APIs or controllers, ordering the middleware pipeline, picking singleton, scoped or transient lifetimes without captive dependencies, binding and validating settings with the options pattern, request validation, JWT or cookie authentication with policy-based authorization, RFC 7807 problem details for errors, and liveness and readiness health checks. Use when building or reviewing an ASP.NET Core service, wiring Program.cs, debugging a 401, 500 or middleware-order bug, or adding auth, validation or health endpoints to a .NET web app.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs the .NET SDK (dotnet CLI). Written for .NET 8 and later; .NET 10-only features are marked.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: runs-commands
|
|
10
|
+
kete-loom/requires: "dotnet"
|
|
11
|
+
kete-loom/owner: "Kete-org"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# ASP.NET Core patterns
|
|
15
|
+
|
|
16
|
+
Wire the host so requests flow through the right middleware, services live as long as they should, and every error comes back in one shape. For C# language style follow `csharp-patterns`; for xUnit and `WebApplicationFactory` tests follow `csharp-testing`; for the data layer follow `ef-core-patterns`.
|
|
17
|
+
|
|
18
|
+
## 0. Before you change anything
|
|
19
|
+
|
|
20
|
+
1. Read the `.csproj` `TargetFramework` and `Program.cs`. Match the project's style (minimal APIs or controllers, `TypedResults` or `IActionResult`).
|
|
21
|
+
2. Run `dotnet build` and `dotnet test`. If either fails before you start, **stop and tell the user**.
|
|
22
|
+
|
|
23
|
+
## 1. Minimal APIs or controllers
|
|
24
|
+
|
|
25
|
+
| Choose | When |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Minimal APIs | New services, small to medium APIs, you want `TypedResults` and route groups |
|
|
28
|
+
| Controllers | The project already uses them, or you need filters, model binding conventions or OData-style features built around `ControllerBase` |
|
|
29
|
+
|
|
30
|
+
Don't mix both in one feature area. For minimal APIs:
|
|
31
|
+
|
|
32
|
+
- Group routes: `var orders = app.MapGroup("/orders").RequireAuthorization();`
|
|
33
|
+
- Keep handlers short; move them into static methods or a class per feature (`OrderEndpoints.Map(app)`), not one giant `Program.cs`.
|
|
34
|
+
- Return `TypedResults` with a `Results<Ok<OrderDto>, NotFound>` return type so OpenAPI and tests see every outcome.
|
|
35
|
+
- Accept `CancellationToken` in handlers and pass it to every async call.
|
|
36
|
+
|
|
37
|
+
## 2. Middleware order
|
|
38
|
+
|
|
39
|
+
Order matters; the request passes top to bottom and the response bottom to top. The usual order:
|
|
40
|
+
|
|
41
|
+
```csharp
|
|
42
|
+
app.UseExceptionHandler(); // first, so it catches everything below
|
|
43
|
+
if (!app.Environment.IsDevelopment()) app.UseHsts();
|
|
44
|
+
app.UseHttpsRedirection();
|
|
45
|
+
app.UseStaticFiles(); // or app.MapStaticAssets() on .NET 9+
|
|
46
|
+
app.UseRouting(); // implicit if omitted; explicit when order matters
|
|
47
|
+
app.UseCors(); // after routing, before auth
|
|
48
|
+
app.UseAuthentication();
|
|
49
|
+
app.UseAuthorization();
|
|
50
|
+
app.UseRateLimiter(); // after routing when using endpoint-specific policies
|
|
51
|
+
// custom middleware that needs the user goes here
|
|
52
|
+
app.MapControllers(); // or Map... endpoints
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Symptoms of a wrong order: CORS preflight failing with 401 (auth before CORS), `[Authorize]` ignored or `User` empty (auth after endpoints, or authentication missing), errors returning HTML or empty 500s (exception handler not first).
|
|
56
|
+
|
|
57
|
+
## 3. DI lifetimes
|
|
58
|
+
|
|
59
|
+
| Lifetime | Use for | Never |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Singleton | Stateless, thread-safe services, caches, `HttpClient` handlers via factory | Inject a scoped service (captive dependency) |
|
|
62
|
+
| Scoped | One per request: `DbContext`, unit of work, current-user accessors | Resolve from the root provider or a singleton |
|
|
63
|
+
| Transient | Lightweight, stateless helpers | Hold expensive resources |
|
|
64
|
+
|
|
65
|
+
- Keep `ValidateScopes` and `ValidateOnBuild` on (default in Development) so captive dependencies fail at startup.
|
|
66
|
+
- `BackgroundService` and other singletons that need scoped services create a scope: `using var scope = scopeFactory.CreateScope();`.
|
|
67
|
+
- HTTP clients: `builder.Services.AddHttpClient<PaymentsClient>(c => c.BaseAddress = ...)`. Never `new HttpClient()` per call.
|
|
68
|
+
- Prefer constructor injection. Don't inject `IServiceProvider` to resolve things manually.
|
|
69
|
+
|
|
70
|
+
## 4. Options pattern
|
|
71
|
+
|
|
72
|
+
```csharp
|
|
73
|
+
builder.Services.AddOptions<SmtpOptions>()
|
|
74
|
+
.Bind(builder.Configuration.GetSection("Smtp"))
|
|
75
|
+
.ValidateDataAnnotations()
|
|
76
|
+
.ValidateOnStart();
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `IOptions<T>`: read once, singleton-safe. `IOptionsSnapshot<T>`: re-read per request (scoped). `IOptionsMonitor<T>`: change notifications, singleton-safe.
|
|
80
|
+
- `ValidateOnStart()` makes a missing setting fail at boot, not on the first request.
|
|
81
|
+
- Secrets: user-secrets (`dotnet user-secrets set "Smtp:Password" ...`) in development, environment variables or a vault provider in production. Never in `appsettings.json` committed to git.
|
|
82
|
+
- Environment variable form of `Smtp:Password` is `Smtp__Password`.
|
|
83
|
+
|
|
84
|
+
## 5. Validation
|
|
85
|
+
|
|
86
|
+
- Controllers with `[ApiController]` return a 400 `ValidationProblemDetails` automatically when DataAnnotations fail.
|
|
87
|
+
- Minimal APIs on .NET 10: `builder.Services.AddValidation();` validates DataAnnotations on query, header and body parameters and returns 400 problem details; opt out per endpoint with `.DisableValidation()`.
|
|
88
|
+
- Minimal APIs before .NET 10: validate in an endpoint filter or with the FluentValidation library the project already uses, and return `TypedResults.ValidationProblem(errors)`.
|
|
89
|
+
- Validate business rules (stock, ownership, state transitions) in the domain or handler, not only with attributes.
|
|
90
|
+
|
|
91
|
+
## 6. Authentication and authorization
|
|
92
|
+
|
|
93
|
+
```csharp
|
|
94
|
+
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
95
|
+
.AddJwtBearer(o => { o.Authority = ...; o.Audience = ...; });
|
|
96
|
+
builder.Services.AddAuthorizationBuilder()
|
|
97
|
+
.AddPolicy("orders:write", p => p.RequireClaim("scope", "orders:write"))
|
|
98
|
+
.SetFallbackPolicy(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
- A fallback policy makes endpoints secure by default; mark public ones with `.AllowAnonymous()` / `[AllowAnonymous]`.
|
|
102
|
+
- Use named policies (`.RequireAuthorization("orders:write")`), not role strings scattered across handlers.
|
|
103
|
+
- Resource checks (does this user own order 42?) use `IAuthorizationService.AuthorizeAsync(User, order, "OwnerPolicy")` or a query scoped to the user. Return 404 when revealing existence would leak data.
|
|
104
|
+
- Cookie auth for browser apps needs antiforgery on form posts; JWT APIs don't use cookies.
|
|
105
|
+
- Never disable `ValidateIssuer`, `ValidateAudience` or `ValidateLifetime` to "make it work".
|
|
106
|
+
|
|
107
|
+
## 7. Problem details for every error
|
|
108
|
+
|
|
109
|
+
```csharp
|
|
110
|
+
builder.Services.AddProblemDetails();
|
|
111
|
+
app.UseExceptionHandler();
|
|
112
|
+
app.UseStatusCodePages();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- `UseExceptionHandler()` with no arguments throws at startup unless `AddProblemDetails()` or an `IExceptionHandler` is registered.
|
|
116
|
+
- Unhandled exceptions become `application/problem+json` 500s without stack traces outside Development.
|
|
117
|
+
- Expected failures return `TypedResults.Problem(...)` / `ValidationProblem(...)` or `Problem()` in controllers with a stable `type` and `title`.
|
|
118
|
+
- For custom mapping (domain exception to 409), implement `IExceptionHandler` and register with `AddExceptionHandler<T>()`.
|
|
119
|
+
- Log the exception once, in the handler, with the trace id; return the trace id, not the message, to the client.
|
|
120
|
+
|
|
121
|
+
## 8. Health checks
|
|
122
|
+
|
|
123
|
+
```csharp
|
|
124
|
+
builder.Services.AddHealthChecks()
|
|
125
|
+
.AddCheck("self", () => HealthCheckResult.Healthy(), tags: ["live"])
|
|
126
|
+
.AddDbContextCheck<AppDbContext>(tags: ["ready"]); // Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
|
|
127
|
+
app.MapHealthChecks("/health/live", new() { Predicate = r => r.Tags.Contains("live") });
|
|
128
|
+
app.MapHealthChecks("/health/ready", new() { Predicate = r => r.Tags.Contains("ready") });
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- Liveness checks only the process; readiness checks dependencies. A database outage must not make the orchestrator restart every pod.
|
|
132
|
+
- A fallback authorization policy also applies to `MapHealthChecks`, so probes start getting 401. Add `.AllowAnonymous()` to the health endpoints (or restrict them by host/port with `RequireHost`), and keep them cheap and free of secrets.
|
|
133
|
+
|
|
134
|
+
## Stop and ask the user
|
|
135
|
+
|
|
136
|
+
- Before changing the authentication scheme, token validation parameters or the fallback policy.
|
|
137
|
+
- Before changing CORS to allow any origin with credentials.
|
|
138
|
+
- Before moving between minimal APIs and controllers for existing endpoints.
|
|
139
|
+
|
|
140
|
+
## Never
|
|
141
|
+
|
|
142
|
+
- Never put secrets in `appsettings*.json` in source control.
|
|
143
|
+
- Never `.Result` or `.Wait()` on tasks in request code.
|
|
144
|
+
- Never return exception messages or stack traces to clients in production.
|
|
145
|
+
- Never register `DbContext` as a singleton.
|
|
146
|
+
|
|
147
|
+
## Finish
|
|
148
|
+
|
|
149
|
+
Run `dotnet build` with warnings visible and `dotnet test`. Report: files changed, pipeline order changes, new services and their lifetimes, and endpoints whose auth changed.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"CORS preflight returns 401 in my ASP.NET Core API, is my middleware order wrong?",
|
|
4
|
+
"Should this new .NET 8 service use minimal APIs or controllers, and how do I group the routes?",
|
|
5
|
+
"Bind the Smtp section of appsettings to an options class in ASP.NET Core and fail at startup if it's missing",
|
|
6
|
+
"Make every unhandled exception in our ASP.NET Core API return RFC 7807 problem details",
|
|
7
|
+
"Add liveness and readiness health check endpoints to the ASP.NET Core orders service"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Turn on nullable reference types across this C# class library and fix the warnings",
|
|
11
|
+
"Write an xUnit test with WebApplicationFactory for the orders endpoint",
|
|
12
|
+
"My EF Core query throws 'could not be translated', how do I rewrite it?",
|
|
13
|
+
"Add a dotnet ef migration for the new Invoice table",
|
|
14
|
+
"Write a Kubernetes deployment manifest with readiness probes for this container"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auth-patterns
|
|
3
|
+
description: Implementing login, sessions and access control correctly on the server - password hashing with Argon2id or bcrypt, cookie sessions versus JWT access tokens, OAuth 2.1 and OpenID Connect authorization code flow with PKCE, TOTP and passkey MFA, role- and attribute-based permission checks, safe token storage in browsers and mobile apps, and password reset and account recovery. Use when building or changing sign-up, sign-in, logout, social login or SSO, adding roles and permissions, deciding where to keep tokens, wiring up an identity provider, or designing a forgot-password flow.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Framework-neutral; examples name common libraries but the rules apply to any backend language.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: security
|
|
9
|
+
kete-loom/risk: writes-files
|
|
10
|
+
kete-loom/owner: "Kete-org"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Authentication and authorization patterns
|
|
14
|
+
|
|
15
|
+
Build auth that holds up when the client is hostile. This skill is for writing or changing auth code. To audit existing code for flaws, use the security-review skill or the security-reviewer agent.
|
|
16
|
+
|
|
17
|
+
## 0. Decide before writing code
|
|
18
|
+
|
|
19
|
+
1. **Prefer not to build it.** If the framework ships auth (Django auth, Rails 8's authentication generator or Devise, ASP.NET Core Identity, Laravel Fortify/Sanctum, Spring Security) or the project already uses a managed identity provider, use that. Hand-rolled crypto, token formats or OAuth servers are a **stop and ask** point.
|
|
20
|
+
2. Identify the client types: server-rendered web, SPA, mobile/desktop app, machine-to-machine. They need different token handling (section 3).
|
|
21
|
+
3. Find the existing pattern: search the codebase for the session middleware, the current-user helper and how routes are protected. Extend it; don't add a second auth system.
|
|
22
|
+
|
|
23
|
+
## 1. Passwords
|
|
24
|
+
|
|
25
|
+
- Hash with **Argon2id** (minimum m=19 MiB, t=2, p=1). If unavailable: scrypt (N=2^17, r=8, p=1), bcrypt (cost 10 or more; it ignores input past **72 bytes**, so cap length or pre-handle long input), or PBKDF2-HMAC-SHA256 at 600,000 iterations where FIPS is required. These are the OWASP Password Storage Cheat Sheet minimums; raise them as hardware allows.
|
|
26
|
+
- Use the library's own `hash` and `verify`; never compare hashes with `==`. Store the full encoded string (it carries the salt and parameters) and rehash on login when parameters change.
|
|
27
|
+
- Policy (NIST SP 800-63B style): favour length over composition rules, allow at least 64 characters and any Unicode, reject passwords found in a breached-password list, no forced periodic rotation, no password hints or security questions.
|
|
28
|
+
- Login responses and timing must not reveal whether the account exists: same message for unknown user and wrong password, and run a dummy verify for unknown users.
|
|
29
|
+
- Rate-limit by account and by IP, with backoff, not permanent lockout (lockout is itself a denial-of-service tool).
|
|
30
|
+
|
|
31
|
+
## 2. Sessions vs tokens
|
|
32
|
+
|
|
33
|
+
Default for a browser app on your own domain: **server-side session with an opaque ID in a cookie.** It is revocable, small and safe from script access.
|
|
34
|
+
|
|
35
|
+
| Use | When |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Cookie session (opaque ID, server store) | Web app and API on the same site, including SPAs served from your domain or through a backend-for-frontend |
|
|
38
|
+
| Short-lived JWT access token + refresh token | APIs called by mobile apps, third parties or many services that must verify without a session store |
|
|
39
|
+
| Client credentials / workload identity | Machine to machine; no user |
|
|
40
|
+
|
|
41
|
+
Session cookie flags: `HttpOnly; Secure; SameSite=Lax` (or `Strict`), `Path=/`, and the `__Host-` name prefix so it can't be set by a subdomain. On login and on privilege change, **issue a new session ID** (prevents fixation). Enforce idle and absolute timeouts. Logout deletes the server-side session, not just the cookie. Cookie-authenticated state-changing requests need CSRF protection (framework token, or `SameSite` plus an `Origin` check).
|
|
42
|
+
|
|
43
|
+
JWT rules, if you use them:
|
|
44
|
+
|
|
45
|
+
1. Verify the signature with an **allow-list of algorithms** fixed in config; reject `none` and never take the algorithm or key from the token header.
|
|
46
|
+
2. Check `iss`, `aud`, `exp` and `nbf` on every request, with a small clock skew.
|
|
47
|
+
3. Access tokens live minutes, not days. Put an ID and roles in them, never secrets or personal data (JWTs are readable by anyone).
|
|
48
|
+
4. Refresh tokens are opaque, stored hashed server-side, **rotated on every use**, and a reused old one revokes the whole family.
|
|
49
|
+
5. You can't revoke a JWT before it expires without a deny-list; keep lifetimes short for that reason.
|
|
50
|
+
|
|
51
|
+
## 3. Token storage by client
|
|
52
|
+
|
|
53
|
+
- **Server-rendered or same-site SPA**: HttpOnly cookie. Do not put tokens in `localStorage` or `sessionStorage`; any XSS can read them.
|
|
54
|
+
- **SPA calling third-party APIs**: prefer a backend-for-frontend that holds tokens server-side and gives the browser only a session cookie. If tokens must live in the browser, keep them in memory and use refresh token rotation.
|
|
55
|
+
- **Mobile**: iOS Keychain, Android Keystore-backed storage. Never in plain shared preferences, files or logs.
|
|
56
|
+
- **Servers and CI**: secret manager or environment, never in the repo.
|
|
57
|
+
|
|
58
|
+
## 4. OAuth 2.1 and OpenID Connect
|
|
59
|
+
|
|
60
|
+
Use a maintained client library and the provider's discovery document (`/.well-known/openid-configuration`). The flow for every user-facing client is **authorization code with PKCE (`S256`)**, including confidential server-side clients. Never implement the implicit grant or the resource owner password grant: RFC 9700 (OAuth 2.0 Security BCP) says the password grant MUST NOT be used and clients SHOULD NOT use the implicit grant, and the OAuth 2.1 draft removes both.
|
|
61
|
+
|
|
62
|
+
Non-negotiable checks: exact redirect URI matching, a random `state` bound to the user's session, `nonce` in OIDC, ID token signature and claims validation, and linking the account by the provider's `sub` + `iss` (not by email alone unless the provider asserts `email_verified` and you accept that risk). Full flow, validation list and pitfalls: `references/oauth-oidc.md`.
|
|
63
|
+
|
|
64
|
+
## 5. MFA
|
|
65
|
+
|
|
66
|
+
- Offer **passkeys / WebAuthn** where possible; they are phishing-resistant. Use a maintained WebAuthn server library and verify origin, RP ID and the signature counter it reports.
|
|
67
|
+
- **TOTP** (RFC 6238): 30-second step, accept at most one step of drift, reject a code already used in its window, store the shared secret encrypted, rate-limit attempts.
|
|
68
|
+
- SMS and email codes are weaker fallbacks; never the only second factor for admin accounts.
|
|
69
|
+
- **Recovery codes**: generated once, shown once, stored hashed, single use.
|
|
70
|
+
- Require re-authentication (step-up) before changing email, password, MFA settings or payout details.
|
|
71
|
+
|
|
72
|
+
## 6. Authorization
|
|
73
|
+
|
|
74
|
+
1. **Deny by default.** Every route, resolver, RPC and background job that acts for a user checks permission on the server. Hidden UI is not a control.
|
|
75
|
+
2. Check **the action on this resource**, not just the role: load the object, then `can(user, "update", invoice)`. Scope queries by owner or tenant (`WHERE tenant_id = :current_tenant`) so another tenant's ID returns nothing (prevents IDOR).
|
|
76
|
+
3. **RBAC** for coarse capability (admin, member, viewer); **ABAC or relationship rules** for ownership, tenant, state ("only the author can edit a draft"). Put the rules in one policy module or library (Pundit, CASL, django-rules, Spring `@PreAuthorize`, OPA/Cedar), not scattered `if` statements.
|
|
77
|
+
4. Never trust client-sent roles, user IDs, tenant IDs or prices; derive them from the session.
|
|
78
|
+
5. Write tests for the negative cases: another user's resource, a lower role, a deactivated account, an expired session.
|
|
79
|
+
|
|
80
|
+
## 7. Account recovery
|
|
81
|
+
|
|
82
|
+
- Reset tokens: at least 128 bits from a CSPRNG, **stored hashed**, single use, expiring in minutes to an hour, invalidated when a new one is issued.
|
|
83
|
+
- Same response whether or not the email exists. Send the link only to the address already on file.
|
|
84
|
+
- On reset: invalidate all existing sessions and refresh tokens, notify the user, and do not log them in silently if MFA is enabled (still require the second factor).
|
|
85
|
+
- Email change: confirm via the new address and notify the old one.
|
|
86
|
+
- Support-driven recovery needs a documented identity check; it is the usual way accounts get taken over.
|
|
87
|
+
|
|
88
|
+
## 8. Logging
|
|
89
|
+
|
|
90
|
+
Log sign-in success and failure, MFA changes, password resets, role changes and token revocations with user ID, IP and time. Never log passwords, tokens, reset links, session IDs or TOTP secrets.
|
|
91
|
+
|
|
92
|
+
## Never
|
|
93
|
+
|
|
94
|
+
- Never store passwords reversibly or with fast hashes (MD5, SHA-1, SHA-256 alone).
|
|
95
|
+
- Never invent your own token format, signature scheme or OAuth server.
|
|
96
|
+
- Never put tokens in URLs, `localStorage`, logs or analytics.
|
|
97
|
+
- Never authorize from data the client sends.
|
|
98
|
+
- Never weaken an existing control (shorter hash cost, longer token life, removed CSRF check) without telling the user.
|
|
99
|
+
|
|
100
|
+
## Before you finish
|
|
101
|
+
|
|
102
|
+
- Tests cover: wrong password, unknown user, expired and tampered token, reused refresh token, another user's resource, missing role, CSRF on a cookie-authenticated mutation, reset token reuse.
|
|
103
|
+
- Run the project's tests and linters.
|
|
104
|
+
- Summarise for the user: what flow you built, where secrets are read from, token lifetimes, and anything left for them to configure at the identity provider.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Add Google sign-in to our Express app using OIDC with PKCE",
|
|
4
|
+
"Should I use JWTs or server sessions for my SPA's login?",
|
|
5
|
+
"How should we hash user passwords? We're on bcrypt cost 8 right now",
|
|
6
|
+
"Implement a forgot-password flow with reset links that expire",
|
|
7
|
+
"Add roles and per-resource permissions so members can only edit their own team's projects",
|
|
8
|
+
"Where should my React Native app store the access and refresh tokens?"
|
|
9
|
+
],
|
|
10
|
+
"should_not_trigger": [
|
|
11
|
+
"Find the vulnerabilities in our existing login handler code",
|
|
12
|
+
"Threat model our new SSO integration with the customer's identity provider",
|
|
13
|
+
"Add a password strength meter to the signup form UI",
|
|
14
|
+
"Design REST endpoints and error formats for our public orders API",
|
|
15
|
+
"Write a HIPAA access control policy document for our clinic records system"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# OAuth 2.1 / OpenID Connect: authorization code flow with PKCE
|
|
2
|
+
|
|
3
|
+
Read this when wiring up social login, SSO or any OAuth client. Status note: OAuth 2.1 is still an IETF Internet-Draft (draft-ietf-oauth-v2-1) at the time of writing; its rules consolidate RFC 6749, RFC 7636 (PKCE) and RFC 9700 (OAuth 2.0 Security Best Current Practice, January 2025). Follow RFC 9700 where your provider is OAuth 2.0.
|
|
4
|
+
|
|
5
|
+
## Flow
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
1. Client creates:
|
|
9
|
+
code_verifier = 43-128 chars from a CSPRNG (base64url)
|
|
10
|
+
code_challenge = BASE64URL(SHA256(code_verifier)), method S256
|
|
11
|
+
state = random, stored in the user's session (CSRF protection)
|
|
12
|
+
nonce = random, stored in the session (OIDC replay protection)
|
|
13
|
+
|
|
14
|
+
2. Redirect the browser to the authorization endpoint:
|
|
15
|
+
GET /authorize?response_type=code&client_id=...&redirect_uri=<exact registered URI>
|
|
16
|
+
&scope=openid%20profile%20email&state=...&nonce=...
|
|
17
|
+
&code_challenge=...&code_challenge_method=S256
|
|
18
|
+
|
|
19
|
+
3. Provider redirects back: GET <redirect_uri>?code=...&state=...
|
|
20
|
+
- Reject if state is missing or differs from the session value. Delete it after use.
|
|
21
|
+
- If the provider supports it, check the `iss` response parameter (RFC 9207) matches the expected issuer (mix-up defence).
|
|
22
|
+
|
|
23
|
+
4. Server exchanges the code (back channel):
|
|
24
|
+
POST /token grant_type=authorization_code&code=...&redirect_uri=...&code_verifier=...
|
|
25
|
+
Confidential clients also authenticate (client secret, or better private_key_jwt / mTLS).
|
|
26
|
+
|
|
27
|
+
5. Validate the ID token (OIDC), then create your own session.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## ID token validation (OIDC Core)
|
|
31
|
+
|
|
32
|
+
1. Signature verifies against a key from the provider's `jwks_uri` (cache keys; refetch on unknown `kid`). Algorithm is in your allow-list, never `none`.
|
|
33
|
+
2. `iss` equals the expected issuer exactly.
|
|
34
|
+
3. `aud` contains your `client_id`; if multiple audiences, `azp` equals your `client_id`.
|
|
35
|
+
4. `exp` is in the future; `iat` is recent.
|
|
36
|
+
5. `nonce` equals the value stored in the session.
|
|
37
|
+
6. Identify the user by `iss` + `sub`. Email is not a stable identifier and may be unverified.
|
|
38
|
+
|
|
39
|
+
Most libraries do all of this; confirm the one you use does and that you have not disabled any check.
|
|
40
|
+
|
|
41
|
+
## Client types
|
|
42
|
+
|
|
43
|
+
| Client | Credentials | Notes |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| Server-side web app | Confidential (secret or key) | Still use PKCE. Tokens stay on the server; browser gets a session cookie. |
|
|
46
|
+
| SPA | Public | Best: backend-for-frontend holds tokens. Otherwise PKCE, in-memory tokens, refresh token rotation, short lifetimes. |
|
|
47
|
+
| Native / mobile | Public | System browser (ASWebAuthenticationSession, Custom Tabs), never an embedded web view. Claimed HTTPS redirect (universal/app links) or loopback for desktop. |
|
|
48
|
+
| Machine to machine | Confidential | `client_credentials` grant; no user, no refresh token. |
|
|
49
|
+
|
|
50
|
+
## Pitfalls
|
|
51
|
+
|
|
52
|
+
- **Open redirect via redirect_uri**: register exact URIs; never accept wildcards or a user-supplied return URL without an allow-list. After login, only redirect to relative paths you validate.
|
|
53
|
+
- **Account takeover by email linking**: linking a social login to an existing local account by email alone lets anyone who controls that email at a sloppy provider take the account. Link by `iss` + `sub`, and require the user to sign in to the existing account to link it.
|
|
54
|
+
- **Leaking codes or tokens**: no tokens in URLs or fragments, set `Referrer-Policy: no-referrer` (or strict) on the callback page, never log the callback query string.
|
|
55
|
+
- **Over-broad scopes**: request only what you use; incremental consent for more.
|
|
56
|
+
- **Access token as identity**: for "who is the user", use the ID token or `userinfo`, not an access token meant for an API.
|
|
57
|
+
- **Using the provider's access token as your session**: create your own session after login; the provider's tokens are for calling the provider.
|
|
58
|
+
- **Refresh tokens**: rotate on use with reuse detection, or sender-constrain them (DPoP, RFC 9449, or mTLS) where the provider supports it.
|
|
59
|
+
- **Logout**: end your own session; use the provider's RP-initiated logout endpoint if single sign-out is required.
|
|
60
|
+
|
|
61
|
+
## Grants never to implement
|
|
62
|
+
|
|
63
|
+
- Implicit (`response_type=token`): tokens in the URL fragment, no PKCE binding.
|
|
64
|
+
- Resource owner password credentials: your app sees the user's provider password; defeats MFA and phishing resistance.
|