zone-engine/SCOPE.md
tegwick a211d61e70 docs: finish security zone adoption workplan
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
2026-08-22 15:40:55 +02:00

8.8 KiB
Raw Blame History

SCOPE

What this repository is about, when it is relevant, and when it is not. The argument for its existence is INTENT.md; the checkable gates and the retirement condition are GOAL.md.


One-liner

Authority for security zones — the bands of enforcement rigidity that scope where a control bites, and the lifecycle of time-boxed exceptions that relax them during deep refactors without leaving a permanent hole.


Why this exists

Enforcement controls in this estate have been repo-wide booleans. ops-warden's flex-auth pre-sign gate (policy.enabled with fail_closed: true) was the first to become flippable, and flipping it would have made flex-auth a hard dependency of every warden sign — including the SSH certificates the ops-bridge tunnels depend on, one of which carries the policy call itself.

Across an estate under continuous deep refactor, uniform enforcement hardens exactly the access needed to perform the refactor. The flip was deferred under ops-warden's ADR-0006enforcement is zone-scoped, never a global flag — and this repo is what that ADR defers to.


In scope

  • Zone identity and admission standards. What zones exist, and the standard a workload must meet to be admitted to one. Security policy is about the running workload and whoever answers for it — the repo providing the software only suggests. A zone is a floor a workload qualifies against, not a label applied to it, and it is the tenancy-posture Decision 8.2 tier-minimum mechanism rather than a new one.
  • Time-boxed exception lifecycle. A relaxation with an expiry enforced by something rather than intended, plus the record of who widened what, when, and until when. This is the task that decides whether this repo needs a runtime at all.
  • The membership declaration, carried in each repo's tenancy.yaml under the reserved top-level zones: key, with tenancy-posture_v0.1 §6 carried over verbatim: accuracy, not altitude.
  • Drafting the canon standard, offered to net-kingdom for publication in the family of tenancy-posture_v0.1 and the *-engine boundary contracts.
  • Naming stance vocabularyenforced / advisory / exempt — as something owners express, not as something this repo evaluates.

Out of scope

  • Authorization decisions. flex-auth is the PDP and stays the only one.
  • Stance for controls flex-auth decides. Settled on review: for the pre-sign gate, stance lives in a flex-auth policy package, not in compiled membership. flex-auth's decision envelope stamps matched_policy_version and policy_package, and registry content appears nowhere in that provenance — stance in the registry would let two decisions with the same policy version and the same request differ, with nothing in the audit trail explaining why. Membership is ours; stance is theirs.
  • The fail-open / fail-closed axis. Also settled on review: a PDP returns an effect. Fail-open describes what a policy enforcement point does when the PDP is unreachable — no decision is rendered, so no compiled data and no policy rule can reach it. The failure-mode axis is modelled PEP-side, by the repo that owns the control.
  • organization_posture. Ruled out of the declaration by canon: a fleet-wide, time-varying scalar describing the estate is not a property of a declaring service, and a per-repo copy of a global goes stale in as many places as there are repos. It is an input to stance selection, read by the model, never absorbed into it.
  • Network segmentation. "Zone" is overloaded; the routing sense is someone else's word.
  • Substrate placement. Reefs are repo-manager's. That reef-railiance is single-node and therefore caps availability for everything bound to it is a canon composition defect (NK-WP-0027), not a zone problem — and zone-engine is explicitly not blocked on it.
  • Identity, secrets, tenancykey-cape, OpenBao / secrets-engine, tenant-engine.
  • Implementing anyone's controls. Owners keep them; this model says where they bite.
  • Publishing canon. net-kingdom owns canon; policy-nexus publishes.

Settled by review (2026-08-19)

ZONE-WP-0001 was reviewed by both affected owners before any modelling began. Their answers are binding on this repo and are recorded in the workplan.

Question Answer Ruled by
A new standard, or a seventh axis of tenancy-posture_v0.1? Separate standard. The six axes are ladders where higher is stronger and desirable; enforcement stance is not monotone — ADR-0006 is the finding that the top rung is wrong for the SSH lane. And an accurately declared exempt as an axis would be conformant and exempt: a conformance rule handing out its own exemption. net-kingdom, Decision 5.6
Then where is membership declared? tenancy.yaml, reserved top-level zones: key. One declaration surface, one review cadence, one validator; two standards, because they have different owners and different conformance semantics. net-kingdom, Decision 5.6
Does membership need a flex-auth schema change? No. Resource metadata / labels / attributes are already flattened into the Rego input, so a compiler emitting a zone field is readable today. flex-auth
Is "never synchronously in a decision path" the right invariant? No — that is a latency guarantee, not an authority one. Replaced: identity and membership here, effect in a flex-auth policy package. flex-auth
Are reefs ours to reconcile? No, and the attempt surfaced a canon defect instead (NK-WP-0027). net-kingdom

Two constraints inherited from that review

  • trust_zone already exists inside the PDP, and is dead. ops-warden/scripts/build_flex_auth_registry.py hardcodes "trust_zone": "platform" on every ssh-cert resource; it reaches the Rego input and no policy rule reads it. This repo's own warning about "zone" being overloaded named network segmentation as the hazard; the live collision is a dormant, plausibly-named field sitting exactly where membership would go. The compiler must resolve it — reuse or rename, deliberately.
  • flex-auth has no reload path. Registry and policy are loaded once at process start from a digest-pinned image. An exception compiled as inert registry data therefore expires only when a human redeploys — expiry by intention, which is precisely what the exception lifecycle must not be. An exception carrying not_after, evaluated against decision time in policy, does expire on its own: granting costs a redeploy, lapsing is automatic.

Relationship to what already exists

Mechanism Owner Relationship
tenancy-posture_v0.1 net-kingdom canon Sibling standard and carrier file. Structural model: graduated levels, per-repo declaration with evidence and review dates, accuracy over altitude
Environment posture + workload maturity M0M3 ops-warden (WP-0015) Candidate membership inputs
organization_posture: build ops-warden (WP-0029) An input to stance selection. Explicitly not part of the declaration
Reefs / bound_reefs repo-manager Separate axis. Their interaction with availability is NK-WP-0027, not ours
Compiled registry snapshot flex-auth How membership reaches the PDP — no schema change needed, one name collision to resolve
Policy package flex-auth Where stance lives for controls flex-auth decides
warden plan verdicts + reasons ops-warden (WP-0029) Existing verdict machinery to extend, not parallel

Current state (2026-08-22)

ZONE-WP-0001 is finished. T01T05 established the model: ownership is confirmed, the estate is partitioned, stance and failure mode are modelled, the exception lifecycle requires no zone-engine runtime, and the declaration/compiler contract is drafted. The integrated owner draft is docs/security-zones_v0.1.md.

Net-kingdom Decisions 5.6.1 and 5.6.2 settle the workload boundary. Operational execution units declare authoritative workload identity directly in tenancy.yaml; absence resolves to unknown, never inference. The standard is published in net-kingdom canon, and T07 proves adoption in ops-warden and flex-auth with zone-engine compiling both declarations. No API, storage, or synchronous lookup has been shipped because the exception lifecycle showed that none is needed.


Relevant when

  • A control is about to be enabled and "enforced where?" has no answer
  • A deep refactor needs relaxed rigidity in a band of the estate, with an expiry
  • A repo is filling in the zones: key of its tenancy.yaml

Not relevant when

  • Asking whether a specific request is allowed → flex-auth
  • Placing a workload on a substrate → repo-manager reefs
  • Anything about network reachability