Promotion and Gates
- A snapshot is a resolved compliance posture, frozen at publication. Its content is immutable; only its approval status changes afterwards.
- A binding points one project environment at one snapshot. That binding is what the registry serves.
- Promotion is the act of moving a snapshot into an environment. Protected environments run it past a gate first.
- Waivers are exceptions with a stated expiry. Approved, unexpired waivers are frozen into the binding at promotion time — after which editing, revoking, or outliving the expiry does not change what production is already serving.
- Rollback repoints an environment at the previous snapshot. It moves the snapshot only — the frozen waiver set is left exactly as the last promotion built it.
Why promotion exists
A compliance posture that can be edited in place has no defensible history. If an auditor asks what production enforced on a given date, "the current configuration" is not an answer — it changes every time someone edits it.
compliance.tf separates authoring from what is live. You edit a draft freely. Publishing freezes that draft into a snapshot that can never be modified. An environment is then bound to a specific snapshot. Production changes only when someone deliberately promotes a different snapshot to it, and that act is recorded.
The objects
| Object | Mutable? | What it is |
|---|---|---|
| Config | Yes | A named workspace holding a draft posture: which frameworks are enforced, which controls are added or forbidden, which operational rules apply. |
| Draft | Yes | The editable content of a config. Concurrent edits are detected rather than silently merged. |
| Snapshot | No | A published, fully resolved posture — frameworks expanded to a concrete control set. Only its approval status can change after publication. |
| Binding | Yes | The pointer from one project environment to one snapshot, plus the waivers frozen at the moment of binding. |
| Waiver | Yes | An approved exception to one control or rule, scoped to one environment, carrying a stated expiry. |
Environments
Every project has exactly three environments: dev, staging, and prod. They are not created or named — they exist for every project, and a record for one appears the first time you act on it, whether that is binding a snapshot or proposing a waiver.
An environment is either protected or not. Protection is what turns a bind into a gated promotion. By default prod is protected and the other two are not.
- Unprotected environment. Binding a snapshot is a direct action: no gate runs. Authorization still applies — you need permission to bind — but none of the gate conditions below are evaluated. This is deliberate;
devshould be fast to iterate against. - Protected environment. Every attempt runs the promotion gate first, and the gate can refuse.
The lifecycle
Publishing and approving are separate steps on purpose. Publishing says "this posture is finished". Approving says "someone accountable has reviewed it". A protected environment requires the second signal, not just the first.
Promoting
A promotion names a snapshot and a target environment. On a protected environment the gate evaluates the request and returns a list of blockers. Each blocker has a severity: a block refuses the promotion, a warn records a concern and lets it through.
You do not have to attempt a promotion to find out how the gate will judge it. The preview endpoint runs the same gate without changing anything, and returns the blockers alongside a diff of what would change and which waivers would carry over. It reports the gate's verdict on the state at the moment you ask, and reserves nothing: anything that changes afterwards is evaluated afresh when you promote.
Waivers
A waiver records a decision to accept a specific gap for a limited time. It names the control or rule, an expiry, and a justification. Waivers are proposed and approved as separate acts.
The important property is when a waiver takes effect on an environment, and the matching question of when its expiry takes effect.
A waiver sitting on an environment is only a proposal until a promotion happens. At promotion time, waivers that are both approved and unexpired are copied into the binding and frozen there.
The expiry is checked at that moment — the freeze — and not afterwards. Once a waiver is frozen into a binding, it applies to what the registry serves for as long as that binding stands, whether or not its stated expiry has since passed. An expiry is therefore a rule about which waivers are eligible to be frozen, not a timer that withdraws a live exception.
To clear an expired waiver from an environment, promote a different snapshot to it — a bind or promote that actually writes a new binding is what re-runs the eligibility check and rebuilds the frozen set. Two things that look like they would work do not: re-promoting the snapshot already bound is a no-change write, and a rollback repoints the snapshot without rebuilding the frozen set. Neither refreshes anything. If you need to audit this across an estate, read each environment's frozen waiver set and compare the expiry dates against today rather than assuming lapsed entries have fallen out.
Consequences worth understanding:
- Approving a waiver does not change what production serves. The next promotion does.
- Revoking a waiver does not change what production serves either. The frozen copy stays in effect until a bind or promote writes a new binding and drops it.
- A waiver that expires stops being carried into new bindings, but the already-frozen copy stays in force until a bind or promote writes a new binding for that environment. Rollback is not such an operation: it repoints the snapshot on its own code path, without rebuilding the frozen waiver set.
This is what makes a binding reproducible. What the registry serves for an environment is fully determined by the binding, not by the current state of an editable waiver list.
Operating the gate
The rest of this page is the operator's half: every gate blocker and what raises it, the guarantees that hold under concurrent promotions and partial failure, and the permission each action requires.
Audit trail
Every promotion, bind, rollback and waiver decision is recorded as an append-only event, written in the same atomic operation as the change it describes. Reading the trail requires the audit:read permission.
The audit trail covers what each record contains, how to read a window of it, what it cannot tell you, and the retention caveat that matters if you intend to rely on it as evidence.
Related
- Configs and snapshots — authoring, publishing, and what "resolved" means
- Projects and environments — project structure and environment protection
- Access control — the full permission model