rsc-universal 0.1.1
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 +279 -0
- package/manifest.json +4761 -0
- package/package.json +59 -0
- package/schema/frontmatter.schema.json +12 -0
- package/scripts/build-manifest.js +72 -0
- package/scripts/consult.js +106 -0
- package/scripts/detect-repo.js +118 -0
- package/scripts/doctor.js +21 -0
- package/scripts/eval-lint.sh +179 -0
- package/scripts/install-apply.js +52 -0
- package/scripts/install-plan.js +13 -0
- package/scripts/lib/behavior-score.js +103 -0
- package/scripts/lib/frontmatter.js +47 -0
- package/scripts/lib/harden-policy.js +41 -0
- package/scripts/lib/manifest.js +18 -0
- package/scripts/lib/recommend.js +36 -0
- package/scripts/lib/registry.js +110 -0
- package/scripts/lib/result-envelope.js +35 -0
- package/scripts/lib/state.js +12 -0
- package/scripts/lib/ui.js +17 -0
- package/scripts/reviewer-guard.sh +67 -0
- package/scripts/rsc.js +108 -0
- package/scripts/skill-behavior-eval.js +33 -0
- package/scripts/skill-behavior-eval.workflow.js +136 -0
- package/scripts/skill-behavior-rubric.md +63 -0
- package/scripts/skill-harden-rubric.md +40 -0
- package/scripts/skill-harden.workflow.js +161 -0
- package/scripts/skill-rubric.md +39 -0
- package/scripts/skill-scoreboard.workflow.js +35 -0
- package/skills/ab-testing/SKILL.md +191 -0
- package/skills/ab-testing/evals/README.md +8 -0
- package/skills/ab-testing/evals/cases.yaml +49 -0
- package/skills/ab-testing/references/pitfalls.md +74 -0
- package/skills/ab-testing/references/sample-size-and-cuped.md +128 -0
- package/skills/ab-testing/scripts/verify.sh +89 -0
- package/skills/accessibility/SKILL.md +218 -0
- package/skills/accessibility/evals/README.md +3 -0
- package/skills/accessibility/evals/cases.yaml +47 -0
- package/skills/accessibility/references/aria-patterns.md +113 -0
- package/skills/accessibility/references/wcag22-checklist.md +83 -0
- package/skills/accessibility/scripts/verify.sh +103 -0
- package/skills/ads/SKILL.md +175 -0
- package/skills/ads/evals/README.md +15 -0
- package/skills/ads/evals/cases.yaml +58 -0
- package/skills/ads/references/platform-specs.md +73 -0
- package/skills/ads/references/roas-model.md +77 -0
- package/skills/ads/scripts/verify.sh +210 -0
- package/skills/agent-eval/SKILL.md +213 -0
- package/skills/agent-eval/evals/README.md +12 -0
- package/skills/agent-eval/evals/cases.yaml +45 -0
- package/skills/agent-eval/references/judge-design.md +118 -0
- package/skills/agent-eval/references/runner-and-gate.md +183 -0
- package/skills/agent-eval/scripts/verify.sh +161 -0
- package/skills/agent-safety/SKILL.md +176 -0
- package/skills/agent-safety/evals/README.md +12 -0
- package/skills/agent-safety/evals/cases.yaml +46 -0
- package/skills/agent-safety/references/threat-model.md +51 -0
- package/skills/ai-media/SKILL.md +196 -0
- package/skills/ai-media/evals/README.md +3 -0
- package/skills/ai-media/evals/cases.yaml +45 -0
- package/skills/ai-media/references/ffmpeg-assembly.md +117 -0
- package/skills/ai-media/references/models-and-params.md +78 -0
- package/skills/ai-media/scripts/verify.sh +103 -0
- package/skills/analytics/SKILL.md +219 -0
- package/skills/analytics/evals/README.md +9 -0
- package/skills/analytics/evals/cases.yaml +53 -0
- package/skills/analytics/references/event-taxonomy.md +75 -0
- package/skills/analytics/references/ga4-setup.md +122 -0
- package/skills/analytics/references/posthog-setup.md +100 -0
- package/skills/analytics/scripts/verify.sh +95 -0
- package/skills/analyze/SKILL.md +136 -0
- package/skills/analyze/evals/README.md +72 -0
- package/skills/analyze/evals/cases.yaml +74 -0
- package/skills/angular/SKILL.md +288 -0
- package/skills/angular/evals/README.md +3 -0
- package/skills/angular/evals/cases.yaml +38 -0
- package/skills/angular/references/migration.md +81 -0
- package/skills/angular/references/signals-rxjs.md +92 -0
- package/skills/angular/scripts/verify.sh +122 -0
- package/skills/api-connector-builder/SKILL.md +285 -0
- package/skills/api-connector-builder/evals/README.md +11 -0
- package/skills/api-connector-builder/evals/cases.yaml +47 -0
- package/skills/api-connector-builder/references/auth-flows.md +132 -0
- package/skills/api-connector-builder/references/pagination.md +144 -0
- package/skills/api-connector-builder/scripts/verify.sh +172 -0
- package/skills/api-design/SKILL.md +189 -0
- package/skills/api-design/evals/README.md +3 -0
- package/skills/api-design/evals/cases.yaml +45 -0
- package/skills/api-design/references/graphql-design.md +70 -0
- package/skills/api-design/references/openapi-contract.md +86 -0
- package/skills/api-design/references/rest-conventions.md +63 -0
- package/skills/api-design/references/versioning-and-evolution.md +49 -0
- package/skills/api-design/scripts/verify.sh +138 -0
- package/skills/article-writing/SKILL.md +175 -0
- package/skills/article-writing/evals/README.md +3 -0
- package/skills/article-writing/evals/cases.yaml +47 -0
- package/skills/article-writing/references/ai-tell-banlist.md +114 -0
- package/skills/article-writing/references/on-page-seo.md +133 -0
- package/skills/article-writing/scripts/verify.sh +165 -0
- package/skills/astro/SKILL.md +275 -0
- package/skills/astro/evals/README.md +3 -0
- package/skills/astro/evals/cases.yaml +41 -0
- package/skills/astro/references/content-layer.md +118 -0
- package/skills/astro/references/deploy-and-integrations.md +163 -0
- package/skills/astro/scripts/verify.sh +137 -0
- package/skills/author-skill/SKILL.md +206 -0
- package/skills/author-skill/evals/README.md +66 -0
- package/skills/author-skill/evals/cases.yaml +75 -0
- package/skills/author-skill/references/description-recipe.md +84 -0
- package/skills/author-skill/references/eval-authoring.md +74 -0
- package/skills/author-skill/references/rsc-conventions.md +91 -0
- package/skills/automation-flows/SKILL.md +132 -0
- package/skills/automation-flows/evals/README.md +5 -0
- package/skills/automation-flows/evals/cases.yaml +44 -0
- package/skills/automation-flows/references/error-handling.md +58 -0
- package/skills/automation-flows/references/n8n-workflow-json.md +63 -0
- package/skills/automation-flows/scripts/verify.sh +78 -0
- package/skills/aws-essentials/SKILL.md +223 -0
- package/skills/aws-essentials/evals/README.md +10 -0
- package/skills/aws-essentials/evals/cases.yaml +44 -0
- package/skills/aws-essentials/references/iam-least-privilege.md +134 -0
- package/skills/aws-essentials/references/rds-cloudfront-recipes.md +127 -0
- package/skills/aws-essentials/scripts/verify.sh +99 -0
- package/skills/backups/SKILL.md +137 -0
- package/skills/backups/evals/README.md +3 -0
- package/skills/backups/evals/cases.yaml +42 -0
- package/skills/backups/references/engine-recipes.md +121 -0
- package/skills/backups/references/restore-runbook.md +65 -0
- package/skills/backups/scripts/verify.sh +80 -0
- package/skills/bash-scripting/SKILL.md +231 -0
- package/skills/bash-scripting/evals/README.md +3 -0
- package/skills/bash-scripting/evals/cases.yaml +45 -0
- package/skills/bash-scripting/references/portability.md +97 -0
- package/skills/bash-scripting/scripts/verify.sh +140 -0
- package/skills/bookkeeping/SKILL.md +184 -0
- package/skills/bookkeeping/evals/README.md +5 -0
- package/skills/bookkeeping/evals/cases.yaml +52 -0
- package/skills/bookkeeping/references/chart-of-accounts.md +87 -0
- package/skills/bookkeeping/references/reconciliation-playbook.md +54 -0
- package/skills/bookkeeping/references/tricky-transactions.md +192 -0
- package/skills/brand-identity/SKILL.md +161 -0
- package/skills/brand-identity/evals/README.md +14 -0
- package/skills/brand-identity/evals/cases.yaml +43 -0
- package/skills/brand-identity/references/color-and-tokens.md +129 -0
- package/skills/brand-identity/references/logo-and-assets.md +117 -0
- package/skills/brand-identity/scripts/verify.sh +224 -0
- package/skills/brand-voice/SKILL.md +183 -0
- package/skills/brand-voice/evals/README.md +3 -0
- package/skills/brand-voice/evals/cases.yaml +57 -0
- package/skills/brand-voice/references/voice-guide-template.md +150 -0
- package/skills/brand-voice/references/word-bank.md +61 -0
- package/skills/brand-voice/scripts/verify.sh +190 -0
- package/skills/building-agents/SKILL.md +469 -0
- package/skills/building-agents/evals/README.md +68 -0
- package/skills/building-agents/evals/cases.yaml +60 -0
- package/skills/building-agents/references/agent-loops-and-harness.md +371 -0
- package/skills/building-agents/references/evals-and-observability.md +420 -0
- package/skills/building-agents/references/mcp-servers.md +294 -0
- package/skills/building-agents/references/provider-abstraction.md +489 -0
- package/skills/building-agents/references/tools-and-rag.md +417 -0
- package/skills/building-agents/scripts/verify.sh +121 -0
- package/skills/business-intelligence/SKILL.md +176 -0
- package/skills/business-intelligence/evals/README.md +3 -0
- package/skills/business-intelligence/evals/cases.yaml +43 -0
- package/skills/business-intelligence/references/authoring-semantic-models.md +120 -0
- package/skills/business-intelligence/references/wiring-agents-and-apis.md +79 -0
- package/skills/business-intelligence/scripts/verify.sh +143 -0
- package/skills/calendar-scheduling/SKILL.md +196 -0
- package/skills/calendar-scheduling/evals/README.md +14 -0
- package/skills/calendar-scheduling/evals/cases.yaml +45 -0
- package/skills/calendar-scheduling/references/google-calendar-sync.md +78 -0
- package/skills/calendar-scheduling/references/provider-matrix.md +71 -0
- package/skills/calendar-scheduling/scripts/verify.sh +117 -0
- package/skills/case-studies/SKILL.md +147 -0
- package/skills/case-studies/evals/README.md +3 -0
- package/skills/case-studies/evals/cases.yaml +63 -0
- package/skills/case-studies/references/case-study-skeleton.md +90 -0
- package/skills/case-studies/references/consent-and-substantiation.md +80 -0
- package/skills/case-studies/scripts/verify.sh +161 -0
- package/skills/chatbot/SKILL.md +168 -0
- package/skills/chatbot/evals/README.md +13 -0
- package/skills/chatbot/evals/cases.yaml +43 -0
- package/skills/chatbot/references/handoff-and-sales.md +71 -0
- package/skills/chatbot/references/system-prompt-and-guardrails.md +78 -0
- package/skills/chatbot/scripts/verify.sh +162 -0
- package/skills/chrome-extension/SKILL.md +169 -0
- package/skills/chrome-extension/evals/README.md +12 -0
- package/skills/chrome-extension/evals/cases.yaml +40 -0
- package/skills/chrome-extension/references/store-and-migration.md +84 -0
- package/skills/chrome-extension/scripts/verify.sh +62 -0
- package/skills/clarify/SKILL.md +159 -0
- package/skills/clarify/evals/README.md +70 -0
- package/skills/clarify/evals/cases.yaml +71 -0
- package/skills/clickhouse-analytics/SKILL.md +165 -0
- package/skills/clickhouse-analytics/evals/README.md +3 -0
- package/skills/clickhouse-analytics/evals/cases.yaml +45 -0
- package/skills/clickhouse-analytics/references/ingestion-and-mvs.md +109 -0
- package/skills/clickhouse-analytics/references/query-optimization.md +76 -0
- package/skills/clickhouse-analytics/references/schema-and-engines.md +63 -0
- package/skills/clickhouse-analytics/scripts/verify.sh +109 -0
- package/skills/client-onboarding/SKILL.md +254 -0
- package/skills/client-onboarding/evals/README.md +14 -0
- package/skills/client-onboarding/evals/cases.yaml +40 -0
- package/skills/client-onboarding/references/onboarding-playbook.md +126 -0
- package/skills/cloudflare/SKILL.md +191 -0
- package/skills/cloudflare/evals/README.md +15 -0
- package/skills/cloudflare/evals/cases.yaml +46 -0
- package/skills/cloudflare/references/storage-primitives.md +104 -0
- package/skills/cloudflare/references/wrangler-config.md +91 -0
- package/skills/cloudflare/scripts/verify.sh +133 -0
- package/skills/code-review/SKILL.md +143 -0
- package/skills/code-review/evals/README.md +3 -0
- package/skills/code-review/evals/cases.yaml +55 -0
- package/skills/code-review/references/pr-workflow.md +67 -0
- package/skills/codebase-onboarding/SKILL.md +133 -0
- package/skills/codebase-onboarding/evals/README.md +3 -0
- package/skills/codebase-onboarding/evals/cases.yaml +69 -0
- package/skills/codebase-onboarding/references/recon-playbook.md +57 -0
- package/skills/codebase-onboarding/scripts/verify.sh +54 -0
- package/skills/cold-outreach/SKILL.md +206 -0
- package/skills/cold-outreach/evals/README.md +3 -0
- package/skills/cold-outreach/evals/cases.yaml +60 -0
- package/skills/cold-outreach/references/compliance-footer.md +50 -0
- package/skills/cold-outreach/references/hook-derivation.md +73 -0
- package/skills/cold-outreach/references/templates.md +88 -0
- package/skills/cold-outreach/scripts/verify.sh +170 -0
- package/skills/community/SKILL.md +225 -0
- package/skills/community/evals/README.md +3 -0
- package/skills/community/evals/cases.yaml +40 -0
- package/skills/community/references/metrics-and-rituals.md +58 -0
- package/skills/community/references/platform-playbooks.md +64 -0
- package/skills/community/scripts/verify.sh +83 -0
- package/skills/competitor-watch/SKILL.md +193 -0
- package/skills/competitor-watch/evals/README.md +19 -0
- package/skills/competitor-watch/evals/cases.yaml +54 -0
- package/skills/competitor-watch/references/monitoring-config.md +124 -0
- package/skills/competitor-watch/references/tracker-schema.md +79 -0
- package/skills/competitor-watch/scripts/verify.sh +253 -0
- package/skills/compliance/SKILL.md +184 -0
- package/skills/compliance/evals/README.md +14 -0
- package/skills/compliance/evals/cases.yaml +46 -0
- package/skills/compliance/references/frameworks.md +108 -0
- package/skills/compliance/references/operating-rhythm.md +79 -0
- package/skills/compliance/scripts/verify.sh +168 -0
- package/skills/compose-multiplatform/SKILL.md +198 -0
- package/skills/compose-multiplatform/evals/README.md +3 -0
- package/skills/compose-multiplatform/evals/cases.yaml +40 -0
- package/skills/compose-multiplatform/references/ios-interop.md +91 -0
- package/skills/compose-multiplatform/references/project-setup.md +96 -0
- package/skills/compose-multiplatform/scripts/verify.sh +123 -0
- package/skills/constitution/SKILL.md +160 -0
- package/skills/constitution/evals/README.md +68 -0
- package/skills/constitution/evals/cases.yaml +72 -0
- package/skills/constitution/references/constitution-template.md +90 -0
- package/skills/content-engine/SKILL.md +164 -0
- package/skills/content-engine/evals/README.md +17 -0
- package/skills/content-engine/evals/cases.yaml +62 -0
- package/skills/content-engine/references/atomization.md +81 -0
- package/skills/content-engine/references/brief-and-pipeline.md +90 -0
- package/skills/content-engine/scripts/verify.sh +146 -0
- package/skills/context-budget/SKILL.md +132 -0
- package/skills/context-budget/evals/README.md +11 -0
- package/skills/context-budget/evals/cases.yaml +40 -0
- package/skills/context-budget/references/handoff-and-compaction.md +96 -0
- package/skills/continuous-learning/SKILL.md +136 -0
- package/skills/continuous-learning/evals/README.md +16 -0
- package/skills/continuous-learning/evals/cases.yaml +39 -0
- package/skills/continuous-learning/references/lesson-routing.md +106 -0
- package/skills/contracts/SKILL.md +124 -0
- package/skills/contracts/evals/README.md +3 -0
- package/skills/contracts/evals/cases.yaml +42 -0
- package/skills/contracts/references/clause-library.md +129 -0
- package/skills/contracts/references/review-playbook.md +49 -0
- package/skills/contracts/scripts/verify.sh +53 -0
- package/skills/coolify/SKILL.md +201 -0
- package/skills/coolify/evals/README.md +21 -0
- package/skills/coolify/evals/cases.yaml +46 -0
- package/skills/coolify/references/databases-and-backups.md +99 -0
- package/skills/coolify/references/deploy-recipes.md +105 -0
- package/skills/coolify/references/install-and-proxy.md +80 -0
- package/skills/coolify/scripts/verify.sh +123 -0
- package/skills/cost-tracking/SKILL.md +183 -0
- package/skills/cost-tracking/evals/README.md +3 -0
- package/skills/cost-tracking/evals/cases.yaml +45 -0
- package/skills/cost-tracking/references/cloud-caps.md +52 -0
- package/skills/cost-tracking/references/pricing-tables.md +51 -0
- package/skills/cost-tracking/scripts/verify.sh +135 -0
- package/skills/course-builder/SKILL.md +186 -0
- package/skills/course-builder/evals/README.md +16 -0
- package/skills/course-builder/evals/cases.yaml +49 -0
- package/skills/course-builder/references/assessment-design.md +74 -0
- package/skills/course-builder/references/grounding-and-scoping.md +69 -0
- package/skills/course-builder/references/outcomes-and-blooms.md +82 -0
- package/skills/course-builder/scripts/verify.sh +247 -0
- package/skills/course-storytelling/SKILL.md +205 -0
- package/skills/course-storytelling/evals/README.md +54 -0
- package/skills/course-storytelling/evals/cases.yaml +50 -0
- package/skills/course-storytelling/references/brunson-frameworks.md +190 -0
- package/skills/course-storytelling/references/concept-landing-recipe.md +136 -0
- package/skills/course-storytelling/references/course-analysis.md +124 -0
- package/skills/course-storytelling/references/learner-grounding.md +183 -0
- package/skills/course-storytelling/references/mental-models.md +115 -0
- package/skills/course-storytelling/scripts/verify.sh +223 -0
- package/skills/cpp/SKILL.md +349 -0
- package/skills/cpp/evals/README.md +14 -0
- package/skills/cpp/evals/cases.yaml +44 -0
- package/skills/cpp/references/cmake.md +167 -0
- package/skills/cpp/references/move-and-templates.md +130 -0
- package/skills/cpp/references/undefined-behavior.md +86 -0
- package/skills/cpp/scripts/verify.sh +165 -0
- package/skills/csharp-dotnet/SKILL.md +291 -0
- package/skills/csharp-dotnet/evals/README.md +3 -0
- package/skills/csharp-dotnet/evals/cases.yaml +48 -0
- package/skills/csharp-dotnet/references/aspnetcore.md +99 -0
- package/skills/csharp-dotnet/references/async.md +82 -0
- package/skills/csharp-dotnet/references/efcore.md +96 -0
- package/skills/csharp-dotnet/scripts/verify.sh +90 -0
- package/skills/customer-support/SKILL.md +193 -0
- package/skills/customer-support/evals/README.md +13 -0
- package/skills/customer-support/evals/cases.yaml +61 -0
- package/skills/customer-support/references/macros-and-sla.md +142 -0
- package/skills/dashboard/SKILL.md +205 -0
- package/skills/dashboard/evals/README.md +3 -0
- package/skills/dashboard/evals/cases.yaml +50 -0
- package/skills/dashboard/references/chart-selection.md +34 -0
- package/skills/dashboard/references/tile-schema.md +164 -0
- package/skills/dashboard/scripts/verify.sh +130 -0
- package/skills/data-cleaning/SKILL.md +285 -0
- package/skills/data-cleaning/evals/README.md +16 -0
- package/skills/data-cleaning/evals/cases.yaml +57 -0
- package/skills/data-cleaning/references/normalization-recipes.md +136 -0
- package/skills/data-cleaning/references/validation-patterns.md +134 -0
- package/skills/data-cleaning/scripts/verify.sh +115 -0
- package/skills/data-policy/SKILL.md +163 -0
- package/skills/data-policy/evals/README.md +15 -0
- package/skills/data-policy/evals/cases.yaml +44 -0
- package/skills/data-policy/references/consent-and-ropa.md +97 -0
- package/skills/data-policy/references/retention-schedule.md +83 -0
- package/skills/data-policy/scripts/verify.sh +143 -0
- package/skills/data-scraper/SKILL.md +134 -0
- package/skills/data-scraper/evals/README.md +3 -0
- package/skills/data-scraper/evals/cases.yaml +46 -0
- package/skills/data-scraper/references/anti-bot.md +85 -0
- package/skills/data-scraper/references/frameworks.md +116 -0
- package/skills/data-scraper/references/legal-compliance.md +59 -0
- package/skills/data-scraper/scripts/verify.sh +166 -0
- package/skills/db-migrations/SKILL.md +254 -0
- package/skills/db-migrations/evals/README.md +10 -0
- package/skills/db-migrations/evals/cases.yaml +46 -0
- package/skills/db-migrations/references/backfill-and-batching.md +105 -0
- package/skills/db-migrations/references/expand-contract-playbook.md +152 -0
- package/skills/db-migrations/references/tools-and-runners.md +88 -0
- package/skills/db-migrations/scripts/verify.sh +112 -0
- package/skills/debug/SKILL.md +227 -0
- package/skills/debug/evals/README.md +88 -0
- package/skills/debug/evals/cases.yaml +74 -0
- package/skills/decision-records/SKILL.md +189 -0
- package/skills/decision-records/evals/README.md +3 -0
- package/skills/decision-records/evals/cases.yaml +43 -0
- package/skills/decision-records/references/templates.md +232 -0
- package/skills/decision-records/scripts/verify.sh +105 -0
- package/skills/deployment/SKILL.md +439 -0
- package/skills/deployment/evals/README.md +50 -0
- package/skills/deployment/evals/cases.yaml +53 -0
- package/skills/deployment/references/coolify.md +216 -0
- package/skills/deployment/references/dockerfiles-by-stack.md +319 -0
- package/skills/deployment/references/github-actions.md +295 -0
- package/skills/deployment/references/hosting-targets.md +272 -0
- package/skills/deployment/scripts/verify.sh +134 -0
- package/skills/design/SKILL.md +399 -0
- package/skills/design/evals/README.md +53 -0
- package/skills/design/evals/cases.yaml +56 -0
- package/skills/design/references/brand-grounding.md +187 -0
- package/skills/design/references/copywriting-frameworks.md +138 -0
- package/skills/design/references/landing-anatomy-and-cro.md +202 -0
- package/skills/design/references/motion-and-interaction.md +182 -0
- package/skills/design/references/research-method.md +147 -0
- package/skills/design/references/signature-and-craft.md +148 -0
- package/skills/design/references/trends-2026.md +80 -0
- package/skills/design/references/visual-system.md +236 -0
- package/skills/design/scripts/verify.sh +248 -0
- package/skills/digitalocean/SKILL.md +251 -0
- package/skills/digitalocean/evals/README.md +10 -0
- package/skills/digitalocean/evals/cases.yaml +37 -0
- package/skills/digitalocean/references/app-spec.md +126 -0
- package/skills/digitalocean/references/droplet-ops.md +95 -0
- package/skills/digitalocean/scripts/verify.sh +102 -0
- package/skills/django/SKILL.md +268 -0
- package/skills/django/evals/README.md +11 -0
- package/skills/django/evals/cases.yaml +47 -0
- package/skills/django/references/drf.md +109 -0
- package/skills/django/references/orm-performance.md +91 -0
- package/skills/django/references/security.md +81 -0
- package/skills/django/references/testing.md +86 -0
- package/skills/django/scripts/verify.sh +115 -0
- package/skills/docker/SKILL.md +283 -0
- package/skills/docker/evals/README.md +10 -0
- package/skills/docker/evals/cases.yaml +44 -0
- package/skills/docker/references/base-images-and-stages.md +104 -0
- package/skills/docker/references/compose-recipes.md +109 -0
- package/skills/docker/scripts/verify.sh +149 -0
- package/skills/document-processing/SKILL.md +214 -0
- package/skills/document-processing/evals/README.md +3 -0
- package/skills/document-processing/evals/cases.yaml +65 -0
- package/skills/document-processing/references/engines.md +67 -0
- package/skills/document-processing/scripts/verify.sh +172 -0
- package/skills/domains-dns/SKILL.md +146 -0
- package/skills/domains-dns/evals/README.md +16 -0
- package/skills/domains-dns/evals/cases.yaml +47 -0
- package/skills/domains-dns/references/record-cookbook.md +94 -0
- package/skills/domains-dns/references/tls-and-acme.md +90 -0
- package/skills/domains-dns/references/verify-and-debug.md +64 -0
- package/skills/domains-dns/scripts/verify.sh +163 -0
- package/skills/drizzle-orm/SKILL.md +234 -0
- package/skills/drizzle-orm/evals/README.md +12 -0
- package/skills/drizzle-orm/evals/cases.yaml +47 -0
- package/skills/drizzle-orm/references/relations-and-drivers.md +118 -0
- package/skills/drizzle-orm/scripts/verify.sh +155 -0
- package/skills/duckdb/SKILL.md +207 -0
- package/skills/duckdb/evals/README.md +31 -0
- package/skills/duckdb/evals/cases.yaml +41 -0
- package/skills/duckdb/references/python-and-interop.md +105 -0
- package/skills/duckdb/references/remote-and-lakehouse.md +101 -0
- package/skills/duckdb/scripts/verify.sh +71 -0
- package/skills/dynamodb/SKILL.md +217 -0
- package/skills/dynamodb/evals/README.md +8 -0
- package/skills/dynamodb/evals/cases.yaml +46 -0
- package/skills/dynamodb/references/access-patterns.md +127 -0
- package/skills/dynamodb/references/capacity-and-limits.md +78 -0
- package/skills/dynamodb/scripts/verify.sh +108 -0
- package/skills/e-signature/SKILL.md +185 -0
- package/skills/e-signature/evals/README.md +3 -0
- package/skills/e-signature/evals/cases.yaml +44 -0
- package/skills/e-signature/references/docusign.md +83 -0
- package/skills/e-signature/references/dropbox-sign.md +73 -0
- package/skills/e-signature/references/legal-tiers.md +37 -0
- package/skills/e-signature/scripts/verify.sh +81 -0
- package/skills/e2e-testing/SKILL.md +243 -0
- package/skills/e2e-testing/evals/README.md +10 -0
- package/skills/e2e-testing/evals/cases.yaml +64 -0
- package/skills/e2e-testing/references/config-and-ci.md +156 -0
- package/skills/e2e-testing/references/flakiness-playbook.md +124 -0
- package/skills/e2e-testing/scripts/verify.sh +117 -0
- package/skills/electron/SKILL.md +221 -0
- package/skills/electron/evals/README.md +13 -0
- package/skills/electron/evals/cases.yaml +38 -0
- package/skills/electron/references/packaging-and-updates.md +122 -0
- package/skills/electron/references/security-and-ipc.md +158 -0
- package/skills/electron/scripts/verify.sh +143 -0
- package/skills/elixir/SKILL.md +217 -0
- package/skills/elixir/evals/README.md +3 -0
- package/skills/elixir/evals/cases.yaml +41 -0
- package/skills/elixir/references/mix-and-releases.md +91 -0
- package/skills/elixir/references/otp-patterns.md +96 -0
- package/skills/elixir/scripts/verify.sh +76 -0
- package/skills/email-connector/SKILL.md +294 -0
- package/skills/email-connector/evals/README.md +19 -0
- package/skills/email-connector/evals/cases.yaml +39 -0
- package/skills/email-connector/references/providers.md +107 -0
- package/skills/email-connector/scripts/verify.sh +72 -0
- package/skills/email-deliverability/SKILL.md +168 -0
- package/skills/email-deliverability/evals/README.md +21 -0
- package/skills/email-deliverability/evals/cases.yaml +45 -0
- package/skills/email-deliverability/scripts/verify.sh +98 -0
- package/skills/embeddings-search/SKILL.md +193 -0
- package/skills/embeddings-search/evals/README.md +10 -0
- package/skills/embeddings-search/evals/cases.yaml +44 -0
- package/skills/embeddings-search/references/evaluation.md +86 -0
- package/skills/embeddings-search/references/models.md +73 -0
- package/skills/embeddings-search/scripts/verify.sh +103 -0
- package/skills/error-handling/SKILL.md +307 -0
- package/skills/error-handling/evals/README.md +12 -0
- package/skills/error-handling/evals/cases.yaml +46 -0
- package/skills/error-handling/references/boundaries-and-messaging.md +120 -0
- package/skills/error-handling/references/retry-and-resilience.md +154 -0
- package/skills/error-handling/scripts/verify.sh +110 -0
- package/skills/expo/SKILL.md +253 -0
- package/skills/expo/evals/README.md +13 -0
- package/skills/expo/evals/cases.yaml +44 -0
- package/skills/expo/references/config-plugins.md +117 -0
- package/skills/expo/references/eas-update.md +118 -0
- package/skills/expo/scripts/verify.sh +132 -0
- package/skills/fal/SKILL.md +210 -0
- package/skills/fal/evals/README.md +3 -0
- package/skills/fal/evals/cases.yaml +42 -0
- package/skills/fal/references/models-and-cost.md +53 -0
- package/skills/fal/references/queue-and-webhooks.md +153 -0
- package/skills/fal/scripts/verify.sh +72 -0
- package/skills/fastapi/SKILL.md +499 -0
- package/skills/fastapi/evals/README.md +50 -0
- package/skills/fastapi/evals/cases.yaml +55 -0
- package/skills/fastapi/references/database.md +347 -0
- package/skills/fastapi/references/production.md +338 -0
- package/skills/fastapi/references/security.md +330 -0
- package/skills/fastapi/references/testing.md +349 -0
- package/skills/fastapi/scripts/verify.sh +116 -0
- package/skills/finance-ops/SKILL.md +149 -0
- package/skills/finance-ops/evals/README.md +3 -0
- package/skills/finance-ops/evals/cases.yaml +39 -0
- package/skills/finance-ops/references/cash-flow-forecast.md +57 -0
- package/skills/finance-ops/references/month-close.md +59 -0
- package/skills/finance-ops/references/reconciliation.md +65 -0
- package/skills/finance-ops/scripts/verify.sh +166 -0
- package/skills/financial-model/SKILL.md +170 -0
- package/skills/financial-model/evals/README.md +3 -0
- package/skills/financial-model/evals/cases.yaml +53 -0
- package/skills/financial-model/references/benchmarks-and-scenarios.md +55 -0
- package/skills/financial-model/references/model-structure.md +67 -0
- package/skills/financial-model/references/revenue-build.md +68 -0
- package/skills/financial-model/scripts/verify.sh +232 -0
- package/skills/firebase/SKILL.md +251 -0
- package/skills/firebase/evals/README.md +12 -0
- package/skills/firebase/evals/cases.yaml +45 -0
- package/skills/firebase/references/cloud-functions.md +102 -0
- package/skills/firebase/references/data-modeling.md +108 -0
- package/skills/firebase/references/security-rules.md +137 -0
- package/skills/firebase/scripts/verify.sh +98 -0
- package/skills/flutter/SKILL.md +448 -0
- package/skills/flutter/evals/README.md +54 -0
- package/skills/flutter/evals/cases.yaml +69 -0
- package/skills/flutter/references/architecture-and-state.md +499 -0
- package/skills/flutter/references/i18n-and-dependencies.md +197 -0
- package/skills/flutter/references/performance.md +299 -0
- package/skills/flutter/references/testing.md +385 -0
- package/skills/flutter/references/ui-and-navigation.md +378 -0
- package/skills/flutter/scripts/verify.sh +104 -0
- package/skills/fly-io/SKILL.md +206 -0
- package/skills/fly-io/evals/README.md +3 -0
- package/skills/fly-io/evals/cases.yaml +42 -0
- package/skills/fly-io/references/fly-toml.md +155 -0
- package/skills/fly-io/references/multi-region.md +66 -0
- package/skills/fly-io/scripts/verify.sh +90 -0
- package/skills/forecasting/SKILL.md +139 -0
- package/skills/forecasting/evals/README.md +13 -0
- package/skills/forecasting/evals/cases.yaml +47 -0
- package/skills/forecasting/references/accuracy-and-backtesting.md +104 -0
- package/skills/forecasting/references/methods-cheatsheet.md +94 -0
- package/skills/forecasting/scripts/verify.sh +99 -0
- package/skills/fundraising/SKILL.md +162 -0
- package/skills/fundraising/evals/README.md +18 -0
- package/skills/fundraising/evals/cases.yaml +76 -0
- package/skills/fundraising/references/funnel-math.md +90 -0
- package/skills/fundraising/references/process-playbook.md +97 -0
- package/skills/gcp-essentials/SKILL.md +327 -0
- package/skills/gcp-essentials/evals/README.md +12 -0
- package/skills/gcp-essentials/evals/cases.yaml +38 -0
- package/skills/gcp-essentials/references/deploy-recipes.md +81 -0
- package/skills/gcp-essentials/references/iam-and-auth.md +94 -0
- package/skills/gcp-essentials/references/networking-and-sql.md +74 -0
- package/skills/gcp-essentials/scripts/verify.sh +158 -0
- package/skills/gdpr-privacy/SKILL.md +167 -0
- package/skills/gdpr-privacy/evals/README.md +3 -0
- package/skills/gdpr-privacy/evals/cases.yaml +47 -0
- package/skills/gdpr-privacy/references/dpa-and-transfers.md +63 -0
- package/skills/gdpr-privacy/references/dsar-and-consent.md +83 -0
- package/skills/gdpr-privacy/references/privacy-policy-blueprint.md +99 -0
- package/skills/gdpr-privacy/scripts/verify.sh +84 -0
- package/skills/git-workflow/SKILL.md +190 -0
- package/skills/git-workflow/evals/README.md +10 -0
- package/skills/git-workflow/evals/cases.yaml +47 -0
- package/skills/git-workflow/references/interactive-rebase.md +89 -0
- package/skills/github-actions/SKILL.md +256 -0
- package/skills/github-actions/evals/README.md +3 -0
- package/skills/github-actions/evals/cases.yaml +45 -0
- package/skills/github-actions/references/caching-and-matrix.md +92 -0
- package/skills/github-actions/references/oidc-deploys.md +130 -0
- package/skills/github-actions/scripts/verify.sh +105 -0
- package/skills/go/SKILL.md +438 -0
- package/skills/go/evals/README.md +56 -0
- package/skills/go/evals/cases.yaml +55 -0
- package/skills/go/references/concurrency.md +557 -0
- package/skills/go/references/http-services.md +529 -0
- package/skills/go/references/testing.md +338 -0
- package/skills/go/scripts/verify.sh +109 -0
- package/skills/google-workspace/SKILL.md +287 -0
- package/skills/google-workspace/evals/README.md +16 -0
- package/skills/google-workspace/evals/cases.yaml +44 -0
- package/skills/google-workspace/references/api-recipes.md +148 -0
- package/skills/google-workspace/references/auth-setup.md +100 -0
- package/skills/google-workspace/scripts/verify.sh +128 -0
- package/skills/grants/SKILL.md +171 -0
- package/skills/grants/evals/README.md +3 -0
- package/skills/grants/evals/cases.yaml +69 -0
- package/skills/grants/references/budget-justification.md +71 -0
- package/skills/grants/references/jurisdictions.md +35 -0
- package/skills/grants/references/logic-model.md +66 -0
- package/skills/grants/scripts/verify.sh +193 -0
- package/skills/harness/SKILL.md +329 -0
- package/skills/harness/assets/_TEMPLATE/.env.example +8 -0
- package/skills/harness/assets/_TEMPLATE/CREDENTIALS.md +25 -0
- package/skills/harness/assets/_TEMPLATE/README.md +25 -0
- package/skills/harness/assets/_TEMPLATE/test_connection.sh +30 -0
- package/skills/harness/evals/README.md +54 -0
- package/skills/harness/evals/cases.yaml +72 -0
- package/skills/harness/examples/audit-example.md +120 -0
- package/skills/harness/references/agents-md-template.md +41 -0
- package/skills/harness/references/audit-report-template.html +140 -0
- package/skills/harness/references/audit-report-template.md +116 -0
- package/skills/harness/references/claude-md-template.md +98 -0
- package/skills/harness/references/inbox-readme-template.md +51 -0
- package/skills/harness/references/ingest-formats.md +185 -0
- package/skills/harness/references/providers.yaml +3410 -0
- package/skills/harness/references/tools-readme-template.md +88 -0
- package/skills/harness/references/wiki-archive-template.html +81 -0
- package/skills/harness/references/wiki-article-template.md +20 -0
- package/skills/harness/references/wiki-dashboard-template.html +136 -0
- package/skills/harness/references/wiki-deep-improve-report-template.html +126 -0
- package/skills/harness/references/wiki-gaps-template.md +18 -0
- package/skills/harness/references/wiki-index-template.md +23 -0
- package/skills/harness/references/wiki-protocol.md +699 -0
- package/skills/harness/references/wiki-raw-template.md +7 -0
- package/skills/hetzner/SKILL.md +221 -0
- package/skills/hetzner/evals/README.md +35 -0
- package/skills/hetzner/evals/cases.yaml +46 -0
- package/skills/hetzner/references/cloud-init.md +120 -0
- package/skills/hetzner/references/plans-and-locations.md +56 -0
- package/skills/hetzner/scripts/verify.sh +122 -0
- package/skills/hiring/SKILL.md +248 -0
- package/skills/hiring/evals/README.md +13 -0
- package/skills/hiring/evals/cases.yaml +41 -0
- package/skills/hiring/references/templates.md +118 -0
- package/skills/htmx/SKILL.md +261 -0
- package/skills/htmx/evals/README.md +3 -0
- package/skills/htmx/evals/cases.yaml +38 -0
- package/skills/htmx/references/patterns.md +113 -0
- package/skills/htmx/references/server-contract.md +91 -0
- package/skills/htmx/scripts/verify.sh +93 -0
- package/skills/huggingface/SKILL.md +190 -0
- package/skills/huggingface/evals/README.md +11 -0
- package/skills/huggingface/evals/cases.yaml +41 -0
- package/skills/huggingface/references/endpoints-and-spaces.md +99 -0
- package/skills/huggingface/references/hub-and-cli.md +85 -0
- package/skills/huggingface/references/inference-providers.md +115 -0
- package/skills/huggingface/scripts/verify.sh +123 -0
- package/skills/implement/SKILL.md +283 -0
- package/skills/implement/evals/README.md +56 -0
- package/skills/implement/evals/cases.yaml +43 -0
- package/skills/init/SKILL.md +184 -0
- package/skills/init/evals/README.md +49 -0
- package/skills/init/evals/cases.yaml +74 -0
- package/skills/init/references/accompaniment-and-profile.md +140 -0
- package/skills/init/references/discovery.md +90 -0
- package/skills/init/references/recommend-skills.md +115 -0
- package/skills/init/scripts/verify.sh +122 -0
- package/skills/instagram-api/SKILL.md +241 -0
- package/skills/instagram-api/evals/README.md +3 -0
- package/skills/instagram-api/evals/cases.yaml +43 -0
- package/skills/instagram-api/references/insights-metrics.md +88 -0
- package/skills/instagram-api/references/publish-reel.md +98 -0
- package/skills/instagram-api/scripts/verify.sh +137 -0
- package/skills/inventory/SKILL.md +131 -0
- package/skills/inventory/evals/README.md +3 -0
- package/skills/inventory/evals/cases.yaml +43 -0
- package/skills/inventory/references/abc-xyz.md +52 -0
- package/skills/inventory/references/ddmrp.md +32 -0
- package/skills/inventory/references/reorder-policies.md +85 -0
- package/skills/inventory/references/safety-stock.md +63 -0
- package/skills/inventory/scripts/verify.sh +155 -0
- package/skills/investor-materials/SKILL.md +175 -0
- package/skills/investor-materials/evals/README.md +15 -0
- package/skills/investor-materials/evals/cases.yaml +60 -0
- package/skills/investor-materials/references/dataroom-checklist.md +134 -0
- package/skills/investor-materials/references/update-and-onepager-templates.md +152 -0
- package/skills/investor-materials/scripts/verify.sh +148 -0
- package/skills/invoicing/SKILL.md +154 -0
- package/skills/invoicing/evals/README.md +5 -0
- package/skills/invoicing/evals/cases.yaml +49 -0
- package/skills/invoicing/references/dunning-ladder.md +53 -0
- package/skills/invoicing/references/e-invoicing-mandates.md +43 -0
- package/skills/invoicing/scripts/fixtures/broken-invoice.json +13 -0
- package/skills/invoicing/scripts/fixtures/valid-invoice.json +15 -0
- package/skills/invoicing/scripts/verify.sh +133 -0
- package/skills/ip-trademark/SKILL.md +186 -0
- package/skills/ip-trademark/evals/README.md +10 -0
- package/skills/ip-trademark/evals/cases.yaml +47 -0
- package/skills/ip-trademark/references/jurisdictions.md +63 -0
- package/skills/ip-trademark/references/ownership-and-licensing.md +90 -0
- package/skills/java/SKILL.md +341 -0
- package/skills/java/evals/README.md +23 -0
- package/skills/java/evals/cases.yaml +43 -0
- package/skills/java/references/builds.md +133 -0
- package/skills/java/references/concurrency.md +108 -0
- package/skills/java/references/streams.md +102 -0
- package/skills/java/scripts/verify.sh +107 -0
- package/skills/knowledge-ops/SKILL.md +125 -0
- package/skills/knowledge-ops/evals/README.md +16 -0
- package/skills/knowledge-ops/evals/cases.yaml +50 -0
- package/skills/knowledge-ops/references/gardening-playbook.md +116 -0
- package/skills/kotlin-android/SKILL.md +245 -0
- package/skills/kotlin-android/evals/README.md +13 -0
- package/skills/kotlin-android/evals/cases.yaml +56 -0
- package/skills/kotlin-android/references/architecture.md +200 -0
- package/skills/kotlin-android/references/gradle-setup.md +125 -0
- package/skills/kotlin-android/scripts/verify.sh +109 -0
- package/skills/kpi-framework/SKILL.md +199 -0
- package/skills/kpi-framework/evals/README.md +11 -0
- package/skills/kpi-framework/evals/cases.yaml +42 -0
- package/skills/kpi-framework/references/definition-and-targets.md +64 -0
- package/skills/kpi-framework/references/metric-catalog.md +84 -0
- package/skills/landing-copy/SKILL.md +153 -0
- package/skills/landing-copy/evals/README.md +18 -0
- package/skills/landing-copy/evals/cases.yaml +63 -0
- package/skills/landing-copy/references/frameworks.md +61 -0
- package/skills/landing-copy/references/page-skeleton.md +92 -0
- package/skills/landing-copy/scripts/verify.sh +164 -0
- package/skills/laravel/SKILL.md +301 -0
- package/skills/laravel/evals/README.md +10 -0
- package/skills/laravel/evals/cases.yaml +45 -0
- package/skills/laravel/references/eloquent-patterns.md +126 -0
- package/skills/laravel/references/queues-and-scheduling.md +153 -0
- package/skills/laravel/scripts/verify.sh +128 -0
- package/skills/lead-gen/SKILL.md +155 -0
- package/skills/lead-gen/evals/README.md +3 -0
- package/skills/lead-gen/evals/cases.yaml +43 -0
- package/skills/lead-gen/references/data-sources.md +87 -0
- package/skills/lead-gen/references/scoring-model.md +93 -0
- package/skills/lead-gen/scripts/verify.sh +179 -0
- package/skills/linkedin-api/SKILL.md +211 -0
- package/skills/linkedin-api/evals/README.md +3 -0
- package/skills/linkedin-api/evals/cases.yaml +41 -0
- package/skills/linkedin-api/references/api-reference.md +168 -0
- package/skills/linkedin-api/scripts/verify.sh +98 -0
- package/skills/linkedin-carousels/SKILL.md +239 -0
- package/skills/linkedin-carousels/evals/README.md +13 -0
- package/skills/linkedin-carousels/evals/cases.yaml +62 -0
- package/skills/linkedin-carousels/references/carousel-patterns.md +200 -0
- package/skills/linkedin-carousels/scripts/verify.sh +160 -0
- package/skills/linkedin-content/SKILL.md +162 -0
- package/skills/linkedin-content/evals/README.md +13 -0
- package/skills/linkedin-content/evals/cases.yaml +62 -0
- package/skills/linkedin-content/references/hooks-and-formats.md +114 -0
- package/skills/linkedin-content/scripts/verify.sh +154 -0
- package/skills/linkedin-outreach/SKILL.md +174 -0
- package/skills/linkedin-outreach/evals/README.md +3 -0
- package/skills/linkedin-outreach/evals/cases.yaml +43 -0
- package/skills/linkedin-outreach/references/ledger-schema.md +48 -0
- package/skills/linkedin-outreach/references/sales-navigator-playbook.md +61 -0
- package/skills/linkedin-outreach/scripts/verify.sh +120 -0
- package/skills/linkedin-strategy/SKILL.md +167 -0
- package/skills/linkedin-strategy/evals/README.md +3 -0
- package/skills/linkedin-strategy/evals/cases.yaml +49 -0
- package/skills/linkedin-strategy/references/ssi-and-pillars.md +59 -0
- package/skills/linkedin-strategy/references/wiki-records.md +62 -0
- package/skills/linkedin-strategy/scripts/verify.sh +120 -0
- package/skills/llm-pipeline/SKILL.md +155 -0
- package/skills/llm-pipeline/evals/README.md +3 -0
- package/skills/llm-pipeline/evals/cases.yaml +44 -0
- package/skills/llm-pipeline/references/caching-layers.md +60 -0
- package/skills/llm-pipeline/references/litellm-router.md +101 -0
- package/skills/llm-pipeline/scripts/verify.sh +169 -0
- package/skills/logistics-ops/SKILL.md +219 -0
- package/skills/logistics-ops/evals/README.md +20 -0
- package/skills/logistics-ops/evals/cases.yaml +48 -0
- package/skills/logistics-ops/references/carriers-and-claims.md +105 -0
- package/skills/market-research/SKILL.md +145 -0
- package/skills/market-research/evals/README.md +3 -0
- package/skills/market-research/evals/cases.yaml +48 -0
- package/skills/market-research/references/demand-signals.md +63 -0
- package/skills/market-research/references/sizing-playbook.md +121 -0
- package/skills/market-research/scripts/verify.sh +215 -0
- package/skills/marketing/SKILL.md +233 -0
- package/skills/marketing/evals/README.md +61 -0
- package/skills/marketing/evals/cases.yaml +84 -0
- package/skills/marketing/references/brand-grounding.md +197 -0
- package/skills/marketing/references/campaigns-and-channels.md +151 -0
- package/skills/marketing/references/copy-frameworks.md +166 -0
- package/skills/marketing/references/landing-copy.md +191 -0
- package/skills/marketing/references/seo-geo.md +391 -0
- package/skills/marketing/scripts/seo_audit.py +166 -0
- package/skills/marketing/scripts/verify.sh +233 -0
- package/skills/medium-publishing/SKILL.md +152 -0
- package/skills/medium-publishing/evals/README.md +3 -0
- package/skills/medium-publishing/evals/cases.yaml +42 -0
- package/skills/medium-publishing/references/cross-post-and-canonical.md +65 -0
- package/skills/medium-publishing/references/legacy-api.md +100 -0
- package/skills/medium-strategy/SKILL.md +161 -0
- package/skills/medium-strategy/evals/README.md +3 -0
- package/skills/medium-strategy/evals/cases.yaml +50 -0
- package/skills/medium-strategy/references/distribution-and-boost.md +65 -0
- package/skills/medium-strategy/references/wiki-records.md +60 -0
- package/skills/medium-strategy/scripts/verify.sh +118 -0
- package/skills/medium-writing/SKILL.md +140 -0
- package/skills/medium-writing/evals/README.md +5 -0
- package/skills/medium-writing/evals/cases.yaml +39 -0
- package/skills/medium-writing/references/title-patterns.md +79 -0
- package/skills/meeting-notes/SKILL.md +168 -0
- package/skills/meeting-notes/evals/README.md +14 -0
- package/skills/meeting-notes/evals/cases.yaml +46 -0
- package/skills/meeting-notes/references/templates.md +140 -0
- package/skills/modal/SKILL.md +307 -0
- package/skills/modal/evals/README.md +29 -0
- package/skills/modal/evals/cases.yaml +50 -0
- package/skills/modal/references/images-gpu-cookbook.md +160 -0
- package/skills/modal/references/web-and-scaling.md +138 -0
- package/skills/modal/scripts/verify.sh +127 -0
- package/skills/mongodb/SKILL.md +342 -0
- package/skills/mongodb/evals/README.md +29 -0
- package/skills/mongodb/evals/cases.yaml +41 -0
- package/skills/mongodb/references/aggregation.md +115 -0
- package/skills/mongodb/references/data-modeling.md +135 -0
- package/skills/mongodb/references/transactions-and-ops.md +128 -0
- package/skills/mongodb/scripts/verify.sh +151 -0
- package/skills/monitoring/SKILL.md +155 -0
- package/skills/monitoring/evals/README.md +3 -0
- package/skills/monitoring/evals/cases.yaml +47 -0
- package/skills/monitoring/references/burn-rate-and-oncall.md +128 -0
- package/skills/monitoring/references/tool-setup.md +154 -0
- package/skills/monitoring/scripts/verify.sh +145 -0
- package/skills/mysql/SKILL.md +249 -0
- package/skills/mysql/evals/README.md +12 -0
- package/skills/mysql/evals/cases.yaml +49 -0
- package/skills/mysql/references/indexing-and-explain.md +161 -0
- package/skills/mysql/references/mysql-vs-mariadb.md +78 -0
- package/skills/mysql/references/online-ddl-and-migrations.md +120 -0
- package/skills/mysql/references/replication-and-ha.md +115 -0
- package/skills/mysql/scripts/verify.sh +141 -0
- package/skills/neon/SKILL.md +218 -0
- package/skills/neon/evals/README.md +11 -0
- package/skills/neon/evals/cases.yaml +45 -0
- package/skills/neon/references/branching-ci.md +86 -0
- package/skills/neon/scripts/verify.sh +78 -0
- package/skills/nestjs/SKILL.md +225 -0
- package/skills/nestjs/evals/README.md +3 -0
- package/skills/nestjs/evals/cases.yaml +38 -0
- package/skills/nestjs/references/cross-cutting.md +135 -0
- package/skills/nestjs/references/testing-recipes.md +105 -0
- package/skills/nestjs/scripts/verify.sh +98 -0
- package/skills/netlify/SKILL.md +208 -0
- package/skills/netlify/evals/README.md +13 -0
- package/skills/netlify/evals/cases.yaml +43 -0
- package/skills/netlify/references/functions.md +97 -0
- package/skills/netlify/references/netlify-toml.md +115 -0
- package/skills/netlify/scripts/verify.sh +95 -0
- package/skills/newsletter/SKILL.md +162 -0
- package/skills/newsletter/evals/README.md +12 -0
- package/skills/newsletter/evals/cases.yaml +42 -0
- package/skills/newsletter/references/growth-loops.md +73 -0
- package/skills/newsletter/references/welcome-sequence.md +62 -0
- package/skills/newsletter/scripts/verify.sh +173 -0
- package/skills/nextjs/SKILL.md +472 -0
- package/skills/nextjs/evals/README.md +59 -0
- package/skills/nextjs/evals/cases.yaml +56 -0
- package/skills/nextjs/references/data-and-caching.md +309 -0
- package/skills/nextjs/references/metadata.md +208 -0
- package/skills/nextjs/references/performance.md +325 -0
- package/skills/nextjs/references/react.md +383 -0
- package/skills/nextjs/references/security.md +239 -0
- package/skills/nextjs/references/testing.md +290 -0
- package/skills/nextjs/scripts/verify.sh +141 -0
- package/skills/no-code-app/SKILL.md +153 -0
- package/skills/no-code-app/evals/README.md +3 -0
- package/skills/no-code-app/evals/cases.yaml +43 -0
- package/skills/no-code-app/references/platform-limits.md +100 -0
- package/skills/nodejs/SKILL.md +242 -0
- package/skills/nodejs/evals/README.md +3 -0
- package/skills/nodejs/evals/cases.yaml +39 -0
- package/skills/nodejs/references/express5-migration.md +53 -0
- package/skills/nodejs/references/graceful-shutdown.md +73 -0
- package/skills/nodejs/scripts/verify.sh +122 -0
- package/skills/notion-connector/SKILL.md +234 -0
- package/skills/notion-connector/evals/README.md +15 -0
- package/skills/notion-connector/evals/cases.yaml +45 -0
- package/skills/notion-connector/references/api-versions.md +63 -0
- package/skills/notion-connector/references/property-shapes.md +110 -0
- package/skills/notion-connector/references/sync-patterns.md +95 -0
- package/skills/notion-connector/scripts/verify.sh +162 -0
- package/skills/observability/SKILL.md +231 -0
- package/skills/observability/evals/README.md +3 -0
- package/skills/observability/evals/cases.yaml +49 -0
- package/skills/observability/references/collector-config.md +98 -0
- package/skills/observability/references/instrumentation-recipes.md +115 -0
- package/skills/observability/scripts/verify.sh +156 -0
- package/skills/ollama/SKILL.md +213 -0
- package/skills/ollama/evals/README.md +9 -0
- package/skills/ollama/evals/cases.yaml +43 -0
- package/skills/ollama/references/api.md +148 -0
- package/skills/ollama/references/hardware-sizing.md +87 -0
- package/skills/ollama/scripts/verify.sh +116 -0
- package/skills/orient/SKILL.md +54 -0
- package/skills/orient/evals/README.md +16 -0
- package/skills/orient/evals/cases.yaml +57 -0
- package/skills/orient/references/orientation-contract.md +34 -0
- package/skills/parallel/SKILL.md +198 -0
- package/skills/parallel/evals/README.md +62 -0
- package/skills/parallel/evals/cases.yaml +44 -0
- package/skills/people-ops/SKILL.md +122 -0
- package/skills/people-ops/evals/README.md +14 -0
- package/skills/people-ops/evals/cases.yaml +43 -0
- package/skills/people-ops/references/templates.md +129 -0
- package/skills/performance/SKILL.md +221 -0
- package/skills/performance/evals/README.md +3 -0
- package/skills/performance/evals/cases.yaml +47 -0
- package/skills/performance/references/profiling-playbook.md +54 -0
- package/skills/performance/scripts/verify.sh +94 -0
- package/skills/phoenix/SKILL.md +169 -0
- package/skills/phoenix/evals/README.md +3 -0
- package/skills/phoenix/evals/cases.yaml +40 -0
- package/skills/phoenix/references/auth-and-scopes.md +82 -0
- package/skills/phoenix/references/ecto-patterns.md +93 -0
- package/skills/phoenix/references/liveview.md +134 -0
- package/skills/phoenix/scripts/verify.sh +73 -0
- package/skills/php/SKILL.md +397 -0
- package/skills/php/evals/README.md +12 -0
- package/skills/php/evals/cases.yaml +45 -0
- package/skills/php/references/tooling.md +170 -0
- package/skills/php/references/type-system.md +220 -0
- package/skills/php/scripts/verify.sh +155 -0
- package/skills/pitch-deck/SKILL.md +209 -0
- package/skills/pitch-deck/evals/README.md +15 -0
- package/skills/pitch-deck/evals/cases.yaml +55 -0
- package/skills/pitch-deck/references/numbers-that-matter.md +78 -0
- package/skills/pitch-deck/references/slide-spine.md +149 -0
- package/skills/pitch-deck/scripts/verify.sh +186 -0
- package/skills/plan/SKILL.md +204 -0
- package/skills/plan/evals/README.md +62 -0
- package/skills/plan/evals/cases.yaml +49 -0
- package/skills/plan/references/plan-template.md +124 -0
- package/skills/planetscale/SKILL.md +223 -0
- package/skills/planetscale/evals/README.md +11 -0
- package/skills/planetscale/evals/cases.yaml +46 -0
- package/skills/planetscale/references/deploy-requests.md +75 -0
- package/skills/planetscale/references/no-foreign-keys.md +88 -0
- package/skills/planetscale/scripts/verify.sh +115 -0
- package/skills/podcast/SKILL.md +166 -0
- package/skills/podcast/evals/README.md +17 -0
- package/skills/podcast/evals/cases.yaml +61 -0
- package/skills/podcast/references/rss-and-namespace.md +136 -0
- package/skills/podcast/scripts/verify.sh +246 -0
- package/skills/postgresdb/SKILL.md +372 -0
- package/skills/postgresdb/evals/README.md +55 -0
- package/skills/postgresdb/evals/cases.yaml +57 -0
- package/skills/postgresdb/references/migrations.md +279 -0
- package/skills/postgresdb/references/operations-and-security.md +267 -0
- package/skills/postgresdb/references/query-optimization.md +374 -0
- package/skills/postgresdb/references/schema-and-indexing.md +379 -0
- package/skills/postgresdb/scripts/verify.sh +191 -0
- package/skills/presentations/SKILL.md +296 -0
- package/skills/presentations/evals/README.md +61 -0
- package/skills/presentations/evals/cases.yaml +56 -0
- package/skills/presentations/references/brand-grounding.md +160 -0
- package/skills/presentations/references/markdown-decks.md +290 -0
- package/skills/presentations/references/pptx-python.md +242 -0
- package/skills/presentations/references/slide-design.md +261 -0
- package/skills/presentations/references/storytelling-and-decks.md +150 -0
- package/skills/presentations/scripts/verify.sh +252 -0
- package/skills/press-kit/SKILL.md +243 -0
- package/skills/press-kit/evals/README.md +15 -0
- package/skills/press-kit/evals/cases.yaml +55 -0
- package/skills/press-kit/references/release-types.md +102 -0
- package/skills/press-kit/references/templates.md +132 -0
- package/skills/press-kit/scripts/verify.sh +161 -0
- package/skills/pricing/SKILL.md +160 -0
- package/skills/pricing/evals/README.md +5 -0
- package/skills/pricing/evals/cases.yaml +44 -0
- package/skills/pricing/references/localization.md +56 -0
- package/skills/pricing/references/pricing-models.md +55 -0
- package/skills/pricing/scripts/verify.sh +91 -0
- package/skills/prisma-orm/SKILL.md +320 -0
- package/skills/prisma-orm/evals/README.md +12 -0
- package/skills/prisma-orm/evals/cases.yaml +56 -0
- package/skills/prisma-orm/references/migrations-and-v7-upgrade.md +197 -0
- package/skills/prisma-orm/references/queries-and-performance.md +169 -0
- package/skills/prisma-orm/scripts/verify.sh +137 -0
- package/skills/procurement/SKILL.md +179 -0
- package/skills/procurement/evals/README.md +20 -0
- package/skills/procurement/evals/cases.yaml +49 -0
- package/skills/procurement/references/scorecard-and-tco.md +100 -0
- package/skills/procurement/references/sourcing-requests.md +116 -0
- package/skills/procurement/scripts/verify.sh +280 -0
- package/skills/project-ops/SKILL.md +130 -0
- package/skills/project-ops/evals/README.md +3 -0
- package/skills/project-ops/evals/cases.yaml +71 -0
- package/skills/project-ops/references/raid-and-rag.md +58 -0
- package/skills/project-ops/references/status-report-template.md +68 -0
- package/skills/project-ops/scripts/verify.sh +257 -0
- package/skills/prompt-engineering/SKILL.md +138 -0
- package/skills/prompt-engineering/evals/README.md +11 -0
- package/skills/prompt-engineering/evals/cases.yaml +46 -0
- package/skills/prompt-engineering/references/eval-templates.md +94 -0
- package/skills/prompt-engineering/references/output-contracts.md +120 -0
- package/skills/prompt-engineering/scripts/verify.sh +84 -0
- package/skills/proposals/SKILL.md +159 -0
- package/skills/proposals/evals/README.md +3 -0
- package/skills/proposals/evals/cases.yaml +53 -0
- package/skills/proposals/references/proposal-skeleton.md +110 -0
- package/skills/proposals/references/sow-skeleton.md +79 -0
- package/skills/proposals/scripts/verify.sh +201 -0
- package/skills/python/SKILL.md +369 -0
- package/skills/python/evals/README.md +19 -0
- package/skills/python/evals/cases.yaml +46 -0
- package/skills/python/references/async.md +136 -0
- package/skills/python/references/stdlib.md +162 -0
- package/skills/python/references/typing.md +160 -0
- package/skills/python/scripts/verify.sh +125 -0
- package/skills/rag/SKILL.md +226 -0
- package/skills/rag/evals/README.md +13 -0
- package/skills/rag/evals/cases.yaml +45 -0
- package/skills/rag/references/evaluation.md +99 -0
- package/skills/rag/references/pipeline.md +151 -0
- package/skills/rag/scripts/verify.sh +99 -0
- package/skills/rails/SKILL.md +264 -0
- package/skills/rails/evals/README.md +12 -0
- package/skills/rails/evals/cases.yaml +47 -0
- package/skills/rails/references/activerecord.md +148 -0
- package/skills/rails/references/hotwire.md +139 -0
- package/skills/rails/references/testing.md +110 -0
- package/skills/rails/scripts/verify.sh +128 -0
- package/skills/railway/SKILL.md +245 -0
- package/skills/railway/evals/README.md +14 -0
- package/skills/railway/evals/cases.yaml +44 -0
- package/skills/railway/references/cli-cookbook.md +137 -0
- package/skills/railway/references/config-as-code.md +120 -0
- package/skills/railway/scripts/verify.sh +162 -0
- package/skills/react/SKILL.md +222 -0
- package/skills/react/evals/README.md +3 -0
- package/skills/react/evals/cases.yaml +43 -0
- package/skills/react/references/data-and-state.md +152 -0
- package/skills/react/references/performance.md +75 -0
- package/skills/react/references/routing.md +99 -0
- package/skills/react/scripts/verify.sh +123 -0
- package/skills/react-native/SKILL.md +220 -0
- package/skills/react-native/evals/README.md +3 -0
- package/skills/react-native/evals/cases.yaml +42 -0
- package/skills/react-native/references/native-modules.md +123 -0
- package/skills/react-native/references/performance-debugging.md +46 -0
- package/skills/react-native/scripts/verify.sh +117 -0
- package/skills/redis/SKILL.md +298 -0
- package/skills/redis/evals/README.md +10 -0
- package/skills/redis/evals/cases.yaml +43 -0
- package/skills/redis/references/caching.md +116 -0
- package/skills/redis/references/locks-and-rate-limiting.md +140 -0
- package/skills/redis/references/queues.md +102 -0
- package/skills/redis/scripts/verify.sh +164 -0
- package/skills/remotion-video/SKILL.md +218 -0
- package/skills/remotion-video/evals/README.md +23 -0
- package/skills/remotion-video/evals/cases.yaml +64 -0
- package/skills/remotion-video/references/captions-pipeline.md +163 -0
- package/skills/remotion-video/references/render-and-pipeline.md +131 -0
- package/skills/remotion-video/scripts/verify.sh +169 -0
- package/skills/render/SKILL.md +256 -0
- package/skills/render/evals/README.md +12 -0
- package/skills/render/evals/cases.yaml +45 -0
- package/skills/render/references/blueprint-reference.md +203 -0
- package/skills/render/scripts/verify.sh +167 -0
- package/skills/replicate/SKILL.md +210 -0
- package/skills/replicate/evals/README.md +9 -0
- package/skills/replicate/evals/cases.yaml +45 -0
- package/skills/replicate/references/cog-packaging.md +89 -0
- package/skills/replicate/references/deployments-api.md +87 -0
- package/skills/replicate/references/webhooks-and-async.md +110 -0
- package/skills/replicate/scripts/verify.sh +162 -0
- package/skills/replicate-images/SKILL.md +241 -0
- package/skills/replicate-images/evals/README.md +13 -0
- package/skills/replicate-images/evals/cases.yaml +41 -0
- package/skills/replicate-images/references/editing-recipes.md +129 -0
- package/skills/replicate-images/references/models.md +131 -0
- package/skills/replicate-images/scripts/verify.sh +178 -0
- package/skills/reporting/SKILL.md +178 -0
- package/skills/reporting/evals/README.md +12 -0
- package/skills/reporting/evals/cases.yaml +46 -0
- package/skills/reporting/references/pipeline.md +213 -0
- package/skills/reporting/scripts/verify.sh +149 -0
- package/skills/research-ops/SKILL.md +200 -0
- package/skills/research-ops/evals/README.md +13 -0
- package/skills/research-ops/evals/cases.yaml +38 -0
- package/skills/research-ops/references/credibility-rubric.md +78 -0
- package/skills/research-ops/references/memo-template.md +63 -0
- package/skills/research-ops/scripts/verify.sh +181 -0
- package/skills/retention/SKILL.md +206 -0
- package/skills/retention/evals/README.md +13 -0
- package/skills/retention/evals/cases.yaml +42 -0
- package/skills/retention/references/health-score-and-metrics.md +97 -0
- package/skills/retention/references/save-and-winback-plays.md +65 -0
- package/skills/review/SKILL.md +222 -0
- package/skills/review/evals/README.md +84 -0
- package/skills/review/evals/cases.yaml +55 -0
- package/skills/review-management/SKILL.md +204 -0
- package/skills/review-management/evals/README.md +13 -0
- package/skills/review-management/evals/cases.yaml +60 -0
- package/skills/review-management/references/platform-apis.md +86 -0
- package/skills/review-management/scripts/verify.sh +128 -0
- package/skills/ruby/SKILL.md +316 -0
- package/skills/ruby/evals/README.md +12 -0
- package/skills/ruby/evals/cases.yaml +41 -0
- package/skills/ruby/references/gems-and-testing.md +208 -0
- package/skills/ruby/references/metaprogramming.md +161 -0
- package/skills/ruby/scripts/verify.sh +83 -0
- package/skills/runpod/SKILL.md +238 -0
- package/skills/runpod/evals/README.md +11 -0
- package/skills/runpod/evals/cases.yaml +47 -0
- package/skills/runpod/references/cost-and-scaling.md +85 -0
- package/skills/runpod/references/serverless-workers.md +101 -0
- package/skills/runpod/scripts/verify.sh +126 -0
- package/skills/rust/SKILL.md +395 -0
- package/skills/rust/evals/README.md +12 -0
- package/skills/rust/evals/cases.yaml +42 -0
- package/skills/rust/references/async-tokio.md +141 -0
- package/skills/rust/references/axum-service.md +132 -0
- package/skills/rust/references/ownership.md +86 -0
- package/skills/rust/references/testing.md +108 -0
- package/skills/rust/scripts/verify.sh +91 -0
- package/skills/sales-pipeline/SKILL.md +162 -0
- package/skills/sales-pipeline/evals/README.md +13 -0
- package/skills/sales-pipeline/evals/cases.yaml +60 -0
- package/skills/sales-pipeline/references/forecasting-math.md +82 -0
- package/skills/sales-pipeline/references/stage-playbook.md +84 -0
- package/skills/sales-pipeline/scripts/verify.sh +210 -0
- package/skills/scaling/SKILL.md +137 -0
- package/skills/scaling/evals/README.md +3 -0
- package/skills/scaling/evals/cases.yaml +42 -0
- package/skills/scaling/references/load-testing-k6.md +127 -0
- package/skills/scaling/scripts/example.load.js +24 -0
- package/skills/scaling/scripts/verify.sh +70 -0
- package/skills/sdd/SKILL.md +203 -0
- package/skills/sdd/evals/README.md +60 -0
- package/skills/sdd/evals/cases.yaml +78 -0
- package/skills/sdd-init/SKILL.md +148 -0
- package/skills/sdd-init/evals/README.md +3 -0
- package/skills/sdd-init/evals/cases.yaml +43 -0
- package/skills/secure-coding/SKILL.md +365 -0
- package/skills/secure-coding/evals/README.md +68 -0
- package/skills/secure-coding/evals/cases.yaml +55 -0
- package/skills/secure-coding/references/authn-authz.md +249 -0
- package/skills/secure-coding/references/owasp-by-stack.md +574 -0
- package/skills/secure-coding/references/secrets-and-supply-chain.md +205 -0
- package/skills/secure-coding/references/threat-modeling.md +213 -0
- package/skills/secure-coding/scripts/verify.sh +208 -0
- package/skills/security-scan/SKILL.md +239 -0
- package/skills/security-scan/evals/README.md +14 -0
- package/skills/security-scan/evals/cases.yaml +50 -0
- package/skills/security-scan/references/tools.md +98 -0
- package/skills/security-scan/references/triage.md +93 -0
- package/skills/security-scan/scripts/verify.sh +108 -0
- package/skills/seo-geo/SKILL.md +192 -0
- package/skills/seo-geo/evals/README.md +14 -0
- package/skills/seo-geo/evals/cases.yaml +45 -0
- package/skills/seo-geo/references/ai-crawler-control.md +104 -0
- package/skills/seo-geo/references/schema-recipes.md +130 -0
- package/skills/seo-geo/scripts/verify.sh +236 -0
- package/skills/ship/SKILL.md +258 -0
- package/skills/ship/evals/README.md +89 -0
- package/skills/ship/evals/cases.yaml +44 -0
- package/skills/shopify/SKILL.md +229 -0
- package/skills/shopify/evals/README.md +14 -0
- package/skills/shopify/evals/cases.yaml +41 -0
- package/skills/shopify/references/apps-graphql.md +103 -0
- package/skills/shopify/references/checkout-extensibility.md +71 -0
- package/skills/shopify/references/liquid-themes.md +89 -0
- package/skills/shopify/scripts/verify.sh +120 -0
- package/skills/shortform-editing/SKILL.md +161 -0
- package/skills/shortform-editing/evals/README.md +16 -0
- package/skills/shortform-editing/evals/cases.yaml +61 -0
- package/skills/shortform-editing/references/captions.md +85 -0
- package/skills/shortform-editing/references/ffmpeg-pipeline.md +126 -0
- package/skills/shortform-editing/scripts/verify.sh +148 -0
- package/skills/shortform-ideation/SKILL.md +153 -0
- package/skills/shortform-ideation/evals/README.md +20 -0
- package/skills/shortform-ideation/evals/cases.yaml +58 -0
- package/skills/shortform-ideation/references/experiment-ledger.md +85 -0
- package/skills/shortform-ideation/references/trend-sources.md +69 -0
- package/skills/shortform-ideation/scripts/verify.sh +172 -0
- package/skills/shortform-packaging/SKILL.md +247 -0
- package/skills/shortform-packaging/evals/README.md +10 -0
- package/skills/shortform-packaging/evals/cases.yaml +48 -0
- package/skills/shortform-packaging/references/package-templates.md +117 -0
- package/skills/shortform-packaging/scripts/verify.sh +210 -0
- package/skills/shortform-strategy/SKILL.md +149 -0
- package/skills/shortform-strategy/evals/README.md +3 -0
- package/skills/shortform-strategy/evals/cases.yaml +52 -0
- package/skills/shortform-strategy/references/learning-loop-template.md +49 -0
- package/skills/shortform-strategy/references/platform-signals-2026.md +46 -0
- package/skills/shortform-strategy/scripts/verify.sh +176 -0
- package/skills/skill-scout/SKILL.md +133 -0
- package/skills/skill-scout/evals/README.md +12 -0
- package/skills/skill-scout/evals/cases.yaml +56 -0
- package/skills/skill-scout/references/install-commands.md +76 -0
- package/skills/skill-scout/scripts/verify.sh +154 -0
- package/skills/social-publisher/SKILL.md +179 -0
- package/skills/social-publisher/evals/README.md +14 -0
- package/skills/social-publisher/evals/cases.yaml +55 -0
- package/skills/social-publisher/references/calendar-schema.md +97 -0
- package/skills/social-publisher/references/platform-limits.md +56 -0
- package/skills/social-publisher/scripts/verify.sh +232 -0
- package/skills/solid-js/SKILL.md +260 -0
- package/skills/solid-js/evals/README.md +3 -0
- package/skills/solid-js/evals/cases.yaml +38 -0
- package/skills/solid-js/references/reactivity-deep-dive.md +89 -0
- package/skills/solid-js/references/router-and-start.md +93 -0
- package/skills/solid-js/scripts/verify.sh +130 -0
- package/skills/sop-builder/SKILL.md +233 -0
- package/skills/sop-builder/evals/README.md +14 -0
- package/skills/sop-builder/evals/cases.yaml +48 -0
- package/skills/sop-builder/references/sop-skeleton.md +170 -0
- package/skills/specify/SKILL.md +214 -0
- package/skills/specify/evals/README.md +73 -0
- package/skills/specify/evals/cases.yaml +80 -0
- package/skills/specify/references/eliciting-requirements.md +77 -0
- package/skills/specify/references/spec-template.md +60 -0
- package/skills/spreadsheet-ops/SKILL.md +180 -0
- package/skills/spreadsheet-ops/evals/README.md +33 -0
- package/skills/spreadsheet-ops/evals/cases.yaml +42 -0
- package/skills/spreadsheet-ops/references/formula-cookbook.md +70 -0
- package/skills/spreadsheet-ops/references/python-excel.md +87 -0
- package/skills/spreadsheet-ops/references/sheets-api-appsscript.md +118 -0
- package/skills/spreadsheet-ops/scripts/verify.sh +152 -0
- package/skills/spring-boot/SKILL.md +375 -0
- package/skills/spring-boot/evals/README.md +11 -0
- package/skills/spring-boot/evals/cases.yaml +49 -0
- package/skills/spring-boot/references/jpa.md +94 -0
- package/skills/spring-boot/references/security.md +92 -0
- package/skills/spring-boot/references/testing.md +95 -0
- package/skills/spring-boot/scripts/verify.sh +115 -0
- package/skills/sql/SKILL.md +286 -0
- package/skills/sql/evals/README.md +9 -0
- package/skills/sql/evals/cases.yaml +49 -0
- package/skills/sql/references/ctes-and-recursion.md +63 -0
- package/skills/sql/references/joins-and-sets.md +71 -0
- package/skills/sql/references/portability.md +38 -0
- package/skills/sql/references/window-functions.md +72 -0
- package/skills/sql/scripts/verify.sh +139 -0
- package/skills/sqlite-turso/SKILL.md +214 -0
- package/skills/sqlite-turso/evals/README.md +24 -0
- package/skills/sqlite-turso/evals/cases.yaml +45 -0
- package/skills/sqlite-turso/references/embedded-replicas.md +96 -0
- package/skills/sqlite-turso/scripts/verify.sh +95 -0
- package/skills/stripe/SKILL.md +269 -0
- package/skills/stripe/evals/README.md +11 -0
- package/skills/stripe/evals/cases.yaml +45 -0
- package/skills/stripe/references/going-live.md +64 -0
- package/skills/stripe/references/webhook-events.md +79 -0
- package/skills/stripe/scripts/verify.sh +130 -0
- package/skills/structured-extraction/SKILL.md +230 -0
- package/skills/structured-extraction/evals/README.md +13 -0
- package/skills/structured-extraction/evals/cases.yaml +70 -0
- package/skills/structured-extraction/references/providers.md +152 -0
- package/skills/structured-extraction/scripts/verify.sh +160 -0
- package/skills/suggest/SKILL.md +30 -0
- package/skills/suggest/evals/README.md +14 -0
- package/skills/suggest/evals/cases.yaml +51 -0
- package/skills/supabase/SKILL.md +268 -0
- package/skills/supabase/evals/README.md +12 -0
- package/skills/supabase/evals/cases.yaml +42 -0
- package/skills/supabase/references/auth-ssr.md +173 -0
- package/skills/supabase/references/rls-cookbook.md +122 -0
- package/skills/supabase/scripts/verify.sh +149 -0
- package/skills/svelte/SKILL.md +238 -0
- package/skills/svelte/evals/README.md +3 -0
- package/skills/svelte/evals/cases.yaml +41 -0
- package/skills/svelte/references/runes.md +97 -0
- package/skills/svelte/references/sveltekit-data.md +156 -0
- package/skills/svelte/scripts/verify.sh +128 -0
- package/skills/swift-ios/SKILL.md +217 -0
- package/skills/swift-ios/evals/README.md +3 -0
- package/skills/swift-ios/evals/cases.yaml +46 -0
- package/skills/swift-ios/references/concurrency.md +132 -0
- package/skills/swift-ios/references/testing.md +112 -0
- package/skills/swift-ios/scripts/verify.sh +98 -0
- package/skills/tasks/SKILL.md +260 -0
- package/skills/tasks/evals/README.md +70 -0
- package/skills/tasks/evals/cases.yaml +75 -0
- package/skills/tauri/SKILL.md +224 -0
- package/skills/tauri/evals/README.md +12 -0
- package/skills/tauri/evals/cases.yaml +46 -0
- package/skills/tauri/references/bundling-distribution.md +129 -0
- package/skills/tauri/references/security.md +143 -0
- package/skills/tauri/scripts/verify.sh +178 -0
- package/skills/technical-writing/SKILL.md +230 -0
- package/skills/technical-writing/evals/README.md +12 -0
- package/skills/technical-writing/evals/cases.yaml +53 -0
- package/skills/technical-writing/references/diataxis-modes.md +131 -0
- package/skills/technical-writing/references/vale-starter.md +90 -0
- package/skills/technical-writing/scripts/verify.sh +83 -0
- package/skills/terms-conditions/SKILL.md +147 -0
- package/skills/terms-conditions/evals/README.md +14 -0
- package/skills/terms-conditions/evals/cases.yaml +48 -0
- package/skills/terms-conditions/references/clause-library.md +158 -0
- package/skills/terms-conditions/references/notices-and-aup.md +125 -0
- package/skills/terms-conditions/scripts/verify.sh +92 -0
- package/skills/testing-go/SKILL.md +246 -0
- package/skills/testing-go/evals/README.md +3 -0
- package/skills/testing-go/evals/cases.yaml +44 -0
- package/skills/testing-go/references/coverage-and-benchmarks.md +85 -0
- package/skills/testing-go/references/mocks-and-fakes.md +140 -0
- package/skills/testing-go/references/synctest-and-concurrency.md +82 -0
- package/skills/testing-go/scripts/verify.sh +72 -0
- package/skills/testing-py/SKILL.md +179 -0
- package/skills/testing-py/evals/README.md +5 -0
- package/skills/testing-py/evals/cases.yaml +44 -0
- package/skills/testing-py/references/mocking.md +141 -0
- package/skills/testing-py/references/property-testing.md +99 -0
- package/skills/testing-py/scripts/verify.sh +117 -0
- package/skills/testing-web/SKILL.md +224 -0
- package/skills/testing-web/evals/README.md +11 -0
- package/skills/testing-web/evals/cases.yaml +52 -0
- package/skills/testing-web/references/jest-setup.md +88 -0
- package/skills/testing-web/references/recipes.md +116 -0
- package/skills/testing-web/scripts/verify.sh +111 -0
- package/skills/tiktok-api/SKILL.md +315 -0
- package/skills/tiktok-api/evals/README.md +17 -0
- package/skills/tiktok-api/evals/cases.yaml +51 -0
- package/skills/tiktok-api/references/metrics-and-publish.md +127 -0
- package/skills/tiktok-api/references/oauth-setup.md +105 -0
- package/skills/tiktok-api/references/wiki-schema.md +85 -0
- package/skills/tiktok-api/scripts/verify.sh +96 -0
- package/skills/together-fireworks/SKILL.md +181 -0
- package/skills/together-fireworks/evals/README.md +3 -0
- package/skills/together-fireworks/evals/cases.yaml +50 -0
- package/skills/together-fireworks/references/batch-and-tuning.md +59 -0
- package/skills/together-fireworks/references/models-and-pricing.md +79 -0
- package/skills/together-fireworks/scripts/verify.sh +165 -0
- package/skills/translation-l10n/SKILL.md +229 -0
- package/skills/translation-l10n/evals/README.md +3 -0
- package/skills/translation-l10n/evals/cases.yaml +39 -0
- package/skills/translation-l10n/references/icu-cookbook.md +82 -0
- package/skills/translation-l10n/references/rtl-and-bidi.md +60 -0
- package/skills/typescript/SKILL.md +258 -0
- package/skills/typescript/evals/README.md +15 -0
- package/skills/typescript/evals/cases.yaml +46 -0
- package/skills/typescript/references/build-and-monorepo.md +141 -0
- package/skills/typescript/references/type-system.md +162 -0
- package/skills/typescript/scripts/verify.sh +52 -0
- package/skills/unit-economics/SKILL.md +180 -0
- package/skills/unit-economics/evals/README.md +5 -0
- package/skills/unit-economics/evals/cases.yaml +43 -0
- package/skills/unit-economics/references/formulas.md +144 -0
- package/skills/unit-economics/scripts/verify.sh +179 -0
- package/skills/vector-db/SKILL.md +189 -0
- package/skills/vector-db/evals/README.md +10 -0
- package/skills/vector-db/evals/cases.yaml +45 -0
- package/skills/vector-db/references/engines.md +175 -0
- package/skills/vector-db/references/tuning.md +62 -0
- package/skills/vector-db/scripts/verify.sh +110 -0
- package/skills/vercel/SKILL.md +242 -0
- package/skills/vercel/evals/README.md +23 -0
- package/skills/vercel/evals/cases.yaml +45 -0
- package/skills/vercel/references/cli-cookbook.md +98 -0
- package/skills/vercel/references/vercel-json.md +120 -0
- package/skills/vercel/scripts/verify.sh +168 -0
- package/skills/verify/SKILL.md +188 -0
- package/skills/verify/evals/README.md +78 -0
- package/skills/verify/evals/cases.yaml +74 -0
- package/skills/video-shorts/SKILL.md +163 -0
- package/skills/video-shorts/evals/README.md +15 -0
- package/skills/video-shorts/evals/cases.yaml +56 -0
- package/skills/video-shorts/references/hook-and-script-patterns.md +95 -0
- package/skills/video-shorts/references/specs-and-safe-zones.md +74 -0
- package/skills/video-shorts/scripts/verify.sh +172 -0
- package/skills/vue-nuxt/SKILL.md +384 -0
- package/skills/vue-nuxt/evals/README.md +11 -0
- package/skills/vue-nuxt/evals/cases.yaml +49 -0
- package/skills/vue-nuxt/references/data-and-state.md +127 -0
- package/skills/vue-nuxt/references/migration-nuxt4.md +79 -0
- package/skills/vue-nuxt/references/nitro-and-rendering.md +117 -0
- package/skills/vue-nuxt/references/reactivity.md +135 -0
- package/skills/vue-nuxt/scripts/verify.sh +148 -0
- package/skills/webhooks/SKILL.md +246 -0
- package/skills/webhooks/evals/README.md +15 -0
- package/skills/webhooks/evals/cases.yaml +46 -0
- package/skills/webhooks/references/framework-raw-body.md +97 -0
- package/skills/webhooks/references/signature-schemes.md +66 -0
- package/skills/webhooks/scripts/verify.sh +142 -0
- package/skills/webinar/SKILL.md +196 -0
- package/skills/webinar/evals/README.md +14 -0
- package/skills/webinar/evals/cases.yaml +44 -0
- package/skills/webinar/references/email-cadence.md +75 -0
- package/skills/webinar/references/run-of-show.md +83 -0
- package/skills/whatsapp-telegram/SKILL.md +235 -0
- package/skills/whatsapp-telegram/evals/README.md +11 -0
- package/skills/whatsapp-telegram/evals/cases.yaml +44 -0
- package/skills/whatsapp-telegram/references/telegram-bot-api.md +91 -0
- package/skills/whatsapp-telegram/references/whatsapp-cloud-api.md +103 -0
- package/skills/whatsapp-telegram/scripts/verify.sh +90 -0
- package/skills/wordpress/SKILL.md +224 -0
- package/skills/wordpress/evals/README.md +3 -0
- package/skills/wordpress/evals/cases.yaml +50 -0
- package/skills/wordpress/references/hardening.md +108 -0
- package/skills/wordpress/references/performance.md +80 -0
- package/skills/wordpress/references/woocommerce.md +65 -0
- package/skills/wordpress/scripts/verify.sh +96 -0
- package/skills/worktrees/SKILL.md +199 -0
- package/skills/worktrees/evals/README.md +78 -0
- package/skills/worktrees/evals/cases.yaml +47 -0
- package/skills/youtube-api/SKILL.md +286 -0
- package/skills/youtube-api/evals/README.md +3 -0
- package/skills/youtube-api/evals/cases.yaml +50 -0
- package/skills/youtube-api/references/analytics-queries.md +89 -0
- package/skills/youtube-api/references/oauth-setup.md +55 -0
- package/skills/youtube-api/references/wiki-schema.md +70 -0
- package/skills/youtube-api/scripts/verify.sh +84 -0
- package/skills/youtube-ideation/SKILL.md +234 -0
- package/skills/youtube-ideation/evals/README.md +14 -0
- package/skills/youtube-ideation/evals/cases.yaml +52 -0
- package/skills/youtube-ideation/references/idea-ledger-and-loop.md +89 -0
- package/skills/youtube-ideation/references/research-and-signals.md +92 -0
- package/skills/youtube-ideation/scripts/verify.sh +237 -0
- package/skills/youtube-packaging/SKILL.md +220 -0
- package/skills/youtube-packaging/evals/README.md +16 -0
- package/skills/youtube-packaging/evals/cases.yaml +48 -0
- package/skills/youtube-packaging/references/description-and-chapters.md +135 -0
- package/skills/youtube-packaging/scripts/verify.sh +250 -0
- package/skills/youtube-strategy/SKILL.md +157 -0
- package/skills/youtube-strategy/evals/README.md +5 -0
- package/skills/youtube-strategy/evals/cases.yaml +61 -0
- package/skills/youtube-strategy/references/channel-architecture.md +46 -0
- package/skills/youtube-strategy/references/wiki-records.md +86 -0
- package/skills/youtube-strategy/scripts/verify.sh +118 -0
- package/skills/youtube-thumbnails/SKILL.md +180 -0
- package/skills/youtube-thumbnails/evals/README.md +11 -0
- package/skills/youtube-thumbnails/evals/cases.yaml +48 -0
- package/skills/youtube-thumbnails/references/composition-and-specs.md +69 -0
- package/skills/youtube-thumbnails/references/experiment-log-format.md +65 -0
- package/skills/youtube-thumbnails/scripts/verify.sh +123 -0
- package/targets/claude.js +23 -0
- package/targets/codex.js +29 -0
- package/targets/cursor.js +20 -0
- package/targets/gemini.js +29 -0
- package/targets/index.js +55 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# Securing a FastAPI service
|
|
2
|
+
|
|
3
|
+
Concrete, FastAPI-specific hardening on Python 3.12+: argon2-cffi 23+ password hashing, PyJWT
|
|
4
|
+
2.10+ with validated claims and **pinned algorithms**, RBAC dependencies, env-specific CORS,
|
|
5
|
+
shared-store rate limiting, injection-proof queries, `SecretStr` handling, log redaction,
|
|
6
|
+
security headers, and dependency auditing. For language-agnostic theory, **See Also
|
|
7
|
+
`secure-coding`**.
|
|
8
|
+
|
|
9
|
+
## Password hashing
|
|
10
|
+
|
|
11
|
+
Use argon2id via argon2-cffi. Never MD5/SHA/plain (no work factor, GPU-crackable). bcrypt is an
|
|
12
|
+
acceptable fallback where argon2 is unavailable. Verification is constant-time and raises on
|
|
13
|
+
mismatch; re-hash on successful login when stored parameters fall behind current defaults.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from argon2 import PasswordHasher
|
|
17
|
+
from argon2.exceptions import VerifyMismatchError
|
|
18
|
+
|
|
19
|
+
ph = PasswordHasher()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def hash_password(plain: str) -> str:
|
|
23
|
+
return ph.hash(plain)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def verify_password(stored_hash: str, plain: str) -> tuple[bool, str | None]:
|
|
27
|
+
try:
|
|
28
|
+
ph.verify(stored_hash, plain)
|
|
29
|
+
except VerifyMismatchError:
|
|
30
|
+
return False, None
|
|
31
|
+
new_hash = ph.hash(plain) if ph.check_needs_rehash(stored_hash) else None
|
|
32
|
+
return True, new_hash
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
When `verify_password` returns a non-`None` second element, persist it: the stored hash used
|
|
36
|
+
weaker parameters and was just upgraded transparently on a correct login.
|
|
37
|
+
|
|
38
|
+
## OAuth2 password flow + JWT
|
|
39
|
+
|
|
40
|
+
`OAuth2PasswordBearer` declares the token scheme (and powers the Swagger "Authorize" button).
|
|
41
|
+
The login route verifies credentials and returns a short-lived access token.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from fastapi import APIRouter, Depends
|
|
45
|
+
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
|
46
|
+
|
|
47
|
+
from app.api.deps import DbSession
|
|
48
|
+
from app.core.security import create_access_token, verify_password
|
|
49
|
+
from app.exceptions import Unauthorized
|
|
50
|
+
from app.services import user_service
|
|
51
|
+
|
|
52
|
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")
|
|
53
|
+
router = APIRouter()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@router.post("/login")
|
|
57
|
+
async def login(db: DbSession, form: OAuth2PasswordRequestForm = Depends()) -> dict[str, str]:
|
|
58
|
+
user = await user_service.get_by_email(db, form.username)
|
|
59
|
+
if user is None:
|
|
60
|
+
raise Unauthorized("Invalid credentials")
|
|
61
|
+
ok, new_hash = verify_password(user.hashed_password, form.password)
|
|
62
|
+
if not ok:
|
|
63
|
+
raise Unauthorized("Invalid credentials")
|
|
64
|
+
if new_hash is not None:
|
|
65
|
+
user.hashed_password = new_hash
|
|
66
|
+
await db.flush()
|
|
67
|
+
return {"access_token": create_access_token(str(user.id)), "token_type": "bearer"}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Mint tokens with explicit `exp`, `iat`, `iss`, `aud`, `sub`; decode by **pinning `algorithms`**
|
|
71
|
+
and requiring the claims — never trust the token header's `alg`.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from datetime import UTC, datetime, timedelta
|
|
75
|
+
|
|
76
|
+
import jwt
|
|
77
|
+
|
|
78
|
+
from app.core.config import get_settings
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def create_access_token(subject: str) -> str:
|
|
82
|
+
s = get_settings()
|
|
83
|
+
now = datetime.now(UTC)
|
|
84
|
+
payload = {
|
|
85
|
+
"sub": subject, "iss": s.jwt_issuer, "aud": s.jwt_audience,
|
|
86
|
+
"iat": now, "exp": now + timedelta(seconds=s.access_token_ttl_seconds),
|
|
87
|
+
}
|
|
88
|
+
return jwt.encode(payload, s.jwt_secret.get_secret_value(), algorithm=s.jwt_algorithm)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def decode_token(token: str) -> dict:
|
|
92
|
+
s = get_settings()
|
|
93
|
+
return jwt.decode(
|
|
94
|
+
token, s.jwt_secret.get_secret_value(),
|
|
95
|
+
algorithms=[s.jwt_algorithm], # pinned — never accept the header's alg
|
|
96
|
+
audience=s.jwt_audience, issuer=s.jwt_issuer,
|
|
97
|
+
options={"require": ["exp", "iss", "aud", "sub"]},
|
|
98
|
+
)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Bad: `jwt.decode(token, key, algorithms=["none"])` or omitting `algorithms` entirely — both
|
|
102
|
+
accept `alg=none`, making tokens forgeable with no signature. For asymmetric keys prefer RS256
|
|
103
|
+
(verify with the public key; sign only on the issuer). Resolve the token into the current user
|
|
104
|
+
in a dependency:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from typing import Annotated
|
|
108
|
+
|
|
109
|
+
import jwt
|
|
110
|
+
from fastapi import Depends
|
|
111
|
+
|
|
112
|
+
from app.api.deps import DbSession
|
|
113
|
+
from app.core.security import decode_token, oauth2_scheme
|
|
114
|
+
from app.exceptions import Unauthorized
|
|
115
|
+
from app.models.user import User
|
|
116
|
+
from app.services import user_service
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
async def get_current_user(
|
|
120
|
+
db: DbSession, token: Annotated[str, Depends(oauth2_scheme)]
|
|
121
|
+
) -> User:
|
|
122
|
+
try:
|
|
123
|
+
payload = decode_token(token)
|
|
124
|
+
except jwt.PyJWTError as exc:
|
|
125
|
+
raise Unauthorized("Invalid or expired token") from exc
|
|
126
|
+
user = await user_service.get_user(db, payload["sub"])
|
|
127
|
+
if user is None or not user.is_active:
|
|
128
|
+
raise Unauthorized("User not found or inactive")
|
|
129
|
+
return user
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
CurrentUser = Annotated[User, Depends(get_current_user)]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## RBAC
|
|
136
|
+
|
|
137
|
+
A dependency factory that reads a `role` claim and raises `Forbidden` (403) when the caller's
|
|
138
|
+
role is not permitted. Compose it into a router via `dependencies=[Depends(require_roles("admin"))]`
|
|
139
|
+
or as a typed parameter.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from collections.abc import Callable
|
|
143
|
+
from typing import Annotated
|
|
144
|
+
|
|
145
|
+
from fastapi import Depends
|
|
146
|
+
|
|
147
|
+
from app.core.security import decode_token, oauth2_scheme
|
|
148
|
+
from app.exceptions import Forbidden, Unauthorized
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def require_roles(*allowed: str) -> Callable[..., None]:
|
|
152
|
+
async def _dep(token: Annotated[str, Depends(oauth2_scheme)]) -> None:
|
|
153
|
+
try:
|
|
154
|
+
payload = decode_token(token)
|
|
155
|
+
except Exception as exc:
|
|
156
|
+
raise Unauthorized() from exc
|
|
157
|
+
if payload.get("role") not in allowed:
|
|
158
|
+
raise Forbidden(f"Requires one of: {', '.join(allowed)}")
|
|
159
|
+
return _dep
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
For private resources, prefer returning **404 over 403** when the caller is authenticated but
|
|
163
|
+
not the owner — a 403 confirms the resource exists, leaking its presence to a probing attacker.
|
|
164
|
+
Use 403 only where existence is already public and the action specifically is forbidden.
|
|
165
|
+
|
|
166
|
+
## CORS
|
|
167
|
+
|
|
168
|
+
CORS is enforced by the browser, not a server-side authorization control — but a wrong config
|
|
169
|
+
either breaks legitimate frontends or invites credentialed cross-origin abuse. Pin an explicit
|
|
170
|
+
origin list per environment; the `["*"]` + credentials combination is invalid (the browser
|
|
171
|
+
rejects it and Starlette refuses to echo `*` for credentialed requests).
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
175
|
+
|
|
176
|
+
# settings.cors_origins, e.g. dev: ["http://localhost:3000"], prod: ["https://app.example.com"]
|
|
177
|
+
app.add_middleware(
|
|
178
|
+
CORSMiddleware,
|
|
179
|
+
allow_origins=settings.cors_origins, # explicit list per env — never ["*"] with creds
|
|
180
|
+
allow_credentials=bool(settings.cors_origins),
|
|
181
|
+
allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
182
|
+
allow_headers=["Authorization", "Content-Type"],
|
|
183
|
+
max_age=600, # cache preflight to cut OPTIONS chatter
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Rate limiting
|
|
188
|
+
|
|
189
|
+
Limits must live in a **shared store** (Redis, or the API gateway), never per-process
|
|
190
|
+
counters. With multiple uvicorn workers, replicas, or serverless instances, per-process limits
|
|
191
|
+
fail open — each process counts independently, so N processes allow N× the intended rate.
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from fastapi import Request
|
|
195
|
+
from fastapi.responses import JSONResponse
|
|
196
|
+
from slowapi import Limiter
|
|
197
|
+
from slowapi.errors import RateLimitExceeded
|
|
198
|
+
from slowapi.util import get_remote_address
|
|
199
|
+
|
|
200
|
+
limiter = Limiter(key_func=get_remote_address, storage_uri="redis://redis:6379/0")
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# On the app:
|
|
204
|
+
# app.state.limiter = limiter
|
|
205
|
+
# app.add_exception_handler(RateLimitExceeded, rate_limit_handler)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def rate_limit_handler(request: Request, exc: RateLimitExceeded) -> JSONResponse:
|
|
209
|
+
return JSONResponse(
|
|
210
|
+
status_code=429,
|
|
211
|
+
headers={"Retry-After": "60"},
|
|
212
|
+
content={"error": {"code": "rate_limited", "message": "Too many requests", "details": []}},
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# On the route:
|
|
217
|
+
# @router.post("/login")
|
|
218
|
+
# @limiter.limit("5/minute")
|
|
219
|
+
# async def login(request: Request, ...): ...
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Rate-limit auth endpoints (`/login`, `/register`, password reset) and expensive writes first —
|
|
223
|
+
those are the brute-force and abuse targets.
|
|
224
|
+
|
|
225
|
+
## Injection
|
|
226
|
+
|
|
227
|
+
Pydantic validates request bodies; `Query(ge=, le=)` and `Path(...)` bound query/path params.
|
|
228
|
+
For the database, use SQLAlchemy expressions or bound parameters — never interpolate user input
|
|
229
|
+
into SQL.
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
from sqlalchemy import select, text
|
|
233
|
+
|
|
234
|
+
from app.models.user import User
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# Bad: f-string SQL -> classic SQLi.
|
|
238
|
+
async def bad(db, email: str):
|
|
239
|
+
return await db.execute(text(f"SELECT * FROM users WHERE email = '{email}'")) # noqa: S608
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# Good: ORM expression — value is bound, never concatenated.
|
|
243
|
+
async def good_orm(db, email: str):
|
|
244
|
+
return await db.execute(select(User).where(User.email == email))
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# Good: raw SQL with bound params when you truly need text().
|
|
248
|
+
async def good_text(db, email: str):
|
|
249
|
+
return await db.execute(text("SELECT * FROM users WHERE email = :email"), {"email": email})
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Secret handling
|
|
253
|
+
|
|
254
|
+
- Type every secret as `SecretStr` in `Settings`; its `repr` renders `**********`, so it cannot
|
|
255
|
+
leak via logs or tracebacks.
|
|
256
|
+
- Call `.get_secret_value()` only at the point of use (signing/decoding), never to store or log.
|
|
257
|
+
- Keep `.env` gitignored; commit a `.env.example` with names but no values.
|
|
258
|
+
- In production read secrets from a manager (AWS Secrets Manager, Vault, Doppler) injected as
|
|
259
|
+
env vars; rotate signing keys and support a short overlap window during rotation.
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
from app.core.config import get_settings
|
|
263
|
+
|
|
264
|
+
s = get_settings()
|
|
265
|
+
key = s.jwt_secret.get_secret_value() # only here, only momentarily
|
|
266
|
+
# logger.info("config", jwt_secret=s.jwt_secret) # safe: logs "**********", not the value
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Log redaction
|
|
270
|
+
|
|
271
|
+
Strip credentials and PII before logs are emitted. A structlog processor (or stdlib filter) that
|
|
272
|
+
masks known-sensitive keys, applied app-wide:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from typing import Any
|
|
276
|
+
|
|
277
|
+
SENSITIVE = {"authorization", "cookie", "set-cookie", "password", "token", "access_token",
|
|
278
|
+
"refresh_token", "secret", "ssn", "credit_card"}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def redact_processor(_logger: object, _method: str, event: dict[str, Any]) -> dict[str, Any]:
|
|
282
|
+
for key in list(event):
|
|
283
|
+
if key.lower() in SENSITIVE:
|
|
284
|
+
event[key] = "***REDACTED***"
|
|
285
|
+
return event
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
# Wire into structlog.configure(processors=[..., redact_processor, JSONRenderer()])
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Security headers & misc
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
from fastapi import FastAPI
|
|
295
|
+
from starlette.middleware.trustedhost import TrustedHostMiddleware
|
|
296
|
+
|
|
297
|
+
from app.core.config import get_settings
|
|
298
|
+
|
|
299
|
+
settings = get_settings()
|
|
300
|
+
in_prod = settings.environment == "production"
|
|
301
|
+
|
|
302
|
+
# Disable interactive docs in prod if the API is not public.
|
|
303
|
+
app = FastAPI(docs_url=None if in_prod else "/docs", redoc_url=None if in_prod else "/redoc")
|
|
304
|
+
|
|
305
|
+
# Reject Host-header spoofing / DNS rebinding.
|
|
306
|
+
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["api.example.com", "*.example.com"])
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Add response headers via a small middleware: `Strict-Transport-Security`
|
|
310
|
+
(`max-age=63072000; includeSubDomains`), `Content-Security-Policy` tuned to the API,
|
|
311
|
+
`X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`. Enforce a request body size limit at
|
|
312
|
+
the proxy (e.g. nginx `client_max_body_size`) so oversized payloads never reach the app.
|
|
313
|
+
|
|
314
|
+
## Dependency audit
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
uv run pip-audit
|
|
318
|
+
uv pip compile --generate-hashes -o requirements.lock pyproject.toml
|
|
319
|
+
uv pip sync requirements.lock
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Gate CI on `pip-audit`: a non-zero exit means a dependency has a known CVE. Pin and hash the
|
|
323
|
+
lockfile so installs are reproducible and tamper-evident, and enable Dependabot (or Renovate) to
|
|
324
|
+
open update PRs automatically. Treat a failing audit as a build break, not a warning.
|
|
325
|
+
|
|
326
|
+
## See Also
|
|
327
|
+
|
|
328
|
+
- [`secure-coding`](../../secure-coding/SKILL.md) — language-agnostic injection, authz, and secret-handling rules (never leak internals through error responses).
|
|
329
|
+
- [`production.md`](production.md) — TLS termination, proxy headers, observability.
|
|
330
|
+
- [`postgresdb`](../../postgresdb/SKILL.md) — row-level security, DB roles/grants, and PgBouncer auth.
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# Testing async FastAPI
|
|
2
|
+
|
|
3
|
+
Deep-dive companion to `SKILL.md → Testing (embedded summary)`. The goal: fast, isolated,
|
|
4
|
+
async-correct tests that hit the real ASGI app over `httpx.ASGITransport`, run against a
|
|
5
|
+
**real PostgreSQL 16** inside a per-test transaction that rolls back, and gate CI on
|
|
6
|
+
coverage. No `TestClient`-only patterns, no SQLite-as-Postgres pretending, no leaking state
|
|
7
|
+
between tests.
|
|
8
|
+
|
|
9
|
+
## Setup & config
|
|
10
|
+
|
|
11
|
+
Configure pytest once in `pyproject.toml`. `asyncio_mode = "auto"` means every `async def
|
|
12
|
+
test_*` runs without an explicit `@pytest.mark.asyncio`.
|
|
13
|
+
|
|
14
|
+
```toml
|
|
15
|
+
[tool.pytest.ini_options]
|
|
16
|
+
asyncio_mode = "auto"
|
|
17
|
+
testpaths = ["tests"]
|
|
18
|
+
addopts = [
|
|
19
|
+
"--strict-markers",
|
|
20
|
+
"--cov=app",
|
|
21
|
+
"--cov-report=term-missing",
|
|
22
|
+
"--cov-fail-under=85",
|
|
23
|
+
]
|
|
24
|
+
filterwarnings = ["error"]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Install the test toolchain as dev dependencies:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv add --dev pytest pytest-asyncio pytest-cov httpx respx testcontainers[postgres]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Test DB strategy
|
|
34
|
+
|
|
35
|
+
Test against a **real PostgreSQL 16**, not SQLite. SQLite lacks Postgres types (`UUID`,
|
|
36
|
+
`JSONB`, arrays, `tsvector`), enforces constraints differently, and has different SQL
|
|
37
|
+
semantics — green-on-SQLite tests routinely break on production Postgres. Spin up a
|
|
38
|
+
disposable container with `testcontainers` (or point at a dedicated throwaway test DB).
|
|
39
|
+
A session-scoped engine fixture creates the schema once and disposes it at the end.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import pytest
|
|
43
|
+
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
|
|
44
|
+
from testcontainers.postgres import PostgresContainer
|
|
45
|
+
|
|
46
|
+
from app.db.base import Base
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pytest.fixture(scope="session")
|
|
50
|
+
async def engine():
|
|
51
|
+
with PostgresContainer("postgres:16-alpine") as pg:
|
|
52
|
+
url = pg.get_connection_url().replace("psycopg2", "asyncpg")
|
|
53
|
+
eng = create_async_engine(url)
|
|
54
|
+
async with eng.begin() as conn:
|
|
55
|
+
await conn.run_sync(Base.metadata.create_all)
|
|
56
|
+
yield eng
|
|
57
|
+
await eng.dispose()
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
For an existing test DB instead of a container, read its URL from an env var
|
|
61
|
+
(`APP_TEST_DATABASE_URL`) and skip the `PostgresContainer` block; everything downstream is
|
|
62
|
+
identical.
|
|
63
|
+
|
|
64
|
+
## Transactional isolation fixture
|
|
65
|
+
|
|
66
|
+
The canonical SQLAlchemy 2.0 async per-test rollback recipe. Open a connection, begin an
|
|
67
|
+
outer transaction on it, and bind an `AsyncSession` with
|
|
68
|
+
`join_transaction_mode="create_savepoint"`. With that mode, every `session.commit()` the
|
|
69
|
+
service code runs only releases an internal SAVEPOINT — the outer transaction stays open and
|
|
70
|
+
is rolled back at teardown, so the DB is pristine between tests with no `create_all` /
|
|
71
|
+
`drop_all` per test. The mode is built into SQLAlchemy 2.0+, so the old
|
|
72
|
+
`after_transaction_end` event listener that manually restarted savepoints is no longer
|
|
73
|
+
needed.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import pytest
|
|
77
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@pytest.fixture
|
|
81
|
+
async def db_session(engine) -> AsyncSession:
|
|
82
|
+
async with engine.connect() as connection:
|
|
83
|
+
outer = await connection.begin()
|
|
84
|
+
session = AsyncSession(
|
|
85
|
+
bind=connection,
|
|
86
|
+
expire_on_commit=False,
|
|
87
|
+
join_transaction_mode="create_savepoint", # commits become SAVEPOINT releases
|
|
88
|
+
)
|
|
89
|
+
try:
|
|
90
|
+
yield session
|
|
91
|
+
finally:
|
|
92
|
+
await session.close()
|
|
93
|
+
await outer.rollback() # discard everything the test wrote
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The session's `commit()` calls never reach the database as real commits, so each test sees a
|
|
97
|
+
clean schema and the rollback at teardown leaves no residue for the next test.
|
|
98
|
+
|
|
99
|
+
## The async client fixture
|
|
100
|
+
|
|
101
|
+
Put this in `conftest.py`. It builds the app, swaps the request `get_db` for the
|
|
102
|
+
transactional test session, and drives it over `ASGITransport` (in-process, no socket).
|
|
103
|
+
`base_url="http://test"` satisfies httpx's absolute-URL requirement.
|
|
104
|
+
|
|
105
|
+
Build the app in its own fixture so other fixtures (auth, feature flags) can register
|
|
106
|
+
`dependency_overrides` on the *same* instance the client drives — no reaching into
|
|
107
|
+
`client._transport.app`.
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import pytest
|
|
111
|
+
from fastapi import FastAPI
|
|
112
|
+
from httpx import ASGITransport, AsyncClient
|
|
113
|
+
|
|
114
|
+
from app.api.deps import get_db
|
|
115
|
+
from app.main import create_app
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@pytest.fixture
|
|
119
|
+
def app(db_session) -> FastAPI:
|
|
120
|
+
application = create_app()
|
|
121
|
+
application.dependency_overrides[get_db] = lambda: db_session
|
|
122
|
+
return application
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pytest.fixture
|
|
126
|
+
async def client(app: FastAPI) -> AsyncClient:
|
|
127
|
+
transport = ASGITransport(app=app)
|
|
128
|
+
async with AsyncClient(transport=transport, base_url="http://test") as c:
|
|
129
|
+
yield c
|
|
130
|
+
app.dependency_overrides.clear()
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The override yields the **same** `db_session` the test sees, so assertions made directly on
|
|
134
|
+
the session observe exactly what the handler wrote (before rollback).
|
|
135
|
+
|
|
136
|
+
## Auth override fixture
|
|
137
|
+
|
|
138
|
+
Two strategies. Use (a) for the common case — you want to test business logic, not the JWT
|
|
139
|
+
machinery. Use (b) when you are specifically exercising the decode/claims path.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
# (a) Inject a fixed user, bypassing the real token decode.
|
|
143
|
+
import pytest
|
|
144
|
+
from fastapi import FastAPI
|
|
145
|
+
|
|
146
|
+
from app.api.deps import get_current_user
|
|
147
|
+
from app.models.user import User
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@pytest.fixture
|
|
151
|
+
async def auth_client(app: FastAPI, client, db_session) -> AsyncClient:
|
|
152
|
+
user = User(email="auth@example.com", full_name="Auth", hashed_password="x")
|
|
153
|
+
db_session.add(user)
|
|
154
|
+
await db_session.flush()
|
|
155
|
+
# Override on the same app the client drives — no client._transport.app reach-in.
|
|
156
|
+
app.dependency_overrides[get_current_user] = lambda: user
|
|
157
|
+
return client
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# (b) Mint a real JWT and send it through the real get_current_user decode path.
|
|
162
|
+
import pytest
|
|
163
|
+
|
|
164
|
+
from app.core.security import create_access_token
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@pytest.fixture
|
|
168
|
+
async def bearer_headers(db_session) -> dict[str, str]:
|
|
169
|
+
from app.models.user import User
|
|
170
|
+
|
|
171
|
+
user = User(email="real@example.com", full_name="Real", hashed_password="x")
|
|
172
|
+
db_session.add(user)
|
|
173
|
+
await db_session.flush()
|
|
174
|
+
token = create_access_token(subject=str(user.id))
|
|
175
|
+
return {"Authorization": f"Bearer {token}"}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Factories & fixtures
|
|
179
|
+
|
|
180
|
+
Prefer plain async builder functions over global factory state — explicit, mypy-friendly,
|
|
181
|
+
no hidden sequences. Override any field per call.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from app.models.user import User
|
|
185
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
async def make_user(db: AsyncSession, **overrides) -> User:
|
|
189
|
+
defaults = {"email": "u@example.com", "full_name": "U", "hashed_password": "x"}
|
|
190
|
+
user = User(**{**defaults, **overrides})
|
|
191
|
+
db.add(user)
|
|
192
|
+
await db.flush()
|
|
193
|
+
return user
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Parametrize with readable `ids=` so failures name the case:
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
import pytest
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@pytest.mark.parametrize(
|
|
203
|
+
("payload", "expected_field"),
|
|
204
|
+
[
|
|
205
|
+
({"email": "bad", "full_name": "A", "password": "x" * 12}, "email"),
|
|
206
|
+
({"email": "a@b.com", "full_name": "", "password": "x" * 12}, "full_name"),
|
|
207
|
+
({"email": "a@b.com", "full_name": "A", "password": "short"}, "password"),
|
|
208
|
+
],
|
|
209
|
+
ids=["bad-email", "empty-name", "short-password"],
|
|
210
|
+
)
|
|
211
|
+
async def test_validation_fields(client, payload, expected_field) -> None:
|
|
212
|
+
resp = await client.post("/api/v1/users", json=payload)
|
|
213
|
+
assert resp.status_code == 422
|
|
214
|
+
assert resp.json()["error"]["details"][0]["field"] == expected_field
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Testing endpoints
|
|
218
|
+
|
|
219
|
+
Cover the happy path, the created-201 contract, the validation envelope, and domain errors.
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from httpx import AsyncClient
|
|
223
|
+
|
|
224
|
+
from tests.factories import make_user
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
async def test_list_users_pagination(client: AsyncClient, db_session) -> None:
|
|
228
|
+
for i in range(3):
|
|
229
|
+
await make_user(db_session, email=f"u{i}@example.com")
|
|
230
|
+
resp = await client.get("/api/v1/users", params={"limit": 2, "offset": 0})
|
|
231
|
+
assert resp.status_code == 200
|
|
232
|
+
assert len(resp.json()) == 2
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
async def test_create_user_201_location(client: AsyncClient) -> None:
|
|
236
|
+
resp = await client.post("/api/v1/users", json={
|
|
237
|
+
"email": "new@example.com", "full_name": "New", "password": "correct-horse-battery",
|
|
238
|
+
})
|
|
239
|
+
assert resp.status_code == 201
|
|
240
|
+
assert resp.headers["Location"].startswith("/api/v1/users/")
|
|
241
|
+
assert "hashed_password" not in resp.json()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
async def test_create_user_validation_envelope(client: AsyncClient) -> None:
|
|
245
|
+
resp = await client.post("/api/v1/users", json={"email": "nope"})
|
|
246
|
+
assert resp.status_code == 422
|
|
247
|
+
body = resp.json()
|
|
248
|
+
assert body["error"]["code"] == "validation_error"
|
|
249
|
+
assert body["error"]["details"][0]["field"]
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
async def test_duplicate_email_conflict(client: AsyncClient, db_session) -> None:
|
|
253
|
+
await make_user(db_session, email="dupe@example.com")
|
|
254
|
+
resp = await client.post("/api/v1/users", json={
|
|
255
|
+
"email": "dupe@example.com", "full_name": "Dupe", "password": "correct-horse-battery",
|
|
256
|
+
})
|
|
257
|
+
assert resp.status_code == 409
|
|
258
|
+
assert resp.json()["error"]["code"] == "conflict"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Testing background tasks & external calls
|
|
262
|
+
|
|
263
|
+
Mock outbound httpx with **respx** — never hit the network in unit tests.
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
import httpx
|
|
267
|
+
import respx
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@respx.mock
|
|
271
|
+
async def test_outbound_call(client: httpx.AsyncClient) -> None:
|
|
272
|
+
route = respx.post("https://payments.example.com/charge").mock(
|
|
273
|
+
return_value=httpx.Response(200, json={"status": "ok"})
|
|
274
|
+
)
|
|
275
|
+
resp = await client.post("/api/v1/orders", json={"amount": 100})
|
|
276
|
+
assert resp.status_code == 201
|
|
277
|
+
assert route.called
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
For `BackgroundTasks`, assert the side effect by overriding the task target with a spy
|
|
281
|
+
(e.g. `monkeypatch.setattr("app.services.email.send_welcome_email", spy)`) and asserting the
|
|
282
|
+
spy was awaited with the expected args — the task runs after the response is sent, so make
|
|
283
|
+
the override visible before the request.
|
|
284
|
+
|
|
285
|
+
## TDD discipline
|
|
286
|
+
|
|
287
|
+
Red → green → refactor for a new `GET /users/{id}`. Follow
|
|
288
|
+
`superpowers:test-driven-development`: write the failing test first, watch it fail, then
|
|
289
|
+
write the minimum to pass.
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
# RED — write this first; it fails (404/route missing).
|
|
293
|
+
async def test_get_user_by_id(client, db_session) -> None:
|
|
294
|
+
user = await make_user(db_session, email="byid@example.com")
|
|
295
|
+
resp = await client.get(f"/api/v1/users/{user.id}")
|
|
296
|
+
assert resp.status_code == 200
|
|
297
|
+
assert resp.json()["email"] == "byid@example.com"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
# GREEN — minimal handler + service to pass.
|
|
302
|
+
# app/services/user_service.py
|
|
303
|
+
from uuid import UUID
|
|
304
|
+
|
|
305
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
306
|
+
|
|
307
|
+
from app.exceptions import NotFoundError
|
|
308
|
+
from app.models.user import User
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
async def get_user(db: AsyncSession, user_id: UUID) -> User:
|
|
312
|
+
user = await db.get(User, user_id)
|
|
313
|
+
if user is None:
|
|
314
|
+
raise NotFoundError("User", str(user_id))
|
|
315
|
+
return user
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
# app/api/routers/users.py
|
|
319
|
+
from uuid import UUID
|
|
320
|
+
|
|
321
|
+
from app.api.deps import DbSession
|
|
322
|
+
from app.schemas.user import UserResponse
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
@router.get("/{user_id}", response_model=UserResponse)
|
|
326
|
+
async def get_user(user_id: UUID, db: DbSession) -> UserResponse:
|
|
327
|
+
return await user_service.get_user(db, user_id)
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Refactor step: once green, extract shared lookup, add the 404-envelope test, and confirm the
|
|
331
|
+
suite stays green before moving on.
|
|
332
|
+
|
|
333
|
+
## Coverage gate & CI
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
uv run pytest --cov=app --cov-report=term-missing
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
`--cov-fail-under=85` in `pyproject.toml` is the single source of truth — do not pass a
|
|
340
|
+
second threshold on the command line. Add `--cov-branch` for branch coverage; the lines that
|
|
341
|
+
*must* be covered are the auth and error paths: 401, 403, 404, 409, 422, and the catch-all
|
|
342
|
+
500. In CI, run `uv run pytest` after `ruff` and `mypy` so a failing lint/type check blocks
|
|
343
|
+
before the (slower) test job.
|
|
344
|
+
|
|
345
|
+
## See Also
|
|
346
|
+
|
|
347
|
+
- [`database.md`](database.md) — the engine/session wiring these fixtures build on.
|
|
348
|
+
- [`security.md`](security.md) — `create_access_token` and `get_current_user` used by the auth fixtures.
|
|
349
|
+
- `superpowers:test-driven-development` — red/green/refactor discipline these tests follow.
|