Exemption Workflow
Use this time-boxed, audited, owner-approved waiver path for a specific rule
assignment against a specific scope. Backed by the schema in
rule-catalog/schema/exemption.json
and a CI validator that runs on every PR that touches
rule-catalog/exemptions/.
When to use an exemption
Section titled “When to use an exemption”An exemption suppresses enforce for a specific rule against a specific scope. It is the right tool when all of the following hold:
- The rule is correct in general but wrong for this scope.
- The scope is narrowed to a resource group (or narrower).
- There is a plan to remove the exemption - an exemption is a stall, not a fix.
- The impact scope of leaving the rule off is understood and bounded.
If the rule is wrong in general, retire the rule via the rule-catalog
pipeline instead. If the wrong dimension is auto-vs-human approval, tune
risk-classification, not the rule.
- Requester - any member of the
aw-contributorsEntra group (or above) MAY open an exemption PR. - Approver - MUST be an
aw-ownersmember. Approver ≠ Requester- branch protection enforces “author ≠ reviewer”, and the exemption
artifact carries
requested_byandapproved_byfields the CI check inspects for distinct values.
- branch protection enforces “author ≠ reviewer”, and the exemption
artifact carries
- Auditor - every state transition (active / expired / revoked) writes an audit-log entry with the actor principal.
Procedure
Section titled “Procedure”- Open a PR using the
Exemption Requesttemplate. - Fill the artifact at
rule-catalog/exemptions/<id>.jsonaccording to the schema. - CI runs:
- Schema validation (
exemption-checkjob). - Author-≠-reviewer branch-protection rule (repo settings).
requested_by≠approved_bymodel invariant.expires_at > created_atmodel invariant.
- Schema validation (
- Owner-tier review + merge. The merge has no side effect on the live Azure resources today; enforcement suppression takes effect once the catalog pipeline (Phase 2) picks the exemption up.
- Auto-expiry. The repository job changes only the reviewed artifact to
state=expired. The runtime coordinator resolves an exact reviewed assignment binding and publishes agovernance.reapply-rule-assignmentproposal with a stable idempotency key. The proposal passes through ordinary risk evaluation, human approval, Thor execution, rollback, audit, and independent effect verification. Missing binding, revision conflict, unavailable delivery, or unknown delivery outcome remains held and safe to retry.
Time-boxing
Section titled “Time-boxing”expires_atMUST be strictly aftercreated_at.- No hard maximum window is codified here; longer windows MUST be justified in the PR body.
- A lookahead digest is eligible on the default A1 channel 14 days before
expires_at. Each item names the exact exemption revision, rule, expiry instant, and requester mention. Notification delivery grants no authority and never delays expiry.
Revocation
Section titled “Revocation”An owner MAY revoke an active exemption by:
- Editing the artifact to
state=revoked, settingrevoked_atandrevoked_by. - Merging the revocation PR - Owner-tier review, no self-approval.
Revocation flips enforce back on immediately (the moment the catalog pipeline observes the state change).
Escalation
Section titled “Escalation”- If CI is flapping on a request that plainly satisfies the schema, page
aw-ownerson the default A1 channel with the CI log attached. - If an exemption is denied but the environment is materially at risk,
escalate to
aw-break-glass- under Conditional Access, this is a short-lived, audited grant, not a bypass.
References
Section titled “References”| Artifact | Path |
|---|---|
| Design: Human Override | ../../.github/instructions/architecture.instructions.md#human-override |
| Exemption schema | ../../services/core-control-plane/src/fdai/rule_catalog/schema/exemption.schema.json |
CI check (exemption-check job) | ../../.github/workflows/ci.yml |
| Expiry CLI | ../../scripts/governance/exemption-expire.py |
| PR template | ../../.github/PULL_REQUEST_TEMPLATE/exemption.md |