@polymorphism-tech/morph-spec 4.3.3 → 4.3.5
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/.morph/.morphversion +5 -0
- package/.morph/analytics/threads-log.jsonl +9 -0
- package/{stacks/blazor-azure/.morph → .morph}/config/agents.json +948 -948
- package/.morph/config/config.json +9 -0
- package/{stacks/blazor-azure/.morph → .morph}/project/context/README.md +1 -1
- package/.morph/project/context/detection-log.md +16 -0
- package/.morph/project/standards/inferred.md +59 -0
- package/.morph/state.json +48 -0
- package/.morph/templates/.idea/morph-templates.xml +92 -0
- package/.morph/templates/.vscode/morph-templates.code-snippets +186 -0
- package/.morph/templates/IDE-SNIPPETS.md +266 -0
- package/.morph/templates/README.md +814 -0
- package/.morph/templates/REGISTRY.json +1677 -0
- package/.morph/templates/code/dotnet/backend/repository.cs +141 -0
- package/.morph/templates/code/dotnet/backend/service.cs +139 -0
- package/.morph/templates/code/dotnet/contracts/Commands.cs +74 -0
- package/.morph/templates/code/dotnet/contracts/Entities.cs +25 -0
- package/.morph/templates/code/dotnet/contracts/Queries.cs +74 -0
- package/.morph/templates/code/dotnet/contracts/README.md +74 -0
- package/.morph/templates/code/dotnet/contracts/api-contracts.cs +173 -0
- package/.morph/templates/code/dotnet/contracts/contracts.cs +217 -0
- package/.morph/templates/code/dotnet/database/migration.cs +83 -0
- package/.morph/templates/code/dotnet/frontend/component.razor +239 -0
- package/.morph/templates/code/dotnet/jobs/agent.cs +163 -0
- package/.morph/templates/code/dotnet/jobs/job.cs +171 -0
- package/.morph/templates/code/dotnet/test.cs +239 -0
- package/.morph/templates/code/sql/rls-policy.sql +57 -0
- package/.morph/templates/code/sql/supabase-migration.sql +100 -0
- package/.morph/templates/code/sql/supabase-migration.template.sql +113 -0
- package/.morph/templates/code/typescript/contracts.ts +168 -0
- package/.morph/templates/context/CONTEXT-FEATURE.md +276 -0
- package/.morph/templates/context/CONTEXT.md +181 -0
- package/.morph/templates/docs/proposal.md +182 -0
- package/.morph/templates/docs/spec.md +149 -0
- package/.morph/templates/examples/design-system-examples.md +357 -0
- package/.morph/templates/examples/spec-examples.md +90 -0
- package/.morph/templates/feature/decisions.md +187 -0
- package/.morph/templates/feature/recap.md +146 -0
- package/.morph/templates/feature/tasks.md +199 -0
- package/.morph/templates/infrastructure/azure/Dockerfile.example +82 -0
- package/.morph/templates/infrastructure/azure/README.md +286 -0
- package/.morph/templates/infrastructure/azure/app-insights.bicep +63 -0
- package/.morph/templates/infrastructure/azure/app-service.bicep +164 -0
- package/.morph/templates/infrastructure/azure/container-app-env.bicep +49 -0
- package/.morph/templates/infrastructure/azure/container-app.bicep +156 -0
- package/.morph/templates/infrastructure/azure/deploy-checklist.md +426 -0
- package/.morph/templates/infrastructure/azure/deploy.ps1 +229 -0
- package/.morph/templates/infrastructure/azure/deploy.sh +208 -0
- package/.morph/templates/infrastructure/azure/key-vault.bicep +91 -0
- package/.morph/templates/infrastructure/azure/main.bicep +189 -0
- package/.morph/templates/infrastructure/azure/parameters.dev.json +29 -0
- package/.morph/templates/infrastructure/azure/parameters.prod.json +29 -0
- package/.morph/templates/infrastructure/azure/parameters.staging.json +29 -0
- package/.morph/templates/infrastructure/azure/sql-database.bicep +103 -0
- package/.morph/templates/infrastructure/azure/storage.bicep +106 -0
- package/.morph/templates/infrastructure/docker/Dockerfile.template +58 -0
- package/.morph/templates/infrastructure/docker/docker-compose.template.yml +67 -0
- package/.morph/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -0
- package/.morph/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -0
- package/.morph/templates/infrastructure/docker/easypanel.template.json +54 -0
- package/.morph/templates/infrastructure/github/README.md +593 -0
- package/.morph/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +22 -0
- package/.morph/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -0
- package/.morph/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -0
- package/.morph/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +61 -0
- package/.morph/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +31 -0
- package/.morph/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -0
- package/.morph/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -0
- package/.morph/templates/integrations/asaas-client.cs +387 -0
- package/.morph/templates/integrations/asaas-webhook.cs +351 -0
- package/.morph/templates/integrations/azure-identity-config.cs +288 -0
- package/.morph/templates/integrations/clerk-config.cs +258 -0
- package/.morph/templates/meta-prompts/fusion/fusion-agent.md +76 -0
- package/.morph/templates/meta-prompts/fusion/fusion-aggregator.md +100 -0
- package/.morph/templates/meta-prompts/hops/hop-retry.md +78 -0
- package/.morph/templates/meta-prompts/hops/hop-validation.md +97 -0
- package/.morph/templates/meta-prompts/hops/hop-wrapper.md +36 -0
- package/.morph/templates/meta-prompts/parallel-workers/parallel-coordinator.md +113 -0
- package/.morph/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -0
- package/.morph/templates/meta-prompts/squad-leaders/backend-squad.md +90 -0
- package/.morph/templates/meta-prompts/squad-leaders/frontend-squad.md +126 -0
- package/.morph/templates/meta-prompts/squad-leaders/squad-leader.md +43 -0
- package/.morph/templates/meta-prompts/validators/checkpoint-validator.md +107 -0
- package/.morph/templates/meta-prompts/validators/pre-commit-validator.md +95 -0
- package/.morph/templates/saas/subscription.cs +347 -0
- package/.morph/templates/saas/tenant.cs +338 -0
- package/.morph/templates/state.template.json +17 -0
- package/.morph/templates/ui/FluentDesignTheme.cs +149 -0
- package/.morph/templates/ui/MudTheme.cs +281 -0
- package/.morph/templates/ui/design-system.css +226 -0
- package/bin/detect-agents.js +1 -2
- package/bin/morph-spec.js +1 -14
- package/framework/agents.json +948 -0
- package/{stacks/nextjs-supabase/.claude → framework}/commands/morph-infra.md +1 -1
- package/framework/hooks/README.md +282 -0
- package/framework/hooks/agent-stop/validate-and-continue.js +96 -0
- package/framework/hooks/agent-stop/validate-checkpoints.js +101 -0
- package/framework/hooks/agent-stop/validate-tests.js +109 -0
- package/framework/hooks/agent-teams/dispatch.js +67 -0
- package/framework/hooks/agent-teams/phase-advanced.js +80 -0
- package/framework/hooks/agent-teams/task-completed.js +76 -0
- package/framework/hooks/agent-teams/teammate-idle.js +70 -0
- package/framework/hooks/commit-msg/conventional-commits.sh +33 -0
- package/framework/hooks/pre-commit/agents.sh +25 -0
- package/framework/hooks/pre-commit/orchestrator.sh +64 -0
- package/framework/hooks/pre-commit/specs.sh +50 -0
- package/framework/hooks/pre-push/run-tests.sh +44 -0
- package/framework/index/troubleshooting-index.json +184 -0
- package/framework/memory/patterns-learned.md +766 -0
- package/framework/skills/level-0-meta/README.md +7 -0
- package/framework/skills/level-0-meta/code-review.md +226 -0
- package/framework/skills/level-0-meta/morph-checklist.md +117 -0
- package/framework/skills/level-0-meta/simulation-checklist.md +77 -0
- package/framework/skills/level-1-workflows/README.md +7 -0
- package/framework/skills/level-1-workflows/morph-replicate.md +213 -0
- package/framework/skills/level-1-workflows/phase-clarify.md +131 -0
- package/framework/skills/level-1-workflows/phase-design.md +213 -0
- package/framework/skills/level-1-workflows/phase-setup.md +106 -0
- package/framework/skills/level-1-workflows/phase-tasks.md +164 -0
- package/framework/skills/level-1-workflows/phase-uiux.md +169 -0
- package/framework/skills/level-2-domains/README.md +14 -0
- package/framework/skills/level-2-domains/ai-agents/ai-system-architect.md +192 -0
- package/framework/skills/level-2-domains/architecture/po-pm-advisor.md +197 -0
- package/framework/skills/level-2-domains/architecture/prompt-engineer.md +189 -0
- package/framework/skills/level-2-domains/architecture/seo-growth-hacker.md +320 -0
- package/framework/skills/level-2-domains/architecture/standards-architect.md +156 -0
- package/framework/skills/level-2-domains/backend/api-designer.md +59 -0
- package/framework/skills/level-2-domains/backend/dotnet-senior.md +77 -0
- package/framework/skills/level-2-domains/backend/ef-modeler.md +58 -0
- package/framework/skills/level-2-domains/backend/hangfire-orchestrator.md +126 -0
- package/framework/skills/level-2-domains/backend/ms-agent-expert.md +45 -0
- package/framework/skills/level-2-domains/frontend/blazor-builder.md +210 -0
- package/framework/skills/level-2-domains/frontend/nextjs-expert.md +154 -0
- package/framework/skills/level-2-domains/frontend/ui-ux-designer.md +191 -0
- package/framework/skills/level-2-domains/infrastructure/azure-architect.md +142 -0
- package/framework/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +699 -0
- package/framework/skills/level-2-domains/infrastructure/bicep-architect.md +126 -0
- package/framework/skills/level-2-domains/infrastructure/container-specialist.md +131 -0
- package/framework/skills/level-2-domains/infrastructure/devops-engineer.md +119 -0
- package/framework/skills/level-2-domains/integrations/asaas-financial.md +130 -0
- package/framework/skills/level-2-domains/integrations/azure-identity.md +142 -0
- package/framework/skills/level-2-domains/integrations/clerk-auth.md +108 -0
- package/framework/skills/level-2-domains/integrations/hangfire-orchestrator.md +64 -0
- package/framework/skills/level-2-domains/integrations/resend-email.md +119 -0
- package/framework/skills/level-2-domains/quality/code-analyzer.md +235 -0
- package/framework/skills/level-2-domains/quality/testing-specialist.md +126 -0
- package/framework/skills/level-3-technologies/README.md +7 -0
- package/framework/skills/level-4-patterns/README.md +7 -0
- package/framework/squad-templates/backend-only.json +34 -0
- package/framework/squad-templates/frontend-only.json +34 -0
- package/framework/squad-templates/full-stack.json +52 -0
- package/framework/templates/.idea/morph-templates.xml +92 -0
- package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
- package/framework/templates/IDE-SNIPPETS.md +266 -0
- package/framework/templates/README.md +814 -0
- package/framework/templates/REGISTRY.json +1677 -0
- package/framework/templates/code/dotnet/backend/repository.cs +141 -0
- package/framework/templates/code/dotnet/backend/service.cs +139 -0
- package/framework/templates/code/dotnet/contracts/Commands.cs +74 -0
- package/framework/templates/code/dotnet/contracts/Entities.cs +25 -0
- package/framework/templates/code/dotnet/contracts/Queries.cs +74 -0
- package/framework/templates/code/dotnet/contracts/README.md +74 -0
- package/framework/templates/code/dotnet/contracts/api-contracts.cs +173 -0
- package/framework/templates/code/dotnet/contracts/contracts.cs +217 -0
- package/framework/templates/code/dotnet/database/migration.cs +83 -0
- package/framework/templates/code/dotnet/frontend/component.razor +239 -0
- package/framework/templates/code/dotnet/jobs/agent.cs +163 -0
- package/framework/templates/code/dotnet/jobs/job.cs +171 -0
- package/framework/templates/code/dotnet/test.cs +239 -0
- package/framework/templates/code/sql/rls-policy.sql +57 -0
- package/framework/templates/code/sql/supabase-migration.sql +100 -0
- package/framework/templates/code/sql/supabase-migration.template.sql +113 -0
- package/framework/templates/code/typescript/contracts.ts +168 -0
- package/framework/templates/context/CONTEXT-FEATURE.md +276 -0
- package/framework/templates/context/CONTEXT.md +181 -0
- package/framework/templates/docs/proposal.md +182 -0
- package/framework/templates/docs/spec.md +149 -0
- package/framework/templates/examples/design-system-examples.md +357 -0
- package/framework/templates/examples/spec-examples.md +90 -0
- package/framework/templates/feature/decisions.md +187 -0
- package/framework/templates/feature/recap.md +146 -0
- package/framework/templates/feature/tasks.md +199 -0
- package/framework/templates/infrastructure/azure/Dockerfile.example +82 -0
- package/framework/templates/infrastructure/azure/README.md +286 -0
- package/framework/templates/infrastructure/azure/app-insights.bicep +63 -0
- package/framework/templates/infrastructure/azure/app-service.bicep +164 -0
- package/framework/templates/infrastructure/azure/container-app-env.bicep +49 -0
- package/framework/templates/infrastructure/azure/container-app.bicep +156 -0
- package/framework/templates/infrastructure/azure/deploy-checklist.md +426 -0
- package/framework/templates/infrastructure/azure/deploy.ps1 +229 -0
- package/framework/templates/infrastructure/azure/deploy.sh +208 -0
- package/framework/templates/infrastructure/azure/key-vault.bicep +91 -0
- package/framework/templates/infrastructure/azure/main.bicep +189 -0
- package/framework/templates/infrastructure/azure/parameters.dev.json +29 -0
- package/framework/templates/infrastructure/azure/parameters.prod.json +29 -0
- package/framework/templates/infrastructure/azure/parameters.staging.json +29 -0
- package/framework/templates/infrastructure/azure/sql-database.bicep +103 -0
- package/framework/templates/infrastructure/azure/storage.bicep +106 -0
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -0
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +67 -0
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -0
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -0
- package/framework/templates/infrastructure/docker/easypanel.template.json +54 -0
- package/framework/templates/infrastructure/github/README.md +593 -0
- package/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +22 -0
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -0
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -0
- package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +61 -0
- package/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +31 -0
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -0
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -0
- package/framework/templates/integrations/asaas-client.cs +387 -0
- package/framework/templates/integrations/asaas-webhook.cs +351 -0
- package/framework/templates/integrations/azure-identity-config.cs +288 -0
- package/framework/templates/integrations/clerk-config.cs +258 -0
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -0
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -0
- package/framework/templates/meta-prompts/hops/hop-retry.md +78 -0
- package/framework/templates/meta-prompts/hops/hop-validation.md +97 -0
- package/framework/templates/meta-prompts/hops/hop-wrapper.md +36 -0
- package/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +113 -0
- package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -0
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +90 -0
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +126 -0
- package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +43 -0
- package/framework/templates/meta-prompts/validators/checkpoint-validator.md +107 -0
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -0
- package/framework/templates/saas/subscription.cs +347 -0
- package/framework/templates/saas/tenant.cs +338 -0
- package/framework/templates/state.template.json +17 -0
- package/framework/templates/ui/FluentDesignTheme.cs +149 -0
- package/framework/templates/ui/MudTheme.cs +281 -0
- package/framework/templates/ui/design-system.css +226 -0
- package/framework/workflows/README.md +1041 -0
- package/framework/workflows/configs/design-impl.json +49 -0
- package/framework/workflows/configs/fast-track.json +42 -0
- package/framework/workflows/configs/full-morph.json +79 -0
- package/framework/workflows/configs/fusion.json +39 -0
- package/framework/workflows/configs/long-running.json +33 -0
- package/framework/workflows/configs/standard.json +60 -0
- package/framework/workflows/configs/ui-refresh.json +49 -0
- package/framework/workflows/configs/zero-touch.json +75 -0
- package/framework/workflows/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -0
- package/framework/workflows/docs/design-impl.md +37 -0
- package/framework/workflows/docs/enforcement-pipeline.md +668 -0
- package/framework/workflows/docs/fast-track.md +29 -0
- package/framework/workflows/docs/full-morph.md +76 -0
- package/framework/workflows/docs/standard.md +44 -0
- package/framework/workflows/docs/ui-refresh.md +39 -0
- package/package.json +3 -3
- package/src/commands/feature/create-story.js +11 -7
- package/src/commands/project/detect-agents.js +1 -2
- package/src/commands/project/init.js +69 -32
- package/src/commands/project/update.js +102 -15
- package/src/commands/templates/template-customize.js +3 -17
- package/src/commands/templates/template-list.js +1 -15
- package/src/commands/templates/template-render.js +2 -3
- package/src/commands/templates/template-show.js +3 -5
- package/src/core/templates/template-registry.js +9 -23
- package/src/lib/detectors/structure-detector.js +3 -3
- package/src/lib/generators/context-generator.js +18 -6
- package/src/lib/hooks/hook-executor.js +0 -2
- package/src/lib/orchestration/team-orchestrator.js +1 -2
- package/src/lib/standards/standards-context-injector.js +3 -4
- package/src/lib/troubleshooting/troubleshoot-grep.js +3 -9
- package/src/lib/validators/validation-runner.js +1 -2
- package/src/utils/file-copier.js +1 -2
- package/docs/README.md +0 -144
- package/docs/api/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -978
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -1049
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/api/scripts/collapse.js +0 -39
- package/docs/api/scripts/commonNav.js +0 -28
- package/docs/api/scripts/linenumber.js +0 -25
- package/docs/api/scripts/nav.js +0 -12
- package/docs/api/scripts/polyfill.js +0 -4
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/api/scripts/prettify/lang-css.js +0 -2
- package/docs/api/scripts/prettify/prettify.js +0 -28
- package/docs/api/scripts/search.js +0 -99
- package/docs/api/styles/jsdoc.css +0 -776
- package/docs/api/styles/prettify.css +0 -80
- package/docs/cli-auto-detection.md +0 -219
- package/docs/getting-started.md +0 -296
- package/docs/installation.md +0 -361
- package/docs/next-generation/AGENTS.md +0 -521
- package/docs/next-generation/ANALYSIS.md +0 -555
- package/docs/next-generation/ARCHITECTURE.md +0 -436
- package/docs/next-generation/CONTEXT-OPTIMIZATION.md +0 -267
- package/docs/next-generation/EXECUTION-FLOW.md +0 -274
- package/docs/next-generation/FEATURES.md +0 -688
- package/docs/next-generation/META-PROMPTS.md +0 -235
- package/docs/next-generation/MIGRATION-GUIDE.md +0 -253
- package/docs/next-generation/README.md +0 -231
- package/docs/next-generation/ROADMAP.md +0 -801
- package/docs/next-generation/THREAD-MANAGEMENT.md +0 -240
- package/docs/templates.md +0 -418
- package/docs/troubleshooting.md +0 -269
- package/docs/validation-checklist.md +0 -264
- package/scripts/postinstall.js +0 -132
- package/src/lib/stacks/index.js +0 -7
- package/src/lib/stacks/stack-resolver.js +0 -180
- package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
- package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
- package/stacks/blazor-azure/.morph/.morphversion +0 -5
- package/stacks/blazor-azure/.morph/config/config.json +0 -9
- package/stacks/blazor-azure/CLAUDE.md +0 -155
- package/stacks/blazor-azure/README.md +0 -79
- package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +0 -221
- package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +0 -79
- package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +0 -529
- package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +0 -227
- package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +0 -122
- package/stacks/nextjs-supabase/.claude/commands/morph-status.md +0 -86
- package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +0 -122
- package/stacks/nextjs-supabase/.morph/.morphversion +0 -5
- package/stacks/nextjs-supabase/.morph/config/agents.json +0 -345
- package/stacks/nextjs-supabase/.morph/config/config.json +0 -9
- package/stacks/nextjs-supabase/.morph/project/context/README.md +0 -17
- package/stacks/nextjs-supabase/CLAUDE.md +0 -155
- package/stacks/nextjs-supabase/README.md +0 -103
- /package/{stacks/blazor-azure/.morph → .morph}/standards/ai-agents/blazor-ui.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/ai-agents/production.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/ai-agents/setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/ai-agents/team-orchestration.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/ai-agents/workflows.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/architecture/ddd/aggregates.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/architecture/ddd/entities.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/architecture/ddd/value-objects.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/api/minimal-api.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/api/rest.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/api/validation.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/authentication/passkeys.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/database/ef-core.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/database/migrations.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/database/postgresql/database.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/database/repository-patterns.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/database/vector-search-rag.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/dotnet/async.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/dotnet/core.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/dotnet/di.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/dotnet/program-cs-checklist.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/integrations/asaas/asaas-api.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/integrations/clerk/clerk-auth.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/backend/integrations/resend/resend-email.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/context/analytics.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/context/bundles.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/context/priming.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/core/architecture.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/core/coding.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/core/git-branching-strategy.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/core/git.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/core/testing.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/data/nosql/blob-storage.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/data/nosql/cache/redis.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/data/nosql/cosmos-db.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/data/vector-search/azure-ai-search.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/data/vector-search/rag-chunking.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/design-checklist.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/fluent-ui-setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/fluent-ui.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/html-conversion.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/lifecycle.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/pitfalls.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/blazor/state.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/design-system/animations.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/design-system/naming.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/frontend/nextjs/nextjs-patterns.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/azure.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/devops/local-development.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/services/functions.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/services/service-bus.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/azure/services/storage.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/docker/easypanel-deploy.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/supabase/mcp-setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/supabase/supabase-auth.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/supabase/supabase-pgvector.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/supabase/supabase-rls.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/infrastructure/supabase/supabase-storage.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/integration/api/graphql.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/integration/api/grpc.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/integration/api/rest-design.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/integration/event-driven/cqrs.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/integration/event-driven/event-sourcing.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/integration/event-driven/service-bus.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/observability/logging.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/observability/metrics.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/observability/monitoring.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/observability/tracing.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/workflows/parallel-execution.md +0 -0
- /package/{stacks/blazor-azure/.morph → .morph}/standards/workflows/thread-management.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-apply.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-archive.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-preflight.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-proposal.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-status.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-troubleshoot.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/ai-agents/blazor-ui.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/ai-agents/production.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/ai-agents/setup.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/ai-agents/team-orchestration.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/ai-agents/workflows.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/architecture/ddd/aggregates.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/architecture/ddd/entities.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/architecture/ddd/value-objects.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/api/minimal-api.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/api/rest.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/api/validation.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/authentication/passkeys.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/database/ef-core.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/database/migrations.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/database/postgresql/database.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/database/repository-patterns.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/database/vector-search-rag.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/dotnet/async.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/dotnet/core.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/dotnet/di.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/dotnet/program-cs-checklist.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/integrations/asaas/asaas-api.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/integrations/clerk/clerk-auth.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/backend/integrations/resend/resend-email.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/context/analytics.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/context/bundles.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/context/priming.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/core/architecture.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/core/coding.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/core/git-branching-strategy.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/core/git.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/core/testing.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/data/nosql/blob-storage.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/data/nosql/cache/redis.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/data/nosql/cosmos-db.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/data/vector-search/azure-ai-search.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/data/vector-search/rag-chunking.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/design-checklist.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/fluent-ui-setup.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/fluent-ui.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/html-conversion.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/lifecycle.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/pitfalls.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/blazor/state.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/design-system/animations.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/design-system/naming.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/frontend/nextjs/nextjs-patterns.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/azure.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/devops/local-development.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/services/functions.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/services/service-bus.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/azure/services/storage.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/docker/easypanel-deploy.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/supabase/mcp-setup.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/supabase/supabase-auth.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/supabase/supabase-pgvector.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/supabase/supabase-rls.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/infrastructure/supabase/supabase-storage.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/integration/api/graphql.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/integration/api/grpc.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/integration/api/rest-design.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/integration/event-driven/cqrs.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/integration/event-driven/event-sourcing.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/integration/event-driven/service-bus.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/observability/logging.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/observability/metrics.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/observability/monitoring.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/observability/tracing.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/workflows/parallel-execution.md +0 -0
- /package/{stacks/nextjs-supabase/.morph → framework}/standards/workflows/thread-management.md +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Bicep Architect
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** bicep, iac, infrastructure as code, provision, azure resource, deploy
|
|
4
|
+
|
|
5
|
+
Especialista em Infrastructure as Code com Azure Bicep. **Zero Portal** — all infra via code.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
infra/
|
|
11
|
+
├── main.bicep # Entry point
|
|
12
|
+
├── main.bicepparam # Parameters (alt to JSON)
|
|
13
|
+
├── parameters.dev.json
|
|
14
|
+
├── parameters.prod.json
|
|
15
|
+
└── modules/
|
|
16
|
+
├── container-app.bicep
|
|
17
|
+
├── container-app-env.bicep
|
|
18
|
+
├── sql-database.bicep
|
|
19
|
+
├── storage.bicep
|
|
20
|
+
├── key-vault.bicep
|
|
21
|
+
├── app-insights.bicep
|
|
22
|
+
├── service-bus.bicep
|
|
23
|
+
└── redis-cache.bicep
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Main Template Pattern
|
|
27
|
+
|
|
28
|
+
```bicep
|
|
29
|
+
targetScope = 'resourceGroup'
|
|
30
|
+
|
|
31
|
+
@allowed(['dev', 'staging', 'prod'])
|
|
32
|
+
param environment string = 'dev'
|
|
33
|
+
param location string = resourceGroup().location
|
|
34
|
+
@minLength(3) @maxLength(20) param appName string
|
|
35
|
+
@secure() param sqlAdminPassword string
|
|
36
|
+
|
|
37
|
+
var resourcePrefix = '${appName}-${environment}'
|
|
38
|
+
var tags = { environment: environment, application: appName, managedBy: 'bicep' }
|
|
39
|
+
|
|
40
|
+
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
|
|
41
|
+
name: '${resourcePrefix}-logs'
|
|
42
|
+
location: location
|
|
43
|
+
tags: tags
|
|
44
|
+
properties: { sku: { name: 'PerGB2018' }, retentionInDays: 30 }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module appInsights 'modules/app-insights.bicep' = { name: 'appInsights', params: { ... } }
|
|
48
|
+
module containerAppEnv 'modules/container-app-env.bicep' = { name: 'env', params: { ... } }
|
|
49
|
+
module containerApp 'modules/container-app.bicep' = { name: 'app', params: { ... } }
|
|
50
|
+
module sqlDatabase 'modules/sql-database.bicep' = { name: 'sql', params: { ... } }
|
|
51
|
+
module keyVault 'modules/key-vault.bicep' = { name: 'kv', params: { ... } }
|
|
52
|
+
|
|
53
|
+
output containerAppUrl string = containerApp.outputs.url
|
|
54
|
+
output sqlConnectionString string = sqlDatabase.outputs.connectionString
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## SQL Database Module (Free Tier)
|
|
58
|
+
|
|
59
|
+
```bicep
|
|
60
|
+
// modules/sql-database.bicep
|
|
61
|
+
param serverName string
|
|
62
|
+
param databaseName string
|
|
63
|
+
param location string
|
|
64
|
+
param tags object = {}
|
|
65
|
+
param adminUsername string = 'sqladmin'
|
|
66
|
+
@secure() param adminPassword string
|
|
67
|
+
param useFree bool = true
|
|
68
|
+
|
|
69
|
+
resource sqlServer 'Microsoft.Sql/servers@2023-05-01-preview' = {
|
|
70
|
+
name: serverName
|
|
71
|
+
location: location
|
|
72
|
+
tags: tags
|
|
73
|
+
properties: { administratorLogin: adminUsername, administratorLoginPassword: adminPassword,
|
|
74
|
+
version: '12.0', minimalTlsVersion: '1.2', publicNetworkAccess: 'Enabled' }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
resource db 'Microsoft.Sql/servers/databases@2023-05-01-preview' = {
|
|
78
|
+
parent: sqlServer
|
|
79
|
+
name: databaseName
|
|
80
|
+
location: location
|
|
81
|
+
sku: useFree ? { name: 'Free', tier: 'Free' } : { name: 'Basic', tier: 'Basic' }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
resource firewall 'Microsoft.Sql/servers/firewallRules@2023-05-01-preview' = {
|
|
85
|
+
parent: sqlServer
|
|
86
|
+
name: 'AllowAllAzureIps'
|
|
87
|
+
properties: { startIpAddress: '0.0.0.0', endIpAddress: '0.0.0.0' }
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
> **Container App module:** See `container-specialist.md` for full Container App + ACR Bicep.
|
|
92
|
+
|
|
93
|
+
## Commands
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
az bicep build --file infra/main.bicep # Validate
|
|
97
|
+
az deployment group what-if -g rg-app-dev -f infra/main.bicep -p @infra/parameters.dev.json # Preview
|
|
98
|
+
az deployment group create -g rg-app-dev -f infra/main.bicep -p @infra/parameters.dev.json # Deploy
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Parameters File
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
|
|
106
|
+
"contentVersion": "1.0.0.0",
|
|
107
|
+
"parameters": {
|
|
108
|
+
"environment": { "value": "dev" },
|
|
109
|
+
"appName": { "value": "myapp" },
|
|
110
|
+
"sqlAdminPassword": { "reference": { "keyVault": { "id": "/subscriptions/.../vaults/{kv}" }, "secretName": "sql-admin-password" } }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Checklist
|
|
116
|
+
- [ ] Bicep valid (`az bicep build`)
|
|
117
|
+
- [ ] Modules for reusable resources
|
|
118
|
+
- [ ] Parameters for dev and prod
|
|
119
|
+
- [ ] Secrets referenced from Key Vault
|
|
120
|
+
- [ ] Tags on all resources
|
|
121
|
+
- [ ] What-if executed before deploy
|
|
122
|
+
- [ ] Outputs for important values
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Container Specialist
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** docker, container, containerize, container apps, acr, registry, image
|
|
4
|
+
|
|
5
|
+
Especialista em containerização com Docker e deploy para Azure Container Apps.
|
|
6
|
+
|
|
7
|
+
## Dockerfile (.NET Multi-stage)
|
|
8
|
+
|
|
9
|
+
```dockerfile
|
|
10
|
+
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
|
11
|
+
WORKDIR /src
|
|
12
|
+
COPY ["src/Web/Web.csproj", "src/Web/"]
|
|
13
|
+
COPY ["src/Application/Application.csproj", "src/Application/"]
|
|
14
|
+
COPY ["src/Domain/Domain.csproj", "src/Domain/"]
|
|
15
|
+
COPY ["src/Infrastructure/Infrastructure.csproj", "src/Infrastructure/"]
|
|
16
|
+
RUN dotnet restore "src/Web/Web.csproj"
|
|
17
|
+
COPY . .
|
|
18
|
+
WORKDIR "/src/src/Web"
|
|
19
|
+
RUN dotnet publish "Web.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
|
20
|
+
|
|
21
|
+
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
|
22
|
+
WORKDIR /app
|
|
23
|
+
RUN addgroup -g 1000 appgroup && adduser -u 1000 -G appgroup -D appuser
|
|
24
|
+
COPY --from=publish /app/publish .
|
|
25
|
+
RUN chown -R appuser:appgroup /app
|
|
26
|
+
USER appuser
|
|
27
|
+
EXPOSE 8080
|
|
28
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
29
|
+
CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
|
|
30
|
+
ENTRYPOINT ["dotnet", "Web.dll"]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Image Sizes
|
|
34
|
+
| Base Image | Size |
|
|
35
|
+
|------------|------|
|
|
36
|
+
| `aspnet:10.0` | ~220MB |
|
|
37
|
+
| `aspnet:10.0-alpine` | ~110MB |
|
|
38
|
+
| `aspnet:10.0-chiseled` | ~80MB (most secure) |
|
|
39
|
+
|
|
40
|
+
## ACR (Azure Container Registry)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
az acr create -g rg-myapp -n myappacr --sku Basic
|
|
44
|
+
az acr login -n myappacr
|
|
45
|
+
az acr build --registry myappacr --image myapp:v1 .
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Container App (Bicep)
|
|
49
|
+
|
|
50
|
+
```bicep
|
|
51
|
+
param name string
|
|
52
|
+
param location string
|
|
53
|
+
param tags object = {}
|
|
54
|
+
param environmentId string
|
|
55
|
+
param containerImage string
|
|
56
|
+
param registryServer string
|
|
57
|
+
param registryUsername string
|
|
58
|
+
@secure() param registryPassword string
|
|
59
|
+
|
|
60
|
+
resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
|
|
61
|
+
name: name
|
|
62
|
+
location: location
|
|
63
|
+
tags: tags
|
|
64
|
+
properties: {
|
|
65
|
+
managedEnvironmentId: environmentId
|
|
66
|
+
configuration: {
|
|
67
|
+
ingress: { external: true, targetPort: 8080, transport: 'http', allowInsecure: false }
|
|
68
|
+
registries: [{ server: registryServer, username: registryUsername, passwordSecretRef: 'reg-pwd' }]
|
|
69
|
+
secrets: [{ name: 'reg-pwd', value: registryPassword }]
|
|
70
|
+
}
|
|
71
|
+
template: {
|
|
72
|
+
containers: [{
|
|
73
|
+
name: name, image: containerImage
|
|
74
|
+
resources: { cpu: json('0.25'), memory: '0.5Gi' }
|
|
75
|
+
probes: [
|
|
76
|
+
{ type: 'Liveness', httpGet: { path: '/health', port: 8080 }, initialDelaySeconds: 10 }
|
|
77
|
+
{ type: 'Readiness', httpGet: { path: '/health/ready', port: 8080 }, initialDelaySeconds: 5 }
|
|
78
|
+
]
|
|
79
|
+
}]
|
|
80
|
+
scale: { minReplicas: 0, maxReplicas: 5
|
|
81
|
+
rules: [{ name: 'http-scale', http: { metadata: { concurrentRequests: '100' } } }]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
output url string = 'https://${containerApp.properties.configuration.ingress.fqdn}'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Health Checks (ASP.NET)
|
|
90
|
+
|
|
91
|
+
```csharp
|
|
92
|
+
builder.Services.AddHealthChecks()
|
|
93
|
+
.AddSqlServer(connString, name: "database", tags: new[] { "ready" });
|
|
94
|
+
|
|
95
|
+
app.MapHealthChecks("/health");
|
|
96
|
+
app.MapHealthChecks("/health/ready", new() { Predicate = c => c.Tags.Contains("ready") });
|
|
97
|
+
app.MapHealthChecks("/health/live", new() { Predicate = _ => false }); // Always healthy
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Docker Compose (Dev)
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
services:
|
|
104
|
+
web:
|
|
105
|
+
build: { context: ., dockerfile: Dockerfile }
|
|
106
|
+
ports: ["8080:8080"]
|
|
107
|
+
environment:
|
|
108
|
+
- ConnectionStrings__Default=Server=db;Database=App;User=sa;Password=Pass!;TrustServerCertificate=true
|
|
109
|
+
depends_on: { db: { condition: service_healthy } }
|
|
110
|
+
db:
|
|
111
|
+
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
112
|
+
environment: [ACCEPT_EULA=Y, SA_PASSWORD=YourStrong!Passw0rd]
|
|
113
|
+
ports: ["1433:1433"]
|
|
114
|
+
volumes: [sqldata:/var/opt/mssql]
|
|
115
|
+
volumes:
|
|
116
|
+
sqldata:
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Checklist
|
|
120
|
+
- [ ] Dockerfile multi-stage with alpine/chiseled
|
|
121
|
+
- [ ] .dockerignore configured
|
|
122
|
+
- [ ] Non-root user in container
|
|
123
|
+
- [ ] Health checks (liveness + readiness)
|
|
124
|
+
- [ ] Docker Compose for dev
|
|
125
|
+
- [ ] ACR created and configured
|
|
126
|
+
- [ ] Container App with scale-to-zero
|
|
127
|
+
- [ ] Probes configured
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# DevOps Engineer
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** pipeline, ci/cd, deploy, release, azure devops, github actions, build, automation
|
|
4
|
+
|
|
5
|
+
Especialista em CI/CD, pipelines e automação de deploy.
|
|
6
|
+
|
|
7
|
+
## Azure Pipelines
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
trigger:
|
|
11
|
+
branches: { include: [main, develop] }
|
|
12
|
+
paths: { exclude: ['**/*.md'] }
|
|
13
|
+
|
|
14
|
+
variables:
|
|
15
|
+
buildConfiguration: 'Release'
|
|
16
|
+
dotnetVersion: '10.0.x'
|
|
17
|
+
|
|
18
|
+
stages:
|
|
19
|
+
- stage: Build
|
|
20
|
+
jobs:
|
|
21
|
+
- job: BuildJob
|
|
22
|
+
pool: { vmImage: 'ubuntu-latest' }
|
|
23
|
+
steps:
|
|
24
|
+
- task: UseDotNet@2
|
|
25
|
+
inputs: { version: '$(dotnetVersion)' }
|
|
26
|
+
- task: DotNetCoreCLI@2
|
|
27
|
+
displayName: 'Restore'
|
|
28
|
+
inputs: { command: 'restore', projects: '**/*.csproj' }
|
|
29
|
+
- task: DotNetCoreCLI@2
|
|
30
|
+
displayName: 'Build'
|
|
31
|
+
inputs: { command: 'build', arguments: '-c $(buildConfiguration) --no-restore' }
|
|
32
|
+
- task: DotNetCoreCLI@2
|
|
33
|
+
displayName: 'Test'
|
|
34
|
+
inputs: { command: 'test', projects: '**/tests/**/*.csproj', arguments: '--collect:"XPlat Code Coverage"' }
|
|
35
|
+
- task: DotNetCoreCLI@2
|
|
36
|
+
displayName: 'Publish'
|
|
37
|
+
inputs: { command: 'publish', publishWebProjects: true, arguments: '-c $(buildConfiguration) -o $(Build.ArtifactStagingDirectory)' }
|
|
38
|
+
- task: PublishBuildArtifacts@1
|
|
39
|
+
inputs: { pathToPublish: '$(Build.ArtifactStagingDirectory)', artifactName: 'drop' }
|
|
40
|
+
|
|
41
|
+
- stage: DeployDev
|
|
42
|
+
dependsOn: Build
|
|
43
|
+
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
|
|
44
|
+
jobs:
|
|
45
|
+
- deployment: Deploy
|
|
46
|
+
environment: 'development'
|
|
47
|
+
strategy:
|
|
48
|
+
runOnce:
|
|
49
|
+
deploy:
|
|
50
|
+
steps:
|
|
51
|
+
- task: AzureCLI@2
|
|
52
|
+
inputs:
|
|
53
|
+
scriptType: 'bash'
|
|
54
|
+
inlineScript: 'az containerapp update --name app-dev -g rg-dev --image $(image)'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## GitHub Actions
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
name: CI/CD
|
|
61
|
+
on:
|
|
62
|
+
push: { branches: [main, develop] }
|
|
63
|
+
pull_request: { branches: [main] }
|
|
64
|
+
|
|
65
|
+
jobs:
|
|
66
|
+
build:
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
- uses: actions/setup-dotnet@v4
|
|
71
|
+
with: { dotnet-version: '10.0.x' }
|
|
72
|
+
- run: dotnet restore && dotnet build -c Release --no-restore && dotnet test -c Release --no-build
|
|
73
|
+
- run: dotnet publish src/Web/Web.csproj -c Release -o ./publish
|
|
74
|
+
|
|
75
|
+
docker:
|
|
76
|
+
needs: build
|
|
77
|
+
if: github.event_name == 'push'
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
permissions: { contents: read, packages: write }
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
- uses: docker/login-action@v3
|
|
83
|
+
with: { registry: ghcr.io, username: '${{ github.actor }}', password: '${{ secrets.GITHUB_TOKEN }}' }
|
|
84
|
+
- uses: docker/build-push-action@v5
|
|
85
|
+
with: { push: true, tags: 'ghcr.io/${{ github.repository }}:${{ github.sha }}' }
|
|
86
|
+
|
|
87
|
+
deploy:
|
|
88
|
+
needs: docker
|
|
89
|
+
if: github.ref == 'refs/heads/main'
|
|
90
|
+
runs-on: ubuntu-latest
|
|
91
|
+
environment: production
|
|
92
|
+
steps:
|
|
93
|
+
- uses: azure/login@v2
|
|
94
|
+
with: { creds: '${{ secrets.AZURE_CREDENTIALS }}' }
|
|
95
|
+
- uses: azure/container-apps-deploy-action@v1
|
|
96
|
+
with: { resourceGroup: rg-prod, containerAppName: app-prod, imageToDeploy: 'ghcr.io/${{ github.repository }}:${{ github.sha }}' }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> **Dockerfile:** See `container-specialist.md` for optimized multi-stage Dockerfile.
|
|
100
|
+
|
|
101
|
+
## Secrets Management
|
|
102
|
+
|
|
103
|
+
| Platform | Method |
|
|
104
|
+
|----------|--------|
|
|
105
|
+
| Azure DevOps | Variable Groups + Key Vault references |
|
|
106
|
+
| GitHub Actions | Repository/Environment Secrets |
|
|
107
|
+
|
|
108
|
+
## Checklist
|
|
109
|
+
- [ ] Trigger configured (branches, paths)
|
|
110
|
+
- [ ] Build: restore, build, test, publish
|
|
111
|
+
- [ ] Code coverage published
|
|
112
|
+
- [ ] Deploy to dev automatic (develop branch)
|
|
113
|
+
- [ ] Deploy to prod with approval (main branch)
|
|
114
|
+
- [ ] Secrets in Key Vault or variable groups
|
|
115
|
+
- [ ] Health check after deploy
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Asaas Financial
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** asaas, payment, pix, boleto, cobranca, subscription, billing, pagamento
|
|
4
|
+
|
|
5
|
+
Integração com Asaas para pagamentos no Brasil. API REST, sem SDK .NET oficial. Suporta PIX, Boleto, Cartão.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```csharp
|
|
10
|
+
// appsettings.json
|
|
11
|
+
{ "Asaas": { "BaseUrl": "https://sandbox.asaas.com/api/v3", "ApiKey": "${ASAAS_API_KEY}" } }
|
|
12
|
+
|
|
13
|
+
// Program.cs
|
|
14
|
+
builder.Services.Configure<AsaasOptions>(builder.Configuration.GetSection("Asaas"));
|
|
15
|
+
builder.Services.AddHttpClient<IAsaasClient, AsaasClient>((sp, client) =>
|
|
16
|
+
{
|
|
17
|
+
var options = sp.GetRequiredService<IOptions<AsaasOptions>>().Value;
|
|
18
|
+
client.BaseAddress = new Uri(options.BaseUrl);
|
|
19
|
+
client.DefaultRequestHeaders.Add("access_token", options.ApiKey);
|
|
20
|
+
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Client Interface
|
|
25
|
+
|
|
26
|
+
```csharp
|
|
27
|
+
public interface IAsaasClient
|
|
28
|
+
{
|
|
29
|
+
Task<AsaasCustomer> CreateCustomerAsync(CreateCustomerRequest request);
|
|
30
|
+
Task<AsaasPayment> CreatePaymentAsync(CreatePaymentRequest request);
|
|
31
|
+
Task<AsaasPayment> GetPaymentAsync(string paymentId);
|
|
32
|
+
Task<AsaasSubscription> CreateSubscriptionAsync(CreateSubscriptionRequest request);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Implementation: standard `HttpClient.PostAsJsonAsync` / `GetAsync` + `ReadFromJsonAsync` pattern. Log errors, throw `AsaasException` on failure.
|
|
37
|
+
|
|
38
|
+
## DTOs (all use `[JsonPropertyName]`)
|
|
39
|
+
|
|
40
|
+
```csharp
|
|
41
|
+
public record CreateCustomerRequest
|
|
42
|
+
{
|
|
43
|
+
[JsonPropertyName("name")] public required string Name { get; init; }
|
|
44
|
+
[JsonPropertyName("cpfCnpj")] public required string CpfCnpj { get; init; } // REQUIRED even in sandbox
|
|
45
|
+
[JsonPropertyName("email")] public string? Email { get; init; }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public record CreatePaymentRequest
|
|
49
|
+
{
|
|
50
|
+
[JsonPropertyName("customer")] public required string Customer { get; init; }
|
|
51
|
+
[JsonPropertyName("billingType")] public required string BillingType { get; init; } // BOLETO, PIX, CREDIT_CARD
|
|
52
|
+
[JsonPropertyName("value")] public required decimal Value { get; init; }
|
|
53
|
+
[JsonPropertyName("dueDate")] public required string DueDate { get; init; } // yyyy-MM-dd
|
|
54
|
+
[JsonPropertyName("description")] public string? Description { get; init; }
|
|
55
|
+
[JsonPropertyName("externalReference")] public string? ExternalReference { get; init; }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public record AsaasPayment
|
|
59
|
+
{
|
|
60
|
+
[JsonPropertyName("id")] public string Id { get; init; } = "";
|
|
61
|
+
[JsonPropertyName("status")] public string Status { get; init; } = ""; // PENDING, RECEIVED, CONFIRMED, OVERDUE
|
|
62
|
+
[JsonPropertyName("invoiceUrl")] public string? InvoiceUrl { get; init; }
|
|
63
|
+
[JsonPropertyName("bankSlipUrl")] public string? BankSlipUrl { get; init; }
|
|
64
|
+
[JsonPropertyName("pixQrCode")] public AsaasPixQrCode? PixQrCode { get; init; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public record AsaasPixQrCode
|
|
68
|
+
{
|
|
69
|
+
[JsonPropertyName("encodedImage")] public string? EncodedImage { get; init; } // Base64
|
|
70
|
+
[JsonPropertyName("payload")] public string? Payload { get; init; } // PIX copia-e-cola
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Follow same pattern for `CreateSubscriptionRequest` (add `cycle`: MONTHLY/WEEKLY/YEARLY, `nextDueDate`).
|
|
75
|
+
|
|
76
|
+
## Webhooks
|
|
77
|
+
|
|
78
|
+
```csharp
|
|
79
|
+
[ApiController, Route("api/webhooks/asaas")]
|
|
80
|
+
public class AsaasWebhookController(IPaymentService payments, ILogger<AsaasWebhookController> logger) : ControllerBase
|
|
81
|
+
{
|
|
82
|
+
[HttpPost]
|
|
83
|
+
public async Task<IActionResult> Handle([FromBody] AsaasWebhookPayload payload)
|
|
84
|
+
{
|
|
85
|
+
logger.LogInformation("Asaas webhook: {Event} payment {Id}", payload.Event, payload.Payment?.Id);
|
|
86
|
+
switch (payload.Event)
|
|
87
|
+
{
|
|
88
|
+
case "PAYMENT_CONFIRMED": case "PAYMENT_RECEIVED":
|
|
89
|
+
await payments.ConfirmPaymentAsync(payload.Payment!.Id); break;
|
|
90
|
+
case "PAYMENT_OVERDUE":
|
|
91
|
+
await payments.MarkOverdueAsync(payload.Payment!.Id); break;
|
|
92
|
+
case "PAYMENT_REFUNDED":
|
|
93
|
+
await payments.RefundPaymentAsync(payload.Payment!.Id); break;
|
|
94
|
+
}
|
|
95
|
+
return Ok();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Environments
|
|
101
|
+
|
|
102
|
+
| Environment | Base URL |
|
|
103
|
+
|-------------|----------|
|
|
104
|
+
| Sandbox | `https://sandbox.asaas.com/api/v3` |
|
|
105
|
+
| Production | `https://www.asaas.com/api/v3` |
|
|
106
|
+
|
|
107
|
+
## Gotchas
|
|
108
|
+
|
|
109
|
+
| Issue | Fix |
|
|
110
|
+
|-------|-----|
|
|
111
|
+
| PIX QR Code returns Base64, NOT URL | `$"data:image/png;base64,{response.EncodedImage}"` |
|
|
112
|
+
| CPF required even in sandbox | Always include `cpfCnpj` in CreateCustomer |
|
|
113
|
+
| Missing `User-Agent` header | Add to HttpClient defaults |
|
|
114
|
+
| Date format must be `yyyy-MM-dd` | `DateTime.Today.AddDays(1).ToString("yyyy-MM-dd")` |
|
|
115
|
+
|
|
116
|
+
## Checklist
|
|
117
|
+
|
|
118
|
+
- [ ] API Key configured (not hardcoded)
|
|
119
|
+
- [ ] HttpClient with retry policy (Polly)
|
|
120
|
+
- [ ] Headers: `access_token` + `User-Agent`
|
|
121
|
+
- [ ] CPF/CNPJ always included for customers
|
|
122
|
+
- [ ] PIX QR Code → data URI conversion
|
|
123
|
+
- [ ] Dates in `yyyy-MM-dd` format
|
|
124
|
+
- [ ] Webhook endpoint + signature validation
|
|
125
|
+
- [ ] ExternalReference for reconciliation
|
|
126
|
+
- [ ] Tests with sandbox
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Azure Identity (Microsoft Identity)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** identity, entra, azure ad, microsoft auth, msal, oauth, oidc, microsoft identity
|
|
4
|
+
|
|
5
|
+
Microsoft Identity Platform for .NET/Blazor. SDK: `Microsoft.Identity.Web`.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
dotnet add package Microsoft.Identity.Web
|
|
11
|
+
dotnet add package Microsoft.Identity.Web.UI # For Blazor
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
// appsettings.json
|
|
16
|
+
{ "AzureAd": {
|
|
17
|
+
"Instance": "https://login.microsoftonline.com/",
|
|
18
|
+
"Domain": "yourdomain.onmicrosoft.com",
|
|
19
|
+
"TenantId": "your-tenant-id",
|
|
20
|
+
"ClientId": "your-client-id",
|
|
21
|
+
"ClientSecret": "${AZURE_AD_CLIENT_SECRET}",
|
|
22
|
+
"CallbackPath": "/signin-oidc"
|
|
23
|
+
} }
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```csharp
|
|
27
|
+
// Program.cs
|
|
28
|
+
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
29
|
+
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
|
|
30
|
+
builder.Services.AddControllersWithViews().AddMicrosoftIdentityUI();
|
|
31
|
+
builder.Services.AddAuthorization();
|
|
32
|
+
app.UseAuthentication();
|
|
33
|
+
app.UseAuthorization();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Blazor Server
|
|
37
|
+
|
|
38
|
+
```csharp
|
|
39
|
+
// Additional setup
|
|
40
|
+
builder.Services.AddServerSideBlazor().AddMicrosoftIdentityConsentHandler();
|
|
41
|
+
|
|
42
|
+
// App.razor
|
|
43
|
+
<CascadingAuthenticationState>
|
|
44
|
+
<Router AppAssembly="@typeof(App).Assembly">
|
|
45
|
+
<Found Context="routeData">
|
|
46
|
+
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
|
|
47
|
+
<NotAuthorized>
|
|
48
|
+
@if (!context.User.Identity?.IsAuthenticated ?? true) { <RedirectToLogin /> }
|
|
49
|
+
else { <p>No permission.</p> }
|
|
50
|
+
</NotAuthorized>
|
|
51
|
+
</AuthorizeRouteView>
|
|
52
|
+
</Found>
|
|
53
|
+
</Router>
|
|
54
|
+
</CascadingAuthenticationState>
|
|
55
|
+
|
|
56
|
+
// RedirectToLogin.razor
|
|
57
|
+
@inject NavigationManager Nav
|
|
58
|
+
@code {
|
|
59
|
+
protected override void OnInitialized() =>
|
|
60
|
+
Nav.NavigateTo($"MicrosoftIdentity/Account/SignIn?redirectUri={Uri.EscapeDataString(Nav.Uri)}", forceLoad: true);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Protected Pages
|
|
65
|
+
|
|
66
|
+
```razor
|
|
67
|
+
@page "/secure"
|
|
68
|
+
@attribute [Authorize]
|
|
69
|
+
|
|
70
|
+
<AuthorizeView>
|
|
71
|
+
<Authorized>Welcome, @context.User.Identity?.Name!</Authorized>
|
|
72
|
+
</AuthorizeView>
|
|
73
|
+
|
|
74
|
+
<AuthorizeView Roles="Admin"><Authorized><AdminPanel /></Authorized></AuthorizeView>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## API Protection
|
|
78
|
+
|
|
79
|
+
```csharp
|
|
80
|
+
// API Program.cs
|
|
81
|
+
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
82
|
+
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
|
|
83
|
+
|
|
84
|
+
// Controller
|
|
85
|
+
[ApiController, Route("api/[controller]"), Authorize]
|
|
86
|
+
public class ProfileController : ControllerBase
|
|
87
|
+
{
|
|
88
|
+
[HttpGet]
|
|
89
|
+
public IActionResult GetProfile() => Ok(new {
|
|
90
|
+
UserId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value,
|
|
91
|
+
Name = User.Identity?.Name
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
[HttpGet("admin"), Authorize(Roles = "Admin")]
|
|
95
|
+
public IActionResult AdminOnly() => Ok("Admin access");
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Downstream APIs (Microsoft Graph)
|
|
100
|
+
|
|
101
|
+
```csharp
|
|
102
|
+
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
|
103
|
+
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
|
|
104
|
+
.EnableTokenAcquisitionToCallDownstreamApi()
|
|
105
|
+
.AddMicrosoftGraph(builder.Configuration.GetSection("Graph"))
|
|
106
|
+
.AddInMemoryTokenCaches();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Authorization Policies
|
|
110
|
+
|
|
111
|
+
```csharp
|
|
112
|
+
builder.Services.AddAuthorization(o => {
|
|
113
|
+
o.AddPolicy("RequireAdmin", p => p.RequireRole("Admin"));
|
|
114
|
+
o.AddPolicy("RequireManager", p => p.RequireAssertion(c =>
|
|
115
|
+
c.User.IsInRole("Admin") || c.User.IsInRole("Manager")));
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Multi-tenant & B2C
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
// Multi-tenant: TenantId = "common" or "organizations"
|
|
123
|
+
// Then validate allowed tenants in TokenValidationParameters.IssuerValidator
|
|
124
|
+
|
|
125
|
+
// B2C: Use "AzureAdB2C" section with SignUpSignInPolicyId, ResetPasswordPolicyId
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Checklist
|
|
129
|
+
|
|
130
|
+
- [ ] App registered in Azure Portal
|
|
131
|
+
- [ ] Client ID + Tenant ID configured
|
|
132
|
+
- [ ] Client Secret in Key Vault
|
|
133
|
+
- [ ] Redirect URIs configured
|
|
134
|
+
- [ ] API permissions defined
|
|
135
|
+
- [ ] Token caching configured
|
|
136
|
+
- [ ] Authorization policies created
|
|
137
|
+
- [ ] Logout flow implemented
|
|
138
|
+
- [ ] Token expiry error handling
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
*MORPH-SPEC by Polymorphism Tech*
|