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,347 @@
|
|
|
1
|
+
# Async SQLAlchemy 2.0 + Alembic
|
|
2
|
+
|
|
3
|
+
The async persistence layer for a FastAPI service on SQLAlchemy 2.0, asyncpg 0.30 (or
|
|
4
|
+
psycopg 3 async), Alembic 1.13+, and PostgreSQL 16. The rules that prevent the two failures that
|
|
5
|
+
sink async ORM code: **one session per request with explicit commit/rollback**, and **never lazy-load
|
|
6
|
+
a relationship in async** — eager-load everything you serialize.
|
|
7
|
+
|
|
8
|
+
## Engine & session factory
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
from collections.abc import AsyncIterator
|
|
12
|
+
|
|
13
|
+
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
|
|
14
|
+
|
|
15
|
+
from app.core.config import get_settings
|
|
16
|
+
|
|
17
|
+
engine = create_async_engine(
|
|
18
|
+
str(get_settings().database_url),
|
|
19
|
+
pool_size=10,
|
|
20
|
+
max_overflow=20,
|
|
21
|
+
pool_pre_ping=True,
|
|
22
|
+
pool_recycle=1800,
|
|
23
|
+
)
|
|
24
|
+
async_session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def get_db() -> AsyncIterator[AsyncSession]:
|
|
28
|
+
async with async_session_factory() as session:
|
|
29
|
+
try:
|
|
30
|
+
yield session
|
|
31
|
+
await session.commit()
|
|
32
|
+
except Exception:
|
|
33
|
+
await session.rollback()
|
|
34
|
+
raise
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`expire_on_commit=False` is mandatory: with the default `True`, attributes expire after commit
|
|
38
|
+
and the *next* access triggers a lazy reload — which in async raises `MissingGreenlet`. The
|
|
39
|
+
`get_db` dependency owns the transaction lifecycle; services call `flush`, never `commit`.
|
|
40
|
+
|
|
41
|
+
## Declarative models (2.0 style)
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from datetime import datetime
|
|
45
|
+
from uuid import UUID, uuid4
|
|
46
|
+
|
|
47
|
+
from sqlalchemy import func
|
|
48
|
+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Base(DeclarativeBase):
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class TimestampMixin:
|
|
56
|
+
created_at: Mapped[datetime] = mapped_column(server_default=func.now())
|
|
57
|
+
updated_at: Mapped[datetime] = mapped_column(
|
|
58
|
+
server_default=func.now(), onupdate=func.now()
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class User(TimestampMixin, Base):
|
|
63
|
+
__tablename__ = "users"
|
|
64
|
+
|
|
65
|
+
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
|
66
|
+
email: Mapped[str] = mapped_column(unique=True, index=True)
|
|
67
|
+
full_name: Mapped[str]
|
|
68
|
+
hashed_password: Mapped[str]
|
|
69
|
+
is_active: Mapped[bool] = mapped_column(default=True)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`Mapped[...]` drives both the Python type and (where unambiguous) the column type. A bare
|
|
73
|
+
`Mapped[str]` is `NOT NULL`; `Mapped[str | None]` is nullable. `server_default=func.now()` puts
|
|
74
|
+
the default in the database (resilient to non-ORM writes); `onupdate` fires on ORM updates.
|
|
75
|
+
|
|
76
|
+
## Relationships
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from uuid import UUID, uuid4
|
|
80
|
+
|
|
81
|
+
from sqlalchemy import ForeignKey
|
|
82
|
+
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
83
|
+
|
|
84
|
+
from app.db.base import Base
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Order(Base):
|
|
88
|
+
__tablename__ = "orders"
|
|
89
|
+
|
|
90
|
+
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
|
91
|
+
user_id: Mapped[UUID] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True)
|
|
92
|
+
amount_cents: Mapped[int]
|
|
93
|
+
|
|
94
|
+
user: Mapped["User"] = relationship(back_populates="orders")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# On the User model:
|
|
98
|
+
# orders: Mapped[list["Order"]] = relationship(
|
|
99
|
+
# back_populates="user", cascade="all, delete-orphan"
|
|
100
|
+
# )
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`back_populates` keeps both sides in sync in the identity map. `cascade="all, delete-orphan"`
|
|
104
|
+
deletes orphaned children when removed from the collection; pair it with a DB-level
|
|
105
|
+
`ondelete="CASCADE"` on the FK so deletes are correct even outside the ORM.
|
|
106
|
+
|
|
107
|
+
## Querying
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from uuid import UUID
|
|
111
|
+
|
|
112
|
+
from sqlalchemy import delete, func, select, update
|
|
113
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
114
|
+
|
|
115
|
+
from app.models.user import User
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
async def queries(db: AsyncSession, pk: UUID, email: str) -> None:
|
|
119
|
+
# Filtered, ordered, paginated SELECT -> list of model instances.
|
|
120
|
+
result = await db.execute(
|
|
121
|
+
select(User).where(User.is_active.is_(True)).order_by(User.created_at.desc()).limit(50)
|
|
122
|
+
)
|
|
123
|
+
users: list[User] = list(result.scalars().all())
|
|
124
|
+
|
|
125
|
+
# Single row or None (raises on >1):
|
|
126
|
+
one = await db.execute(select(User).where(User.email == email))
|
|
127
|
+
maybe_user: User | None = one.scalar_one_or_none()
|
|
128
|
+
|
|
129
|
+
# Fast identity-map lookup by primary key:
|
|
130
|
+
by_pk: User | None = await db.get(User, pk)
|
|
131
|
+
|
|
132
|
+
# Core UPDATE / DELETE with RETURNING (no round-trip to reload):
|
|
133
|
+
updated = await db.execute(
|
|
134
|
+
update(User).where(User.id == pk).values(is_active=False).returning(User.id)
|
|
135
|
+
)
|
|
136
|
+
_changed_id = updated.scalar_one_or_none()
|
|
137
|
+
await db.execute(delete(User).where(User.id == pk))
|
|
138
|
+
|
|
139
|
+
# Aggregate:
|
|
140
|
+
total = await db.execute(select(func.count()).select_from(User))
|
|
141
|
+
_count: int = total.scalar_one()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Use `.scalars()` to unwrap single-entity rows into model instances; without it you get `Row`
|
|
145
|
+
tuples. `scalar_one_or_none()` is the safe "fetch by unique key" idiom; `db.get` is the only one
|
|
146
|
+
that consults the identity map first and can skip a query entirely.
|
|
147
|
+
|
|
148
|
+
## N+1 & eager loading
|
|
149
|
+
|
|
150
|
+
**Lazy loading is unsafe in async SQLAlchemy.** Accessing an unloaded relationship outside an
|
|
151
|
+
awaited load triggers implicit I/O on the event loop and raises
|
|
152
|
+
`sqlalchemy.exc.MissingGreenlet` (or, if it ever succeeds, fires one query per parent row — the
|
|
153
|
+
N+1). Load relationships explicitly.
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
# Bad: lazy access in async -> MissingGreenlet, or N+1 if it slips through.
|
|
157
|
+
async def bad(db: AsyncSession) -> list[int]:
|
|
158
|
+
result = await db.execute(select(User))
|
|
159
|
+
users = result.scalars().all()
|
|
160
|
+
return [len(u.orders) for u in users] # u.orders was never loaded -> raises / N queries
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from sqlalchemy.orm import joinedload, selectinload
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# Good: eager-load up front in one extra query (collections) / one join (scalars).
|
|
168
|
+
async def good_collections(db: AsyncSession) -> list[int]:
|
|
169
|
+
result = await db.execute(select(User).options(selectinload(User.orders)))
|
|
170
|
+
users = result.scalars().unique().all()
|
|
171
|
+
return [len(u.orders) for u in users]
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
async def good_scalar(db: AsyncSession) -> list[str]:
|
|
175
|
+
result = await db.execute(select(Order).options(joinedload(Order.user)))
|
|
176
|
+
orders = result.scalars().all()
|
|
177
|
+
return [o.user.full_name for o in orders]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Choose `selectinload` for collections (one follow-up `IN (...)` query, no row multiplication);
|
|
181
|
+
choose `joinedload` for scalar many-to-one (a single `JOIN`, no extra round-trip). Call
|
|
182
|
+
`.unique()` when a `joinedload` on a collection would otherwise duplicate parent rows.
|
|
183
|
+
|
|
184
|
+
## Repository / CRUD layer
|
|
185
|
+
|
|
186
|
+
Keep `select`/`flush` out of routers behind a generic repository so persistence is swappable
|
|
187
|
+
and testable in isolation.
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from typing import Generic, TypeVar
|
|
191
|
+
from uuid import UUID
|
|
192
|
+
|
|
193
|
+
from sqlalchemy import select
|
|
194
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
195
|
+
|
|
196
|
+
from app.db.base import Base
|
|
197
|
+
|
|
198
|
+
ModelT = TypeVar("ModelT", bound=Base)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class Repository(Generic[ModelT]):
|
|
202
|
+
def __init__(self, model: type[ModelT], db: AsyncSession) -> None:
|
|
203
|
+
self.model = model
|
|
204
|
+
self.db = db
|
|
205
|
+
|
|
206
|
+
async def get(self, pk: UUID) -> ModelT | None:
|
|
207
|
+
return await self.db.get(self.model, pk)
|
|
208
|
+
|
|
209
|
+
async def list(self, limit: int, offset: int) -> list[ModelT]:
|
|
210
|
+
result = await self.db.execute(select(self.model).limit(limit).offset(offset))
|
|
211
|
+
return list(result.scalars().all())
|
|
212
|
+
|
|
213
|
+
async def add(self, obj: ModelT) -> ModelT:
|
|
214
|
+
self.db.add(obj)
|
|
215
|
+
await self.db.flush()
|
|
216
|
+
return obj
|
|
217
|
+
|
|
218
|
+
async def delete(self, obj: ModelT) -> None:
|
|
219
|
+
await self.db.delete(obj)
|
|
220
|
+
await self.db.flush()
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`flush` pushes pending SQL (assigning generated PKs / surfacing constraint errors) **without**
|
|
224
|
+
committing — the request's `get_db` owns the outer commit. Services compose repositories and
|
|
225
|
+
enforce business rules; routers call services.
|
|
226
|
+
|
|
227
|
+
## Transactions
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
async def transfer(db: AsyncSession, debit_id, credit_id, cents: int) -> None:
|
|
234
|
+
# Multi-statement atomicity: both updates commit together or neither does.
|
|
235
|
+
async with db.begin():
|
|
236
|
+
await debit(db, debit_id, cents)
|
|
237
|
+
await credit(db, credit_id, cents)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
async def with_savepoint(db: AsyncSession) -> None:
|
|
241
|
+
# Nested SAVEPOINT: roll back a sub-step without aborting the whole transaction.
|
|
242
|
+
async with db.begin_nested():
|
|
243
|
+
await risky_step(db)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
With the `get_db` commit-on-success pattern, prefer `flush` inside services and let the
|
|
247
|
+
dependency own the single outer commit. Reach for `db.begin()` explicitly only when a service
|
|
248
|
+
must guarantee atomicity across statements it would otherwise leave to the request boundary.
|
|
249
|
+
|
|
250
|
+
## Alembic (async)
|
|
251
|
+
|
|
252
|
+
Async migrations need an `env.py` that runs the engine inside an event loop and dispatches DDL
|
|
253
|
+
via `run_sync`.
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
import asyncio
|
|
257
|
+
from logging.config import fileConfig
|
|
258
|
+
|
|
259
|
+
from alembic import context
|
|
260
|
+
from sqlalchemy import pool
|
|
261
|
+
from sqlalchemy.engine import Connection
|
|
262
|
+
from sqlalchemy.ext.asyncio import async_engine_from_config
|
|
263
|
+
|
|
264
|
+
from app.core.config import get_settings
|
|
265
|
+
from app.db.base import Base
|
|
266
|
+
|
|
267
|
+
config = context.config
|
|
268
|
+
config.set_main_option("sqlalchemy.url", str(get_settings().database_url))
|
|
269
|
+
if config.config_file_name is not None:
|
|
270
|
+
fileConfig(config.config_file_name)
|
|
271
|
+
|
|
272
|
+
target_metadata = Base.metadata
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def do_run_migrations(connection: Connection) -> None:
|
|
276
|
+
context.configure(connection=connection, target_metadata=target_metadata, compare_type=True)
|
|
277
|
+
with context.begin_transaction():
|
|
278
|
+
context.run_migrations()
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
async def run_async_migrations() -> None:
|
|
282
|
+
connectable = async_engine_from_config(
|
|
283
|
+
config.get_section(config.config_ini_section, {}),
|
|
284
|
+
prefix="sqlalchemy.",
|
|
285
|
+
poolclass=pool.NullPool,
|
|
286
|
+
)
|
|
287
|
+
async with connectable.connect() as connection:
|
|
288
|
+
await connection.run_sync(do_run_migrations)
|
|
289
|
+
await connectable.dispose()
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def run_migrations_online() -> None:
|
|
293
|
+
asyncio.run(run_async_migrations())
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
run_migrations_online()
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
```ini
|
|
300
|
+
# alembic.ini (sqlalchemy.url is overridden from env in env.py; leave a placeholder here)
|
|
301
|
+
[alembic]
|
|
302
|
+
script_location = alembic
|
|
303
|
+
sqlalchemy.url = driver://user:pass@localhost/dbname
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
alembic revision --autogenerate -m "create users"
|
|
308
|
+
alembic upgrade head
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Autogenerate is a draft, not an oracle: it misses server defaults, CHECK constraints, some type
|
|
312
|
+
changes, and table/column renames (it sees a drop + add). **Always read the generated migration**
|
|
313
|
+
before committing, and add `compare_type=True` (above) to catch column type drift. For a
|
|
314
|
+
review-then-apply workflow in prod, emit offline SQL with `alembic upgrade head --sql`.
|
|
315
|
+
|
|
316
|
+
## Connection pooling & production
|
|
317
|
+
|
|
318
|
+
Total open connections is bounded by `workers × (pool_size + max_overflow)` and must stay under
|
|
319
|
+
Postgres `max_connections` (default 100) with headroom for admin and other clients. With 5
|
|
320
|
+
gunicorn workers and the engine above (`10 + 20`), that is up to 150 connections — already over
|
|
321
|
+
the default. Either shrink the pool, raise `max_connections`, or front the DB with pgbouncer.
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
325
|
+
from sqlalchemy.pool import NullPool
|
|
326
|
+
|
|
327
|
+
# Behind pgbouncer in transaction-pooling mode: SQLAlchemy must not pool, and asyncpg's
|
|
328
|
+
# prepared-statement cache breaks because statements outlive the server-side session.
|
|
329
|
+
engine = create_async_engine(
|
|
330
|
+
"postgresql+asyncpg://user:pass@pgbouncer:6432/app",
|
|
331
|
+
poolclass=NullPool,
|
|
332
|
+
connect_args={
|
|
333
|
+
"statement_cache_size": 0,
|
|
334
|
+
"server_settings": {"statement_timeout": "5000"}, # ms; kill runaway queries
|
|
335
|
+
},
|
|
336
|
+
)
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
`pool_pre_ping=True` issues a cheap liveness check before handing out a connection, transparently
|
|
340
|
+
replacing ones the DB or a load balancer dropped. `pool_recycle=1800` proactively closes
|
|
341
|
+
connections older than 30 minutes to dodge idle-timeout resets. A `statement_timeout` is the
|
|
342
|
+
backstop that stops one slow query from holding a connection forever.
|
|
343
|
+
|
|
344
|
+
## See Also
|
|
345
|
+
|
|
346
|
+
- [`production.md`](production.md) — worker/pool math, health checks, graceful shutdown.
|
|
347
|
+
- [`postgresdb`](../../postgresdb/SKILL.md) — engine-level schema/index design, EXPLAIN, expand-contract migrations, PgBouncer pooling beneath this async layer.
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Running FastAPI in production
|
|
2
|
+
|
|
3
|
+
Shipping an async FastAPI service: ASGI server + worker math, structured JSON logging with
|
|
4
|
+
request correlation, liveness vs readiness probes, graceful shutdown, pagination and caching at
|
|
5
|
+
scale, performance defaults, and observability. For the container image and CI/CD pipeline,
|
|
6
|
+
**See Also [`deployment`](../../deployment/SKILL.md)** — this file keeps only a Docker *note*.
|
|
7
|
+
|
|
8
|
+
## ASGI server
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# Dev: one process, autoreload on file change.
|
|
12
|
+
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
|
|
13
|
+
|
|
14
|
+
# Prod: gunicorn process manager + uvicorn workers (install the `uvicorn-worker` package).
|
|
15
|
+
# Worker count rule of thumb: (2 * CPU cores) + 1
|
|
16
|
+
gunicorn app.main:app \
|
|
17
|
+
-k uvicorn_worker.UvicornWorker \
|
|
18
|
+
--workers 5 --timeout 30 --graceful-timeout 30 \
|
|
19
|
+
--bind 0.0.0.0:8000 --forwarded-allow-ips '*'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Never run `--reload` in prod: it watches the filesystem, spawns a reloader process, and
|
|
23
|
+
disables key optimizations. gunicorn gives you a battle-tested process manager (restart on
|
|
24
|
+
crash, graceful reload). The worker class lives in the standalone `uvicorn-worker` package
|
|
25
|
+
(`pip install uvicorn-worker`) — the old `uvicorn.workers.UvicornWorker` was deprecated in
|
|
26
|
+
uvicorn 0.30 and only emits a warning today. `uvicorn app.main:app --workers 5` is a fine
|
|
27
|
+
gunicorn-free alternative.
|
|
28
|
+
`--timeout` kills a worker stuck on a single request; `--graceful-timeout` is the drain window on
|
|
29
|
+
shutdown. For async workloads the `(2×CPU)+1` formula is a starting point — profile real
|
|
30
|
+
concurrency, since one async worker handles many in-flight requests.
|
|
31
|
+
|
|
32
|
+
## Structured logging
|
|
33
|
+
|
|
34
|
+
Emit JSON so logs are queryable, and bind a request id so every line in a request correlates.
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import logging
|
|
38
|
+
|
|
39
|
+
import structlog
|
|
40
|
+
|
|
41
|
+
structlog.configure(
|
|
42
|
+
processors=[
|
|
43
|
+
structlog.contextvars.merge_contextvars,
|
|
44
|
+
structlog.processors.add_log_level,
|
|
45
|
+
structlog.processors.TimeStamper(fmt="iso"),
|
|
46
|
+
structlog.processors.dict_tracebacks,
|
|
47
|
+
structlog.processors.JSONRenderer(),
|
|
48
|
+
],
|
|
49
|
+
wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
|
|
50
|
+
cache_logger_on_first_use=True,
|
|
51
|
+
)
|
|
52
|
+
logger = structlog.get_logger()
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import uuid
|
|
57
|
+
|
|
58
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
59
|
+
from starlette.requests import Request
|
|
60
|
+
from starlette.types import ASGIApp
|
|
61
|
+
import structlog
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class RequestIDMiddleware(BaseHTTPMiddleware):
|
|
65
|
+
def __init__(self, app: ASGIApp) -> None:
|
|
66
|
+
super().__init__(app)
|
|
67
|
+
|
|
68
|
+
async def dispatch(self, request: Request, call_next):
|
|
69
|
+
request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
|
|
70
|
+
structlog.contextvars.bind_contextvars(request_id=request_id, path=request.url.path)
|
|
71
|
+
try:
|
|
72
|
+
response = await call_next(request)
|
|
73
|
+
finally:
|
|
74
|
+
structlog.contextvars.clear_contextvars()
|
|
75
|
+
response.headers["X-Request-ID"] = request_id
|
|
76
|
+
return response
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`merge_contextvars` injects the bound `request_id` into every log emitted during the request,
|
|
80
|
+
so a single trace id stitches the whole call together. Route uvicorn's own loggers (`uvicorn`,
|
|
81
|
+
`uvicorn.access`) into the same JSON handler so access logs match your format; set log level by
|
|
82
|
+
environment (`DEBUG` in dev, `INFO`/`WARNING` in prod).
|
|
83
|
+
|
|
84
|
+
## Health & readiness
|
|
85
|
+
|
|
86
|
+
Split liveness from readiness: liveness must not touch dependencies (a flaky DB should not kill
|
|
87
|
+
the pod), readiness must verify them (a pod with a dead DB should leave the load balancer).
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from fastapi import APIRouter, Response, status
|
|
91
|
+
from sqlalchemy import select
|
|
92
|
+
|
|
93
|
+
from app.api.deps import DbSession
|
|
94
|
+
|
|
95
|
+
router = APIRouter()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@router.get("")
|
|
99
|
+
async def liveness() -> dict[str, str]:
|
|
100
|
+
return {"status": "ok"} # no dependencies — "is the process up?"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@router.get("/ready")
|
|
104
|
+
async def readiness(db: DbSession, response: Response) -> dict[str, str]:
|
|
105
|
+
try:
|
|
106
|
+
await db.execute(select(1))
|
|
107
|
+
except Exception:
|
|
108
|
+
response.status_code = status.HTTP_503_SERVICE_UNAVAILABLE
|
|
109
|
+
return {"status": "unavailable"}
|
|
110
|
+
return {"status": "ready"} # pings DB/cache — "can it serve traffic?"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
In Kubernetes, a failing **liveness** probe restarts the pod; a failing **readiness** probe only
|
|
114
|
+
removes it from the Service endpoints until it recovers. Wire `/health` to liveness and
|
|
115
|
+
`/health/ready` to readiness accordingly.
|
|
116
|
+
|
|
117
|
+
## Graceful shutdown
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from contextlib import asynccontextmanager
|
|
121
|
+
|
|
122
|
+
from fastapi import FastAPI
|
|
123
|
+
|
|
124
|
+
from app.db.base import engine
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@asynccontextmanager
|
|
128
|
+
async def lifespan(app: FastAPI):
|
|
129
|
+
yield
|
|
130
|
+
# Drain: stop accepting work, finish in-flight requests, then release resources.
|
|
131
|
+
await engine.dispose() # close pooled DB connections so the DB sees a clean exit
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
On `SIGTERM`, gunicorn/uvicorn stop accepting new connections and give in-flight requests up to
|
|
135
|
+
`--graceful-timeout` to finish before forcing exit; the lifespan teardown then runs. Make
|
|
136
|
+
shutdown **idempotent** (safe if called twice) and ensure any in-process background work is
|
|
137
|
+
drained or handed off — connection draining at the load balancer plus the graceful window
|
|
138
|
+
prevents dropped requests during a rolling deploy.
|
|
139
|
+
|
|
140
|
+
## Pagination at scale
|
|
141
|
+
|
|
142
|
+
Offset pagination (`LIMIT/OFFSET`) is simple but degrades: large offsets force the DB to scan
|
|
143
|
+
and discard rows, and concurrent inserts shift the window (duplicates/skips). Keyset (cursor)
|
|
144
|
+
pagination stays O(page size) and stable.
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from base64 import urlsafe_b64decode, urlsafe_b64encode
|
|
148
|
+
from uuid import UUID
|
|
149
|
+
|
|
150
|
+
from sqlalchemy import select
|
|
151
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
152
|
+
|
|
153
|
+
from app.models.user import User
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
async def keyset_page(db: AsyncSession, after: UUID | None, limit: int) -> tuple[list[User], str | None]:
|
|
157
|
+
stmt = select(User).order_by(User.created_at.desc(), User.id.desc()).limit(limit)
|
|
158
|
+
if after is not None:
|
|
159
|
+
stmt = stmt.where(User.id < after) # seek past the last id of the prev page
|
|
160
|
+
rows = list((await db.execute(stmt)).scalars().all())
|
|
161
|
+
next_cursor = urlsafe_b64encode(str(rows[-1].id).encode()).decode() if len(rows) == limit else None
|
|
162
|
+
return rows, next_cursor
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Always include a unique tiebreaker (`id`) in the `ORDER BY` so the ordering is total and stable.
|
|
166
|
+
`COUNT(*)` for a total is expensive on large tables — make it optional or approximate. Return a
|
|
167
|
+
`meta`/`links` envelope with the encoded cursor and a `next`/`prev` link; the contract here is
|
|
168
|
+
a REST-design concern, while the keyset SQL above is the FastAPI-side implementation.
|
|
169
|
+
|
|
170
|
+
## Caching
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
from hashlib import sha256
|
|
174
|
+
|
|
175
|
+
import orjson
|
|
176
|
+
import redis.asyncio as aioredis
|
|
177
|
+
from fastapi import Response
|
|
178
|
+
|
|
179
|
+
redis = aioredis.from_url("redis://redis:6379/0")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
async def cached_json(key: str, ttl: int, build):
|
|
183
|
+
cached = await redis.get(key)
|
|
184
|
+
if cached is not None:
|
|
185
|
+
return orjson.loads(cached)
|
|
186
|
+
value = await build()
|
|
187
|
+
await redis.set(key, orjson.dumps(value), ex=ttl) # explicit TTL; invalidate on write
|
|
188
|
+
return value
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def set_etag(response: Response, payload: bytes) -> None:
|
|
192
|
+
etag = sha256(payload).hexdigest()
|
|
193
|
+
response.headers["ETag"] = f'"{etag}"'
|
|
194
|
+
response.headers["Cache-Control"] = "private, max-age=30"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Invalidate the cache key explicitly on any write to the underlying resource — TTL alone serves
|
|
198
|
+
stale data. Guard against cache stampede (many misses recomputing at once) with a short lock
|
|
199
|
+
(`SET key val NX EX`) or jittered TTLs. Use `@lru_cache` only for pure, process-local config
|
|
200
|
+
like `get_settings`.
|
|
201
|
+
|
|
202
|
+
## Performance
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from fastapi import FastAPI
|
|
206
|
+
from fastapi.responses import ORJSONResponse
|
|
207
|
+
|
|
208
|
+
app = FastAPI(default_response_class=ORJSONResponse) # orjson: faster, handles UUID/datetime
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Behind a reverse proxy or load balancer, pass `--proxy-headers` (uvicorn) /
|
|
212
|
+
`--forwarded-allow-ips` (gunicorn) so `X-Forwarded-For`/`-Proto` are trusted and `request.url`
|
|
213
|
+
reflects the public scheme. Add `GZipMiddleware` for large JSON responses — it trades CPU for
|
|
214
|
+
bandwidth, so only enable above a size threshold (`minimum_size=1000`). Never run sync/blocking
|
|
215
|
+
I/O on the event loop; offload CPU-bound work with `await anyio.to_thread.run_sync(...)`. Profile
|
|
216
|
+
hot paths with `py-spy record` against a running worker (no code changes, no restart).
|
|
217
|
+
|
|
218
|
+
## Observability
|
|
219
|
+
|
|
220
|
+
Instrument with OpenTelemetry (`opentelemetry-instrumentation-fastapi`) for distributed traces,
|
|
221
|
+
or a Prometheus middleware (`prometheus-fastapi-instrumentator`) for metrics. Track the RED
|
|
222
|
+
signals — **R**ate (requests/sec), **E**rrors (5xx ratio), **D**uration (p50/p95/p99 latency) —
|
|
223
|
+
per route, and alert on error ratio and tail latency rather than averages.
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
# from prometheus_fastapi_instrumentator import Instrumentator
|
|
227
|
+
# Instrumentator().instrument(app).expose(app, endpoint="/metrics")
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Keep this a pointer: pick one tracing and one metrics backend, export to your collector, and
|
|
231
|
+
correlate traces with the `request_id` from the logging middleware.
|
|
232
|
+
|
|
233
|
+
## Customizing the OpenAPI schema
|
|
234
|
+
|
|
235
|
+
FastAPI builds the OpenAPI document lazily and caches it on `app.openapi_schema`. To inject
|
|
236
|
+
extra metadata (servers, security schemes, a logo, tags) build the base schema once, mutate
|
|
237
|
+
it, cache it, and **assign your function to `app.openapi`** — assigning the callable (not
|
|
238
|
+
calling it eagerly) preserves the lazy-build-and-cache contract and lets `/docs` and
|
|
239
|
+
`/openapi.json` pick it up.
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
from typing import Any
|
|
243
|
+
|
|
244
|
+
from fastapi import FastAPI
|
|
245
|
+
from fastapi.openapi.utils import get_openapi
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def customize_openapi(app: FastAPI) -> None:
|
|
249
|
+
def build() -> dict[str, Any]:
|
|
250
|
+
if app.openapi_schema: # serve the cached doc on later calls
|
|
251
|
+
return app.openapi_schema
|
|
252
|
+
schema = get_openapi(
|
|
253
|
+
title=app.title,
|
|
254
|
+
version=app.version,
|
|
255
|
+
description="Authenticate via the OAuth2 password flow at /auth/login.",
|
|
256
|
+
routes=app.routes,
|
|
257
|
+
)
|
|
258
|
+
schema["servers"] = [{"url": "https://api.example.com", "description": "production"}]
|
|
259
|
+
schema.setdefault("components", {})["securitySchemes"] = {
|
|
260
|
+
"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"},
|
|
261
|
+
}
|
|
262
|
+
app.openapi_schema = schema
|
|
263
|
+
return schema
|
|
264
|
+
|
|
265
|
+
app.openapi = build # type: ignore[method-assign] # assign, don't call — keep it lazy
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Call `customize_openapi(app)` inside `create_app()` before returning. **Bad** =
|
|
269
|
+
`app.openapi_schema = customize_openapi(app)()` at import time — it forces the schema to
|
|
270
|
+
build before every route is registered, so late `include_router` calls go missing from the
|
|
271
|
+
docs.
|
|
272
|
+
|
|
273
|
+
## AppError subclasses
|
|
274
|
+
|
|
275
|
+
The base `AppError` + `register_exception_handlers` live in `SKILL.md` (Error handling &
|
|
276
|
+
envelope). Each concrete failure is a subclass that fixes a `code` and HTTP status, so call
|
|
277
|
+
sites stay declarative (`raise NotFoundError("User", ident)`) and the handler renders the
|
|
278
|
+
shared envelope.
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
from fastapi import status
|
|
282
|
+
|
|
283
|
+
from app.exceptions import AppError
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class NotFoundError(AppError):
|
|
287
|
+
def __init__(self, resource: str, ident: str) -> None:
|
|
288
|
+
super().__init__(f"{resource} not found: {ident}", "not_found", 404)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class ConflictError(AppError):
|
|
292
|
+
def __init__(self, message: str) -> None:
|
|
293
|
+
super().__init__(message, "conflict", status.HTTP_409_CONFLICT)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class Unauthorized(AppError):
|
|
297
|
+
def __init__(self, message: str = "Authentication required") -> None:
|
|
298
|
+
super().__init__(message, "unauthorized", status.HTTP_401_UNAUTHORIZED)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class Forbidden(AppError):
|
|
302
|
+
def __init__(self, message: str = "Insufficient permissions") -> None:
|
|
303
|
+
super().__init__(message, "forbidden", status.HTTP_403_FORBIDDEN)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`Unauthorized` and `Forbidden` are the ones raised by the auth/RBAC dependencies in
|
|
307
|
+
[`security.md`](security.md). Prefer `NotFoundError` (404) over `Forbidden` (403) for private
|
|
308
|
+
resources whose existence should not leak to an unauthorized caller.
|
|
309
|
+
|
|
310
|
+
## Docker note
|
|
311
|
+
|
|
312
|
+
```dockerfile
|
|
313
|
+
FROM python:3.12-slim AS base
|
|
314
|
+
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
|
|
315
|
+
RUN useradd --create-home --uid 10001 appuser
|
|
316
|
+
WORKDIR /app
|
|
317
|
+
|
|
318
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
319
|
+
COPY pyproject.toml uv.lock ./
|
|
320
|
+
RUN uv sync --frozen --no-dev
|
|
321
|
+
|
|
322
|
+
COPY app ./app
|
|
323
|
+
USER appuser
|
|
324
|
+
EXPOSE 8000
|
|
325
|
+
HEALTHCHECK --interval=30s --timeout=3s CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/health').status==200 else 1)"
|
|
326
|
+
CMD ["uv", "run", "gunicorn", "app.main:app", "-k", "uvicorn_worker.UvicornWorker", "--workers", "5", "--bind", "0.0.0.0:8000"]
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
A slim base, a non-root user, a frozen lockfile install, an explicit `EXPOSE`, and a
|
|
330
|
+
`HEALTHCHECK` hitting `/health`. For multi-stage builds, Compose, registries, and CI/CD,
|
|
331
|
+
**See Also `deployment`** — do not duplicate the pipeline here.
|
|
332
|
+
|
|
333
|
+
## See Also
|
|
334
|
+
|
|
335
|
+
- [`database.md`](database.md) — pool sizing vs worker count, pgbouncer, statement timeouts.
|
|
336
|
+
- [`security.md`](security.md) — TLS, proxy headers, security headers, secret injection.
|
|
337
|
+
- [`deployment`](../../deployment/SKILL.md) — Dockerfile, Compose, CI/CD, container runtime.
|
|
338
|
+
- [`postgresdb`](../../postgresdb/SKILL.md) — connection-pool ceilings, PgBouncer modes, partitioning at scale.
|