@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.
Files changed (366) hide show
  1. package/assets/capability-packs/registry.v1.json +1 -62
  2. package/assets/client-projection-metadata/copilot-cli-agent-tools.json +12 -0
  3. package/assets/client-projections/github-copilot-cli/.github/copilot/settings.json +13 -0
  4. package/assets/client-projections/github-copilot-cli/.github/instructions/apex-prompt-authoring.instructions.md +1 -1
  5. package/assets/client-projections/github-copilot-cli/.github/workflows/governance-policy-baseline.yml +101 -0
  6. package/assets/client-projections/github-copilot-cli/tools/schemas/governance-baseline.schema.json +118 -0
  7. package/assets/client-projections/github-copilot-cli/tools/scripts/collect-governance-baseline.ps1 +817 -0
  8. package/assets/config/capability-packs.v1.json +1 -32
  9. package/assets/config/governance-reference.v1.json +26379 -0
  10. package/assets/config/recipe-packs.v1.json +1 -26
  11. package/assets/config/runtime-bundle.v1.json +7 -7
  12. package/assets/config/toolchain.v1.json +35 -33
  13. package/assets/config/workflow.v1.json +103 -72
  14. package/assets/customizations/.github/agents/apex-codegen.agent.md +8 -22
  15. package/assets/customizations/.github/agents/apex-validator.agent.md +14 -20
  16. package/assets/customizations/.github/agents/apex.agent.md +108 -75
  17. package/assets/customizations/.github/copilot/settings.json +13 -0
  18. package/assets/customizations/.github/instructions/apex-prompt-authoring.instructions.md +1 -1
  19. package/assets/customizations/.github/skills/apex-architecture/SKILL.md +62 -18
  20. package/assets/customizations/.github/skills/apex-artifacts/SKILL.md +28 -6
  21. package/assets/customizations/.github/skills/apex-azure-adr/SKILL.md +3 -0
  22. package/assets/customizations/.github/skills/apex-azure-cloud-migrate/SKILL.md +3 -0
  23. package/assets/customizations/.github/skills/apex-azure-compliance/SKILL.md +3 -0
  24. package/assets/customizations/.github/skills/apex-azure-compute/SKILL.md +3 -0
  25. package/assets/customizations/.github/skills/apex-azure-cost-optimization/SKILL.md +3 -0
  26. package/assets/customizations/.github/skills/apex-azure-defaults/SKILL.md +3 -0
  27. package/assets/customizations/.github/skills/apex-azure-defaults/references/governance-effects.md +5 -3
  28. package/assets/customizations/.github/skills/apex-azure-deploy/SKILL.md +3 -0
  29. package/assets/customizations/.github/skills/apex-azure-diagnostics/SKILL.md +3 -0
  30. package/assets/customizations/.github/skills/apex-azure-governance/SKILL.md +19 -3
  31. package/assets/customizations/.github/skills/apex-azure-governance/references/evidence-interpretation.md +38 -3
  32. package/assets/customizations/.github/skills/apex-azure-kusto/SKILL.md +3 -0
  33. package/assets/customizations/.github/skills/apex-azure-prepare/SKILL.md +5 -3
  34. package/assets/customizations/.github/skills/apex-azure-quotas/SKILL.md +6 -2
  35. package/assets/customizations/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +4 -3
  36. package/assets/customizations/.github/skills/apex-azure-quotas/references/operational-checklist.md +3 -2
  37. package/assets/customizations/.github/skills/apex-azure-rbac/SKILL.md +3 -0
  38. package/assets/customizations/.github/skills/apex-azure-resources/SKILL.md +3 -0
  39. package/assets/customizations/.github/skills/apex-azure-storage/SKILL.md +3 -0
  40. package/assets/customizations/.github/skills/apex-azure-validate/SKILL.md +3 -0
  41. package/assets/customizations/.github/skills/apex-bicep-patterns/SKILL.md +3 -0
  42. package/assets/customizations/.github/skills/apex-codegen/SKILL.md +6 -2
  43. package/assets/customizations/.github/skills/apex-entra-app-registration/SKILL.md +3 -0
  44. package/assets/customizations/.github/skills/apex-mermaid/SKILL.md +3 -0
  45. package/assets/customizations/.github/skills/apex-microsoft-docs/SKILL.md +3 -0
  46. package/assets/customizations/.github/skills/apex-next/SKILL.md +99 -0
  47. package/assets/customizations/.github/skills/apex-operations/SKILL.md +46 -16
  48. package/assets/customizations/.github/skills/apex-planning/SKILL.md +48 -19
  49. package/assets/customizations/.github/skills/apex-requirements/SKILL.md +61 -26
  50. package/assets/customizations/.github/skills/apex-terraform-import/SKILL.md +3 -0
  51. package/assets/customizations/.github/skills/apex-terraform-patterns/SKILL.md +3 -0
  52. package/assets/customizations/.github/skills/apex-terraform-test/SKILL.md +3 -0
  53. package/assets/customizations/.github/skills/apex-unslop/LICENSE.txt +21 -0
  54. package/assets/customizations/.github/skills/apex-unslop/SKILL.md +94 -0
  55. package/assets/customizations/.github/skills/apex-workflow/SKILL.md +15 -5
  56. package/assets/customizations/.github/workflows/governance-policy-baseline.yml +101 -0
  57. package/assets/customizations/README.md +8 -9
  58. package/assets/customizations/manifest.json +167 -209
  59. package/assets/customizations/tools/schemas/governance-baseline.schema.json +118 -0
  60. package/assets/customizations/tools/scripts/collect-governance-baseline.ps1 +817 -0
  61. package/assets/manifest.json +423 -4241
  62. package/assets/schemas/governance-baseline.schema.json +118 -0
  63. package/dist/assets.d.ts +18 -2
  64. package/dist/assets.js +115 -35
  65. package/dist/bootstrap-wizard.d.ts +37 -0
  66. package/dist/bootstrap-wizard.js +259 -0
  67. package/dist/cli.d.ts +17 -2
  68. package/dist/cli.js +180 -63
  69. package/dist/dependency-revision.js +8 -0
  70. package/dist/errors.d.ts +6 -1
  71. package/dist/errors.js +55 -0
  72. package/dist/host-profile.d.ts +47 -0
  73. package/dist/host-profile.js +269 -0
  74. package/dist/mcp-output-schemas.d.ts +43 -0
  75. package/dist/mcp-output-schemas.js +279 -0
  76. package/dist/mcp-tool-effects.d.ts +101 -0
  77. package/dist/mcp-tool-effects.js +66 -0
  78. package/dist/mcp.d.ts +50 -3
  79. package/dist/mcp.js +800 -87
  80. package/dist/runtime-binding.d.ts +37 -0
  81. package/dist/runtime-binding.js +131 -0
  82. package/dist/service.d.ts +643 -38
  83. package/dist/service.js +4937 -662
  84. package/dist/state-transfer.js +21 -1
  85. package/dist/target-scope.d.ts +4 -0
  86. package/dist/target-scope.js +9 -0
  87. package/dist/version.d.ts +3 -1
  88. package/dist/version.js +19 -1
  89. package/dist/workflow-validators.d.ts +20 -3
  90. package/dist/workflow-validators.js +408 -67
  91. package/dist/workspace-root.d.ts +7 -0
  92. package/dist/workspace-root.js +67 -0
  93. package/package.json +11 -12
  94. package/assets/capability-packs/azure-governance-discovery/source/scripts/discover.py +0 -1189
  95. package/assets/capability-packs/azure-governance-discovery/source/scripts/render_governance.py +0 -676
  96. package/assets/client-projections/github-copilot-cli/.github/agents/apex-architect.agent.md +0 -91
  97. package/assets/client-projections/github-copilot-cli/.github/agents/apex-operator.agent.md +0 -75
  98. package/assets/client-projections/github-copilot-cli/.github/agents/apex-planner.agent.md +0 -88
  99. package/assets/client-projections/github-copilot-cli/.github/agents/apex-requirements.agent.md +0 -99
  100. package/assets/client-projections/github-copilot-cli/.github/agents/apex.agent.md +0 -88
  101. package/assets/client-projections/github-copilot-cli/.github/mcp.json +0 -65
  102. package/assets/client-projections/github-copilot-cli/.github/skills/apex-architecture/SKILL.md +0 -36
  103. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/SKILL.md +0 -65
  104. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/references/presentation-conventions.md +0 -52
  105. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/references/reference-only-outlines.md +0 -78
  106. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/architecture-assessment.md +0 -35
  107. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/cost-estimate.md +0 -47
  108. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/deployment-summary.md +0 -35
  109. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/governance-constraints.md +0 -35
  110. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/implementation-plan.md +0 -43
  111. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/operations-runbook.md +0 -35
  112. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/requirements.md +0 -42
  113. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/resource-inventory.md +0 -29
  114. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/SKILL.md +0 -52
  115. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-examples.md +0 -38
  116. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-guardrails.md +0 -36
  117. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-quality.md +0 -21
  118. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-record-fields.md +0 -57
  119. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/SKILL.md +0 -55
  120. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/lambda-to-functions-assessment.md +0 -29
  121. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/migration-readiness.md +0 -27
  122. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/staged-validation-handoff.md +0 -26
  123. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/workload-mapping.md +0 -27
  124. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/SKILL.md +0 -58
  125. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/references/compliance-finding-criteria.md +0 -63
  126. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/references/operational-checklist.md +0 -24
  127. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/SKILL.md +0 -36
  128. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/compute-selection.md +0 -26
  129. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/pricing-evidence.md +0 -11
  130. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/recommendation-and-scale-rules.md +0 -44
  131. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/SKILL.md +0 -61
  132. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/references/cost-assessment-criteria.md +0 -61
  133. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/references/operational-checklist.md +0 -24
  134. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/SKILL.md +0 -59
  135. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/avm-binding-guidance.md +0 -29
  136. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/baseline-fallbacks.md +0 -53
  137. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/cost-monitoring.md +0 -47
  138. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/decision-boundaries.md +0 -19
  139. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/governance-effects.md +0 -28
  140. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/naming.md +0 -47
  141. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/network-planning.md +0 -47
  142. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/security-baseline.md +0 -40
  143. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/service-selection.md +0 -51
  144. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/tag-precedence.md +0 -31
  145. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/SKILL.md +0 -50
  146. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/references/operational-checklist.md +0 -26
  147. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/references/preview-recovery-verification.md +0 -48
  148. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/SKILL.md +0 -60
  149. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/references/diagnostic-interpretation.md +0 -42
  150. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/references/operational-checklist.md +0 -24
  151. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/SKILL.md +0 -52
  152. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/references/evidence-interpretation.md +0 -58
  153. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/references/operational-checklist.md +0 -25
  154. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/SKILL.md +0 -58
  155. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/references/kql-evidence-interpretation.md +0 -41
  156. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/references/operational-checklist.md +0 -25
  157. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/SKILL.md +0 -52
  158. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
  159. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/references/preparation-lineage.md +0 -36
  160. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/SKILL.md +0 -53
  161. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +0 -48
  162. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/references/operational-checklist.md +0 -23
  163. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/SKILL.md +0 -45
  164. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/references/assignment-intent.md +0 -39
  165. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/references/least-privilege-selection.md +0 -50
  166. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/SKILL.md +0 -54
  167. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/references/inventory-query-patterns.md +0 -49
  168. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/references/operational-checklist.md +0 -24
  169. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/SKILL.md +0 -35
  170. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/security-and-governance.md +0 -12
  171. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/service-auth-and-sdk-boundary.md +0 -33
  172. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/storage-selection.md +0 -12
  173. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/SKILL.md +0 -49
  174. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/references/operational-checklist.md +0 -24
  175. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/references/preflight-evidence.md +0 -43
  176. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/SKILL.md +0 -41
  177. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/avm-and-codegen-acceptance.md +0 -11
  178. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/codegen-acceptance-checklist.md +0 -46
  179. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/compiler-and-provider-gotchas.md +0 -74
  180. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/module-interfaces-and-parameters.md +0 -56
  181. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/network-and-observability.md +0 -52
  182. package/assets/client-projections/github-copilot-cli/.github/skills/apex-codegen/SKILL.md +0 -32
  183. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/SKILL.md +0 -53
  184. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/capability-receipts.md +0 -21
  185. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/design-and-diagnostics.md +0 -36
  186. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/oauth-registration-model.md +0 -26
  187. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/permissions-and-credentials.md +0 -27
  188. package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/SKILL.md +0 -44
  189. package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/references/styling.md +0 -33
  190. package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/references/syntax.md +0 -99
  191. package/assets/client-projections/github-copilot-cli/.github/skills/apex-microsoft-docs/SKILL.md +0 -53
  192. package/assets/client-projections/github-copilot-cli/.github/skills/apex-microsoft-docs/references/research-method.md +0 -91
  193. package/assets/client-projections/github-copilot-cli/.github/skills/apex-operations/SKILL.md +0 -34
  194. package/assets/client-projections/github-copilot-cli/.github/skills/apex-planning/SKILL.md +0 -36
  195. package/assets/client-projections/github-copilot-cli/.github/skills/apex-requirements/SKILL.md +0 -46
  196. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/SKILL.md +0 -47
  197. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/adoption-attestation.md +0 -10
  198. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/import-assessment.md +0 -14
  199. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/import-mapping.md +0 -27
  200. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/mapping-and-adoption-attestation.md +0 -12
  201. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/SKILL.md +0 -49
  202. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-composition-and-refactor.md +0 -20
  203. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-composition-and-state-boundaries.md +0 -11
  204. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-locks-and-codegen-acceptance.md +0 -14
  205. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/network-and-observability.md +0 -12
  206. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/plan-and-change-assessment.md +0 -24
  207. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/SKILL.md +0 -45
  208. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/evidence-acceptance.md +0 -10
  209. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/plan-mode-and-mock-design.md +0 -12
  210. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/plan-mode-test-design.md +0 -23
  211. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/test-design.md +0 -13
  212. package/assets/client-projections/github-copilot-cli/.github/skills/apex-workflow/SKILL.md +0 -37
  213. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-architect.agent.md +0 -100
  214. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-codegen.agent.md +0 -62
  215. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-operator.agent.md +0 -79
  216. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-planner.agent.md +0 -98
  217. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-requirements.agent.md +0 -108
  218. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-reviewer.agent.md +0 -63
  219. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-validator.agent.md +0 -61
  220. package/assets/client-projections/github-copilot-vscode/.github/agents/apex.agent.md +0 -107
  221. package/assets/client-projections/github-copilot-vscode/.github/copilot-instructions.md +0 -13
  222. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-agent-authoring.instructions.md +0 -14
  223. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-artifact-contracts.instructions.md +0 -12
  224. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-automation.instructions.md +0 -12
  225. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-azure-yaml.instructions.md +0 -12
  226. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-bicep.instructions.md +0 -12
  227. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-code-quality.instructions.md +0 -12
  228. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-context.instructions.md +0 -12
  229. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-documentation.instructions.md +0 -12
  230. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-governance.instructions.md +0 -12
  231. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-instruction-authoring.instructions.md +0 -12
  232. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-javascript.instructions.md +0 -11
  233. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-json.instructions.md +0 -11
  234. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-markdown.instructions.md +0 -13
  235. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-powershell.instructions.md +0 -11
  236. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-prompt-authoring.instructions.md +0 -12
  237. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-python.instructions.md +0 -11
  238. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-safe-file-edits.instructions.md +0 -11
  239. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-safe-shell.instructions.md +0 -11
  240. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-shell.instructions.md +0 -11
  241. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-skill-authoring.instructions.md +0 -13
  242. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-terraform.instructions.md +0 -12
  243. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-architecture/SKILL.md +0 -36
  244. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/SKILL.md +0 -65
  245. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/references/presentation-conventions.md +0 -52
  246. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/references/reference-only-outlines.md +0 -78
  247. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/architecture-assessment.md +0 -35
  248. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/cost-estimate.md +0 -47
  249. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/deployment-summary.md +0 -35
  250. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/governance-constraints.md +0 -35
  251. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/implementation-plan.md +0 -43
  252. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/operations-runbook.md +0 -35
  253. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/requirements.md +0 -42
  254. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/resource-inventory.md +0 -29
  255. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/SKILL.md +0 -52
  256. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-examples.md +0 -38
  257. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-guardrails.md +0 -36
  258. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-quality.md +0 -21
  259. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-record-fields.md +0 -57
  260. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/SKILL.md +0 -55
  261. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/lambda-to-functions-assessment.md +0 -29
  262. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/migration-readiness.md +0 -27
  263. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/staged-validation-handoff.md +0 -26
  264. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/workload-mapping.md +0 -27
  265. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/SKILL.md +0 -58
  266. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/references/compliance-finding-criteria.md +0 -63
  267. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/references/operational-checklist.md +0 -24
  268. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/SKILL.md +0 -36
  269. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/compute-selection.md +0 -26
  270. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/pricing-evidence.md +0 -11
  271. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/recommendation-and-scale-rules.md +0 -44
  272. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/SKILL.md +0 -61
  273. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/references/cost-assessment-criteria.md +0 -61
  274. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/references/operational-checklist.md +0 -24
  275. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/SKILL.md +0 -59
  276. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/avm-binding-guidance.md +0 -29
  277. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/baseline-fallbacks.md +0 -53
  278. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/cost-monitoring.md +0 -47
  279. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/decision-boundaries.md +0 -19
  280. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/governance-effects.md +0 -28
  281. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/naming.md +0 -47
  282. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/network-planning.md +0 -47
  283. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/security-baseline.md +0 -40
  284. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/service-selection.md +0 -51
  285. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/tag-precedence.md +0 -31
  286. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/SKILL.md +0 -50
  287. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/references/operational-checklist.md +0 -26
  288. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/references/preview-recovery-verification.md +0 -48
  289. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/SKILL.md +0 -60
  290. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/references/diagnostic-interpretation.md +0 -42
  291. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/references/operational-checklist.md +0 -24
  292. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/SKILL.md +0 -52
  293. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/references/evidence-interpretation.md +0 -58
  294. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/references/operational-checklist.md +0 -25
  295. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/SKILL.md +0 -58
  296. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/references/kql-evidence-interpretation.md +0 -41
  297. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/references/operational-checklist.md +0 -25
  298. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/SKILL.md +0 -52
  299. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
  300. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/references/preparation-lineage.md +0 -36
  301. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/SKILL.md +0 -53
  302. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +0 -48
  303. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/references/operational-checklist.md +0 -23
  304. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/SKILL.md +0 -45
  305. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/references/assignment-intent.md +0 -39
  306. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/references/least-privilege-selection.md +0 -50
  307. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/SKILL.md +0 -54
  308. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/references/inventory-query-patterns.md +0 -49
  309. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/references/operational-checklist.md +0 -24
  310. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/SKILL.md +0 -35
  311. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/security-and-governance.md +0 -12
  312. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/service-auth-and-sdk-boundary.md +0 -33
  313. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/storage-selection.md +0 -12
  314. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/SKILL.md +0 -49
  315. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/references/operational-checklist.md +0 -24
  316. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/references/preflight-evidence.md +0 -43
  317. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/SKILL.md +0 -41
  318. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/avm-and-codegen-acceptance.md +0 -11
  319. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/codegen-acceptance-checklist.md +0 -46
  320. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/compiler-and-provider-gotchas.md +0 -74
  321. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/module-interfaces-and-parameters.md +0 -56
  322. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/network-and-observability.md +0 -52
  323. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-codegen/SKILL.md +0 -32
  324. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/SKILL.md +0 -53
  325. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/capability-receipts.md +0 -21
  326. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/design-and-diagnostics.md +0 -36
  327. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/oauth-registration-model.md +0 -26
  328. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/permissions-and-credentials.md +0 -27
  329. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/SKILL.md +0 -44
  330. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/references/styling.md +0 -33
  331. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/references/syntax.md +0 -99
  332. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-microsoft-docs/SKILL.md +0 -53
  333. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-microsoft-docs/references/research-method.md +0 -91
  334. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-operations/SKILL.md +0 -34
  335. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-planning/SKILL.md +0 -36
  336. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-requirements/SKILL.md +0 -46
  337. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/SKILL.md +0 -47
  338. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/adoption-attestation.md +0 -10
  339. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/import-assessment.md +0 -14
  340. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/import-mapping.md +0 -27
  341. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/mapping-and-adoption-attestation.md +0 -12
  342. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/SKILL.md +0 -49
  343. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-composition-and-refactor.md +0 -20
  344. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-composition-and-state-boundaries.md +0 -11
  345. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-locks-and-codegen-acceptance.md +0 -14
  346. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/network-and-observability.md +0 -12
  347. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/plan-and-change-assessment.md +0 -24
  348. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/SKILL.md +0 -45
  349. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/evidence-acceptance.md +0 -10
  350. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/plan-mode-and-mock-design.md +0 -12
  351. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/plan-mode-test-design.md +0 -23
  352. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/test-design.md +0 -13
  353. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-workflow/SKILL.md +0 -37
  354. package/assets/client-projections/github-copilot-vscode/.vscode/mcp.json +0 -29
  355. package/assets/customizations/.github/agents/apex-architect.agent.md +0 -93
  356. package/assets/customizations/.github/agents/apex-operator.agent.md +0 -72
  357. package/assets/customizations/.github/agents/apex-planner.agent.md +0 -91
  358. package/assets/customizations/.github/agents/apex-requirements.agent.md +0 -101
  359. package/assets/customizations/.github/agents/apex-reviewer.agent.md +0 -60
  360. package/assets/customizations/.github/mcp.json +0 -65
  361. package/assets/customizations/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
  362. package/assets/customizations/.vscode/mcp.json +0 -29
  363. package/dist/azure-mcp-environment.d.ts +0 -2
  364. package/dist/azure-mcp-environment.js +0 -7
  365. package/dist/azure-mcp.d.ts +0 -2
  366. package/dist/azure-mcp.js +0 -21
