@apexops/cli 0.10.0-next.5 → 0.11.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/capability-packs/registry.v1.json +1 -62
- package/assets/client-projection-metadata/copilot-cli-agent-tools.json +12 -0
- package/assets/client-projections/github-copilot-cli/.github/copilot/settings.json +13 -0
- package/assets/client-projections/github-copilot-cli/.github/instructions/apex-prompt-authoring.instructions.md +1 -1
- package/assets/client-projections/github-copilot-cli/.github/workflows/governance-policy-baseline.yml +101 -0
- package/assets/client-projections/github-copilot-cli/tools/schemas/governance-baseline.schema.json +118 -0
- package/assets/client-projections/github-copilot-cli/tools/scripts/collect-governance-baseline.ps1 +817 -0
- package/assets/config/capability-packs.v1.json +1 -32
- package/assets/config/governance-reference.v1.json +26379 -0
- package/assets/config/recipe-packs.v1.json +1 -26
- package/assets/config/runtime-bundle.v1.json +7 -7
- package/assets/config/toolchain.v1.json +35 -33
- package/assets/config/workflow.v1.json +103 -72
- package/assets/customizations/.github/agents/apex-codegen.agent.md +8 -22
- package/assets/customizations/.github/agents/apex-validator.agent.md +14 -20
- package/assets/customizations/.github/agents/apex.agent.md +108 -75
- package/assets/customizations/.github/copilot/settings.json +13 -0
- package/assets/customizations/.github/instructions/apex-prompt-authoring.instructions.md +1 -1
- package/assets/customizations/.github/skills/apex-architecture/SKILL.md +62 -18
- package/assets/customizations/.github/skills/apex-artifacts/SKILL.md +28 -6
- package/assets/customizations/.github/skills/apex-azure-adr/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-cloud-migrate/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-compliance/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-compute/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-cost-optimization/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-defaults/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-defaults/references/governance-effects.md +5 -3
- package/assets/customizations/.github/skills/apex-azure-deploy/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-diagnostics/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-governance/SKILL.md +19 -3
- package/assets/customizations/.github/skills/apex-azure-governance/references/evidence-interpretation.md +38 -3
- package/assets/customizations/.github/skills/apex-azure-kusto/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-prepare/SKILL.md +5 -3
- package/assets/customizations/.github/skills/apex-azure-quotas/SKILL.md +6 -2
- package/assets/customizations/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +4 -3
- package/assets/customizations/.github/skills/apex-azure-quotas/references/operational-checklist.md +3 -2
- package/assets/customizations/.github/skills/apex-azure-rbac/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-resources/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-storage/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-azure-validate/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-bicep-patterns/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-codegen/SKILL.md +6 -2
- package/assets/customizations/.github/skills/apex-entra-app-registration/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-mermaid/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-microsoft-docs/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-next/SKILL.md +99 -0
- package/assets/customizations/.github/skills/apex-operations/SKILL.md +46 -16
- package/assets/customizations/.github/skills/apex-planning/SKILL.md +48 -19
- package/assets/customizations/.github/skills/apex-requirements/SKILL.md +61 -26
- package/assets/customizations/.github/skills/apex-terraform-import/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-terraform-patterns/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-terraform-test/SKILL.md +3 -0
- package/assets/customizations/.github/skills/apex-unslop/LICENSE.txt +21 -0
- package/assets/customizations/.github/skills/apex-unslop/SKILL.md +94 -0
- package/assets/customizations/.github/skills/apex-workflow/SKILL.md +15 -5
- package/assets/customizations/.github/workflows/governance-policy-baseline.yml +101 -0
- package/assets/customizations/README.md +8 -9
- package/assets/customizations/manifest.json +167 -209
- package/assets/customizations/tools/schemas/governance-baseline.schema.json +118 -0
- package/assets/customizations/tools/scripts/collect-governance-baseline.ps1 +817 -0
- package/assets/manifest.json +423 -4241
- package/assets/schemas/governance-baseline.schema.json +118 -0
- package/dist/assets.d.ts +18 -2
- package/dist/assets.js +115 -35
- package/dist/bootstrap-wizard.d.ts +37 -0
- package/dist/bootstrap-wizard.js +259 -0
- package/dist/cli.d.ts +17 -2
- package/dist/cli.js +180 -63
- package/dist/dependency-revision.js +8 -0
- package/dist/errors.d.ts +6 -1
- package/dist/errors.js +55 -0
- package/dist/host-profile.d.ts +47 -0
- package/dist/host-profile.js +269 -0
- package/dist/mcp-output-schemas.d.ts +43 -0
- package/dist/mcp-output-schemas.js +279 -0
- package/dist/mcp-tool-effects.d.ts +101 -0
- package/dist/mcp-tool-effects.js +66 -0
- package/dist/mcp.d.ts +50 -3
- package/dist/mcp.js +800 -87
- package/dist/runtime-binding.d.ts +37 -0
- package/dist/runtime-binding.js +131 -0
- package/dist/service.d.ts +643 -38
- package/dist/service.js +4937 -662
- package/dist/state-transfer.js +21 -1
- package/dist/target-scope.d.ts +4 -0
- package/dist/target-scope.js +9 -0
- package/dist/version.d.ts +3 -1
- package/dist/version.js +19 -1
- package/dist/workflow-validators.d.ts +20 -3
- package/dist/workflow-validators.js +408 -67
- package/dist/workspace-root.d.ts +7 -0
- package/dist/workspace-root.js +67 -0
- package/package.json +11 -12
- package/assets/capability-packs/azure-governance-discovery/source/scripts/discover.py +0 -1189
- package/assets/capability-packs/azure-governance-discovery/source/scripts/render_governance.py +0 -676
- package/assets/client-projections/github-copilot-cli/.github/agents/apex-architect.agent.md +0 -91
- package/assets/client-projections/github-copilot-cli/.github/agents/apex-operator.agent.md +0 -75
- package/assets/client-projections/github-copilot-cli/.github/agents/apex-planner.agent.md +0 -88
- package/assets/client-projections/github-copilot-cli/.github/agents/apex-requirements.agent.md +0 -99
- package/assets/client-projections/github-copilot-cli/.github/agents/apex.agent.md +0 -88
- package/assets/client-projections/github-copilot-cli/.github/mcp.json +0 -65
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-architecture/SKILL.md +0 -36
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/SKILL.md +0 -65
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/references/presentation-conventions.md +0 -52
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/references/reference-only-outlines.md +0 -78
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/architecture-assessment.md +0 -35
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/cost-estimate.md +0 -47
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/deployment-summary.md +0 -35
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/governance-constraints.md +0 -35
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/implementation-plan.md +0 -43
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/operations-runbook.md +0 -35
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/requirements.md +0 -42
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/resource-inventory.md +0 -29
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/SKILL.md +0 -52
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-examples.md +0 -38
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-guardrails.md +0 -36
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-quality.md +0 -21
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-record-fields.md +0 -57
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/SKILL.md +0 -55
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/lambda-to-functions-assessment.md +0 -29
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/migration-readiness.md +0 -27
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/staged-validation-handoff.md +0 -26
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/workload-mapping.md +0 -27
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/SKILL.md +0 -58
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/references/compliance-finding-criteria.md +0 -63
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/SKILL.md +0 -36
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/compute-selection.md +0 -26
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/pricing-evidence.md +0 -11
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/recommendation-and-scale-rules.md +0 -44
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/SKILL.md +0 -61
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/references/cost-assessment-criteria.md +0 -61
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/SKILL.md +0 -59
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/avm-binding-guidance.md +0 -29
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/baseline-fallbacks.md +0 -53
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/cost-monitoring.md +0 -47
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/decision-boundaries.md +0 -19
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/governance-effects.md +0 -28
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/naming.md +0 -47
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/network-planning.md +0 -47
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/security-baseline.md +0 -40
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/service-selection.md +0 -51
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/tag-precedence.md +0 -31
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/SKILL.md +0 -50
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/references/operational-checklist.md +0 -26
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/references/preview-recovery-verification.md +0 -48
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/SKILL.md +0 -60
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/references/diagnostic-interpretation.md +0 -42
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/SKILL.md +0 -52
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/references/evidence-interpretation.md +0 -58
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/references/operational-checklist.md +0 -25
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/SKILL.md +0 -58
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/references/kql-evidence-interpretation.md +0 -41
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/references/operational-checklist.md +0 -25
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/SKILL.md +0 -52
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/references/preparation-lineage.md +0 -36
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/SKILL.md +0 -53
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +0 -48
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/references/operational-checklist.md +0 -23
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/SKILL.md +0 -45
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/references/assignment-intent.md +0 -39
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/references/least-privilege-selection.md +0 -50
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/SKILL.md +0 -54
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/references/inventory-query-patterns.md +0 -49
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/SKILL.md +0 -35
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/security-and-governance.md +0 -12
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/service-auth-and-sdk-boundary.md +0 -33
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/storage-selection.md +0 -12
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/SKILL.md +0 -49
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/references/preflight-evidence.md +0 -43
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/SKILL.md +0 -41
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/avm-and-codegen-acceptance.md +0 -11
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/codegen-acceptance-checklist.md +0 -46
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/compiler-and-provider-gotchas.md +0 -74
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/module-interfaces-and-parameters.md +0 -56
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/network-and-observability.md +0 -52
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-codegen/SKILL.md +0 -32
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/SKILL.md +0 -53
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/capability-receipts.md +0 -21
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/design-and-diagnostics.md +0 -36
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/oauth-registration-model.md +0 -26
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/permissions-and-credentials.md +0 -27
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/SKILL.md +0 -44
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/references/styling.md +0 -33
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/references/syntax.md +0 -99
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-microsoft-docs/SKILL.md +0 -53
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-microsoft-docs/references/research-method.md +0 -91
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-operations/SKILL.md +0 -34
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-planning/SKILL.md +0 -36
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-requirements/SKILL.md +0 -46
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/SKILL.md +0 -47
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/adoption-attestation.md +0 -10
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/import-assessment.md +0 -14
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/import-mapping.md +0 -27
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/mapping-and-adoption-attestation.md +0 -12
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/SKILL.md +0 -49
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-composition-and-refactor.md +0 -20
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-composition-and-state-boundaries.md +0 -11
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-locks-and-codegen-acceptance.md +0 -14
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/network-and-observability.md +0 -12
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/plan-and-change-assessment.md +0 -24
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/SKILL.md +0 -45
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/evidence-acceptance.md +0 -10
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/plan-mode-and-mock-design.md +0 -12
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/plan-mode-test-design.md +0 -23
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/test-design.md +0 -13
- package/assets/client-projections/github-copilot-cli/.github/skills/apex-workflow/SKILL.md +0 -37
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-architect.agent.md +0 -100
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-codegen.agent.md +0 -62
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-operator.agent.md +0 -79
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-planner.agent.md +0 -98
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-requirements.agent.md +0 -108
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-reviewer.agent.md +0 -63
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex-validator.agent.md +0 -61
- package/assets/client-projections/github-copilot-vscode/.github/agents/apex.agent.md +0 -107
- package/assets/client-projections/github-copilot-vscode/.github/copilot-instructions.md +0 -13
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-agent-authoring.instructions.md +0 -14
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-artifact-contracts.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-automation.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-azure-yaml.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-bicep.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-code-quality.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-context.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-documentation.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-governance.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-instruction-authoring.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-javascript.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-json.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-markdown.instructions.md +0 -13
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-powershell.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-prompt-authoring.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-python.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-safe-file-edits.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-safe-shell.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-shell.instructions.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-skill-authoring.instructions.md +0 -13
- package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-terraform.instructions.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-architecture/SKILL.md +0 -36
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/SKILL.md +0 -65
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/references/presentation-conventions.md +0 -52
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/references/reference-only-outlines.md +0 -78
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/architecture-assessment.md +0 -35
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/cost-estimate.md +0 -47
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/deployment-summary.md +0 -35
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/governance-constraints.md +0 -35
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/implementation-plan.md +0 -43
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/operations-runbook.md +0 -35
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/requirements.md +0 -42
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/resource-inventory.md +0 -29
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/SKILL.md +0 -52
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-examples.md +0 -38
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-guardrails.md +0 -36
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-quality.md +0 -21
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-record-fields.md +0 -57
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/SKILL.md +0 -55
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/lambda-to-functions-assessment.md +0 -29
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/migration-readiness.md +0 -27
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/staged-validation-handoff.md +0 -26
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/workload-mapping.md +0 -27
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/SKILL.md +0 -58
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/references/compliance-finding-criteria.md +0 -63
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/SKILL.md +0 -36
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/compute-selection.md +0 -26
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/pricing-evidence.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/recommendation-and-scale-rules.md +0 -44
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/SKILL.md +0 -61
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/references/cost-assessment-criteria.md +0 -61
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/SKILL.md +0 -59
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/avm-binding-guidance.md +0 -29
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/baseline-fallbacks.md +0 -53
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/cost-monitoring.md +0 -47
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/decision-boundaries.md +0 -19
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/governance-effects.md +0 -28
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/naming.md +0 -47
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/network-planning.md +0 -47
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/security-baseline.md +0 -40
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/service-selection.md +0 -51
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/tag-precedence.md +0 -31
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/SKILL.md +0 -50
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/references/operational-checklist.md +0 -26
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/references/preview-recovery-verification.md +0 -48
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/SKILL.md +0 -60
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/references/diagnostic-interpretation.md +0 -42
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/SKILL.md +0 -52
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/references/evidence-interpretation.md +0 -58
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/references/operational-checklist.md +0 -25
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/SKILL.md +0 -58
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/references/kql-evidence-interpretation.md +0 -41
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/references/operational-checklist.md +0 -25
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/SKILL.md +0 -52
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/references/preparation-lineage.md +0 -36
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/SKILL.md +0 -53
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +0 -48
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/references/operational-checklist.md +0 -23
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/SKILL.md +0 -45
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/references/assignment-intent.md +0 -39
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/references/least-privilege-selection.md +0 -50
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/SKILL.md +0 -54
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/references/inventory-query-patterns.md +0 -49
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/SKILL.md +0 -35
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/security-and-governance.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/service-auth-and-sdk-boundary.md +0 -33
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/storage-selection.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/SKILL.md +0 -49
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/references/operational-checklist.md +0 -24
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/references/preflight-evidence.md +0 -43
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/SKILL.md +0 -41
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/avm-and-codegen-acceptance.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/codegen-acceptance-checklist.md +0 -46
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/compiler-and-provider-gotchas.md +0 -74
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/module-interfaces-and-parameters.md +0 -56
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/network-and-observability.md +0 -52
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-codegen/SKILL.md +0 -32
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/SKILL.md +0 -53
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/capability-receipts.md +0 -21
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/design-and-diagnostics.md +0 -36
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/oauth-registration-model.md +0 -26
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/permissions-and-credentials.md +0 -27
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/SKILL.md +0 -44
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/references/styling.md +0 -33
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/references/syntax.md +0 -99
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-microsoft-docs/SKILL.md +0 -53
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-microsoft-docs/references/research-method.md +0 -91
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-operations/SKILL.md +0 -34
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-planning/SKILL.md +0 -36
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-requirements/SKILL.md +0 -46
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/SKILL.md +0 -47
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/adoption-attestation.md +0 -10
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/import-assessment.md +0 -14
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/import-mapping.md +0 -27
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/mapping-and-adoption-attestation.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/SKILL.md +0 -49
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-composition-and-refactor.md +0 -20
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-composition-and-state-boundaries.md +0 -11
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-locks-and-codegen-acceptance.md +0 -14
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/network-and-observability.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/plan-and-change-assessment.md +0 -24
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/SKILL.md +0 -45
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/evidence-acceptance.md +0 -10
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/plan-mode-and-mock-design.md +0 -12
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/plan-mode-test-design.md +0 -23
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/test-design.md +0 -13
- package/assets/client-projections/github-copilot-vscode/.github/skills/apex-workflow/SKILL.md +0 -37
- package/assets/client-projections/github-copilot-vscode/.vscode/mcp.json +0 -29
- package/assets/customizations/.github/agents/apex-architect.agent.md +0 -93
- package/assets/customizations/.github/agents/apex-operator.agent.md +0 -72
- package/assets/customizations/.github/agents/apex-planner.agent.md +0 -91
- package/assets/customizations/.github/agents/apex-requirements.agent.md +0 -101
- package/assets/customizations/.github/agents/apex-reviewer.agent.md +0 -60
- package/assets/customizations/.github/mcp.json +0 -65
- package/assets/customizations/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
- package/assets/customizations/.vscode/mcp.json +0 -29
- package/dist/azure-mcp-environment.d.ts +0 -2
- package/dist/azure-mcp-environment.js +0 -7
- package/dist/azure-mcp.d.ts +0 -2
- package/dist/azure-mcp.js +0 -21
package/assets/capability-packs/azure-governance-discovery/source/scripts/render_governance.py
DELETED
|
@@ -1,676 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# ruff: noqa: E501
|
|
3
|
-
"""Shared governance preview renderer.
|
|
4
|
-
|
|
5
|
-
Extracted from discover.py so both live discovery and cached-baseline
|
|
6
|
-
rendering use the same artifact generator. This module has NO Azure
|
|
7
|
-
dependencies — it only reads an in-memory governance-constraints-v1
|
|
8
|
-
envelope and writes Markdown.
|
|
9
|
-
"""
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import hashlib
|
|
13
|
-
import json
|
|
14
|
-
import re
|
|
15
|
-
from datetime import datetime, timezone
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
from typing import Any
|
|
18
|
-
|
|
19
|
-
# --------------------------------------------------------------------------- #
|
|
20
|
-
# Shared L0 envelope helpers #
|
|
21
|
-
# #
|
|
22
|
-
# These are the canonical implementations consumed by BOTH discover.py #
|
|
23
|
-
# (live path) and render_cached_governance.py (cached baseline path). The #
|
|
24
|
-
# `completeness_signature` MUST be byte-identical for the same upstream #
|
|
25
|
-
# findings set across both paths — that invariant is the foundation of the #
|
|
26
|
-
# Phase 4 resume short-circuit + Phase 8 challenger guard, and is regression #
|
|
27
|
-
# tested in `test_signature_parity.py`. #
|
|
28
|
-
# --------------------------------------------------------------------------- #
|
|
29
|
-
|
|
30
|
-
# L0 envelope: staleness threshold (days). Downstream consumers (Planner,
|
|
31
|
-
# CodeGen, Deploy) treat envelopes older than this as STALE and refuse to
|
|
32
|
-
# proceed without a fresh `--refresh` discovery.
|
|
33
|
-
DEFAULT_TTL_DAYS = 7
|
|
34
|
-
|
|
35
|
-
# API versions emitted into discovery_metadata.api_versions. Keep in sync
|
|
36
|
-
# with the ARM REST calls in discover.py — these constants are the single
|
|
37
|
-
# source of truth for both the live path and any cached-baseline synthesis
|
|
38
|
-
# that needs to claim the version it was originally collected against.
|
|
39
|
-
API_ASSIGNMENTS = "2022-06-01"
|
|
40
|
-
API_DEFINITIONS = "2021-06-01"
|
|
41
|
-
API_EXEMPTIONS = "2022-07-01-preview"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _completeness_signature(findings: list[dict[str, Any]]) -> str:
|
|
45
|
-
"""Return a deterministic sha256 over the stable-sorted policy tuples.
|
|
46
|
-
|
|
47
|
-
The signature is the L0 attestation used by downstream consumers
|
|
48
|
-
(Planner, CodeGen, Deploy) to detect that a constraints file has
|
|
49
|
-
drifted from the snapshot they validated against. Algorithm:
|
|
50
|
-
|
|
51
|
-
1. Build `(policy_id, effect, scope, params)` tuples for each finding.
|
|
52
|
-
2. Sort by `policy_id`.
|
|
53
|
-
3. Serialise each tuple as a compact JSON object with sorted keys.
|
|
54
|
-
4. Join with `\\n` and sha256.
|
|
55
|
-
"""
|
|
56
|
-
tuples: list[dict[str, Any]] = []
|
|
57
|
-
for f in findings:
|
|
58
|
-
tuples.append(
|
|
59
|
-
{
|
|
60
|
-
"policy_id": f.get("policy_id") or "",
|
|
61
|
-
"effect": f.get("effect") or "",
|
|
62
|
-
"scope": f.get("scope") or "",
|
|
63
|
-
"params": f.get("assignment_parameters") or {},
|
|
64
|
-
}
|
|
65
|
-
)
|
|
66
|
-
tuples.sort(key=lambda t: t["policy_id"])
|
|
67
|
-
serialized = "\n".join(json.dumps(t, sort_keys=True, separators=(",", ":")) for t in tuples)
|
|
68
|
-
return "sha256:" + hashlib.sha256(serialized.encode("utf-8")).hexdigest()
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def _extract_management_groups(kept_assignments: list[dict[str, Any]]) -> list[str]:
|
|
72
|
-
"""Return MG ancestry referenced by kept assignment scopes (ordered)."""
|
|
73
|
-
seen: dict[str, None] = {}
|
|
74
|
-
for a in kept_assignments:
|
|
75
|
-
scope = ((a.get("properties") or {}).get("scope") or "").lower()
|
|
76
|
-
marker = "/providers/microsoft.management/managementgroups/"
|
|
77
|
-
if marker not in scope:
|
|
78
|
-
continue
|
|
79
|
-
mg = scope.split(marker, 1)[1].split("/", 1)[0]
|
|
80
|
-
if mg and mg not in seen:
|
|
81
|
-
seen[mg] = None
|
|
82
|
-
return list(seen.keys())
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def _build_discovery_metadata(
|
|
86
|
-
*,
|
|
87
|
-
findings: list[dict[str, Any]],
|
|
88
|
-
subscription_id: str,
|
|
89
|
-
management_groups: list[str],
|
|
90
|
-
page_counts: dict[str, int],
|
|
91
|
-
discovered_at: str,
|
|
92
|
-
discovery_status: str = "COMPLETE",
|
|
93
|
-
ttl_days: int = DEFAULT_TTL_DAYS,
|
|
94
|
-
source: str = "live", # noqa: ARG001 — reserved for future per-source attestation; envelope-level `source` is the consumer-facing field
|
|
95
|
-
api_versions: dict[str, str] | None = None,
|
|
96
|
-
) -> dict[str, Any]:
|
|
97
|
-
"""Compose the L0 `discovery_metadata` envelope.
|
|
98
|
-
|
|
99
|
-
Used by both discover.py (live path, `source="live"`) and the cached
|
|
100
|
-
renderer (`source="github-actions-baseline"`). The returned dict is
|
|
101
|
-
byte-for-byte deterministic given the same inputs — the parity test
|
|
102
|
-
asserts this across both call sites.
|
|
103
|
-
|
|
104
|
-
`source` is currently informational; it is parameterised so future
|
|
105
|
-
revisions can record per-attestation provenance without changing
|
|
106
|
-
the helper signature. The envelope's top-level `source` field is
|
|
107
|
-
what consumers actually read today.
|
|
108
|
-
"""
|
|
109
|
-
return {
|
|
110
|
-
"discovery_status": discovery_status,
|
|
111
|
-
"discovered_at": discovered_at,
|
|
112
|
-
"scope": {
|
|
113
|
-
"subscription_id": subscription_id,
|
|
114
|
-
"management_groups": list(management_groups),
|
|
115
|
-
},
|
|
116
|
-
"api_versions": dict(
|
|
117
|
-
api_versions
|
|
118
|
-
or {
|
|
119
|
-
"policyAssignments": API_ASSIGNMENTS,
|
|
120
|
-
"policyDefinitions": API_DEFINITIONS,
|
|
121
|
-
"policyExemptions": API_EXEMPTIONS,
|
|
122
|
-
}
|
|
123
|
-
),
|
|
124
|
-
"page_counts": dict(page_counts),
|
|
125
|
-
"completeness_signature": _completeness_signature(findings),
|
|
126
|
-
"ttl_days": ttl_days,
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def _utc_now_iso() -> str:
|
|
131
|
-
"""Return the current UTC instant in the ISO-8601 form used by discover.py."""
|
|
132
|
-
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# --------------------------------------------------------------------------- #
|
|
136
|
-
# Preview renderer (Markdown generation) #
|
|
137
|
-
# --------------------------------------------------------------------------- #
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def _infer_project_from_path(out_path: Path) -> str:
|
|
141
|
-
"""Infer project name from the output path (e.g. agent-output/test/04-...).
|
|
142
|
-
|
|
143
|
-
Falls back to 'unknown' if the path doesn't match the expected structure.
|
|
144
|
-
"""
|
|
145
|
-
# Expect: .../agent-output/{project}/04-governance-constraints.json
|
|
146
|
-
parts = out_path.parts
|
|
147
|
-
for i, p in enumerate(parts):
|
|
148
|
-
if p == "agent-output" and i + 1 < len(parts):
|
|
149
|
-
return parts[i + 1]
|
|
150
|
-
return "unknown"
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
def _split_tags(tags_required: list[dict[str, Any]]) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
154
|
-
"""Split tags into resolved and unresolved lists.
|
|
155
|
-
|
|
156
|
-
Resolved tags have actual key names (e.g. 'Environment').
|
|
157
|
-
Unresolved tags carry '[unresolved: ...]' markers from the collector.
|
|
158
|
-
"""
|
|
159
|
-
resolved = []
|
|
160
|
-
unresolved = []
|
|
161
|
-
for t in tags_required:
|
|
162
|
-
name = t.get("name", "")
|
|
163
|
-
if t.get("unresolved") or name.startswith("[unresolved"):
|
|
164
|
-
# Try to extract parameter-based tag names from assignment_parameters
|
|
165
|
-
params = t.get("assignment_parameters", {})
|
|
166
|
-
tag_params = {k: v for k, v in params.items() if k.startswith("tagName") and isinstance(v, str)}
|
|
167
|
-
if tag_params:
|
|
168
|
-
for _key, tag_name in sorted(tag_params.items()):
|
|
169
|
-
resolved.append({"name": tag_name, **{k: v for k, v in t.items() if k != "name"}})
|
|
170
|
-
else:
|
|
171
|
-
unresolved.append(t)
|
|
172
|
-
else:
|
|
173
|
-
resolved.append(t)
|
|
174
|
-
return resolved, unresolved
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def _extract_constraint_value(finding: dict[str, Any]) -> str | None:
|
|
178
|
-
"""Extract the actual constraint value from assignment_parameters or required_value.
|
|
179
|
-
|
|
180
|
-
Returns a human-readable string summarising the constraint, or None.
|
|
181
|
-
"""
|
|
182
|
-
# Prefer explicit required_value if present (including boolean False)
|
|
183
|
-
rv = finding.get("required_value")
|
|
184
|
-
if rv is not None and rv != "":
|
|
185
|
-
if isinstance(rv, bool):
|
|
186
|
-
return str(rv).lower()
|
|
187
|
-
if isinstance(rv, list):
|
|
188
|
-
return ", ".join(str(v) for v in rv[:20])
|
|
189
|
-
return str(rv)
|
|
190
|
-
|
|
191
|
-
params = finding.get("assignment_parameters") or {}
|
|
192
|
-
for pname, pval in params.items():
|
|
193
|
-
# Skip effect overrides: "effect", "Effect", "*MonitoringEffect", "*AppMonitoringEffect", etc.
|
|
194
|
-
if pname.lower().endswith("effect"):
|
|
195
|
-
continue
|
|
196
|
-
if isinstance(pval, list) and pval:
|
|
197
|
-
# Truncate to 20 items for readability
|
|
198
|
-
items = [str(v) for v in pval[:20]]
|
|
199
|
-
suffix = f" … +{len(pval) - 20} more" if len(pval) > 20 else ""
|
|
200
|
-
return ", ".join(items) + suffix
|
|
201
|
-
if isinstance(pval, (str, int, float, bool)) and pval not in (None, ""):
|
|
202
|
-
return str(pval)
|
|
203
|
-
return None
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
def _dedup_blockers(blockers: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
207
|
-
"""Deduplicate blockers that share policy semantics across scopes.
|
|
208
|
-
|
|
209
|
-
Returns a list of representative blockers with a 'scopes' list
|
|
210
|
-
and merged assignment_parameters from all instances.
|
|
211
|
-
"""
|
|
212
|
-
from collections import OrderedDict
|
|
213
|
-
groups: OrderedDict[tuple[str, str, str], list[dict[str, Any]]] = OrderedDict()
|
|
214
|
-
for b in blockers:
|
|
215
|
-
key = (
|
|
216
|
-
b.get("display_name", ""),
|
|
217
|
-
b.get("policy_id", ""),
|
|
218
|
-
json.dumps(b.get("assignment_parameters") or {}, sort_keys=True, separators=(",", ":")),
|
|
219
|
-
)
|
|
220
|
-
groups.setdefault(key, []).append(b)
|
|
221
|
-
|
|
222
|
-
deduped: list[dict[str, Any]] = []
|
|
223
|
-
for _key, items in groups.items():
|
|
224
|
-
rep = dict(items[0]) # shallow copy of first instance
|
|
225
|
-
rep["_scopes"] = [it.get("scope", "") for it in items]
|
|
226
|
-
# Merge assignment_parameters from all instances (first non-empty wins per key)
|
|
227
|
-
merged_params: dict[str, Any] = {}
|
|
228
|
-
for it in items:
|
|
229
|
-
for k, v in (it.get("assignment_parameters") or {}).items():
|
|
230
|
-
if k not in merged_params and v is not None and v != "":
|
|
231
|
-
merged_params[k] = v
|
|
232
|
-
if merged_params:
|
|
233
|
-
rep["assignment_parameters"] = merged_params
|
|
234
|
-
deduped.append(rep)
|
|
235
|
-
return deduped
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def extract_arch_resources(arch_path: str | Path) -> list[dict[str, str]]:
|
|
239
|
-
"""Extract Azure resource types from 02-architecture-assessment.md.
|
|
240
|
-
|
|
241
|
-
Scans for ARM resource type patterns (Microsoft.{Provider}/{Type}) and
|
|
242
|
-
returns a list of {name, arm_type} dicts. Used to pre-populate
|
|
243
|
-
policy→resource mapping in preview.md.
|
|
244
|
-
"""
|
|
245
|
-
arch_path = Path(arch_path)
|
|
246
|
-
if not arch_path.exists():
|
|
247
|
-
return []
|
|
248
|
-
text = arch_path.read_text(errors="replace")
|
|
249
|
-
# Match ARM types like Microsoft.Compute/virtualMachines
|
|
250
|
-
arm_pattern = re.compile(r"Microsoft\.\w+/\w+(?:/\w+)?")
|
|
251
|
-
types_found = sorted(set(arm_pattern.findall(text)))
|
|
252
|
-
# Also extract resource names from Mermaid diagrams or SKU tables
|
|
253
|
-
# Pattern: common name labels like "vm-iis-01", "sql-...", "vnet-..."
|
|
254
|
-
name_pattern = re.compile(r"(?:vm|sql|vnet|kv|st|app|pip|lb|nsg|nic|pe|natgw|log|acr|aks)-[\w-]+", re.IGNORECASE)
|
|
255
|
-
names_found = sorted(set(name_pattern.findall(text)))
|
|
256
|
-
resources: list[dict[str, str]] = []
|
|
257
|
-
for t in types_found:
|
|
258
|
-
resources.append({"arm_type": t, "name": t.split("/")[-1]})
|
|
259
|
-
for n in names_found:
|
|
260
|
-
if not any(r["name"] == n for r in resources):
|
|
261
|
-
resources.append({"arm_type": "", "name": n})
|
|
262
|
-
return resources
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
def emit_preview_md(envelope: dict[str, Any], out_path: Path, arch_resources: list[dict[str, str]] | None = None) -> Path | None:
|
|
266
|
-
"""Write a sibling `.preview.md` with H2 structure matching the template.
|
|
267
|
-
|
|
268
|
-
The agent copies this to `04-governance-constraints.md` and annotates
|
|
269
|
-
placeholder sections only — avoiding the slow mega-patch generation.
|
|
270
|
-
|
|
271
|
-
If `arch_resources` is provided (from `--arch`), the preview includes a
|
|
272
|
-
pre-populated policy→architecture resource mapping table under
|
|
273
|
-
"Plan Adaptations → Architectural Changes".
|
|
274
|
-
"""
|
|
275
|
-
preview_path = out_path.with_suffix(".preview.md")
|
|
276
|
-
project = envelope.get("project") or _infer_project_from_path(out_path)
|
|
277
|
-
summary = envelope.get("discovery_summary", {})
|
|
278
|
-
findings = envelope.get("findings", [])
|
|
279
|
-
tags_required = envelope.get("tags_required", [])
|
|
280
|
-
discovered_at = envelope.get("discovered_at", "")
|
|
281
|
-
has_arch = arch_resources is not None and len(arch_resources) > 0
|
|
282
|
-
|
|
283
|
-
# Normalize null property paths to "" (schema requires string, not null)
|
|
284
|
-
for f in findings:
|
|
285
|
-
if f.get("azurePropertyPath") is None:
|
|
286
|
-
f["azurePropertyPath"] = ""
|
|
287
|
-
if f.get("bicepPropertyPath") is None:
|
|
288
|
-
f["bicepPropertyPath"] = ""
|
|
289
|
-
|
|
290
|
-
# Deduplicate identical findings (same display_name + scope + policy_id) that arise
|
|
291
|
-
# when the same policy is inherited at multiple MG levels with identical parameters.
|
|
292
|
-
_seen_keys: set[tuple[str, ...]] = set()
|
|
293
|
-
deduped_findings: list[dict[str, Any]] = []
|
|
294
|
-
for f in findings:
|
|
295
|
-
key = (
|
|
296
|
-
f.get("display_name", ""),
|
|
297
|
-
f.get("scope", ""),
|
|
298
|
-
f.get("policy_id", ""),
|
|
299
|
-
json.dumps(f.get("assignment_parameters") or {}, sort_keys=True, separators=(",", ":")),
|
|
300
|
-
)
|
|
301
|
-
if key not in _seen_keys:
|
|
302
|
-
_seen_keys.add(key)
|
|
303
|
-
deduped_findings.append(f)
|
|
304
|
-
findings = deduped_findings
|
|
305
|
-
|
|
306
|
-
blockers = [f for f in findings if f.get("classification") == "blocker"]
|
|
307
|
-
auto_remediate = [f for f in findings if f.get("classification") == "auto-remediate"]
|
|
308
|
-
# Group by category for security/network/cost sections
|
|
309
|
-
by_category: dict[str, list[dict[str, Any]]] = {}
|
|
310
|
-
for f in findings:
|
|
311
|
-
cat = (f.get("category") or "Uncategorized").strip()
|
|
312
|
-
by_category.setdefault(cat, []).append(f)
|
|
313
|
-
|
|
314
|
-
# Pre-build security list (with keyword expansion) so Discovery Source count is accurate.
|
|
315
|
-
_security_keywords = {"SFI-", "Safe Secrets", "Key Vault", "Purge Protection", "TLS", "HTTPS", "SSL"}
|
|
316
|
-
security: list[dict[str, Any]] = list(by_category.get("Security", []))
|
|
317
|
-
for _f in findings:
|
|
318
|
-
if _f not in security and any(kw in (_f.get("display_name") or "") for kw in _security_keywords):
|
|
319
|
-
security.append(_f)
|
|
320
|
-
|
|
321
|
-
lines: list[str] = []
|
|
322
|
-
a = lines.append
|
|
323
|
-
|
|
324
|
-
# Header + badge row
|
|
325
|
-
a(f"# 🛡️ Governance Constraints - {project}\n")
|
|
326
|
-
a("")
|
|
327
|
-
a("")
|
|
328
|
-
a("\n")
|
|
329
|
-
|
|
330
|
-
# TOC
|
|
331
|
-
a("<details open>")
|
|
332
|
-
a("<summary><strong>📑 Governance Contents</strong></summary>\n")
|
|
333
|
-
a("- [🔍 Discovery Source](#-discovery-source)")
|
|
334
|
-
a("- [📋 Azure Policy Compliance](#-azure-policy-compliance)")
|
|
335
|
-
a("- [🔄 Plan Adaptations Based on Policies](#-plan-adaptations-based-on-policies)")
|
|
336
|
-
a("- [🚫 Deployment Blockers](#-deployment-blockers)")
|
|
337
|
-
a("- [🏷️ Required Tags](#-required-tags)")
|
|
338
|
-
a("- [🔐 Security Policies](#-security-policies)")
|
|
339
|
-
a("- [💰 Cost Policies](#-cost-policies)")
|
|
340
|
-
a("- [🌐 Network Policies](#-network-policies)")
|
|
341
|
-
a("- [📜 Compliance Frameworks](#-compliance-frameworks)")
|
|
342
|
-
a("- [References](#references)\n")
|
|
343
|
-
a("</details>\n")
|
|
344
|
-
|
|
345
|
-
a(f"> Generated by 04g-Governance agent | {discovered_at}\n")
|
|
346
|
-
|
|
347
|
-
# Cross-nav
|
|
348
|
-
a("| ⬅️ Previous | 📑 Index | Next ➡️ |")
|
|
349
|
-
a("| --- | --- | --- |")
|
|
350
|
-
a("| [02-architecture-assessment.md](02-architecture-assessment.md) | [README](README.md) | [04-implementation-plan.md](04-implementation-plan.md) |\n")
|
|
351
|
-
|
|
352
|
-
# Discovery Source
|
|
353
|
-
a("## 🔍 Discovery Source\n")
|
|
354
|
-
a("| Query | Results | Timestamp |")
|
|
355
|
-
a("| --- | --- | --- |")
|
|
356
|
-
a(f"| Policy Assignments | {summary.get('assignment_kept', 0)} policies discovered | {discovered_at} |")
|
|
357
|
-
a(f"| Tag Policies | {len(tags_required)} tags required | {discovered_at} |")
|
|
358
|
-
a(f"| Security Policies | {len(security)} constraints | {discovered_at} |\n")
|
|
359
|
-
is_cached = envelope.get("source") == "cached_baseline" or envelope.get("cached_baseline", False)
|
|
360
|
-
discovery_method = "Cached governance baseline (governance-policy-baseline.json)" if is_cached else "Azure Policy REST API (discover.py)"
|
|
361
|
-
a(f"**Discovery Method**: {discovery_method}")
|
|
362
|
-
a(f"**Subscription**: {envelope.get('subscription_id', 'unknown')}")
|
|
363
|
-
a(f"**Scope**: Subscription + management-group inherited\n")
|
|
364
|
-
if blockers:
|
|
365
|
-
a(f"> ⚠️ **{len(blockers)} deployment blocker(s)** detected. Review the [Deployment Blockers](#-deployment-blockers) section before proceeding to IaC planning.\n")
|
|
366
|
-
|
|
367
|
-
# Policy Definition Analysis table
|
|
368
|
-
a("### Policy Definition Analysis\n")
|
|
369
|
-
a("| Policy Display Name | Assignment Scope | Effect | Classification | Category | Bicep Property Path | Required Value |")
|
|
370
|
-
a("| --- | --- | --- | --- | --- | --- | --- |")
|
|
371
|
-
for f in findings:
|
|
372
|
-
constraint = _extract_constraint_value(f) or ""
|
|
373
|
-
bpp = f.get("bicepPropertyPath", "")
|
|
374
|
-
# For policies that only check resource type (bpp == "type"), clarify
|
|
375
|
-
if bpp == "type":
|
|
376
|
-
bpp = "type (resource-type constraint)"
|
|
377
|
-
a(f"| {f.get('display_name', '')} | {f.get('scope', '')} | {f.get('effect', '')} "
|
|
378
|
-
f"| {f.get('classification', '')} | {f.get('category', '')} "
|
|
379
|
-
f"| {bpp} | {constraint} |")
|
|
380
|
-
a("")
|
|
381
|
-
|
|
382
|
-
# Azure Policy Compliance
|
|
383
|
-
a("## 📋 Azure Policy Compliance\n")
|
|
384
|
-
if not has_arch:
|
|
385
|
-
a("> **Note**: No architecture assessment provided. IaC impact annotations will be populated during Step 4 (IaC Planning).\n")
|
|
386
|
-
a("| Category | Constraint | Implementation | Status |")
|
|
387
|
-
a("| --- | --- | --- | --- |")
|
|
388
|
-
# Implementation column is descriptive (not prescriptive): when an
|
|
389
|
-
# architecture is provided we redirect the reader to the structured JSON
|
|
390
|
-
# rather than emit an annotation placeholder the agent has to fill in.
|
|
391
|
-
# See plan-optimiseGovernanceAgent.prompt.md Phase 2.
|
|
392
|
-
for cat, items in sorted(by_category.items()):
|
|
393
|
-
for f in items:
|
|
394
|
-
cls = f.get("classification", "")
|
|
395
|
-
if cls == "blocker":
|
|
396
|
-
status_icon = "❌"
|
|
397
|
-
impl = (
|
|
398
|
-
"Blocked — must comply before deployment"
|
|
399
|
-
if not has_arch
|
|
400
|
-
else "See JSON findings[] for structured value."
|
|
401
|
-
)
|
|
402
|
-
elif cls == "auto-remediate":
|
|
403
|
-
status_icon = "✅"
|
|
404
|
-
impl = (
|
|
405
|
-
"Auto-applied by Azure Policy"
|
|
406
|
-
if not has_arch
|
|
407
|
-
else "See JSON findings[] for structured value."
|
|
408
|
-
)
|
|
409
|
-
else:
|
|
410
|
-
status_icon = "⚠️"
|
|
411
|
-
impl = (
|
|
412
|
-
"Audit only — no enforcement"
|
|
413
|
-
if not has_arch
|
|
414
|
-
else "See JSON findings[] for structured value."
|
|
415
|
-
)
|
|
416
|
-
a(f"| {cat} | {f.get('display_name', '')} | {impl} | {status_icon} |")
|
|
417
|
-
a("")
|
|
418
|
-
|
|
419
|
-
# Plan Adaptations
|
|
420
|
-
a("## 🔄 Plan Adaptations Based on Policies\n")
|
|
421
|
-
|
|
422
|
-
# Architectural Changes — pre-populated policy→resource mapping
|
|
423
|
-
a("### Architectural Changes\n")
|
|
424
|
-
if blockers and arch_resources:
|
|
425
|
-
a("| Original Design | Blocking Policy | Effect | Target Resource Types | Adaptation Applied |")
|
|
426
|
-
a("| --- | --- | --- | --- | --- |")
|
|
427
|
-
# Descriptive (not prescriptive) per-row text — the renderer no longer
|
|
428
|
-
# claims annotation work the agent has not done. See plan-
|
|
429
|
-
# optimiseGovernanceAgent.prompt.md Phase 2 for the rationale.
|
|
430
|
-
for f in blockers:
|
|
431
|
-
f_types = set(f.get("resource_types", []))
|
|
432
|
-
matched = [r for r in arch_resources if r.get("arm_type", "") in f_types]
|
|
433
|
-
adaptation_note = (
|
|
434
|
-
"Deny effect — Step 4 must map to an explicit IaC control "
|
|
435
|
-
"or document an exception."
|
|
436
|
-
)
|
|
437
|
-
if matched:
|
|
438
|
-
for r in matched:
|
|
439
|
-
a(f"| {r.get('name', '')} ({r.get('arm_type', '')}) "
|
|
440
|
-
f"| {f.get('display_name', '')} | {f.get('effect', '')} "
|
|
441
|
-
f"| {', '.join(f_types)} | {adaptation_note} |")
|
|
442
|
-
else:
|
|
443
|
-
a(f"| Cross-check against architecture resource map (Step 4 input). "
|
|
444
|
-
f"| {f.get('display_name', '')} | {f.get('effect', '')} "
|
|
445
|
-
f"| {', '.join(f_types)} | {adaptation_note} |")
|
|
446
|
-
elif blockers:
|
|
447
|
-
a("| Original Design | Blocking Policy | Effect | Adaptation Applied |")
|
|
448
|
-
a("| --- | --- | --- | --- |")
|
|
449
|
-
for f in blockers:
|
|
450
|
-
a(f"| No architecture target | {f.get('display_name', '')} | {f.get('effect', '')} "
|
|
451
|
-
f"| Review at Step 4 IaC Planning |")
|
|
452
|
-
else:
|
|
453
|
-
a("✅ Original architecture complies with all discovered policies.\n")
|
|
454
|
-
a("")
|
|
455
|
-
|
|
456
|
-
a("### Auto-Applied Resources\n")
|
|
457
|
-
dine_findings = [f for f in findings if f.get("effect") == "deployIfNotExists"]
|
|
458
|
-
if dine_findings:
|
|
459
|
-
a("| Policy | Effect | Auto-Applied Resource |")
|
|
460
|
-
a("| --- | --- | --- |")
|
|
461
|
-
# DeployIfNotExists effects are platform-driven — the descriptor is
|
|
462
|
-
# the same whether or not architecture context is available, so we
|
|
463
|
-
# drop the conditional placeholder.
|
|
464
|
-
for f in dine_findings:
|
|
465
|
-
a(f"| {f.get('display_name', '')} | DeployIfNotExists | Auto-deployed by Azure Policy |")
|
|
466
|
-
else:
|
|
467
|
-
a("✅ No additional resources will be auto-deployed.\n")
|
|
468
|
-
a("")
|
|
469
|
-
|
|
470
|
-
a("### Auto-Modified Configurations\n")
|
|
471
|
-
modify_findings = [f for f in findings if f.get("effect") == "modify"]
|
|
472
|
-
if modify_findings:
|
|
473
|
-
a("| Policy | Effect | Auto-Applied Change |")
|
|
474
|
-
a("| --- | --- | --- |")
|
|
475
|
-
# Modify effects are platform-driven (see DINE comment above).
|
|
476
|
-
for f in modify_findings:
|
|
477
|
-
a(f"| {f.get('display_name', '')} | Modify | Auto-modified by Azure Policy |")
|
|
478
|
-
else:
|
|
479
|
-
a("✅ No auto-modifications expected.\n")
|
|
480
|
-
a("")
|
|
481
|
-
|
|
482
|
-
# Deployment Blockers (deduplicated by display_name)
|
|
483
|
-
a("## 🚫 Deployment Blockers\n")
|
|
484
|
-
if not blockers:
|
|
485
|
-
a("✅ No deployment blockers detected.\n")
|
|
486
|
-
else:
|
|
487
|
-
deduped = _dedup_blockers(blockers)
|
|
488
|
-
a(f"> **{len(blockers)}** blocker finding(s) from **{len(deduped)}** unique policies (duplicates from multi-scope inheritance are consolidated below).\n")
|
|
489
|
-
for f in deduped:
|
|
490
|
-
a(f"### {f.get('display_name', 'Unknown Policy')}\n")
|
|
491
|
-
a(f"- **Policy ID**: `{f.get('policy_id', '')}`")
|
|
492
|
-
a(f"- **Effect**: {f.get('effect', '')}")
|
|
493
|
-
scopes = f.get("_scopes", [f.get("scope", "")])
|
|
494
|
-
if len(scopes) > 1:
|
|
495
|
-
a(f"- **Scopes** ({len(scopes)} assignments):")
|
|
496
|
-
for s in scopes:
|
|
497
|
-
a(f" - `{s}`")
|
|
498
|
-
else:
|
|
499
|
-
a(f"- **Scope**: {scopes[0]}")
|
|
500
|
-
a(f"- **Category**: {f.get('category', '')}")
|
|
501
|
-
bpp = f.get("bicepPropertyPath", "")
|
|
502
|
-
if bpp == "type":
|
|
503
|
-
bpp = "type (resource-type constraint — enforced at type level, not a specific property)"
|
|
504
|
-
a(f"- **Bicep Property Path**: `{bpp}`")
|
|
505
|
-
constraint = _extract_constraint_value(f)
|
|
506
|
-
a(f"- **Required Value**: {constraint or 'N/A — parameter values not available in cached baseline; run `--refresh` for live lookup'}")
|
|
507
|
-
a("")
|
|
508
|
-
# Resolution guidance is uniform whether or not architecture
|
|
509
|
-
# context is present — the per-finding structured fields above
|
|
510
|
-
# already carry everything the Step 4 planner needs. The prior
|
|
511
|
-
# `<!-- AGENT: annotate resolution options below -->` block was
|
|
512
|
-
# dropped in plan-optimiseGovernanceAgent.prompt.md Phase 2 to
|
|
513
|
-
# remove the placeholder cascade.
|
|
514
|
-
a("> **Resolution**: Review during Step 4 IaC Planning — apply an exemption, use an allowed alternative, or update the policy scope.\n")
|
|
515
|
-
a("")
|
|
516
|
-
|
|
517
|
-
# Required Tags
|
|
518
|
-
a("## 🏷️ Required Tags\n")
|
|
519
|
-
if tags_required:
|
|
520
|
-
# Enrich unresolved tag entries with assignment_parameters from matching findings.
|
|
521
|
-
# tags_required entries from cached baselines lack params; the matching findings carry them.
|
|
522
|
-
findings_by_display_name: dict[str, dict[str, Any]] = {}
|
|
523
|
-
for f in findings:
|
|
524
|
-
dn = f.get("display_name", "")
|
|
525
|
-
if dn and dn not in findings_by_display_name:
|
|
526
|
-
findings_by_display_name[dn] = f
|
|
527
|
-
enriched_tags: list[dict[str, Any]] = []
|
|
528
|
-
for t in tags_required:
|
|
529
|
-
if t.get("unresolved") or t.get("name", "").startswith("[unresolved"):
|
|
530
|
-
source = t.get("source_assignment", "")
|
|
531
|
-
matching = findings_by_display_name.get(source)
|
|
532
|
-
if matching and matching.get("assignment_parameters"):
|
|
533
|
-
t = dict(t)
|
|
534
|
-
t["assignment_parameters"] = matching["assignment_parameters"]
|
|
535
|
-
enriched_tags.append(t)
|
|
536
|
-
resolved, unresolved = _split_tags(enriched_tags)
|
|
537
|
-
a("All resources must include the following tags:\n")
|
|
538
|
-
if unresolved:
|
|
539
|
-
a("> **Note**: Some tag names could not be resolved from cached policy data. "
|
|
540
|
-
"Run with `--refresh` for full tag resolution.\n")
|
|
541
|
-
a("| Tag Name | Source Policy |")
|
|
542
|
-
a("| --- | --- |")
|
|
543
|
-
for t in resolved:
|
|
544
|
-
a(f"| `{t['name']}` | {t.get('source_assignment', t.get('source_policy', ''))} |")
|
|
545
|
-
for t in unresolved:
|
|
546
|
-
a(f"| [unresolved] | {t.get('source_assignment', t.get('source_policy', ''))} — tag key requires live discovery |")
|
|
547
|
-
else:
|
|
548
|
-
a("No tag-enforcement policies discovered.\n")
|
|
549
|
-
a("")
|
|
550
|
-
a("```mermaid")
|
|
551
|
-
a("%%{init: {'theme':'neutral'}}%%")
|
|
552
|
-
a("flowchart TD")
|
|
553
|
-
a(' MG["Management Group Tags"] -->|inherited| SUB["Subscription Tags"]')
|
|
554
|
-
a(' SUB -->|inherited| RG["Resource Group Tags"]')
|
|
555
|
-
a(' RG -->|inherited| RES["Resource Tags"]')
|
|
556
|
-
a(' POL["Azure Policy\\n(Modify effect)"] -->|auto-applies| RES')
|
|
557
|
-
a(" style POL fill:#FFB900,stroke:#333")
|
|
558
|
-
a(" style RES fill:#0078D4,color:#fff,stroke:#333")
|
|
559
|
-
a("```\n")
|
|
560
|
-
|
|
561
|
-
# Security Policies — pre-built list already computed before Discovery Source section.
|
|
562
|
-
a("## 🔐 Security Policies\n")
|
|
563
|
-
if security:
|
|
564
|
-
a("| Policy | Effect | Status |")
|
|
565
|
-
a("| --- | --- | --- |")
|
|
566
|
-
for f in security:
|
|
567
|
-
icon = "❌" if f.get("classification") == "blocker" else "✅"
|
|
568
|
-
a(f"| {f.get('display_name', '')} | {f.get('effect', '')} | {icon} |")
|
|
569
|
-
else:
|
|
570
|
-
a("✅ No security-specific policies discovered.\n")
|
|
571
|
-
a("")
|
|
572
|
-
|
|
573
|
-
# Cost Policies — also pick up cost-related blockers
|
|
574
|
-
a("## 💰 Cost Policies\n")
|
|
575
|
-
cost = list(by_category.get("Cost", []) + by_category.get("Budget", []))
|
|
576
|
-
cost_keywords = {"Block VM SKU", "Block Azure OpenAI Provisioned", "Block Azure Sentinel Commitment",
|
|
577
|
-
"Deny AKS deployment with agent pool count", "Deny VMSS deployment with instance count"}
|
|
578
|
-
for f in findings:
|
|
579
|
-
if f not in cost and any(kw in (f.get("display_name") or "") for kw in cost_keywords):
|
|
580
|
-
cost.append(f)
|
|
581
|
-
if cost:
|
|
582
|
-
a("| Policy | Effect | Constraint |")
|
|
583
|
-
a("| --- | --- | --- |")
|
|
584
|
-
for f in cost:
|
|
585
|
-
constraint = _extract_constraint_value(f) or "See policy parameters"
|
|
586
|
-
a(f"| {f.get('display_name', '')} | {f.get('effect', '')} | {constraint} |")
|
|
587
|
-
else:
|
|
588
|
-
a("No cost-specific policies discovered.\n")
|
|
589
|
-
a("")
|
|
590
|
-
|
|
591
|
-
# Network Policies
|
|
592
|
-
a("## 🌐 Network Policies\n")
|
|
593
|
-
network = list(by_category.get("Network", []) + by_category.get("Networking", []))
|
|
594
|
-
network_keywords = {"vNet peering", "virtual network", "subnet", "NSG", "firewall"}
|
|
595
|
-
for f in findings:
|
|
596
|
-
if f not in network and any(kw.lower() in (f.get("display_name") or "").lower() for kw in network_keywords):
|
|
597
|
-
network.append(f)
|
|
598
|
-
if network:
|
|
599
|
-
a("| Policy | Effect | Constraint |")
|
|
600
|
-
a("| --- | --- | --- |")
|
|
601
|
-
for f in network:
|
|
602
|
-
constraint = _extract_constraint_value(f) or "See policy parameters"
|
|
603
|
-
a(f"| {f.get('display_name', '')} | {f.get('effect', '')} | {constraint} |")
|
|
604
|
-
else:
|
|
605
|
-
a("No network-specific policies discovered.\n")
|
|
606
|
-
location_constraints = envelope.get("location_constraints", [])
|
|
607
|
-
if location_constraints:
|
|
608
|
-
a("### Location Governance\n")
|
|
609
|
-
a("| Policy | Effect | Enforcement | Allowed Locations |")
|
|
610
|
-
a("| --- | --- | --- | --- |")
|
|
611
|
-
for constraint in location_constraints:
|
|
612
|
-
allowed = ", ".join(f"`{value}`" for value in constraint.get("allowed_locations", [])) or "N/A"
|
|
613
|
-
a(
|
|
614
|
-
f"| {constraint.get('display_name', '')} | {constraint.get('effect', '')} "
|
|
615
|
-
f"| {constraint.get('enforcement_mode', '')} | {allowed} |"
|
|
616
|
-
)
|
|
617
|
-
a("")
|
|
618
|
-
|
|
619
|
-
# Compliance Frameworks — notable audit/compliance assignments not in findings
|
|
620
|
-
assignment_inventory = envelope.get("assignment_inventory", [])
|
|
621
|
-
compliance_keywords = {
|
|
622
|
-
"GDPR", "PCI DSS", "HIPAA", "SOC", "ISO 27001", "NIST",
|
|
623
|
-
"Multi Factor Authentication", "MFA", "Security Benchmark",
|
|
624
|
-
"Security Baseline", "CIS",
|
|
625
|
-
}
|
|
626
|
-
# Collect display names already in findings to avoid duplicates
|
|
627
|
-
finding_names = {f.get("display_name", "") for f in findings}
|
|
628
|
-
notable_assignments = []
|
|
629
|
-
for inv in assignment_inventory:
|
|
630
|
-
dn = inv.get("displayName") or inv.get("display_name") or ""
|
|
631
|
-
if dn in finding_names:
|
|
632
|
-
continue
|
|
633
|
-
if any(kw.lower() in dn.lower() for kw in compliance_keywords):
|
|
634
|
-
notable_assignments.append(inv)
|
|
635
|
-
if notable_assignments:
|
|
636
|
-
a("## 📜 Compliance Frameworks\n")
|
|
637
|
-
a("> These audit/compliance assignments are active at subscription or management-group scope. ")
|
|
638
|
-
a("> While they do not block deployments (audit effect), they may impose architecture constraints ")
|
|
639
|
-
a("> (data residency, encryption, access logging, network segmentation).\n")
|
|
640
|
-
a("| Assignment | Scope | Type |")
|
|
641
|
-
a("| --- | --- | --- |")
|
|
642
|
-
for inv in notable_assignments:
|
|
643
|
-
dn = inv.get("displayName") or inv.get("display_name") or ""
|
|
644
|
-
scope = inv.get("scope", "")
|
|
645
|
-
atype = inv.get("assignmentType", "")
|
|
646
|
-
a(f"| {dn} | {scope} | {atype} |")
|
|
647
|
-
a("")
|
|
648
|
-
else:
|
|
649
|
-
a("## 📜 Compliance Frameworks\n")
|
|
650
|
-
a("✅ No compliance framework assignments (GDPR, PCI DSS, HIPAA, etc.) discovered at subscription or management-group scope.\n")
|
|
651
|
-
|
|
652
|
-
# References
|
|
653
|
-
a("## References\n")
|
|
654
|
-
a("| Topic | Link |")
|
|
655
|
-
a("| --- | --- |")
|
|
656
|
-
a("| Azure Policy | [Overview](https://learn.microsoft.com/azure/governance/policy/overview) |")
|
|
657
|
-
a("| Tag Governance | [Tagging Strategy](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-tagging) |\n")
|
|
658
|
-
security_exceptions = envelope.get("security_exceptions", [])
|
|
659
|
-
if security_exceptions:
|
|
660
|
-
a("## Approved Security Exceptions\n")
|
|
661
|
-
a("| ID | Control | Environment | Workload | Expires |")
|
|
662
|
-
a("| --- | --- | --- | --- | --- |")
|
|
663
|
-
for exception in security_exceptions:
|
|
664
|
-
scope = exception.get("scope") or {}
|
|
665
|
-
a(
|
|
666
|
-
f"| `{exception.get('id', '')}` | `{exception.get('control', '')}` "
|
|
667
|
-
f"| `{scope.get('environment', '')}` | `{scope.get('workload', '')}` "
|
|
668
|
-
f"| `{exception.get('expires_at', '')}` |"
|
|
669
|
-
)
|
|
670
|
-
a("")
|
|
671
|
-
a("---\n")
|
|
672
|
-
footer_source = "cached governance baseline" if is_cached else "Azure Policy REST API via discover.py"
|
|
673
|
-
a(f"_Governance constraints discovered from {footer_source}._\n")
|
|
674
|
-
|
|
675
|
-
preview_path.write_text("\n".join(lines) + "\n")
|
|
676
|
-
return preview_path
|