Repository navigation
feat(scripts): Ship ALZ Corp default governance baseline - #762
Conversation
Replace the committed real-tenant baseline with an offline-generated ALZ Corp default: the root, landing_zones and corp archetypes of the pinned platform/alz/2026.10.0 library, resolved with built-in definitions from a pinned azure-policy commit. The generator reuses discover.discover through an offline REST adapter so classification matches a live run. discover.py now evaluates the initiative member pattern if(contains(list, type), effect, 'Disabled') and treats enforceSetting like Append, so these definitions no longer leave discovery PARTIAL. Assignments shipped as DoNotEnforce are kept as informational. The renderer labels the result as assumed governance and stamps the render time, and the loader gains --alz-default.
Phase 0.45 offers the user a choice between live discovery and the shipped ALZ Corp default when the target subscription is absent from the baseline. Choosing the default is recorded as assumed, labelled in the artifacts, and keeps the Step 3.5 review mandatory. The discovery instructions carry the single exception to the no-assumptions rule.
There was a problem hiding this comment.
🟡 Changes recommended
The review found unresolved scope, provenance-validation, and collector-parity defects.
4 open findings
What changed in this PR
Ships an offline ALZ Corp governance baseline for projects without tenant discovery access.
Changes:
- Adds deterministic ALZ baseline generation and provenance.
- Supports explicit assumed-governance rendering.
- Extends policy-effect resolution, schemas, documentation, and tests.
| File | Description |
|---|---|
.github/data/governance-policy-baseline.json.gz |
Stores the generated ALZ baseline. |
tools/scripts/audit-retirement-candidates.mjs |
Registers baseline generation ownership. |
tools/schemas/governance-constraints.schema.json |
Allows the ALZ source type. |
tools/schemas/governance-baseline.schema.json |
Adds ALZ provenance fields. |
package.json |
Adds generation and test commands. |
test_generate_alz_baseline.py |
Tests generation and rendering. |
render_governance.py |
Labels assumed governance in previews. |
render_cached_governance.py |
Handles ALZ baseline rendering. |
governance_baseline.py |
Extracts the synthetic default entry. |
generate_alz_baseline.py |
Generates the pinned offline baseline. |
discover.py |
Resolves conditional effects. |
baseline-check.md |
Documents default-baseline selection. |
governance-discovery.instructions.md |
Permits the explicit assumed-governance exception. |
04g-governance.agent.md |
Routes ALZ baselines through Phase 0.45. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| conditional = _CONDITIONAL_EFFECT.fullmatch(value.strip()) | ||
| if conditional: | ||
| container = normalized.get(conditional.group(1).lower()) | ||
| chosen = normalized.get(conditional.group(3).lower()) | ||
| if isinstance(container, list) and chosen is not None: | ||
| listed = {str(item).lower() for item in container} | ||
| return chosen if conditional.group(2).lower() in listed else conditional.group(4) |
There was a problem hiding this comment.
Not porting this here; the PowerShell collector has wider gaps than the conditional expression (member parameters, assignment overrides, PARTIAL reporting) and the shipped baseline comes from the Python path. Tracked in #763 so the collectors can be aligned as one change with a shared fixture test.
| if args.library_dir: | ||
| library_root = args.library_dir | ||
| else: | ||
| library_root = _extract(LIBRARY_URL, tmp_path / "lib", ("/platform/alz/",)) | ||
| if args.builtins_dir: | ||
| builtins_dir = args.builtins_dir |
There was a problem hiding this comment.
Fixed in b4e0872 (the commit subject there is stale; the content is the change below). --library-dir now requires --library-ref and --builtins-dir requires --azure-policy-ref, and a ref without its directory is rejected. The supplied refs flow into build_baseline, the top-level fields and the provenance, so a local tree can no longer be stamped with the pinned release. Covered by test_local_source_trees_require_explicit_refs.
| if envelope.get("source") == "alz-corp-default": | ||
| # Static policy set, evaluated now; the generation date says nothing about tenant freshness. | ||
| rendered_at = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ") | ||
| envelope["discovered_at"] = rendered_at | ||
| if isinstance(envelope.get("discovery_metadata"), dict): | ||
| envelope["discovery_metadata"]["discovered_at"] = rendered_at |
There was a problem hiding this comment.
Fixed in b4e0872. render_cached_governance.py now requires --subscription <guid> for the alz-corp-default source (exit 2 with subscription-required otherwise), rebinds subscription_id and discovery_metadata.scope.subscription_id to it, and keeps the synthetic ID only as provenance.baseline_subscription_id. baseline-check.md documents the argument; tests cover the rebinding and the rejection cases.
| "baseline_kind": { | ||
| "type": "string", | ||
| "description": "Absent for a tenant baseline collected by the workflow. alz-corp-default marks the shipped, offline-generated ALZ Corp policy set, which is assumed governance and not verified against any tenant.", | ||
| "enum": ["alz-corp-default"] |
There was a problem hiding this comment.
Fixed in b4e0872: governance-baseline.schema.json now has an allOf / if / then requiring alz_library_ref, azure_policy_ref and generated_at whenever baseline_kind is present. validate:governance-baseline still passes on the committed baseline.
Phase 0.45 offers the user a choice between live discovery and the shipped ALZ Corp default when the target subscription is absent from the baseline. Choosing the default is recorded as assumed, labelled in the artifacts, and keeps the Step 3.5 review mandatory. The discovery instructions carry the single exception to the no-assumptions rule.

Description
Replaces the committed real-tenant governance baseline with an offline-generated ALZ Corp default: the
root,landing_zonesandcorparchetypes of ALZ libraryplatform/alz/2026.10.0, with built-in definitions fromAzure/azure-policyat a pinned commit. The generator reusesdiscover.discoverthrough an offline REST adapter,so classification matches a live run. The tenant collector workflow is unchanged, so adopters can still overwrite
the file with their own baseline.
Phase 0.45 now offers "Run live discovery" or "Use ALZ Corp default as assumed governance" when the target
subscription is absent. The default is labelled assumed in the artifacts, and the Step 3.5 review stays mandatory.
Type of Change
Token / latency impact
04g-governance.agent.md; the new procedure lives in the on-demandbaseline-check.mdChanges Made
scripts/generate_alz_baseline.pyand tests;npm run generate:governance-baseline-alzdiscover.py: evaluatesif(contains(list,'type'),effect,'Disabled')and treatsenforceSettinglikeAppend(otherwise the set stays
PARTIAL). Notecollect-governance-baseline.ps1mirrorsdiscover.pyand does not have this yet.render_governance.py,render_cached_governance.py,governance_baseline.py(--alz-default)baseline_kind,alz_library_ref,azure_policy_ref,generated_at; sourcealz-corp-default.github/data/governance-policy-baseline.json.gzregenerated: 75 assignments, 506 findings (83 blockers,220 auto-remediate, 203 informational from
DoNotEnforceassignments); regeneration is byte-identical04g-governance.agent.md,baseline-check.md,governance-discovery.instructions.mdValidation
validate:governance-baseline,test:governance-baseline-python,test:governance-discovery,test:governance-baseline-loader,lint:governance-refs,validate:agents,validate:skills,lint:md,lint:jsonpass (183 pytest tests)collect-governance-baseline.ps1. Despite the earliernote, it does not mirror
discover.pyclosely: it never resolves initiative member parameters or assignmentparameter overrides, silently skips unclassifiable effects, and so never reports
PARTIAL. It already ignoresenforceSetting. Aligning the two collectors is a separate piece of work.