@@ -0,0 +1,817 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Collects Azure Policy assignments across all subscriptions under a
4
+ Management Group or one subscription and writes a governance-baseline-v2 JSON.
5
+
6
+ .DESCRIPTION
7
+ Authenticates via the workflow's azure/login@v2 context, discovers
8
+ descendant subscriptions, collects policy assignments/definitions/
9
+ set-definitions/exemptions per subscription, classifies findings,
10
+ and writes a deterministic baseline.
11
+
12
+ Every successful collection renews discovered_at timestamps,
13
+ including unchanged subscriptions.
14
+
15
+ .PARAMETER ManagementGroupId
16
+ The root Management Group ID to traverse; exclusive with SubscriptionId.
17
+
18
+ .PARAMETER SubscriptionId
19
+ Collect one subscription, including inherited policy, without MG discovery.
20
+
21
+ .PARAMETER OutputDir
22
+ Output directory for baseline files. Default: .github/data
23
+
24
+ .PARAMETER IncludeDefenderAuto
25
+ Switch. If set, retains Defender-for-Cloud auto-assignments.
26
+
27
+ .PARAMETER IncludeDescendants
28
+ Retain resource-group/resource assignments and scoped exemption evidence.
29
+
30
+ .PARAMETER MaxSubscriptions
31
+ Maximum subscriptions to process. Default: 100.
32
+ #>
33
+ [CmdletBinding(DefaultParameterSetName = "ManagementGroup")]
34
+ param(
35
+ [Parameter(Mandatory, ParameterSetName = "ManagementGroup")]
36
+ [ValidateNotNullOrEmpty()]
37
+ [ValidatePattern('\A[a-zA-Z0-9](?:[a-zA-Z0-9_().-]{0,88}[a-zA-Z0-9_()-])?\z')]
38
+ [string]$ManagementGroupId,
39
+
40
+ [Parameter(Mandatory, ParameterSetName = "Subscription")]
41
+ [ValidatePattern('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$')]
42
+ [string]$SubscriptionId,
43
+
44
+ [string]$OutputDir = ".github/data",
45
+
46
+ [switch]$IncludeDefenderAuto,
47
+ [switch]$IncludeDescendants,
48
+
49
+ [ValidateRange(1, [int]::MaxValue)]
50
+ [int]$MaxSubscriptions = 100
51
+ )
52
+
53
+ # StrictMode intentionally omitted — REST API response objects have dynamic
54
+ # properties that vary per endpoint, and strict property access causes false
55
+ # failures. Error handling is via try/catch + ErrorActionPreference Stop.
56
+ $ErrorActionPreference = "Stop"
57
+
58
+ # ─── Constants ─────────────────────────────────────────────────────────────
59
+ $ARM = "https://management.azure.com"
60
+ $API_ASSIGNMENTS = "2022-06-01"
61
+ $API_DEFINITIONS = "2021-06-01"
62
+ $API_EXEMPTIONS = "2022-07-01-preview"
63
+ $API_MG_DESCENDANTS = "2020-05-01"
64
+
65
+ $BLOCKER_EFFECTS = @("Deny")
66
+ $AUTO_REMEDIATE_EFFECTS = @("DeployIfNotExists", "Modify")
67
+ $RELEVANT_EFFECTS = $BLOCKER_EFFECTS + $AUTO_REMEDIATE_EFFECTS
68
+ $DEFENDER_ASSIGNED_BY = @("Security Center", "Microsoft Defender for Cloud")
69
+
70
+ # ─── ARM Token ───────────────────────────────────────────────────────────────
71
+ function Get-ArmToken {
72
+ $tokenJson = az account get-access-token --resource "$ARM" -o json 2>$null
73
+ if ($LASTEXITCODE -ne 0 -or -not $tokenJson) { throw "Failed to acquire ARM token via az account get-access-token" }
74
+ $token = $tokenJson | ConvertFrom-Json
75
+ if ([string]::IsNullOrWhiteSpace($token.accessToken)) { throw "ARM access token is empty" }
76
+ return $token.accessToken
77
+ }
78
+
79
+ function Invoke-ArmRest {
80
+ param([string]$Url, [string]$Token)
81
+ $headers = @{ Authorization = "Bearer $Token"; "Content-Type" = "application/json" }
82
+ $allValues = @()
83
+ $currentUrl = $Url
84
+ $visited = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
85
+ do {
86
+ $requestUri = $null
87
+ if (-not [uri]::TryCreate($currentUrl, [UriKind]::Absolute, [ref]$requestUri) -or
88
+ $requestUri.Scheme -ne "https" -or $requestUri.Authority -ne ([uri]$ARM).Authority -or
89
+ $requestUri.UserInfo -or $requestUri.Fragment) {
90
+ throw "Invalid ARM pagination URL: $currentUrl"
91
+ }
92
+ if (-not $visited.Add($requestUri.AbsoluteUri)) { throw "Repeated ARM pagination URL: $currentUrl" }
93
+ try {
94
+ $response = Invoke-RestMethod -Uri $currentUrl -Headers $headers -Method Get -ErrorAction Stop
95
+ }
96
+ catch {
97
+ throw "ARM REST call failed: $currentUrl - $_"
98
+ }
99
+ if ($null -eq $response -or $response.value -isnot [array]) {
100
+ throw "Invalid ARM list response: $currentUrl"
101
+ }
102
+ $allValues += $response.value
103
+ $nextLink = $response.nextLink
104
+ if ($null -ne $nextLink -and $nextLink -isnot [string]) {
105
+ throw "Invalid ARM nextLink: $currentUrl"
106
+ }
107
+ $currentUrl = $nextLink
108
+ } while ($currentUrl)
109
+ return $allValues
110
+ }
111
+
112
+ function Invoke-ArmRestSingle {
113
+ param([string]$Url, [string]$Token)
114
+ $headers = @{ Authorization = "Bearer $Token"; "Content-Type" = "application/json" }
115
+ try {
116
+ return Invoke-RestMethod -Uri $Url -Headers $headers -Method Get -ErrorAction Stop
117
+ }
118
+ catch {
119
+ throw "ARM REST single fetch failed: $Url - $_"
120
+ }
121
+ }
122
+
123
+ function Get-ArmPolicyDefinition {
124
+ param([string]$Id, [hashtable]$Cache, [string]$ResourceType = "policyDefinitions")
125
+
126
+ $idPattern = "^(?:/subscriptions/[^/?#]+|/providers/Microsoft.Management/managementGroups/[^/?#]+)?/providers/Microsoft.Authorization/$ResourceType/[^/?#]+$"
127
+ if ($Id -notmatch $idPattern) { throw "Invalid $ResourceType resource ID: $Id" }
128
+ $cacheKey = $Id.ToLowerInvariant()
129
+ if (-not $Cache.ContainsKey($cacheKey)) {
130
+ $Cache[$cacheKey] = Invoke-ArmRestSingle -Url "$ARM${Id}?api-version=$API_DEFINITIONS" -Token $Token
131
+ }
132
+ $definition = $Cache[$cacheKey]
133
+ if ($null -eq $definition -or $definition.id -ine $Id -or $null -eq $definition.properties) {
134
+ throw "Invalid $ResourceType response for $Id"
135
+ }
136
+ if ($ResourceType -eq "policySetDefinitions") {
137
+ if ($definition.properties.policyDefinitions -isnot [array]) { throw "Invalid initiative members for $Id" }
138
+ }
139
+ elseif (-not $definition.properties.policyRule.then.effect) {
140
+ throw "Missing policy effect for $Id"
141
+ }
142
+ return $definition
143
+ }
144
+
145
+ # ─── Classification ────────────────────────────────────────────────────────
146
+ function Get-EffectOf {
147
+ param($Defn, $Parameters, $Initiative, $Assignment, $MemberRefId)
148
+ $props = $Defn.properties
149
+ $eff = $props.policyRule.then.effect
150
+ $overridden = $false
151
+ $appliedOverride = $null
152
+ if ($null -ne $Assignment.properties.overrides -and $Assignment.properties.overrides -isnot [array]) {
153
+ throw "Invalid assignment overrides"
154
+ }
155
+ foreach ($override in $Assignment.properties.overrides) {
156
+ if ($override.kind -ne "policyEffect") { throw "Unsupported assignment override kind: $($override.kind)" }
157
+ if ($null -ne $override.selectors -and $override.selectors -isnot [array]) { throw "Invalid policy effect override selectors" }
158
+ $applies = $true
159
+ foreach ($selector in $override.selectors) {
160
+ if ($selector.kind -ne "policyDefinitionReferenceId" -or -not $Initiative) {
161
+ throw "Unsupported policy effect override selector: $($selector.kind)"
162
+ }
163
+ if (($null -ne $selector.in -and $selector.in -isnot [array]) -or
164
+ ($null -ne $selector.notIn -and $selector.notIn -isnot [array]) -or
165
+ ($null -eq $selector.in -and $null -eq $selector.notIn)) {
166
+ throw "Invalid policy effect override selector"
167
+ }
168
+ if ($null -ne $selector.in -and $MemberRefId -notin $selector.in) { $applies = $false }
169
+ if ($null -ne $selector.notIn -and $MemberRefId -in $selector.notIn) { $applies = $false }
170
+ }
171
+ if ($applies) {
172
+ if ($overridden) { throw "Overlapping policy effect overrides for $($Defn.id)" }
173
+ $eff = $override.value
174
+ $overridden = $true
175
+ $appliedOverride = $override
176
+ }
177
+ }
178
+ if (-not $overridden -and $eff -match "^\[parameters\('([^']+)'\)\]$") {
179
+ $paramName = $Matches[1]
180
+ $binding = if ($null -ne $Parameters) { $Parameters.PSObject.Properties[$paramName] } else { $null }
181
+ if ($null -ne $binding) {
182
+ $eff = $binding.Value.value
183
+ if ($Initiative -and $eff -is [string] -and $eff -match "^\[parameters\('([^']+)'\)\]$") {
184
+ $initiativeParamName = $Matches[1]
185
+ $assignmentParameters = $Assignment.properties.parameters
186
+ $assignmentBinding = if ($null -ne $assignmentParameters) { $assignmentParameters.PSObject.Properties[$initiativeParamName] } else { $null }
187
+ if ($null -ne $assignmentBinding) { $eff = $assignmentBinding.Value.value }
188
+ else { $eff = $Initiative.properties.parameters.$initiativeParamName.defaultValue }
189
+ }
190
+ }
191
+ else { $eff = $props.parameters.$paramName.defaultValue }
192
+ }
193
+ if ($eff -isnot [string] -or $eff -notin @("Deny", "DeployIfNotExists", "Modify", "Disabled", "Audit", "AuditIfNotExists", "Append", "Manual", "DenyAction", "Mutate")) {
194
+ throw "Unresolved or unsupported policy effect for $($Defn.id): $eff"
195
+ }
196
+ return @{ effect = [string]$eff; override = $appliedOverride }
197
+ }
198
+
199
+ function Get-Classification {
200
+ param([string]$Effect)
201
+ if ($BLOCKER_EFFECTS -contains $Effect) { return "blocker" }
202
+ if ($AUTO_REMEDIATE_EFFECTS -contains $Effect) { return "auto-remediate" }
203
+ return "informational"
204
+ }
205
+
206
+ function Get-EnforcementMode {
207
+ param($Assignment)
208
+ $property = $Assignment.properties.PSObject.Properties['enforcementMode']
209
+ if ($null -eq $property) { return "Default" }
210
+ $mode = $property.Value
211
+ if ($mode -isnot [string] -or $mode -cnotin @("Default", "DoNotEnforce")) {
212
+ throw "Unsupported assignment enforcementMode for $($Assignment.id)"
213
+ }
214
+ return $mode
215
+ }
216
+
217
+ function Test-IsDefenderAuto {
218
+ param($Assignment)
219
+ $props = $Assignment.properties
220
+ if (-not $props) { return $false }
221
+ if (-not $props.PSObject.Properties['metadata']) { return $false }
222
+ $metadata = $props.metadata
223
+ if (-not $metadata -or -not $metadata.PSObject.Properties['assignedBy']) { return $false }
224
+ $assignedBy = $metadata.assignedBy
225
+ if (-not $assignedBy) { return $false }
226
+ return ($DEFENDER_ASSIGNED_BY -contains $assignedBy)
227
+ }
228
+
229
+ function Get-ResourceTypes {
230
+ param($Defn)
231
+ $types = @()
232
+ $rule = $Defn.properties.policyRule
233
+ if (-not $rule) { return $types }
234
+ $ruleJson = $rule | ConvertTo-Json -Depth 20 -Compress
235
+ $matches = [regex]::Matches($ruleJson, '"type"\s*:\s*"(Microsoft\.\w+/\w+(?:/\w+)?)"')
236
+ foreach ($m in $matches) {
237
+ $t = $m.Groups[1].Value
238
+ if ($types -notcontains $t) { $types += $t }
239
+ }
240
+ return $types
241
+ }
242
+
243
+ function Get-RequiredValue {
244
+ param($Defn)
245
+ $rule = $Defn.properties.policyRule
246
+ if (-not $rule) { return $null }
247
+ $then = $rule.then
248
+ if (-not $then -or -not $then.details) { return $null }
249
+ $val = $then.details.value
250
+ if ($null -ne $val) { return $val }
251
+ $existCond = $then.details.existenceCondition
252
+ if ($existCond) {
253
+ $condJson = $existCond | ConvertTo-Json -Depth 10 -Compress
254
+ $valMatch = [regex]::Match($condJson, '"(?:equals|in)"\s*:\s*(\[.*?\]|"[^"]*"|\d+|true|false)')
255
+ if ($valMatch.Success) { return $valMatch.Groups[1].Value }
256
+ }
257
+ return $null
258
+ }
259
+
260
+ function Get-PropertyPaths {
261
+ param($Defn, $ResourceTypes)
262
+ $result = @{ azurePropertyPath = $null; bicepPropertyPath = $null; pathSemantics = $null }
263
+ $rule = $Defn.properties.policyRule
264
+ if (-not $rule) { return $result }
265
+ $ruleJson = $rule | ConvertTo-Json -Depth 20 -Compress
266
+ # Look for field conditions
267
+ $fieldMatch = [regex]::Match($ruleJson, '"field"\s*:\s*"([^"]+)"')
268
+ if ($fieldMatch.Success) {
269
+ $field = $fieldMatch.Groups[1].Value
270
+ if ($field -match '^Microsoft\.' -or $field -match '^\[') { return $result }
271
+ if ($field -match 'tags\[') {
272
+ $result.pathSemantics = "tag-policy-non-property"
273
+ return $result
274
+ }
275
+ $result.azurePropertyPath = "properties.$field"
276
+ $bicep = $field -replace '\.', '.'
277
+ $result.bicepPropertyPath = $bicep
278
+ }
279
+ return $result
280
+ }
281
+
282
+ function Get-TagsRequired {
283
+ param($Findings)
284
+ $seen = @{}
285
+ $tags = @()
286
+ foreach ($f in $Findings) {
287
+ $isTag = ($f.pathSemantics -eq "tag-policy-non-property") -or (($f.category -split '\s')[0] -ieq "Tags")
288
+ if (-not $isTag) { continue }
289
+ $params = $f.assignment_parameters
290
+ $tagKeys = @()
291
+ foreach ($pn in @("tagName", "tagname", "tag_name")) {
292
+ if ($params -and $params.$pn) {
293
+ $v = $params.$pn
294
+ if ($v -is [string]) { $tagKeys += $v }
295
+ elseif ($v -is [array]) { $tagKeys += $v }
296
+ }
297
+ }
298
+ foreach ($pn in @("tagNames", "listOfTagNames", "tagnames")) {
299
+ if ($params -and $params.$pn -and $params.$pn -is [array]) {
300
+ $tagKeys += $params.$pn
301
+ }
302
+ }
303
+ if ($tagKeys.Count -gt 0) {
304
+ foreach ($key in $tagKeys) {
305
+ $key = $key.Trim()
306
+ if ($key -and -not $seen.ContainsKey($key)) {
307
+ $seen[$key] = $true
308
+ $tags += @{ name = $key; source_policy = $f.policy_id; source_assignment = $f.assignment_display_name }
309
+ }
310
+ }
311
+ }
312
+ else {
313
+ $policyName = ($f.display_name -split '\s')[0..99] -join ' '
314
+ if ($policyName -and -not $seen.ContainsKey($policyName)) {
315
+ $seen[$policyName] = $true
316
+ $tags += @{ name = "[unresolved: $policyName]"; source_policy = $f.policy_id; source_assignment = $f.assignment_display_name; unresolved = "true" }
317
+ }
318
+ }
319
+ }
320
+ return $tags
321
+ }
322
+
323
+ function Get-AllowedLocations {
324
+ param($Findings)
325
+ $locations = [System.Collections.Generic.HashSet[string]]::new()
326
+ foreach ($f in $Findings) {
327
+ $dn = ($f.display_name -replace '\s', ' ').ToLower()
328
+ $cat = ($f.category -replace '\s', ' ').ToLower()
329
+ $isLocation = ($dn -match 'location') -or ($dn -match 'region') -or ($cat -match 'location')
330
+ if ($isLocation) {
331
+ $rv = $f.required_value
332
+ if ($rv -is [array]) { foreach ($v in $rv) { [void]$locations.Add([string]$v) } }
333
+ elseif ($rv -is [string] -and $rv) { [void]$locations.Add($rv) }
334
+ }
335
+ $params = $f.assignment_parameters
336
+ if ($params) {
337
+ foreach ($pn in @("listOfAllowedLocations", "allowedLocations", "listofallowedlocations", "allowedlocations")) {
338
+ if ($params.$pn -is [array]) {
339
+ foreach ($v in $params.$pn) { if ($v) { [void]$locations.Add([string]$v) } }
340
+ }
341
+ }
342
+ }
343
+ }
344
+ return ($locations | Sort-Object)
345
+ }
346
+
347
+ # ─── Process a single subscription ──────────────────────────────────────────
348
+ function Process-Subscription {
349
+ param([string]$SubId, [string]$Token)
350
+
351
+ $base = "$ARM/subscriptions/$SubId/providers/Microsoft.Authorization"
352
+ # Policy assignment and exemption names may contain inner spaces, for example "(ArcBox) Tag resources".
353
+ $POLICY_RESOURCE_NAME = '[^/?#%\s\p{Cc}](?:[^/?#%\p{Cc}]*[^/?#%\s\p{Cc}])?'
354
+ $scopePattern = if ($IncludeDescendants) { "(/subscriptions/$SubId(?:/resourceGroups/[^/?#%\s]+)?(?:/providers/[^/?#%\s]+(?:/[^/?#%\s]+/[^/?#%\s]+)+)*|/providers/Microsoft.Management/managementGroups/[^/?#%\s]+)" } else { '(/subscriptions/[0-9a-f-]{36}|/providers/Microsoft.Management/managementGroups/[^/?#\s]+)' }
355
+
356
+ $scopeFilter = if ($IncludeDescendants) { "" } else { '$filter=atScope()&' }
357
+ $assignments = Invoke-ArmRest -Url "$base/policyAssignments?${scopeFilter}api-version=$API_ASSIGNMENTS" -Token $Token
358
+ $subDefs = Invoke-ArmRest -Url "$base/policyDefinitions?api-version=$API_DEFINITIONS" -Token $Token
359
+ $subSets = Invoke-ArmRest -Url "$base/policySetDefinitions?api-version=$API_DEFINITIONS" -Token $Token
360
+ $exemptions = Invoke-ArmRest -Url "$base/policyExemptions?${scopeFilter}api-version=$API_EXEMPTIONS" -Token $Token
361
+
362
+ $defs = @{}
363
+ foreach ($d in $subDefs) { $defs[($d.id).ToLower()] = $d }
364
+ $sets = @{}
365
+ foreach ($s in $subSets) { $sets[($s.id).ToLower()] = $s }
366
+
367
+ # Build exemption map
368
+ $exemptionMap = @{}
369
+ $collectionTime = [DateTimeOffset]::UtcNow
370
+ $expiredExemptionCount = 0
371
+ foreach ($ex in $exemptions) {
372
+ $exProps = $ex.properties
373
+ if (-not $exProps -or -not $exProps.policyAssignmentId -or $exProps.exemptionCategory -notin @("Waiver", "Mitigated")) {
374
+ throw "Invalid policy exemption"
375
+ }
376
+ if ($ex.id -isnot [string] -or $ex.id -notmatch "^$scopePattern/providers/Microsoft.Authorization/policyExemptions/$POLICY_RESOURCE_NAME\z") {
377
+ throw "Invalid or unsupported policy exemption scope"
378
+ }
379
+ $exemptionScope = $Matches[1]
380
+ if ($exProps.policyAssignmentId -isnot [string] -or $exProps.policyAssignmentId -notmatch "^$scopePattern/providers/Microsoft.Authorization/policyAssignments/$POLICY_RESOURCE_NAME\z") {
381
+ throw "Invalid policy exemption assignment identity"
382
+ }
383
+ $assignmentScope = $Matches[1]
384
+ if ($IncludeDescendants -and $assignmentScope -notmatch '^/providers/Microsoft.Management/' -and
385
+ $exemptionScope -ine $assignmentScope -and -not $exemptionScope.StartsWith("$assignmentScope/", [StringComparison]::OrdinalIgnoreCase)) {
386
+ throw "Policy exemption scope is outside its assignment"
387
+ }
388
+ if (-not ($IncludeDescendants -and $exemptionScope.StartsWith("/subscriptions/$SubId/", [StringComparison]::OrdinalIgnoreCase)) -and $exemptionScope -ine "/subscriptions/$SubId" -and
389
+ ($exemptionScope -notmatch '^/providers/Microsoft.Management/managementGroups/' -or $exemptionScope -ine $assignmentScope)) {
390
+ throw "Policy exemption scope does not cover the collected subscription"
391
+ }
392
+ if ($null -ne $exProps.expiresOn) {
393
+ $expiresAt = [DateTimeOffset]::MinValue
394
+ if ($exProps.expiresOn -is [datetime]) {
395
+ if ($exProps.expiresOn.Kind -eq [DateTimeKind]::Unspecified) { throw "Invalid policy exemption expiresOn timezone" }
396
+ $expiresAt = [DateTimeOffset]$exProps.expiresOn
397
+ }
398
+ elseif ($exProps.expiresOn -isnot [string] -or
399
+ $exProps.expiresOn -notmatch '^\d{4}-\d{2}-\d{2}T.+(?:Z|[+-]\d{2}:\d{2})$' -or
400
+ -not [DateTimeOffset]::TryParse($exProps.expiresOn, [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::None, [ref]$expiresAt)) {
401
+ throw "Invalid policy exemption expiresOn"
402
+ }
403
+ if ($expiresAt -le $collectionTime) { $expiredExemptionCount++; continue }
404
+ }
405
+ if ($exProps.resourceSelectors) { throw "Unsupported policy exemption resourceSelectors" }
406
+ if ($null -ne $exProps.policyDefinitionReferenceIds -and $exProps.policyDefinitionReferenceIds -isnot [array]) {
407
+ throw "Invalid policy exemption member references"
408
+ }
409
+ $asgId = $exProps.policyAssignmentId.ToLower()
410
+ $exemptionMap[$asgId] = @($exemptionMap[$asgId]) + @(@{
411
+ id = $ex.id
412
+ scope = $exemptionScope
413
+ expiresOn = $exProps.expiresOn
414
+ category = $exProps.exemptionCategory
415
+ policyDefinitionReferenceIds = $exProps.policyDefinitionReferenceIds
416
+ })
417
+ }
418
+
419
+ # Filter Defender auto-assignments
420
+ $filteredDefender = @()
421
+ $keptAssignments = @()
422
+ $notScopeExcludedCount = 0
423
+ $targetScope = "/subscriptions/$SubId"
424
+ foreach ($a in $assignments) {
425
+ if ($IncludeDescendants -and ($a.properties.scope -notmatch "^$scopePattern\z" -or $a.properties.scope -match '/\.{1,2}(?:/|$)')) {
426
+ throw "Invalid policy assignment scope"
427
+ }
428
+ if ($a.id -isnot [string] -or $a.id -notmatch "^(.+)/providers/Microsoft.Authorization/policyAssignments/$POLICY_RESOURCE_NAME\z" -or
429
+ $Matches[1] -ine $a.properties.scope) {
430
+ throw "Invalid policy assignment identity"
431
+ }
432
+ $notScopes = $a.properties.notScopes
433
+ if ($null -ne $notScopes -and $notScopes -isnot [array]) { throw "Invalid assignment notScopes" }
434
+ $normalizedNotScopes = @(
435
+ foreach ($excludedScope in $notScopes) {
436
+ if ($excludedScope -isnot [string] -or $excludedScope -notmatch '^/(?:subscriptions/[0-9a-f-]{36}(?:/[^?#]+)?|providers/Microsoft.Management/managementGroups/[^/?#]+?)/?\z') {
437
+ throw "Invalid assignment notScopes entry"
438
+ }
439
+ $excludedScope.TrimEnd('/')
440
+ }
441
+ )
442
+ if ($targetScope -in $normalizedNotScopes -or $a.properties.scope -in $normalizedNotScopes) {
443
+ $notScopeExcludedCount++
444
+ continue
445
+ }
446
+ foreach ($excludedScope in $normalizedNotScopes) {
447
+ if ($excludedScope.StartsWith("$targetScope/", [StringComparison]::OrdinalIgnoreCase)) {
448
+ throw "Partial subscription notScopes cannot be represented: $excludedScope"
449
+ }
450
+ if ($excludedScope -notmatch '^/subscriptions/') {
451
+ throw "Unresolved management group notScopes: $excludedScope"
452
+ }
453
+ }
454
+ if ($a.properties.resourceSelectors) { throw "Unsupported assignment resourceSelectors" }
455
+ if ($null -ne $a.properties.PSObject.Properties['definitionVersion']) {
456
+ throw "Unsupported assignment definitionVersion"
457
+ }
458
+ $null = Get-EnforcementMode $a
459
+ if ((Test-IsDefenderAuto $a) -and -not $IncludeDefenderAuto -and -not $IncludeDescendants) {
460
+ $filteredDefender += ($a.properties.displayName ?? $a.name ?? $a.id ?? "<unknown>")
461
+ }
462
+ else { $keptAssignments += $a }
463
+ }
464
+
465
+ $assignmentInventory = @()
466
+ $findings = @()
467
+ $auditCount = 0
468
+ $disabledCount = 0
469
+ $classifiedPolicyCount = 0
470
+ $otherEffectCount = 0
471
+
472
+ foreach ($a in $keptAssignments) {
473
+ $props = $a.properties
474
+ $display = $props.displayName ?? $a.name ?? $a.id ?? "<unknown>"
475
+ $scope = $props.scope ?? ""
476
+ $policyDefId = ($props.policyDefinitionId ?? "").ToLower()
477
+ $assignmentId = ($a.id ?? "").ToLower()
478
+ $assignmentType = if ($scope.ToLower() -match '/providers/microsoft.management/managementgroups/') { "management-group" } else { "subscription" }
479
+ $enforcementMode = Get-EnforcementMode $a
480
+
481
+ $assignmentInventory += @{
482
+ assignmentId = $a.id
483
+ displayName = $display
484
+ scope = $scope
485
+ assignmentType = $assignmentType
486
+ policyDefinitionId = $policyDefId
487
+ enforcementMode = $enforcementMode
488
+ }
489
+
490
+ if (-not $policyDefId) { throw "Missing policyDefinitionId for assignment $assignmentId" }
491
+
492
+ # Resolve members
493
+ $members = @()
494
+ $policySet = $null
495
+ if ($policyDefId -match '/policysetdefinitions/') {
496
+ $policySet = Get-ArmPolicyDefinition -Id $policyDefId -Cache $sets -ResourceType "policySetDefinitions"
497
+ foreach ($setMember in $policySet.properties.policyDefinitions) {
498
+ if ($null -ne $setMember.PSObject.Properties['definitionVersion']) {
499
+ throw "Unsupported initiative member definitionVersion"
500
+ }
501
+ $memberDefinition = Get-ArmPolicyDefinition -Id $setMember.policyDefinitionId -Cache $defs
502
+ $members += @{ defn = $memberDefinition; memberRefId = $setMember.policyDefinitionReferenceId; parameters = $setMember.parameters }
503
+ }
504
+ }
505
+ else {
506
+ $policyDefinition = Get-ArmPolicyDefinition -Id $policyDefId -Cache $defs
507
+ $members += @{ defn = $policyDefinition; memberRefId = $null; parameters = $props.parameters }
508
+ }
509
+
510
+ foreach ($member in $members) {
511
+ $defn = $member.defn
512
+ $memberRefId = $member.memberRefId
513
+ $effectivePolicy = Get-EffectOf -Defn $defn -Parameters $member.parameters -Initiative $policySet -Assignment $a -MemberRefId $memberRefId
514
+ $eff = $effectivePolicy.effect
515
+ $classifiedPolicyCount++
516
+ if ($eff -eq "Disabled") { $disabledCount++; if (-not $IncludeDescendants) { continue } }
517
+ if ($eff -in @("Audit", "AuditIfNotExists")) { $auditCount++; if (-not $IncludeDescendants) { continue } }
518
+ if ($IncludeDescendants -and $eff -notin ($RELEVANT_EFFECTS + @("Disabled", "Audit", "AuditIfNotExists", "Append"))) { throw "Unsupported policy effect" }
519
+ if (-not $IncludeDescendants -and $eff -notin $RELEVANT_EFFECTS) { $otherEffectCount++; continue }
520
+
521
+ $rtypes = Get-ResourceTypes $defn
522
+ $paths = Get-PropertyPaths $defn $rtypes
523
+ $category = $defn.properties.metadata.category ?? "Uncategorized"
524
+
525
+ $exemption = $null
526
+ $reportedExemptions = @()
527
+ if ($exemptionMap.ContainsKey($assignmentId)) {
528
+ foreach ($candidate in $exemptionMap[$assignmentId]) {
529
+ if ($null -eq $candidate) { continue }
530
+ $refIds = $candidate.policyDefinitionReferenceIds
531
+ if (-not $refIds -or $memberRefId -in $refIds) {
532
+ $reportedExemptions += $candidate
533
+ if (-not $IncludeDescendants) {
534
+ $exemption = $candidate
535
+ }
536
+ if (-not $IncludeDescendants) { break }
537
+ }
538
+ }
539
+ }
540
+
541
+ $classification = Get-Classification $eff
542
+ if ($exemption) { $classification = "informational" }
543
+
544
+ $effectLower = $eff.Substring(0,1).ToLower() + $eff.Substring(1)
545
+
546
+ $finding = [ordered]@{
547
+ policy_id = $defn.id
548
+ display_name = $defn.properties.displayName ?? $defn.name ?? $defn.id
549
+ effect = $effectLower
550
+ enforcementMode = $enforcementMode
551
+ scope = $scope
552
+ assignment_display_name = $display
553
+ assignment_id = $a.id
554
+ classification = $classification
555
+ category = $category
556
+ resource_types = @($rtypes)
557
+ required_value = (Get-RequiredValue $defn)
558
+ azurePropertyPath = $paths.azurePropertyPath
559
+ bicepPropertyPath = $paths.bicepPropertyPath
560
+ exemption = $exemption
561
+ override = $effectivePolicy.override
562
+ }
563
+ if ($policySet) { $finding.policyDefinitionReferenceId = $memberRefId }
564
+ if ($IncludeDescendants) { $finding.reported_exemptions = @($reportedExemptions) }
565
+
566
+ # Assignment parameters
567
+ $assignmentParams = $props.parameters
568
+ $paramValues = [ordered]@{}
569
+ $parameterSource = if ($policySet) { $policySet } else { $defn }
570
+ foreach ($parameter in $parameterSource.properties.parameters.PSObject.Properties) {
571
+ if ($parameter.Value.PSObject.Properties['defaultValue']) {
572
+ $paramValues[$parameter.Name] = $parameter.Value.defaultValue
573
+ }
574
+ }
575
+ foreach ($parameter in $assignmentParams.PSObject.Properties) {
576
+ $paramValues[$parameter.Name] = $parameter.Value.value
577
+ }
578
+ if ($policySet) {
579
+ $memberValues = [ordered]@{}
580
+ foreach ($parameter in $defn.properties.parameters.PSObject.Properties) {
581
+ if ($parameter.Value.PSObject.Properties['defaultValue']) {
582
+ $memberValues[$parameter.Name] = $parameter.Value.defaultValue
583
+ }
584
+ }
585
+ foreach ($parameter in $member.parameters.PSObject.Properties) {
586
+ $val = $parameter.Value.value
587
+ if ($val -is [string] -and $val -match "^\[parameters\('([^']+)'\)\]$" -and $paramValues.Contains($Matches[1])) {
588
+ $val = $paramValues[$Matches[1]]
589
+ }
590
+ $memberValues[$parameter.Name] = $val
591
+ }
592
+ # A member's rule reads only its own parameters, already resolved from the initiative's values.
593
+ # Storing every initiative parameter on every member made baselines too large to import.
594
+ $paramValues = $memberValues
595
+ }
596
+ if ($paramValues.Count -gt 0) { $finding.assignment_parameters = $paramValues }
597
+ if ($paths.pathSemantics) { $finding.pathSemantics = $paths.pathSemantics }
598
+ $findings += $finding
599
+ }
600
+ }
601
+
602
+ $blockerCount = @($findings | Where-Object { $_.classification -eq "blocker" }).Count
603
+ $autoRemediateCount = @($findings | Where-Object { $_.classification -eq "auto-remediate" }).Count
604
+ $exemptedCount = @($findings | Where-Object { $null -ne $_.exemption }).Count
605
+ $infoCount = @($findings | Where-Object { $_.classification -eq "informational" }).Count
606
+ $subScopeCount = ($keptAssignments | Where-Object { $_.properties.scope -and $_.properties.scope.ToLower() -notmatch '/providers/microsoft.management/' }).Count
607
+ $mgInheritedCount = ($keptAssignments | Where-Object { $_.properties.scope -and $_.properties.scope.ToLower() -match '/providers/microsoft.management/' }).Count
608
+
609
+ $tagsRequired = Get-TagsRequired $findings
610
+ $allowedLocations = Get-AllowedLocations $findings
611
+
612
+ # L0 attestation envelope (plan-optimiseGovernanceAgent.prompt.md Phase 3b).
613
+ # We emit every field except `completeness_signature` here; the cached
614
+ # renderer recomputes the signature via the canonical Python helper so
615
+ # the cached path stays byte-identical to the live path for the same
616
+ # upstream findings (F2 decision — single signature algorithm).
617
+ $discoveredAtIso = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ" -AsUTC)
618
+ $managementGroups = @(
619
+ $keptAssignments
620
+ | Where-Object { $_.properties.scope -and ($_.properties.scope.ToLower() -match '/providers/microsoft.management/managementgroups/') }
621
+ | ForEach-Object {
622
+ $marker = '/providers/microsoft.management/managementgroups/'
623
+ $scope = $_.properties.scope.ToLower()
624
+ ($scope -split [regex]::Escape($marker), 2)[1] -split '/', 2 | Select-Object -First 1
625
+ }
626
+ | Where-Object { $_ }
627
+ | Select-Object -Unique
628
+ )
629
+ $discoveryMetadata = [ordered]@{
630
+ discovery_status = "COMPLETE"
631
+ discovered_at = $discoveredAtIso
632
+ scope = [ordered]@{
633
+ subscription_id = $SubId
634
+ management_groups = @($managementGroups)
635
+ }
636
+ api_versions = [ordered]@{
637
+ policyAssignments = $API_ASSIGNMENTS
638
+ policyDefinitions = $API_DEFINITIONS
639
+ policyExemptions = $API_EXEMPTIONS
640
+ }
641
+ page_counts = [ordered]@{
642
+ policyAssignments = $assignments.Count
643
+ policyDefinitions = $defs.Count
644
+ policyExemptions = $exemptions.Count
645
+ }
646
+ # Left blank intentionally — render_cached_governance.py recomputes
647
+ # this via the canonical _completeness_signature helper.
648
+ completeness_signature = ""
649
+ ttl_days = 30
650
+ }
651
+ if ($IncludeDescendants) { $discoveryMetadata.scope.coverage = "subscription-and-descendants-v1" }
652
+
653
+ return [ordered]@{
654
+ schema_version = "governance-constraints-v1"
655
+ subscription_id = $SubId
656
+ discovered_at = $discoveredAtIso
657
+ source = "github-actions-baseline"
658
+ discovery_status = "COMPLETE"
659
+ discovery_metadata = $discoveryMetadata
660
+ discovery_summary = [ordered]@{
661
+ assignment_total = $assignments.Count
662
+ assignment_kept = $keptAssignments.Count
663
+ defender_auto_filtered = $filteredDefender.Count
664
+ not_scope_excluded = $notScopeExcludedCount
665
+ expired_exemption_count = $expiredExemptionCount
666
+ subscription_scope_count = $subScopeCount
667
+ management_group_inherited_count = $mgInheritedCount
668
+ blocker_count = $blockerCount
669
+ auto_remediate_count = $autoRemediateCount
670
+ informational_count = $infoCount
671
+ audit_count = $auditCount
672
+ disabled_count = $disabledCount
673
+ classified_policy_count = $classifiedPolicyCount
674
+ other_effect_count = $otherEffectCount
675
+ exempted_count = $exemptedCount
676
+ }
677
+ assignment_inventory = @($assignmentInventory)
678
+ findings = @($findings)
679
+ tags_required = @($tagsRequired)
680
+ allowed_locations = @($allowedLocations)
681
+ }
682
+ }
683
+
684
+ # ─── Main ────────────────────────────────────────────────────────────────────
685
+ $standalone = $PSCmdlet.ParameterSetName -eq "Subscription"
686
+ Write-Host "Governance Baseline Collector: $(if ($standalone) { $SubscriptionId } else { $ManagementGroupId })"
687
+
688
+ $token = Get-ArmToken
689
+ Write-Host "ARM token acquired"
690
+
691
+ # Discover descendant subscriptions
692
+ if ($standalone) {
693
+ $allSubs = @([pscustomobject]@{ name = $SubscriptionId })
694
+ }
695
+ else {
696
+ $descendantsUrl = "$ARM/providers/Microsoft.Management/managementGroups/$ManagementGroupId/descendants?api-version=$API_MG_DESCENDANTS"
697
+ $descendants = Invoke-ArmRest -Url $descendantsUrl -Token $token
698
+ $allSubs = @($descendants | Where-Object { $_.type -eq "Microsoft.Management/managementGroups/subscriptions" } | Sort-Object { $_.name })
699
+ Write-Host "Discovered $($allSubs.Count) subscriptions under MG: $ManagementGroupId"
700
+ }
701
+
702
+ # Exclusion checks
703
+ $subscriptionsExcluded = @()
704
+ $eligibleSubs = @()
705
+ foreach ($sub in $allSubs) {
706
+ $subId = $sub.name
707
+ try {
708
+ $subDetail = Invoke-RestMethod -Uri "$ARM/subscriptions/${subId}?api-version=2022-12-01" `
709
+ -Headers @{ Authorization = "Bearer $token"; "Content-Type" = "application/json" } `
710
+ -Method Get -ErrorAction Stop
711
+ }
712
+ catch {
713
+ throw "Failed to read subscription $subId - $_"
714
+ }
715
+ $state = $subDetail.subscriptionPolicies.spendingLimit ?? $subDetail.state ?? "Unknown"
716
+ if ($standalone -and $subDetail.state -ne "Enabled") {
717
+ throw "Standalone subscription $subId is not enabled"
718
+ }
719
+ if ($subDetail.state -eq "Disabled") {
720
+ $subscriptionsExcluded += [ordered]@{ subscription_id = $subId; reason = "disabled" }
721
+ Write-Warning "Excluding $subId — disabled"
722
+ continue
723
+ }
724
+ $quotaId = $subDetail.subscriptionPolicies.quotaId ?? ""
725
+ if ($quotaId -like "AAD_*") {
726
+ if ($standalone) { throw "Standalone subscription $subId has AAD quota: $quotaId" }
727
+ $subscriptionsExcluded += [ordered]@{ subscription_id = $subId; reason = "AAD_quota"; quota_id = $quotaId }
728
+ Write-Warning "Excluding $subId — AAD quota: $quotaId"
729
+ continue
730
+ }
731
+ $eligibleSubs += $subId
732
+ }
733
+
734
+ # Apply cap
735
+ $subscriptionsSkipped = @()
736
+ $subsToProcess = $eligibleSubs
737
+ if ($eligibleSubs.Count -gt $MaxSubscriptions) {
738
+ $subsToProcess = $eligibleSubs[0..($MaxSubscriptions - 1)]
739
+ $subscriptionsSkipped = $eligibleSubs[$MaxSubscriptions..($eligibleSubs.Count - 1)]
740
+ Write-Warning "Cap applied: processing $MaxSubscriptions of $($eligibleSubs.Count) eligible. Skipping $($subscriptionsSkipped.Count)."
741
+ }
742
+
743
+ $coverageStatus = if ($subscriptionsSkipped.Count -gt 0) { "PARTIAL" } else { "COMPLETE" }
744
+
745
+ $baselineFile = Join-Path $OutputDir "governance-policy-baseline.json"
746
+
747
+ # Process subscriptions
748
+ $subscriptions = [ordered]@{}
749
+ $totalProcessed = 0
750
+ $subIndex = 0
751
+ foreach ($subId in $subsToProcess) {
752
+ $subIndex++
753
+ Write-Host "Processing subscription ${subIndex}/$($subsToProcess.Count): $subId"
754
+ try {
755
+ $envelope = Process-Subscription -SubId $subId -Token $token
756
+ }
757
+ catch {
758
+ throw "Failed to process subscription $subId - $_"
759
+ }
760
+
761
+ $subscriptions[$subId] = $envelope
762
+ $totalProcessed++
763
+ }
764
+
765
+ # Build summary
766
+ $totalBlockers = 0
767
+ $totalAutoRemediate = 0
768
+ $totalFindings = 0
769
+ foreach ($sub in $subscriptions.Values) {
770
+ $totalBlockers += $sub.discovery_summary.blocker_count
771
+ $totalAutoRemediate += $sub.discovery_summary.auto_remediate_count
772
+ $totalFindings += $sub.findings.Count
773
+ }
774
+
775
+ $baseline = [ordered]@{
776
+ schema_version = "governance-baseline-v2"
777
+ coverage_status = $coverageStatus
778
+ subscriptions_discovered = $allSubs.Count
779
+ subscriptions_processed = $totalProcessed
780
+ subscriptions_skipped = @($subscriptionsSkipped)
781
+ subscriptions_excluded = @($subscriptionsExcluded)
782
+ summary = [ordered]@{
783
+ total_findings = $totalFindings
784
+ total_blockers = $totalBlockers
785
+ total_auto_remediate = $totalAutoRemediate
786
+ subscriptions_complete = $totalProcessed
787
+ }
788
+ subscriptions = $subscriptions
789
+ }
790
+ if ($standalone) { $baseline.subscription_id = $SubscriptionId }
791
+ else { $baseline.management_group_id = $ManagementGroupId }
792
+
793
+ # Write output
794
+ New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
795
+ $baselineFile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($baselineFile)
796
+ $stagingFile = Join-Path ([System.IO.Path]::GetDirectoryName($baselineFile)) ".governance-policy-baseline.$([guid]::NewGuid().ToString('N')).tmp"
797
+ try {
798
+ $baselineJson = $baseline | ConvertTo-Json -Depth 50
799
+ $baselineJson | Set-Content -LiteralPath $stagingFile -NoNewline
800
+ [System.IO.File]::Move($stagingFile, $baselineFile, $true)
801
+ }
802
+ finally {
803
+ [System.IO.File]::Delete($stagingFile)
804
+ }
805
+ Write-Host "Wrote baseline: $baselineFile"
806
+
807
+ # Write raw debug file (gitignored — not committed)
808
+ $rawFile = Join-Path $OutputDir "governance-policy-raw.json"
809
+ try {
810
+ $baseline | ConvertTo-Json -Depth 100 | Set-Content -LiteralPath $rawFile -NoNewline
811
+ Write-Host "Wrote raw debug: $rawFile (gitignored)"
812
+ }
813
+ catch {
814
+ Write-Warning "Could not write optional raw debug file: $_" -WarningAction Continue
815
+ }
816
+
817
+ Write-Host "Done. Coverage: $coverageStatus | Processed: $totalProcessed | Excluded: $($subscriptionsExcluded.Count) | Skipped: $($subscriptionsSkipped.Count)"