ops-warden/docs/adr/ADR-0006-enforcement-is-zone-scoped.md
tegwick 7ce58ae638
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
feat: adopt security zones and explicit workload refs
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
2026-08-22 15:36:37 +02:00

4.5 KiB
Raw Blame History

id type title domain repo status version revision owner binds created updated last_reviewed review_interval enforced_by supersedes successor
ops-warden-adr-0006 adr ADR-0006 — Enforcement is zone-scoped, never a global flag infotech ops-warden superseded 1.0 1 ops-warden ops-warden 2026-08-19 2026-08-22 2026-08-19 6m warden.yaml policy.enabled; scripts/check_policy_caller_identity.py; zone-engine ZONE-WP-0001; WARDEN-WP-0032 ops-warden-adr-0009

ADR-0006 — Enforcement is zone-scoped, never a global flag

Status

Accepted 2026-08-19, at the moment policy.enabled: true was ready to be set and deliberately was not.

Context

WARDEN-WP-0031 finished the calling side of the flex-auth pre-sign gate. The flex-auth pin flex-auth-ops-warden runs callerAuth.mode: enforce; ops-warden presents a bound ServiceAccount token; the readiness gate exits 0 against the enforcing pin and an anonymous /v1/check is 401. Everything needed to set policy.enabled: true was in place.

policy.enabled is a single boolean over the whole repo. Combined with fail_closed: true it makes flex-auth a hard dependency of every warden sign — including the certificates the ops-bridge tunnels depend on, one of which is the tunnel carrying the policy call itself. A dead tunnel or a recreated Service does not degrade signing; it stops it.

That cost might be acceptable for a settled production lane. It is not acceptable uniformly, because ops-warden signs across an estate that is being actively rebuilt. During deep refactors — CoulombCore's decommission, the issue-core move, cluster rebuilds — the same flag would harden exactly the access needed to perform the refactor. Security that stops the work stops being security and starts being an outage with good intentions.

The repo already refuses to treat posture as one-dimensional. WP-0015 shipped environment posture (dev / test / prod) and workload maturity (M0M3); WP-0029 added organization_posture: build as a third axis precisely because the organization's state changes what is reasonable to demand. A global policy.enabled contradicts all of that: it is a fourth control that ignores the three axes already declared.

Decision

Enforcement posture is a property of a zone, not of the repo. ops-warden does not enable a fail-closed authorization gate globally. Before policy.enabled: true is set anywhere, the zones must exist: named bands of differing rigidity, each declaring what is enforced, what is advisory, and what is exempt — and the gate must be scoped to them.

Concretely, until zone-engine's ZONE-WP-0001 defines the zone model:

  • policy.enabled stays false. Its readiness is evidence, not a mandate.
  • A gate that is ready is recorded as ready. Readiness is not a reason to enable; deferral with a stated reason is a legitimate terminal state for a task, not an unfinished one.
  • Any future enforcement control ships zone-aware or does not ship. A second global boolean is the defect this record exists to prevent.

Consequences

We accept that the pre-sign gate remains unexercised in production longer, and that the WP-0031 evidence ages. Re-running scripts/check_policy_caller_identity.py re-establishes it cheaply, and the readiness gate exists precisely so this is a re-check rather than a re-do.

We accept that flex-auth's flex-auth-ops-warden pin sits enforcing with no enforcing consumer. That is not waste: it makes the anonymous path 401 rather than a decision, which was the ADHOC-2026-08-17-T01 condition regardless of whether ops-warden calls it.

We reject the framing that a ready control should be turned on because it is ready. The question is not "does it work" but "which zone is this, and does this zone want this failure mode."

This binds future work. A zone-blind enforcement flag proposed in any ops-warden workplan is out of order under this ADR, and should be sent back to the zone model rather than merged with a caveat in its description.

  • WARDEN-WP-0031 — the calling side that made the flip possible (T05 deferred under this ADR)
  • zone-engine ZONE-WP-0001 — the zone model this record defers to, seeded 2026-08-19 as the owning repo
  • WARDEN-WP-0032 — ops-warden's consumer-side adoption
  • wiki/WorkloadSecurityPosture.md — the two axes already shipped (WP-0015)
  • wiki/PolicyGatedSigning.md — the gate itself
  • history/2026-08-19-flex-auth-caller-identity-evidence.md — readiness evidence
  • flex-auth FLEX-WP-0016 — the enforcing pin