@wazir-dev/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +111 -0
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/assets/composition-engine.mmd +34 -0
- package/assets/demo-script.sh +17 -0
- package/assets/logo-dark.svg +14 -0
- package/assets/logo.svg +14 -0
- package/assets/pipeline.mmd +39 -0
- package/assets/record-demo.sh +51 -0
- package/docs/README.md +51 -0
- package/docs/adapters/context-mode.md +60 -0
- package/docs/concepts/architecture.md +87 -0
- package/docs/concepts/artifact-model.md +60 -0
- package/docs/concepts/composition-engine.md +36 -0
- package/docs/concepts/indexing-and-recall.md +160 -0
- package/docs/concepts/observability.md +41 -0
- package/docs/concepts/roles-and-workflows.md +59 -0
- package/docs/concepts/terminology-policy.md +27 -0
- package/docs/getting-started/01-installation.md +78 -0
- package/docs/getting-started/02-first-run.md +102 -0
- package/docs/getting-started/03-adding-to-project.md +15 -0
- package/docs/getting-started/04-host-setup.md +15 -0
- package/docs/guides/ci-integration.md +15 -0
- package/docs/guides/creating-skills.md +15 -0
- package/docs/guides/expertise-module-authoring.md +15 -0
- package/docs/guides/hook-development.md +15 -0
- package/docs/guides/memory-and-learnings.md +34 -0
- package/docs/guides/multi-host-export.md +15 -0
- package/docs/guides/troubleshooting.md +101 -0
- package/docs/guides/writing-custom-roles.md +15 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
- package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
- package/docs/readmes/INDEX.md +99 -0
- package/docs/readmes/features/expertise/README.md +171 -0
- package/docs/readmes/features/exports/README.md +222 -0
- package/docs/readmes/features/hooks/README.md +103 -0
- package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
- package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
- package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
- package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
- package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
- package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
- package/docs/readmes/features/hooks/session-start.md +119 -0
- package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
- package/docs/readmes/features/roles/README.md +157 -0
- package/docs/readmes/features/roles/clarifier.md +152 -0
- package/docs/readmes/features/roles/content-author.md +190 -0
- package/docs/readmes/features/roles/designer.md +193 -0
- package/docs/readmes/features/roles/executor.md +184 -0
- package/docs/readmes/features/roles/learner.md +210 -0
- package/docs/readmes/features/roles/planner.md +182 -0
- package/docs/readmes/features/roles/researcher.md +164 -0
- package/docs/readmes/features/roles/reviewer.md +184 -0
- package/docs/readmes/features/roles/specifier.md +162 -0
- package/docs/readmes/features/roles/verifier.md +215 -0
- package/docs/readmes/features/schemas/README.md +178 -0
- package/docs/readmes/features/skills/README.md +63 -0
- package/docs/readmes/features/skills/brainstorming.md +96 -0
- package/docs/readmes/features/skills/debugging.md +148 -0
- package/docs/readmes/features/skills/design.md +120 -0
- package/docs/readmes/features/skills/prepare-next.md +109 -0
- package/docs/readmes/features/skills/run-audit.md +159 -0
- package/docs/readmes/features/skills/scan-project.md +109 -0
- package/docs/readmes/features/skills/self-audit.md +176 -0
- package/docs/readmes/features/skills/tdd.md +137 -0
- package/docs/readmes/features/skills/using-skills.md +92 -0
- package/docs/readmes/features/skills/verification.md +120 -0
- package/docs/readmes/features/skills/writing-plans.md +104 -0
- package/docs/readmes/features/tooling/README.md +320 -0
- package/docs/readmes/features/workflows/README.md +186 -0
- package/docs/readmes/features/workflows/author.md +181 -0
- package/docs/readmes/features/workflows/clarify.md +154 -0
- package/docs/readmes/features/workflows/design-review.md +171 -0
- package/docs/readmes/features/workflows/design.md +169 -0
- package/docs/readmes/features/workflows/discover.md +162 -0
- package/docs/readmes/features/workflows/execute.md +173 -0
- package/docs/readmes/features/workflows/learn.md +167 -0
- package/docs/readmes/features/workflows/plan-review.md +165 -0
- package/docs/readmes/features/workflows/plan.md +170 -0
- package/docs/readmes/features/workflows/prepare-next.md +167 -0
- package/docs/readmes/features/workflows/review.md +169 -0
- package/docs/readmes/features/workflows/run-audit.md +191 -0
- package/docs/readmes/features/workflows/spec-challenge.md +159 -0
- package/docs/readmes/features/workflows/specify.md +160 -0
- package/docs/readmes/features/workflows/verify.md +177 -0
- package/docs/readmes/packages/README.md +50 -0
- package/docs/readmes/packages/ajv.md +117 -0
- package/docs/readmes/packages/context-mode.md +118 -0
- package/docs/readmes/packages/gray-matter.md +116 -0
- package/docs/readmes/packages/node-test.md +137 -0
- package/docs/readmes/packages/yaml.md +112 -0
- package/docs/reference/configuration-reference.md +159 -0
- package/docs/reference/expertise-index.md +52 -0
- package/docs/reference/git-flow.md +43 -0
- package/docs/reference/hooks.md +87 -0
- package/docs/reference/host-exports.md +50 -0
- package/docs/reference/launch-checklist.md +172 -0
- package/docs/reference/marketplace-listings.md +76 -0
- package/docs/reference/release-process.md +34 -0
- package/docs/reference/roles-reference.md +77 -0
- package/docs/reference/skills.md +33 -0
- package/docs/reference/templates.md +29 -0
- package/docs/reference/tooling-cli.md +94 -0
- package/docs/truth-claims.yaml +222 -0
- package/expertise/PROGRESS.md +63 -0
- package/expertise/README.md +18 -0
- package/expertise/antipatterns/PROGRESS.md +56 -0
- package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
- package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
- package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
- package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
- package/expertise/antipatterns/backend/index.md +24 -0
- package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
- package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
- package/expertise/antipatterns/code/async-antipatterns.md +622 -0
- package/expertise/antipatterns/code/code-smells.md +1186 -0
- package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
- package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
- package/expertise/antipatterns/code/index.md +27 -0
- package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
- package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
- package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
- package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
- package/expertise/antipatterns/design/dark-patterns.md +1121 -0
- package/expertise/antipatterns/design/index.md +22 -0
- package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
- package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
- package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
- package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
- package/expertise/antipatterns/frontend/index.md +23 -0
- package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
- package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
- package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
- package/expertise/antipatterns/index.md +31 -0
- package/expertise/antipatterns/performance/index.md +20 -0
- package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
- package/expertise/antipatterns/performance/premature-optimization.md +623 -0
- package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
- package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
- package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
- package/expertise/antipatterns/process/index.md +23 -0
- package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
- package/expertise/antipatterns/security/index.md +20 -0
- package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
- package/expertise/antipatterns/security/security-theater.md +843 -0
- package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
- package/expertise/architecture/PROGRESS.md +70 -0
- package/expertise/architecture/data/caching-architecture.md +671 -0
- package/expertise/architecture/data/data-consistency.md +574 -0
- package/expertise/architecture/data/data-modeling.md +536 -0
- package/expertise/architecture/data/event-streams-and-queues.md +634 -0
- package/expertise/architecture/data/index.md +25 -0
- package/expertise/architecture/data/search-architecture.md +663 -0
- package/expertise/architecture/data/sql-vs-nosql.md +708 -0
- package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
- package/expertise/architecture/decisions/build-vs-buy.md +616 -0
- package/expertise/architecture/decisions/index.md +23 -0
- package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
- package/expertise/architecture/decisions/technology-selection.md +616 -0
- package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
- package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
- package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
- package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
- package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
- package/expertise/architecture/distributed/index.md +25 -0
- package/expertise/architecture/distributed/saga-pattern.md +797 -0
- package/expertise/architecture/foundations/architectural-thinking.md +460 -0
- package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
- package/expertise/architecture/foundations/design-principles-solid.md +649 -0
- package/expertise/architecture/foundations/domain-driven-design.md +719 -0
- package/expertise/architecture/foundations/index.md +25 -0
- package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
- package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
- package/expertise/architecture/index.md +34 -0
- package/expertise/architecture/integration/api-design-graphql.md +638 -0
- package/expertise/architecture/integration/api-design-grpc.md +804 -0
- package/expertise/architecture/integration/api-design-rest.md +892 -0
- package/expertise/architecture/integration/index.md +25 -0
- package/expertise/architecture/integration/third-party-integration.md +795 -0
- package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
- package/expertise/architecture/integration/websockets-realtime.md +791 -0
- package/expertise/architecture/mobile-architecture/index.md +22 -0
- package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
- package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
- package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
- package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
- package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
- package/expertise/architecture/patterns/event-driven.md +797 -0
- package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
- package/expertise/architecture/patterns/index.md +27 -0
- package/expertise/architecture/patterns/layered-architecture.md +736 -0
- package/expertise/architecture/patterns/microservices.md +753 -0
- package/expertise/architecture/patterns/modular-monolith.md +692 -0
- package/expertise/architecture/patterns/monolith.md +626 -0
- package/expertise/architecture/patterns/plugin-architecture.md +735 -0
- package/expertise/architecture/patterns/serverless.md +780 -0
- package/expertise/architecture/scaling/database-scaling.md +615 -0
- package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
- package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
- package/expertise/architecture/scaling/index.md +24 -0
- package/expertise/architecture/scaling/multi-tenancy.md +800 -0
- package/expertise/architecture/scaling/stateless-design.md +787 -0
- package/expertise/backend/embedded-firmware.md +625 -0
- package/expertise/backend/go.md +853 -0
- package/expertise/backend/index.md +24 -0
- package/expertise/backend/java-spring.md +448 -0
- package/expertise/backend/node-typescript.md +625 -0
- package/expertise/backend/python-fastapi.md +724 -0
- package/expertise/backend/rust.md +458 -0
- package/expertise/backend/solidity.md +711 -0
- package/expertise/composition-map.yaml +443 -0
- package/expertise/content/foundations/content-modeling.md +395 -0
- package/expertise/content/foundations/editorial-standards.md +449 -0
- package/expertise/content/foundations/index.md +24 -0
- package/expertise/content/foundations/microcopy.md +455 -0
- package/expertise/content/foundations/terminology-governance.md +509 -0
- package/expertise/content/index.md +34 -0
- package/expertise/content/patterns/accessibility-copy.md +518 -0
- package/expertise/content/patterns/index.md +24 -0
- package/expertise/content/patterns/notification-content.md +433 -0
- package/expertise/content/patterns/sample-content.md +486 -0
- package/expertise/content/patterns/state-copy.md +439 -0
- package/expertise/design/PROGRESS.md +58 -0
- package/expertise/design/disciplines/dark-mode-theming.md +577 -0
- package/expertise/design/disciplines/design-systems.md +595 -0
- package/expertise/design/disciplines/index.md +25 -0
- package/expertise/design/disciplines/information-architecture.md +800 -0
- package/expertise/design/disciplines/interaction-design.md +788 -0
- package/expertise/design/disciplines/responsive-design.md +552 -0
- package/expertise/design/disciplines/usability-testing.md +516 -0
- package/expertise/design/disciplines/user-research.md +792 -0
- package/expertise/design/foundations/accessibility-design.md +796 -0
- package/expertise/design/foundations/color-theory.md +797 -0
- package/expertise/design/foundations/iconography.md +795 -0
- package/expertise/design/foundations/index.md +26 -0
- package/expertise/design/foundations/motion-and-animation.md +653 -0
- package/expertise/design/foundations/rtl-design.md +585 -0
- package/expertise/design/foundations/spacing-and-layout.md +607 -0
- package/expertise/design/foundations/typography.md +800 -0
- package/expertise/design/foundations/visual-hierarchy.md +761 -0
- package/expertise/design/index.md +32 -0
- package/expertise/design/patterns/authentication-flows.md +474 -0
- package/expertise/design/patterns/content-consumption.md +789 -0
- package/expertise/design/patterns/data-display.md +618 -0
- package/expertise/design/patterns/e-commerce.md +1494 -0
- package/expertise/design/patterns/feedback-and-states.md +642 -0
- package/expertise/design/patterns/forms-and-input.md +819 -0
- package/expertise/design/patterns/gamification.md +801 -0
- package/expertise/design/patterns/index.md +31 -0
- package/expertise/design/patterns/microinteractions.md +449 -0
- package/expertise/design/patterns/navigation.md +800 -0
- package/expertise/design/patterns/notifications.md +705 -0
- package/expertise/design/patterns/onboarding.md +700 -0
- package/expertise/design/patterns/search-and-filter.md +601 -0
- package/expertise/design/patterns/settings-and-preferences.md +768 -0
- package/expertise/design/patterns/social-and-community.md +748 -0
- package/expertise/design/platforms/desktop-native.md +612 -0
- package/expertise/design/platforms/index.md +25 -0
- package/expertise/design/platforms/mobile-android.md +825 -0
- package/expertise/design/platforms/mobile-cross-platform.md +983 -0
- package/expertise/design/platforms/mobile-ios.md +699 -0
- package/expertise/design/platforms/tablet.md +794 -0
- package/expertise/design/platforms/web-dashboard.md +790 -0
- package/expertise/design/platforms/web-responsive.md +550 -0
- package/expertise/design/psychology/behavioral-nudges.md +449 -0
- package/expertise/design/psychology/cognitive-load.md +1191 -0
- package/expertise/design/psychology/error-psychology.md +778 -0
- package/expertise/design/psychology/index.md +22 -0
- package/expertise/design/psychology/persuasive-design.md +736 -0
- package/expertise/design/psychology/user-mental-models.md +623 -0
- package/expertise/design/tooling/open-pencil.md +266 -0
- package/expertise/frontend/angular.md +1073 -0
- package/expertise/frontend/desktop-electron.md +546 -0
- package/expertise/frontend/flutter.md +782 -0
- package/expertise/frontend/index.md +27 -0
- package/expertise/frontend/native-android.md +409 -0
- package/expertise/frontend/native-ios.md +490 -0
- package/expertise/frontend/react-native.md +1160 -0
- package/expertise/frontend/react.md +808 -0
- package/expertise/frontend/vue.md +1089 -0
- package/expertise/humanize/domain-rules-code.md +79 -0
- package/expertise/humanize/domain-rules-content.md +67 -0
- package/expertise/humanize/domain-rules-technical-docs.md +56 -0
- package/expertise/humanize/index.md +35 -0
- package/expertise/humanize/self-audit-checklist.md +87 -0
- package/expertise/humanize/sentence-patterns.md +218 -0
- package/expertise/humanize/vocabulary-blacklist.md +105 -0
- package/expertise/i18n/PROGRESS.md +65 -0
- package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
- package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
- package/expertise/i18n/advanced/complex-scripts.md +30 -0
- package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
- package/expertise/i18n/advanced/testing-i18n.md +28 -0
- package/expertise/i18n/content/content-adaptation.md +23 -0
- package/expertise/i18n/content/locale-specific-formatting.md +23 -0
- package/expertise/i18n/content/machine-translation-integration.md +28 -0
- package/expertise/i18n/content/translation-management.md +29 -0
- package/expertise/i18n/foundations/date-time-calendars.md +67 -0
- package/expertise/i18n/foundations/i18n-architecture.md +272 -0
- package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
- package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
- package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
- package/expertise/i18n/foundations/string-externalization.md +236 -0
- package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
- package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
- package/expertise/i18n/index.md +38 -0
- package/expertise/i18n/platform/backend-i18n.md +31 -0
- package/expertise/i18n/platform/flutter-i18n.md +148 -0
- package/expertise/i18n/platform/native-android-i18n.md +36 -0
- package/expertise/i18n/platform/native-ios-i18n.md +36 -0
- package/expertise/i18n/platform/react-i18n.md +103 -0
- package/expertise/i18n/platform/web-css-i18n.md +81 -0
- package/expertise/i18n/rtl/arabic-specific.md +175 -0
- package/expertise/i18n/rtl/hebrew-specific.md +149 -0
- package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
- package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
- package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
- package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
- package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
- package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
- package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
- package/expertise/i18n/rtl/rtl-typography.md +160 -0
- package/expertise/index.md +113 -0
- package/expertise/index.yaml +216 -0
- package/expertise/infrastructure/cloud-aws.md +597 -0
- package/expertise/infrastructure/cloud-gcp.md +599 -0
- package/expertise/infrastructure/cybersecurity.md +816 -0
- package/expertise/infrastructure/database-mongodb.md +447 -0
- package/expertise/infrastructure/database-postgres.md +400 -0
- package/expertise/infrastructure/devops-cicd.md +787 -0
- package/expertise/infrastructure/index.md +27 -0
- package/expertise/performance/PROGRESS.md +50 -0
- package/expertise/performance/backend/api-latency.md +1204 -0
- package/expertise/performance/backend/background-jobs.md +506 -0
- package/expertise/performance/backend/connection-pooling.md +1209 -0
- package/expertise/performance/backend/database-query-optimization.md +515 -0
- package/expertise/performance/backend/index.md +23 -0
- package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
- package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
- package/expertise/performance/foundations/caching-strategies.md +489 -0
- package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
- package/expertise/performance/foundations/index.md +24 -0
- package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
- package/expertise/performance/foundations/memory-management.md +964 -0
- package/expertise/performance/foundations/performance-budgets.md +1314 -0
- package/expertise/performance/index.md +31 -0
- package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
- package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
- package/expertise/performance/infrastructure/index.md +22 -0
- package/expertise/performance/infrastructure/load-balancing.md +1081 -0
- package/expertise/performance/infrastructure/observability.md +1079 -0
- package/expertise/performance/mobile/index.md +23 -0
- package/expertise/performance/mobile/mobile-animations.md +544 -0
- package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
- package/expertise/performance/mobile/mobile-network.md +452 -0
- package/expertise/performance/mobile/mobile-rendering.md +599 -0
- package/expertise/performance/mobile/mobile-startup-time.md +505 -0
- package/expertise/performance/platform-specific/flutter-performance.md +647 -0
- package/expertise/performance/platform-specific/index.md +22 -0
- package/expertise/performance/platform-specific/node-performance.md +1307 -0
- package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
- package/expertise/performance/platform-specific/react-performance.md +1403 -0
- package/expertise/performance/web/bundle-optimization.md +1239 -0
- package/expertise/performance/web/image-and-media.md +636 -0
- package/expertise/performance/web/index.md +24 -0
- package/expertise/performance/web/network-optimization.md +1133 -0
- package/expertise/performance/web/rendering-performance.md +1098 -0
- package/expertise/performance/web/ssr-and-hydration.md +918 -0
- package/expertise/performance/web/web-vitals.md +1374 -0
- package/expertise/quality/accessibility.md +985 -0
- package/expertise/quality/evidence-based-verification.md +499 -0
- package/expertise/quality/index.md +24 -0
- package/expertise/quality/ml-model-audit.md +614 -0
- package/expertise/quality/performance.md +600 -0
- package/expertise/quality/testing-api.md +891 -0
- package/expertise/quality/testing-mobile.md +496 -0
- package/expertise/quality/testing-web.md +849 -0
- package/expertise/security/PROGRESS.md +54 -0
- package/expertise/security/agentic-identity.md +540 -0
- package/expertise/security/compliance-frameworks.md +601 -0
- package/expertise/security/data/data-encryption.md +364 -0
- package/expertise/security/data/data-privacy-gdpr.md +692 -0
- package/expertise/security/data/database-security.md +1171 -0
- package/expertise/security/data/index.md +22 -0
- package/expertise/security/data/pii-handling.md +531 -0
- package/expertise/security/foundations/authentication.md +1041 -0
- package/expertise/security/foundations/authorization.md +603 -0
- package/expertise/security/foundations/cryptography.md +1001 -0
- package/expertise/security/foundations/index.md +25 -0
- package/expertise/security/foundations/owasp-top-10.md +1354 -0
- package/expertise/security/foundations/secrets-management.md +1217 -0
- package/expertise/security/foundations/secure-sdlc.md +700 -0
- package/expertise/security/foundations/supply-chain-security.md +698 -0
- package/expertise/security/index.md +31 -0
- package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
- package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
- package/expertise/security/infrastructure/container-security.md +721 -0
- package/expertise/security/infrastructure/incident-response.md +1295 -0
- package/expertise/security/infrastructure/index.md +24 -0
- package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
- package/expertise/security/infrastructure/network-security.md +1337 -0
- package/expertise/security/mobile/index.md +23 -0
- package/expertise/security/mobile/mobile-android-security.md +1218 -0
- package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
- package/expertise/security/mobile/mobile-data-storage.md +1265 -0
- package/expertise/security/mobile/mobile-ios-security.md +1401 -0
- package/expertise/security/mobile/mobile-network-security.md +1520 -0
- package/expertise/security/smart-contract-security.md +594 -0
- package/expertise/security/testing/index.md +22 -0
- package/expertise/security/testing/penetration-testing.md +1258 -0
- package/expertise/security/testing/security-code-review.md +1765 -0
- package/expertise/security/testing/threat-modeling.md +1074 -0
- package/expertise/security/testing/vulnerability-scanning.md +1062 -0
- package/expertise/security/web/api-security.md +586 -0
- package/expertise/security/web/cors-and-headers.md +433 -0
- package/expertise/security/web/csrf.md +562 -0
- package/expertise/security/web/file-upload.md +1477 -0
- package/expertise/security/web/index.md +25 -0
- package/expertise/security/web/injection.md +1375 -0
- package/expertise/security/web/session-management.md +1101 -0
- package/expertise/security/web/xss.md +1158 -0
- package/exports/README.md +17 -0
- package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
- package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
- package/exports/hosts/claude/.claude/agents/designer.md +55 -0
- package/exports/hosts/claude/.claude/agents/executor.md +55 -0
- package/exports/hosts/claude/.claude/agents/learner.md +51 -0
- package/exports/hosts/claude/.claude/agents/planner.md +53 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
- package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
- package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
- package/exports/hosts/claude/.claude/commands/author.md +42 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
- package/exports/hosts/claude/.claude/commands/design.md +44 -0
- package/exports/hosts/claude/.claude/commands/discover.md +37 -0
- package/exports/hosts/claude/.claude/commands/execute.md +48 -0
- package/exports/hosts/claude/.claude/commands/learn.md +38 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
- package/exports/hosts/claude/.claude/commands/plan.md +39 -0
- package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
- package/exports/hosts/claude/.claude/commands/review.md +40 -0
- package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
- package/exports/hosts/claude/.claude/commands/specify.md +38 -0
- package/exports/hosts/claude/.claude/commands/verify.md +37 -0
- package/exports/hosts/claude/.claude/settings.json +34 -0
- package/exports/hosts/claude/CLAUDE.md +19 -0
- package/exports/hosts/claude/export.manifest.json +38 -0
- package/exports/hosts/claude/host-package.json +67 -0
- package/exports/hosts/codex/AGENTS.md +19 -0
- package/exports/hosts/codex/export.manifest.json +38 -0
- package/exports/hosts/codex/host-package.json +41 -0
- package/exports/hosts/cursor/.cursor/hooks.json +16 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
- package/exports/hosts/cursor/export.manifest.json +38 -0
- package/exports/hosts/cursor/host-package.json +42 -0
- package/exports/hosts/gemini/GEMINI.md +19 -0
- package/exports/hosts/gemini/export.manifest.json +38 -0
- package/exports/hosts/gemini/host-package.json +41 -0
- package/hooks/README.md +18 -0
- package/hooks/definitions/loop_cap_guard.yaml +21 -0
- package/hooks/definitions/post_tool_capture.yaml +24 -0
- package/hooks/definitions/pre_compact_summary.yaml +19 -0
- package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
- package/hooks/definitions/protected_path_write_guard.yaml +19 -0
- package/hooks/definitions/session_start.yaml +19 -0
- package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
- package/hooks/loop-cap-guard +17 -0
- package/hooks/post-tool-lint +36 -0
- package/hooks/protected-path-write-guard +17 -0
- package/hooks/session-start +41 -0
- package/llms-full.txt +2355 -0
- package/llms.txt +43 -0
- package/package.json +79 -0
- package/roles/README.md +20 -0
- package/roles/clarifier.md +42 -0
- package/roles/content-author.md +63 -0
- package/roles/designer.md +55 -0
- package/roles/executor.md +55 -0
- package/roles/learner.md +51 -0
- package/roles/planner.md +53 -0
- package/roles/researcher.md +43 -0
- package/roles/reviewer.md +54 -0
- package/roles/specifier.md +47 -0
- package/roles/verifier.md +71 -0
- package/schemas/README.md +24 -0
- package/schemas/accepted-learning.schema.json +20 -0
- package/schemas/author-artifact.schema.json +156 -0
- package/schemas/clarification.schema.json +19 -0
- package/schemas/design-artifact.schema.json +80 -0
- package/schemas/docs-claim.schema.json +18 -0
- package/schemas/export-manifest.schema.json +20 -0
- package/schemas/hook.schema.json +67 -0
- package/schemas/host-export-package.schema.json +18 -0
- package/schemas/implementation-plan.schema.json +19 -0
- package/schemas/proposed-learning.schema.json +19 -0
- package/schemas/research.schema.json +18 -0
- package/schemas/review.schema.json +29 -0
- package/schemas/run-manifest.schema.json +18 -0
- package/schemas/spec-challenge.schema.json +18 -0
- package/schemas/spec.schema.json +20 -0
- package/schemas/usage.schema.json +102 -0
- package/schemas/verification-proof.schema.json +29 -0
- package/schemas/wazir-manifest.schema.json +173 -0
- package/skills/README.md +40 -0
- package/skills/brainstorming/SKILL.md +77 -0
- package/skills/debugging/SKILL.md +50 -0
- package/skills/design/SKILL.md +61 -0
- package/skills/dispatching-parallel-agents/SKILL.md +128 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +169 -0
- package/skills/humanize/SKILL.md +123 -0
- package/skills/init-pipeline/SKILL.md +124 -0
- package/skills/prepare-next/SKILL.md +20 -0
- package/skills/receiving-code-review/SKILL.md +123 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +108 -0
- package/skills/run-audit/SKILL.md +197 -0
- package/skills/scan-project/SKILL.md +41 -0
- package/skills/self-audit/SKILL.md +153 -0
- package/skills/subagent-driven-development/SKILL.md +154 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +102 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tdd/SKILL.md +23 -0
- package/skills/using-git-worktrees/SKILL.md +163 -0
- package/skills/using-skills/SKILL.md +95 -0
- package/skills/verification/SKILL.md +22 -0
- package/skills/wazir/SKILL.md +463 -0
- package/skills/writing-plans/SKILL.md +30 -0
- package/skills/writing-skills/SKILL.md +157 -0
- package/skills/writing-skills/anthropic-best-practices.md +122 -0
- package/skills/writing-skills/persuasion-principles.md +50 -0
- package/templates/README.md +20 -0
- package/templates/artifacts/README.md +10 -0
- package/templates/artifacts/accepted-learning.md +19 -0
- package/templates/artifacts/accepted-learning.template.json +12 -0
- package/templates/artifacts/author.md +74 -0
- package/templates/artifacts/author.template.json +19 -0
- package/templates/artifacts/clarification.md +21 -0
- package/templates/artifacts/clarification.template.json +12 -0
- package/templates/artifacts/execute-notes.md +19 -0
- package/templates/artifacts/implementation-plan.md +21 -0
- package/templates/artifacts/implementation-plan.template.json +11 -0
- package/templates/artifacts/learning-proposal.md +19 -0
- package/templates/artifacts/next-run-handoff.md +21 -0
- package/templates/artifacts/plan-review.md +19 -0
- package/templates/artifacts/proposed-learning.template.json +12 -0
- package/templates/artifacts/research.md +21 -0
- package/templates/artifacts/research.template.json +12 -0
- package/templates/artifacts/review-findings.md +19 -0
- package/templates/artifacts/review.template.json +11 -0
- package/templates/artifacts/run-manifest.template.json +8 -0
- package/templates/artifacts/spec-challenge.md +19 -0
- package/templates/artifacts/spec-challenge.template.json +11 -0
- package/templates/artifacts/spec.md +21 -0
- package/templates/artifacts/spec.template.json +12 -0
- package/templates/artifacts/verification-proof.md +19 -0
- package/templates/artifacts/verification-proof.template.json +11 -0
- package/templates/examples/accepted-learning.example.json +14 -0
- package/templates/examples/author.example.json +152 -0
- package/templates/examples/clarification.example.json +15 -0
- package/templates/examples/docs-claim.example.json +8 -0
- package/templates/examples/export-manifest.example.json +7 -0
- package/templates/examples/host-export-package.example.json +11 -0
- package/templates/examples/implementation-plan.example.json +17 -0
- package/templates/examples/proposed-learning.example.json +13 -0
- package/templates/examples/research.example.json +15 -0
- package/templates/examples/research.example.md +6 -0
- package/templates/examples/review.example.json +17 -0
- package/templates/examples/run-manifest.example.json +9 -0
- package/templates/examples/spec-challenge.example.json +14 -0
- package/templates/examples/spec.example.json +21 -0
- package/templates/examples/verification-proof.example.json +21 -0
- package/templates/examples/wazir-manifest.example.yaml +65 -0
- package/templates/task-definition-schema.md +99 -0
- package/tooling/README.md +20 -0
- package/tooling/src/adapters/context-mode.js +50 -0
- package/tooling/src/capture/command.js +376 -0
- package/tooling/src/capture/store.js +99 -0
- package/tooling/src/capture/usage.js +270 -0
- package/tooling/src/checks/branches.js +50 -0
- package/tooling/src/checks/brand-truth.js +110 -0
- package/tooling/src/checks/changelog.js +231 -0
- package/tooling/src/checks/command-registry.js +36 -0
- package/tooling/src/checks/commits.js +102 -0
- package/tooling/src/checks/docs-drift.js +103 -0
- package/tooling/src/checks/docs-truth.js +201 -0
- package/tooling/src/checks/runtime-surface.js +156 -0
- package/tooling/src/cli.js +116 -0
- package/tooling/src/command-options.js +56 -0
- package/tooling/src/commands/validate.js +320 -0
- package/tooling/src/doctor/command.js +91 -0
- package/tooling/src/export/command.js +77 -0
- package/tooling/src/export/compiler.js +498 -0
- package/tooling/src/guards/loop-cap-guard.js +52 -0
- package/tooling/src/guards/protected-path-write-guard.js +67 -0
- package/tooling/src/index/command.js +152 -0
- package/tooling/src/index/storage.js +1061 -0
- package/tooling/src/index/summarizers.js +261 -0
- package/tooling/src/loaders.js +18 -0
- package/tooling/src/project-root.js +22 -0
- package/tooling/src/recall/command.js +225 -0
- package/tooling/src/schema-validator.js +30 -0
- package/tooling/src/state-root.js +40 -0
- package/tooling/src/status/command.js +71 -0
- package/wazir.manifest.yaml +135 -0
- package/workflows/README.md +19 -0
- package/workflows/author.md +42 -0
- package/workflows/clarify.md +38 -0
- package/workflows/design-review.md +46 -0
- package/workflows/design.md +44 -0
- package/workflows/discover.md +37 -0
- package/workflows/execute.md +48 -0
- package/workflows/learn.md +38 -0
- package/workflows/plan-review.md +42 -0
- package/workflows/plan.md +39 -0
- package/workflows/prepare-next.md +37 -0
- package/workflows/review.md +40 -0
- package/workflows/run-audit.md +41 -0
- package/workflows/spec-challenge.md +41 -0
- package/workflows/specify.md +38 -0
- package/workflows/verify.md +37 -0
|
@@ -0,0 +1,724 @@
|
|
|
1
|
+
# Python + FastAPI -- Expertise Module
|
|
2
|
+
|
|
3
|
+
> A Python/FastAPI backend specialist designs, builds, and maintains high-performance async REST and WebSocket APIs using FastAPI (0.115+), Pydantic v2, async SQLAlchemy 2.0, and modern Python (3.12+).
|
|
4
|
+
> Scope: API design, data modeling, authentication, background tasks, observability, containerized deployment, and production hardening of ASGI services.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Core Patterns & Conventions
|
|
9
|
+
|
|
10
|
+
### Project Structure
|
|
11
|
+
|
|
12
|
+
Organize by **domain/feature**, not file type. Feature-based modules keep related code co-located and scale with team size.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
src/app/
|
|
16
|
+
main.py # App factory, lifespan events
|
|
17
|
+
config.py # Pydantic BaseSettings
|
|
18
|
+
dependencies.py # Shared cross-cutting deps
|
|
19
|
+
features/
|
|
20
|
+
users/
|
|
21
|
+
router.py # APIRouter with /users endpoints
|
|
22
|
+
schemas.py # Pydantic v2 request/response models
|
|
23
|
+
models.py # SQLAlchemy ORM models
|
|
24
|
+
service.py # Business logic
|
|
25
|
+
repository.py # Data access
|
|
26
|
+
orders/ ...
|
|
27
|
+
core/
|
|
28
|
+
security.py # OAuth2, JWT
|
|
29
|
+
middleware.py # Custom ASGI middleware
|
|
30
|
+
logging.py # structlog config
|
|
31
|
+
db/
|
|
32
|
+
session.py # async engine, sessionmaker
|
|
33
|
+
base.py # DeclarativeBase
|
|
34
|
+
migrations/ # Alembic
|
|
35
|
+
tests/
|
|
36
|
+
conftest.py
|
|
37
|
+
features/users/test_router.py, test_service.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Naming Conventions (PEP 8, PEP 257)
|
|
41
|
+
|
|
42
|
+
- Modules/packages: `snake_case` -- Functions/variables: `snake_case` -- Classes: `PascalCase` -- Constants: `UPPER_SNAKE_CASE`
|
|
43
|
+
- Pydantic models: suffix with purpose -- `UserCreate`, `UserRead`, `UserUpdate`
|
|
44
|
+
- SQLAlchemy models: singular noun matching the table -- `User`, `Order`
|
|
45
|
+
- Test files mirror source: `test_router.py`, `test_service.py`
|
|
46
|
+
|
|
47
|
+
### Architecture Patterns
|
|
48
|
+
|
|
49
|
+
**Layered architecture** (pragmatic default): Router (HTTP concerns) -> Service (business logic, transactions) -> Repository (data access, ORM) -> Schema (Pydantic validation). For complex domains, adopt **Clean/Hexagonal Architecture**: abstract repository interfaces as ports, SQLAlchemy implementations as adapters.
|
|
50
|
+
|
|
51
|
+
### Dependency Injection (FastAPI `Depends`)
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
async def get_db() -> AsyncGenerator[AsyncSession, None]:
|
|
55
|
+
async with async_session_maker() as session:
|
|
56
|
+
yield session
|
|
57
|
+
|
|
58
|
+
async def get_user_service(db: AsyncSession = Depends(get_db)) -> UserService:
|
|
59
|
+
return UserService(UserRepository(db))
|
|
60
|
+
|
|
61
|
+
@router.get("/users/{user_id}")
|
|
62
|
+
async def read_user(user_id: int, svc: UserService = Depends(get_user_service)) -> UserRead:
|
|
63
|
+
return await svc.get_by_id(user_id)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- Dependencies are **cached per-request** by default (called once even if used in multiple places)
|
|
67
|
+
- Chain small, focused dependencies -- avoid a single god-dependency
|
|
68
|
+
- Use `app.dependency_overrides` in tests to swap real deps with fakes
|
|
69
|
+
|
|
70
|
+
### Routing and API Versioning
|
|
71
|
+
|
|
72
|
+
Prefix routes with `/api/v1` via `APIRouter(prefix="/api/v1")`. When introducing breaking changes, mount `/api/v2` alongside v1. Mark deprecated endpoints with `deprecated=True`.
|
|
73
|
+
|
|
74
|
+
### Data Validation (Pydantic v2)
|
|
75
|
+
|
|
76
|
+
- Separate Create / Read / Update schemas (never reuse one model for all)
|
|
77
|
+
- `model_config = ConfigDict(strict=True)` for security-sensitive inputs
|
|
78
|
+
- `Field(min_length=1, max_length=255)` for constraints; `Annotated` types for reuse
|
|
79
|
+
- `model_validator(mode="after")` for cross-field validation
|
|
80
|
+
|
|
81
|
+
### Error Handling
|
|
82
|
+
|
|
83
|
+
- `HTTPException` for simple cases; custom exception handlers for domain errors
|
|
84
|
+
- Never leak stack traces in production -- global handler for unhandled exceptions
|
|
85
|
+
- Consistent error shape: `{"error": "<CODE>", "detail": "<message>"}`
|
|
86
|
+
- Correct status codes: 422 validation, 401/403 auth, 404 not found, 409 conflict
|
|
87
|
+
|
|
88
|
+
### Logging and Observability
|
|
89
|
+
|
|
90
|
+
- **structlog** for JSON logging (stdout in prod, colored console in dev)
|
|
91
|
+
- Attach `request_id` (UUID) via middleware for log correlation
|
|
92
|
+
- **OpenTelemetry** `FastAPIInstrumentor` for automatic per-request spans
|
|
93
|
+
- Export: traces to Jaeger/Tempo, metrics to Prometheus, logs to Loki
|
|
94
|
+
- Let the OTel Collector handle protocol conversion -- keep the app simple
|
|
95
|
+
|
|
96
|
+
### Async Patterns
|
|
97
|
+
|
|
98
|
+
- `async def` for I/O-bound routes (DB, HTTP, file I/O)
|
|
99
|
+
- Plain `def` for CPU-bound/trivial -- FastAPI auto-runs sync routes in a threadpool
|
|
100
|
+
- **Never** call blocking I/O inside `async def` -- freezes the event loop for all requests
|
|
101
|
+
- Use `asyncio.to_thread()` for unavoidable blocking; `httpx.AsyncClient` over `requests`
|
|
102
|
+
- Async drivers: `asyncpg` (Postgres), `aiomysql` (MySQL), `aiosqlite` (SQLite)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Production Patterns
|
|
107
|
+
|
|
108
|
+
### Async Database Sessions (SQLAlchemy 2.x)
|
|
109
|
+
|
|
110
|
+
The session lifecycle pattern below handles commit-on-success and rollback-on-error automatically via the `get_db` dependency. Every request gets an isolated session from the connection pool.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from collections.abc import AsyncGenerator
|
|
114
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
|
115
|
+
from sqlalchemy import select
|
|
116
|
+
|
|
117
|
+
engine = create_async_engine(
|
|
118
|
+
settings.DATABASE_URL,
|
|
119
|
+
pool_size=20, # Concurrent connections held open
|
|
120
|
+
max_overflow=10, # Extra connections under burst load
|
|
121
|
+
pool_pre_ping=True, # Verify connections before checkout (detects stale)
|
|
122
|
+
pool_recycle=3600, # Recycle connections after 1 hour (prevents server-side timeout)
|
|
123
|
+
)
|
|
124
|
+
SessionLocal = async_sessionmaker(engine, expire_on_commit=False)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
async def get_db() -> AsyncGenerator[AsyncSession, None]:
|
|
128
|
+
"""Request-scoped session with auto commit/rollback."""
|
|
129
|
+
async with SessionLocal() as session:
|
|
130
|
+
try:
|
|
131
|
+
yield session
|
|
132
|
+
await session.commit()
|
|
133
|
+
except Exception:
|
|
134
|
+
await session.rollback()
|
|
135
|
+
raise
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@app.get("/users/{user_id}")
|
|
139
|
+
async def get_user(user_id: int, db: AsyncSession = Depends(get_db)):
|
|
140
|
+
result = await db.execute(select(User).where(User.id == user_id))
|
|
141
|
+
user = result.scalar_one_or_none()
|
|
142
|
+
if not user:
|
|
143
|
+
raise HTTPException(status_code=404, detail="User not found")
|
|
144
|
+
return user
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Key decisions:**
|
|
148
|
+
- `expire_on_commit=False` — prevents lazy-load attempts after commit (which would fail in async context)
|
|
149
|
+
- `pool_pre_ping=True` — adds ~1ms overhead but prevents "connection reset" errors after DB restarts
|
|
150
|
+
- `pool_recycle=3600` — prevents connections from hitting PostgreSQL's `idle_in_transaction_session_timeout`
|
|
151
|
+
- Session is committed only if no exception is raised — no partial writes on error
|
|
152
|
+
|
|
153
|
+
### Pydantic Validation Patterns
|
|
154
|
+
|
|
155
|
+
Use Pydantic models as the single enforcement point for input constraints. Sanitize user-provided text fields to prevent stored XSS.
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from typing import Generic, TypeVar
|
|
159
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
160
|
+
import bleach
|
|
161
|
+
|
|
162
|
+
T = TypeVar("T")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class CreateOrderRequest(BaseModel):
|
|
166
|
+
product_id: int = Field(..., gt=0, description="Must reference existing product")
|
|
167
|
+
quantity: int = Field(..., ge=1, le=100, description="1-100 items per order")
|
|
168
|
+
notes: str = Field(default="", max_length=500)
|
|
169
|
+
|
|
170
|
+
@field_validator("notes")
|
|
171
|
+
@classmethod
|
|
172
|
+
def sanitize_notes(cls, v: str) -> str:
|
|
173
|
+
"""Strip HTML tags from user input to prevent stored XSS."""
|
|
174
|
+
return bleach.clean(v, strip=True)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class PaginatedResponse(BaseModel, Generic[T]):
|
|
178
|
+
"""Consistent pagination envelope for list endpoints."""
|
|
179
|
+
items: list[T]
|
|
180
|
+
total: int
|
|
181
|
+
page: int
|
|
182
|
+
page_size: int
|
|
183
|
+
has_next: bool
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Pagination usage:**
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
@router.get("/orders", response_model=PaginatedResponse[OrderRead])
|
|
190
|
+
async def list_orders(
|
|
191
|
+
page: int = Query(1, ge=1),
|
|
192
|
+
page_size: int = Query(20, ge=1, le=100),
|
|
193
|
+
db: AsyncSession = Depends(get_db),
|
|
194
|
+
):
|
|
195
|
+
offset = (page - 1) * page_size
|
|
196
|
+
total = await db.scalar(select(func.count()).select_from(Order))
|
|
197
|
+
result = await db.execute(
|
|
198
|
+
select(Order).offset(offset).limit(page_size).order_by(Order.created_at.desc())
|
|
199
|
+
)
|
|
200
|
+
items = result.scalars().all()
|
|
201
|
+
return PaginatedResponse(
|
|
202
|
+
items=items, total=total, page=page,
|
|
203
|
+
page_size=page_size, has_next=(offset + page_size < total),
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Key decisions:**
|
|
208
|
+
- `bleach.clean` at the validator level — sanitization happens before any business logic sees the data
|
|
209
|
+
- Generic `PaginatedResponse[T]` — one envelope for all list endpoints, consistent client-side parsing
|
|
210
|
+
- `page_size` capped at 100 — prevents clients from requesting unbounded result sets
|
|
211
|
+
|
|
212
|
+
### Structured Logging
|
|
213
|
+
|
|
214
|
+
JSON-formatted logs with request correlation IDs are essential for production debugging. structlog provides zero-config structured output with context variable binding.
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
import structlog
|
|
218
|
+
from uuid import uuid4
|
|
219
|
+
from starlette.requests import Request
|
|
220
|
+
from starlette.responses import Response
|
|
221
|
+
|
|
222
|
+
structlog.configure(
|
|
223
|
+
processors=[
|
|
224
|
+
structlog.contextvars.merge_contextvars,
|
|
225
|
+
structlog.processors.add_log_level,
|
|
226
|
+
structlog.processors.TimeStamper(fmt="iso"),
|
|
227
|
+
structlog.processors.JSONRenderer(),
|
|
228
|
+
],
|
|
229
|
+
)
|
|
230
|
+
logger = structlog.get_logger()
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@app.middleware("http")
|
|
234
|
+
async def logging_middleware(request: Request, call_next) -> Response:
|
|
235
|
+
"""Bind request context for all log lines emitted during this request."""
|
|
236
|
+
structlog.contextvars.bind_contextvars(
|
|
237
|
+
request_id=request.headers.get("x-request-id", str(uuid4())),
|
|
238
|
+
method=request.method,
|
|
239
|
+
path=request.url.path,
|
|
240
|
+
)
|
|
241
|
+
response = await call_next(request)
|
|
242
|
+
logger.info("request_completed", status=response.status_code)
|
|
243
|
+
structlog.contextvars.unbind_contextvars("request_id", "method", "path")
|
|
244
|
+
return response
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Key decisions:**
|
|
248
|
+
- `contextvars` — thread-safe and async-safe; every log line within a request includes `request_id` without explicit passing
|
|
249
|
+
- `unbind_contextvars` after response — prevents context leaking across requests in the same worker
|
|
250
|
+
- `JSONRenderer` in prod — machine-parseable for log aggregators (Loki, CloudWatch, Datadog)
|
|
251
|
+
- Honor incoming `x-request-id` header — enables end-to-end tracing when requests originate from other services
|
|
252
|
+
|
|
253
|
+
### Health Check Endpoints
|
|
254
|
+
|
|
255
|
+
Two-tier health checks: shallow (is the process alive?) and deep (are dependencies reachable?). Kubernetes probes, load balancers, and monitoring tools consume these.
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
@app.get("/health", status_code=200)
|
|
259
|
+
async def health_check():
|
|
260
|
+
"""Shallow health check — process is alive and accepting requests."""
|
|
261
|
+
return {"status": "ok"}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@app.get("/ready", status_code=200)
|
|
265
|
+
async def readiness_check(db: AsyncSession = Depends(get_db)):
|
|
266
|
+
"""Deep readiness check — verifies database connectivity."""
|
|
267
|
+
try:
|
|
268
|
+
await db.execute(text("SELECT 1"))
|
|
269
|
+
return {"status": "ready", "db": "connected"}
|
|
270
|
+
except Exception as exc:
|
|
271
|
+
raise HTTPException(
|
|
272
|
+
status_code=503,
|
|
273
|
+
detail={"status": "not_ready", "db": str(exc)},
|
|
274
|
+
)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Production checklist:**
|
|
278
|
+
- Map `/health` to Kubernetes `livenessProbe` — restart if unresponsive
|
|
279
|
+
- Map `/ready` to `readinessProbe` — stop sending traffic if deps are down
|
|
280
|
+
- Add Redis, external API, and queue connectivity checks to `/ready` as needed
|
|
281
|
+
- Keep `/health` dependency-free — it must respond even when the DB is down
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Anti-Patterns & Pitfalls
|
|
286
|
+
|
|
287
|
+
### 1. Blocking I/O Inside `async def`
|
|
288
|
+
`requests.get()` or sync DB drivers inside async endpoints block the event loop, halting all concurrent requests. **Fix:** async libs or `asyncio.to_thread()`.
|
|
289
|
+
|
|
290
|
+
### 2. One Endpoint Calling Another
|
|
291
|
+
Route-to-route calls bypass middleware/DI and create tight coupling. **Fix:** extract shared logic into a service layer.
|
|
292
|
+
|
|
293
|
+
### 3. Everything in `main.py`
|
|
294
|
+
Monolithic files prevent parallel development and make review painful. **Fix:** feature-based modules.
|
|
295
|
+
|
|
296
|
+
### 4. Creating DB Connections Per Request
|
|
297
|
+
Adds 5-20ms latency per request, can exhaust connection limits. **Fix:** connection pooling via `create_async_engine(pool_size=20)` + DI.
|
|
298
|
+
|
|
299
|
+
### 5. Mutable Global State
|
|
300
|
+
Module-level globals cause race conditions in async contexts. **Fix:** `app.state` for singletons, DI for request-scoped state.
|
|
301
|
+
|
|
302
|
+
### 6. Missing Response Models
|
|
303
|
+
Omitting `response_model` leaks sensitive fields (password hashes, internal IDs) and degrades OpenAPI docs. **Fix:** always declare response models.
|
|
304
|
+
|
|
305
|
+
### 7. Catching `Exception` Broadly
|
|
306
|
+
Hides bugs, swallows validation errors, can catch `asyncio.CancelledError` and prevent shutdown. **Fix:** catch specific types.
|
|
307
|
+
|
|
308
|
+
### 8. No Dependency Overrides in Tests
|
|
309
|
+
Tests hitting real DBs/APIs are slow and flaky. **Fix:** `app.dependency_overrides[get_db] = mock_db`.
|
|
310
|
+
|
|
311
|
+
### 9. Ignoring Pydantic v2 Migration
|
|
312
|
+
v1 patterns (`class Config`, `orm_mode`, `@validator`) trigger deprecation warnings and miss 5-50x Rust-core speedups. **Fix:** `ConfigDict(from_attributes=True)`, `@field_validator`.
|
|
313
|
+
|
|
314
|
+
### 10. Sync ORM Sessions in Async Routes
|
|
315
|
+
`sqlalchemy.orm.Session` in `async def` blocks the loop. **Fix:** `AsyncSession` with async engine.
|
|
316
|
+
|
|
317
|
+
### 11. No Authorization Beyond Pydantic
|
|
318
|
+
Pydantic validates shape, not business rules (user A editing user B's data). **Fix:** authorization checks in the service layer.
|
|
319
|
+
|
|
320
|
+
### 12. Hardcoded Configuration
|
|
321
|
+
Secrets in source code are insecure and inflexible. **Fix:** `pydantic-settings` + env vars.
|
|
322
|
+
|
|
323
|
+
### 13. No Timeouts on Outbound Calls
|
|
324
|
+
HTTP calls without timeouts hang forever, consuming workers. **Fix:** `httpx.Timeout(10.0)` on all clients.
|
|
325
|
+
|
|
326
|
+
### 14. Overly Broad CORS (`allow_origins=["*"]`)
|
|
327
|
+
Permits any website to make authenticated requests. **Fix:** whitelist specific origins; `allow_credentials=True` only with explicit lists.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Testing Strategy
|
|
332
|
+
|
|
333
|
+
### Unit Testing (pytest + pytest-asyncio)
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
@pytest.mark.asyncio
|
|
337
|
+
async def test_get_user_returns_user():
|
|
338
|
+
mock_repo = AsyncMock()
|
|
339
|
+
mock_repo.get_by_id.return_value = User(id=1, name="Alice")
|
|
340
|
+
service = UserService(repo=mock_repo)
|
|
341
|
+
result = await service.get_by_id(1)
|
|
342
|
+
assert result.name == "Alice"
|
|
343
|
+
mock_repo.get_by_id.assert_awaited_once_with(1)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Integration Testing (httpx.AsyncClient)
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
@pytest.mark.asyncio
|
|
350
|
+
async def test_create_user():
|
|
351
|
+
transport = ASGITransport(app=app)
|
|
352
|
+
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
|
353
|
+
resp = await client.post("/api/v1/users", json={"name": "Bob", "email": "bob@test.com"})
|
|
354
|
+
assert resp.status_code == 201
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Use `TestClient` (sync) for most tests; `AsyncClient` when testing async deps or DB rollback patterns.
|
|
358
|
+
|
|
359
|
+
### Fixture Organization
|
|
360
|
+
|
|
361
|
+
- `tests/conftest.py` -- app-level: test DB engine, async client, session rollback fixture
|
|
362
|
+
- `tests/features/users/conftest.py` -- domain-specific: user factory, auth headers
|
|
363
|
+
- Key fixtures: `db_session` (transaction + rollback), `client` (with overridden deps), `auth_headers`
|
|
364
|
+
|
|
365
|
+
### Factory Patterns
|
|
366
|
+
|
|
367
|
+
Use `factory_boy` + `faker` for realistic test data. Define one factory per model.
|
|
368
|
+
|
|
369
|
+
### Coverage
|
|
370
|
+
|
|
371
|
+
- **80%+ line coverage** enforced in CI (`pytest-cov --cov-fail-under=80`)
|
|
372
|
+
- 90%+ for service/repository layers; router layer: happy paths + errors + auth boundaries
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Performance Considerations
|
|
377
|
+
|
|
378
|
+
### Async vs Sync Tradeoffs
|
|
379
|
+
|
|
380
|
+
- Async excels at I/O concurrency: one worker handles thousands of concurrent DB/HTTP calls
|
|
381
|
+
- CPU-bound work gets no async benefit -- use `ProcessPoolExecutor` or task queues
|
|
382
|
+
- FastAPI: ~20,000+ req/s vs Django ~4,000-5,000 (2026 benchmarks)
|
|
383
|
+
- One blocking call in an async route negates all concurrency benefits
|
|
384
|
+
|
|
385
|
+
### Connection Pooling (SQLAlchemy Async)
|
|
386
|
+
|
|
387
|
+
```python
|
|
388
|
+
engine = create_async_engine(
|
|
389
|
+
"postgresql+asyncpg://user:pass@host/db",
|
|
390
|
+
pool_size=20, max_overflow=10, pool_pre_ping=True, pool_recycle=3600,
|
|
391
|
+
)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Pool size should match expected concurrency, not worker count. This is the single biggest performance lever.
|
|
395
|
+
|
|
396
|
+
### Caching
|
|
397
|
+
|
|
398
|
+
- **Redis** (`redis.asyncio`): distributed cache for multi-instance deployments
|
|
399
|
+
- **In-memory** (`cachetools`, `lru_cache`): per-process only, not shared across workers
|
|
400
|
+
- Strategy: time-based TTL for most cases, event-based invalidation for critical consistency
|
|
401
|
+
|
|
402
|
+
### Background Tasks
|
|
403
|
+
|
|
404
|
+
| Feature | BackgroundTasks | ARQ | Celery |
|
|
405
|
+
|---|---|---|---|
|
|
406
|
+
| Persistence | None (in-process) | Redis-backed | Redis/RabbitMQ |
|
|
407
|
+
| Async native | Yes | Yes | No (sync default) |
|
|
408
|
+
| Retries | No | Yes | Yes |
|
|
409
|
+
| Monitoring | No | Basic | Flower, extensive |
|
|
410
|
+
| Best for | Fire-and-forget | Async job queues | Enterprise pipelines |
|
|
411
|
+
|
|
412
|
+
- **BackgroundTasks**: lightweight, non-critical (emails). Tasks lost on crash.
|
|
413
|
+
- **ARQ**: async-native, simple, Redis-backed. Best fit for modern FastAPI.
|
|
414
|
+
- **Celery**: battle-tested at scale (Instagram, Mozilla). Complex workflows, scheduling.
|
|
415
|
+
|
|
416
|
+
### Profiling
|
|
417
|
+
|
|
418
|
+
- **py-spy**: sampling profiler, attaches to running processes, near-zero overhead -- best for production
|
|
419
|
+
- **cProfile + snakeviz**: built-in, good for dev, too heavy for prod
|
|
420
|
+
- **OpenTelemetry traces**: identify which dependency (DB, API, compute) dominates latency
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Security Considerations
|
|
425
|
+
|
|
426
|
+
### Authentication (OAuth2 + JWT)
|
|
427
|
+
|
|
428
|
+
```python
|
|
429
|
+
oauth2_scheme = OAuth2PasswordBearer(
|
|
430
|
+
tokenUrl="/api/v1/auth/token",
|
|
431
|
+
scopes={"users:read": "Read users", "users:write": "Write users"},
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
async def get_current_user(
|
|
435
|
+
scopes: SecurityScopes, token: str = Depends(oauth2_scheme), db: AsyncSession = Depends(get_db),
|
|
436
|
+
) -> User:
|
|
437
|
+
payload = decode_jwt(token)
|
|
438
|
+
check_scopes(scopes, payload.get("scopes", []))
|
|
439
|
+
return await get_user_by_id(db, payload["sub"])
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
- **PyJWT** for token encode/decode; **Argon2** (via `pwdlib`) for password hashing (FastAPI 2025+ recommendation, replacing bcrypt)
|
|
443
|
+
- Short-lived access tokens (15-30 min) + refresh tokens (7-30 days) stored server-side for revocation
|
|
444
|
+
|
|
445
|
+
### Input Validation
|
|
446
|
+
|
|
447
|
+
- Pydantic `strict=True` for security-critical endpoints (prevents type coercion)
|
|
448
|
+
- Validate file uploads: MIME type checks, size limits
|
|
449
|
+
- Sanitize user input in logs (log injection prevention)
|
|
450
|
+
|
|
451
|
+
### CORS and Rate Limiting
|
|
452
|
+
|
|
453
|
+
```python
|
|
454
|
+
app.add_middleware(CORSMiddleware, allow_origins=["https://app.example.com"],
|
|
455
|
+
allow_credentials=True, allow_methods=["GET","POST","PUT","DELETE"])
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**SlowAPI** for rate limiting: aggressive on auth (5/min), moderate on writes (60/min), relaxed on reads (300/min).
|
|
459
|
+
|
|
460
|
+
### SQL Injection Prevention
|
|
461
|
+
|
|
462
|
+
Always use parameterized queries (SQLAlchemy default). Never f-string SQL. For raw SQL: `text("SELECT ... WHERE id = :id").bindparams(id=val)`.
|
|
463
|
+
|
|
464
|
+
### Secrets Management
|
|
465
|
+
|
|
466
|
+
`pydantic-settings` + env vars. Never commit `.env`. In production: AWS Secrets Manager, HashiCorp Vault, or GCP Secret Manager. Rotate JWT signing keys periodically.
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## Integration Patterns
|
|
471
|
+
|
|
472
|
+
### Database (SQLAlchemy 2.0+ Async)
|
|
473
|
+
|
|
474
|
+
```python
|
|
475
|
+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
476
|
+
|
|
477
|
+
class Base(DeclarativeBase): pass
|
|
478
|
+
|
|
479
|
+
class User(Base):
|
|
480
|
+
__tablename__ = "users"
|
|
481
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
482
|
+
name: Mapped[str] = mapped_column(String(255))
|
|
483
|
+
email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Use `alembic init -t async alembic` for async migration support.
|
|
487
|
+
|
|
488
|
+
### Message Queues
|
|
489
|
+
|
|
490
|
+
**Celery + Redis**: `celery_app.task` for sync heavy processing, call via `.delay()` from async routes.
|
|
491
|
+
**ARQ**: async-native, define tasks as `async def`, connect via `create_pool(RedisSettings())` in lifespan.
|
|
492
|
+
|
|
493
|
+
### API Design (OpenAPI)
|
|
494
|
+
|
|
495
|
+
- Always define `response_model` for docs and field filtering
|
|
496
|
+
- Use `tags` for grouping, `summary`/`description` on endpoints
|
|
497
|
+
- Schema examples via `ConfigDict(json_schema_extra={"examples": [...]})`
|
|
498
|
+
- `status_code=201` for creation, `204` for deletes
|
|
499
|
+
|
|
500
|
+
### File Uploads and Streaming
|
|
501
|
+
|
|
502
|
+
```python
|
|
503
|
+
@router.post("/upload")
|
|
504
|
+
async def upload_file(file: UploadFile = File(...)):
|
|
505
|
+
contents = await file.read()
|
|
506
|
+
return {"filename": file.filename, "size": len(contents)}
|
|
507
|
+
|
|
508
|
+
@router.get("/export")
|
|
509
|
+
async def export_csv():
|
|
510
|
+
async def generate():
|
|
511
|
+
yield "id,name\n"
|
|
512
|
+
async for row in fetch_rows():
|
|
513
|
+
yield f"{row.id},{row.name}\n"
|
|
514
|
+
return StreamingResponse(generate(), media_type="text/csv")
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### WebSocket Patterns
|
|
518
|
+
|
|
519
|
+
Use a `ConnectionManager` class to track active connections. Implement heartbeat pings (30s intervals) to detect dead connections. Use `@app.websocket("/ws/{room}")` with `try/except WebSocketDisconnect` for cleanup.
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## DevOps & Deployment
|
|
524
|
+
|
|
525
|
+
### Packaging
|
|
526
|
+
|
|
527
|
+
**uv** (2025-2026 standard, 10-100x faster than pip):
|
|
528
|
+
|
|
529
|
+
```toml
|
|
530
|
+
[project]
|
|
531
|
+
requires-python = ">=3.12"
|
|
532
|
+
dependencies = ["fastapi[standard]>=0.115.0", "sqlalchemy[asyncio]>=2.0", "asyncpg>=0.30.0",
|
|
533
|
+
"pydantic-settings>=2.0", "alembic>=1.14"]
|
|
534
|
+
[tool.uv]
|
|
535
|
+
dev-dependencies = ["pytest>=8.0", "pytest-asyncio>=0.24", "httpx>=0.27", "pytest-cov>=5.0"]
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Alternatives: **poetry** (mature), **pip-tools** (minimal).
|
|
539
|
+
|
|
540
|
+
### Docker (Multi-Stage Build)
|
|
541
|
+
|
|
542
|
+
```dockerfile
|
|
543
|
+
FROM python:3.12-slim AS builder
|
|
544
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
545
|
+
WORKDIR /app
|
|
546
|
+
COPY pyproject.toml uv.lock ./
|
|
547
|
+
RUN uv sync --frozen --no-dev
|
|
548
|
+
|
|
549
|
+
FROM python:3.12-slim
|
|
550
|
+
WORKDIR /app
|
|
551
|
+
COPY --from=builder /app/.venv /app/.venv
|
|
552
|
+
COPY src/ ./src/
|
|
553
|
+
ENV PATH="/app/.venv/bin:$PATH"
|
|
554
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Use `python:3.12-slim` (not alpine -- musl libc issues). Copy deps first for layer caching. Run as non-root.
|
|
558
|
+
|
|
559
|
+
### CI/CD (GitHub Actions)
|
|
560
|
+
|
|
561
|
+
```yaml
|
|
562
|
+
steps:
|
|
563
|
+
- uses: actions/checkout@v4
|
|
564
|
+
- uses: astral-sh/setup-uv@v4
|
|
565
|
+
- run: uv sync
|
|
566
|
+
- run: uv run pytest --cov --cov-fail-under=80
|
|
567
|
+
- run: uv run ruff check src/
|
|
568
|
+
- run: uv run mypy src/
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### ASGI Servers
|
|
572
|
+
|
|
573
|
+
Production stack: **Nginx/Traefik** (TLS, load balancing) -> **Gunicorn** (process manager) -> **Uvicorn workers** (ASGI event loop).
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
gunicorn app.main:app --worker-class uvicorn.workers.UvicornWorker \
|
|
577
|
+
--workers 4 --bind 0.0.0.0:8000 --timeout 120
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Uvicorn 0.41+ supports `--workers` natively with dead-worker restart, making Gunicorn optional for simpler deployments.
|
|
581
|
+
|
|
582
|
+
### Monitoring
|
|
583
|
+
|
|
584
|
+
- **Prometheus**: `/metrics` via `prometheus-fastapi-instrumentator` (latency, error rates)
|
|
585
|
+
- **Sentry**: `sentry-sdk[fastapi]` for error capture with user context
|
|
586
|
+
- **Health checks**: `/health` (shallow) and `/ready` (deep -- DB, Redis reachable)
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
## Decision Trees
|
|
591
|
+
|
|
592
|
+
### FastAPI vs Django vs Flask
|
|
593
|
+
|
|
594
|
+
```
|
|
595
|
+
Full-stack web app with admin panel, ORM, auth built in?
|
|
596
|
+
YES -> Django / Django REST Framework
|
|
597
|
+
NO -> High-performance async API with auto-generated docs?
|
|
598
|
+
YES -> FastAPI
|
|
599
|
+
NO -> Maximum flexibility, minimal opinions, tiny footprint?
|
|
600
|
+
YES -> Flask
|
|
601
|
+
NO -> Microservices or AI/ML serving?
|
|
602
|
+
YES -> FastAPI
|
|
603
|
+
NO -> Django (batteries-included reliability)
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
FastAPI: 78k+ stars, fastest-growing Python framework, async-native, AI/ML ecosystem standard. Django: most mature, best full-stack. Flask: simplest, best for tiny services/serverless.
|
|
607
|
+
|
|
608
|
+
### SQLAlchemy vs SQLModel vs Tortoise ORM
|
|
609
|
+
|
|
610
|
+
```
|
|
611
|
+
Maximum control, complex queries, multi-DB?
|
|
612
|
+
YES -> SQLAlchemy 2.0 async
|
|
613
|
+
NO -> Unified Pydantic + ORM models (single source of truth)?
|
|
614
|
+
YES -> SQLModel (built on SQLAlchemy + Pydantic, but pre-1.0 as of 2026)
|
|
615
|
+
NO -> Django-like active-record API?
|
|
616
|
+
YES -> Tortoise ORM
|
|
617
|
+
NO -> Production-critical, large team?
|
|
618
|
+
YES -> SQLAlchemy 2.0 (most mature, largest community)
|
|
619
|
+
NO -> SQLModel (simpler, less boilerplate)
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Celery vs ARQ vs FastAPI BackgroundTasks
|
|
623
|
+
|
|
624
|
+
```
|
|
625
|
+
Task critical (must survive crashes)?
|
|
626
|
+
NO -> FastAPI BackgroundTasks (simplest, in-process)
|
|
627
|
+
YES -> Workload async-native?
|
|
628
|
+
YES -> Need complex workflows (chains, schedules)?
|
|
629
|
+
YES -> Celery
|
|
630
|
+
NO -> ARQ (async-native, simpler, lower overhead)
|
|
631
|
+
NO -> Need enterprise features (monitoring, multi-broker)?
|
|
632
|
+
YES -> Celery
|
|
633
|
+
NO -> ARQ
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## Code Examples
|
|
639
|
+
|
|
640
|
+
### 1. App Factory with Lifespan
|
|
641
|
+
|
|
642
|
+
```python
|
|
643
|
+
from contextlib import asynccontextmanager
|
|
644
|
+
from fastapi import FastAPI
|
|
645
|
+
|
|
646
|
+
@asynccontextmanager
|
|
647
|
+
async def lifespan(app: FastAPI):
|
|
648
|
+
app.state.redis = await aioredis.from_url(settings.REDIS_URL)
|
|
649
|
+
yield
|
|
650
|
+
await app.state.redis.close()
|
|
651
|
+
await engine.dispose()
|
|
652
|
+
|
|
653
|
+
app = FastAPI(title="My API", version="1.0.0", lifespan=lifespan)
|
|
654
|
+
app.include_router(users_router, prefix="/api/v1/users", tags=["users"])
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### 2. Pydantic v2 Settings
|
|
658
|
+
|
|
659
|
+
```python
|
|
660
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
661
|
+
|
|
662
|
+
class Settings(BaseSettings):
|
|
663
|
+
model_config = SettingsConfigDict(env_file=".env", case_sensitive=False)
|
|
664
|
+
DATABASE_URL: PostgresDsn
|
|
665
|
+
JWT_SECRET: str = Field(min_length=32)
|
|
666
|
+
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
|
667
|
+
DEBUG: bool = False
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
### 3. Repository Pattern (Async SQLAlchemy)
|
|
671
|
+
|
|
672
|
+
```python
|
|
673
|
+
class UserRepository:
|
|
674
|
+
def __init__(self, session: AsyncSession):
|
|
675
|
+
self.session = session
|
|
676
|
+
|
|
677
|
+
async def get_by_id(self, user_id: int) -> User | None:
|
|
678
|
+
result = await self.session.execute(select(User).where(User.id == user_id))
|
|
679
|
+
return result.scalar_one_or_none()
|
|
680
|
+
|
|
681
|
+
async def create(self, data: UserCreate) -> User:
|
|
682
|
+
user = User(**data.model_dump())
|
|
683
|
+
self.session.add(user)
|
|
684
|
+
await self.session.flush()
|
|
685
|
+
await self.session.refresh(user)
|
|
686
|
+
return user
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### 4. Authenticated Endpoint with Scopes
|
|
690
|
+
|
|
691
|
+
```python
|
|
692
|
+
@router.put("/{user_id}", response_model=UserRead)
|
|
693
|
+
async def update_user(
|
|
694
|
+
user_id: int, data: UserUpdate,
|
|
695
|
+
current_user: User = Security(get_current_user, scopes=["users:write"]),
|
|
696
|
+
service: UserService = Depends(get_user_service),
|
|
697
|
+
) -> UserRead:
|
|
698
|
+
if current_user.id != user_id and not current_user.is_admin:
|
|
699
|
+
raise HTTPException(status_code=403, detail="Not authorized")
|
|
700
|
+
return await service.update(user_id, data)
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### 5. Async Test Fixture with DB Rollback
|
|
704
|
+
|
|
705
|
+
```python
|
|
706
|
+
@pytest.fixture
|
|
707
|
+
async def db_session():
|
|
708
|
+
async with TestSessionLocal() as session:
|
|
709
|
+
async with session.begin():
|
|
710
|
+
yield session
|
|
711
|
+
await session.rollback()
|
|
712
|
+
|
|
713
|
+
@pytest.fixture
|
|
714
|
+
async def client(db_session: AsyncSession):
|
|
715
|
+
app.dependency_overrides[get_db] = lambda: db_session
|
|
716
|
+
transport = ASGITransport(app=app)
|
|
717
|
+
async with AsyncClient(transport=transport, base_url="http://test") as c:
|
|
718
|
+
yield c
|
|
719
|
+
app.dependency_overrides.clear()
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
724
|
+
*Researched: 2026-03-07 | Sources: [FastAPI Official Docs](https://fastapi.tiangolo.com/), [zhanymkanov/fastapi-best-practices](https://github.com/zhanymkanov/fastapi-best-practices), [FastAPI Best Practices for Production 2026](https://fastlaunchapi.dev/blog/fastapi-best-practices-production-2026), [12 FastAPI Anti-Patterns Killing Throughput (Modexa, 2025)](https://medium.com/@Modexa/12-fastapi-anti-patterns-quietly-killing-throughput-bddaa961634a), [FastAPI Production Patterns 2025](https://orchestrator.dev/blog/2025-1-30-fastapi-production-patterns/), [FastAPI + SQLAlchemy 2.0 Async Patterns (2025)](https://dev-faizan.medium.com/fastapi-sqlalchemy-2-0-modern-async-database-patterns-7879d39b6843), [Securing FastAPI with OAuth2/JWT (2025)](https://medium.com/@bhagyarana80/securing-fastapi-endpoints-with-oauth2-and-jwt-in-2025-2c31bb14cb58), [Practical FastAPI Security Guide](https://blog.greeden.me/en/2025/12/30/practical-fastapi-security-guide-designing-modern-apis-protected-by-jwt-auth-oauth2-scopes-and-api-keys/), [Definitive FastAPI Production Deployment](https://blog.greeden.me/en/2025/09/02/the-definitive-guide-to-fastapi-production-deployment-with-dockeryour-one-stop-reference-for-uvicorn-gunicorn-nginx-https-health-checks-and-observability-2025-edition/), [FastAPI vs Django vs Flask 2026](https://developersvoice.com/blog/python/fastapi_django_flask_architecture_guide/), [SQLModel in 2025](https://python.plainenglish.io/sqlmodel-in-2025-the-hidden-gem-of-fastapi-backends-20ee8c9bf8a6), [ARQ vs BackgroundTasks](https://davidmuraya.com/blog/fastapi-background-tasks-arq-vs-built-in/), [SlowAPI](https://github.com/laurentS/slowapi), [OpenTelemetry + FastAPI](https://signoz.io/blog/opentelemetry-fastapi/), [Structlog Guide](https://www.dash0.com/guides/python-logging-with-structlog)*
|