ops-warden/workplans/WARDEN-WP-0032-security-zones.md
tegwick b845f4b51e
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Draft WARDEN-WP-0032 properly — security zones, ownership question first
Expands the placeholder into a real plan, grounded in what the estate already
has rather than first principles:

- tenancy-posture_v0.1 is the structural model to follow (canon standard +
  per-repo declaration + "accuracy, not altitude"), and its §14 adoption stance
  is "structure, not tooling" — a precedent about sequencing.
- Reefs are substrate placement zones with real risk statements. A security
  zone is not a reef; repo-manager's own "topology is not readiness" applies
  here as "placement is not posture".
- flex-auth is latency-critical and already consumes a compiled registry
  snapshot, so zone membership should reach the PDP by compilation rather than
  a synchronous lookup in the decision path.
- warden plan already returns verdicts with reasons; zone-aware enforcement
  extends that machinery instead of growing a parallel one.

T01 settles ownership before any modelling, because it decides which repo the
rest lives in: canon standard, a zone-engine runtime authority, or flex-auth
policy data. The recommendation is canon-first with zone-engine named as an
explicit promotion — but the time-boxed refactor exception is the case that
could justify an engine immediately, since an expiring grant is state and state
wants an owner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:38:25 +02:00

234 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: WARDEN-WP-0032
type: workplan
title: "Security zones — bands of enforcement rigidity, and where they live"
domain: infotech
repo: ops-warden
status: proposed
owner: ops-warden
topic_slug: netkingdom
planning_priority: P1
depends_on_workplans:
- WARDEN-WP-0015
- WARDEN-WP-0029
- WARDEN-WP-0031
created: "2026-08-19"
updated: "2026-08-19"
---
# WARDEN-WP-0032 — Security zones
`ADR-0006` defers `policy.enabled: true` until enforcement can be scoped to a
zone. This workplan builds the model it defers to, and — first — settles who
owns it.
## The problem, precisely
ops-warden can express *how exposed* something is and *how mature* it is. It
cannot express *how rigidly this band of the estate is governed right now*.
| Axis | Shipped | Answers |
| --- | --- | --- |
| Environment posture (`dev`/`test`/`prod`) | WP-0015 | Where does this run? |
| Workload maturity (`M0``M3`) | WP-0015 | How ready is this workload? |
| `organization_posture: build` | WP-0029 | What state is the org in? |
| **Enforcement stance** | **missing** | **Is this control enforced here, and what happens when it fails?** |
Because the fourth is missing, every enforcement control ops-warden ships is a
repo-wide boolean. `policy.enabled` is the first to become flippable, and
flipping it would make flex-auth a hard dependency of every `warden sign`
including the certificates the ops-bridge tunnels depend on, one of which
carries the policy call itself. Across an estate mid-refactor that hardens
exactly the access needed to perform the refactor.
The three existing axes *describe*. Nothing *decides*. A zone is the object that
decides.
## What already exists — do not reinvent these
Four estate mechanisms are adjacent, and getting the relationships right is most
of the design work.
**`net-kingdom/canon/standards/tenancy-posture_v0.1.md`** — the closest
structural analogue and the model to follow: six orthogonal axes, graduated
levels, a per-repo declaration file (`tenancy.yaml`) carrying current /
implemented / target vectors with evidence and a review date, and §6
"conformance is accuracy, not altitude". Its §14 adoption stance is
*"structure, not tooling"* — a direct precedent about sequencing, and one this
workplan should not quietly break.
**Reefs** (`repo-manager/docs/RailianceAppDeploymentGuide.md`) — `reef-railiance`,
`reef-storage`, named in a rapp's `bound_reefs`. These are **substrate**
placement zones with real risk statements attached (`reef-railiance` carries a
single-node/shared-control-plane residual risk requiring explicit acceptance).
A security zone is *not* a reef — reef answers *where does it run*, zone answers
*how rigidly is it governed* — but they are correlated, and a taxonomy that
ignores reefs will fight them. Also note repo-manager's own ADR-0006: *topology
is not readiness*. The same caution applies here: **placement is not posture.**
**flex-auth** — the PDP, `service_class: latency-critical`, which already
consumes a *compiled registry snapshot*
(`registry/flex-auth/production_registry_snapshot.json`, built by
`scripts/build_flex_auth_registry.py`). This matters enormously for T03: zone
membership can reach the decision point by compilation, with no runtime lookup
and no new service in the request path.
**`warden plan`** (WP-0029) — already classifies a need as `autonomous` /
`founder_required` / `unroutable` from properties of the thing, returning the
`reasons` that produced the verdict. Zone-aware enforcement should extend this
verdict machinery rather than grow a parallel one.
## The question that changes everything else: who owns this?
Three placements are defensible. **T01 settles it before any modelling**,
because the answer changes who writes T02T05 and in which repo they live.
**(a) NetKingdom canon + per-repo declaration.** A `security-zones_v0.1.md`
standard beside `tenancy-posture_v0.1.md`; each repo declares its lanes'
zones in a `zones.yaml` the way it already declares `tenancy.yaml`; flex-auth
enforces from the compiled registry. ops-warden drafts and offers, exactly as it
did for the WP-0015 maturity model. *Strongest fit to precedent; no new runtime
dependency; matches "structure, not tooling".*
**(b) A new `zone-engine` repo.** A runtime authority owning zone identity,
membership, and lifecycle, in the family of `tenant-engine` / `user-engine` /
`secrets-engine` — each of which has a boundary contract in canon. *Justified
if and only if zone membership needs minting, an API other components query, or
— the real candidate — **time-boxed exceptions with expiry and an audit trail of
who widened what**. A standing classification does not need an engine; a
relaxation that must expire probably does.*
**(c) flex-auth policy data.** Zones as attributes in the policy package, no new
artefact anywhere. *Cheapest, and wrong if zones must govern controls flex-auth
does not evaluate — the agent read-boundary (ADR-0004) and `warden desk`
escalation are ops-warden-side and would fall outside.*
**Recommendation to be tested in T01, not assumed:** start at (a), and name
(b) as an explicit promotion with a written trigger, rather than seeding an
engine before the model exists. An empty `zone-engine` would end up defining
zones by accident — through whatever its first schema happened to be — which is
the failure `ADR-0001` names in a different register. The counter-argument
deserves a fair hearing: if time-boxed refactor exceptions are in scope from day
one, (b) may be right immediately, because an expiring grant is state and state
wants an owner.
Under `ADR-0005` ops-warden does not absorb an estate-wide model on its own
authority. A zone model only ops-warden honours is worth much less than one
flex-auth enforces and secrets-engine reads.
## Tasks
```task
id: WARDEN-WP-0032-T01
status: todo
priority: high
```
**Settle ownership and placement.** Take the three options above to
`net-kingdom` (canon) and `flex-auth` (the PDP that would enforce), with the
time-boxed-exception question stated explicitly since it is what decides
between (a) and (b). Record the outcome as a decision with its reasoning — if
it lands outside ops-warden, this workplan's remaining tasks move to the owning
repo and ops-warden keeps only its consumer-side tasks.
Deliverable: a decision record, and coordination messages sent. Do not model
anything before this closes.
```task
id: WARDEN-WP-0032-T02
status: todo
priority: high
```
**Derive the zones from the real estate, not from first principles.** Walk the
27 catalog lanes, the actor inventory (`adm`/`agt`/`atm`), and the workloads
carrying posture descriptors, and find the bands that actually exist. The test
of the model is that it partitions today's estate without a residue of
exceptions; the exceptions found are the most informative output.
Must answer explicitly:
- Is a zone a property of the **actor**, the **lane**, the **workload**, or the
**moment**? The CoulombCore decommission shows the last one is real and is the
hardest to model — a time-boxed relaxation is a different object from a
standing zone, and conflating them produces a permanent hole with a
temporary-sounding name.
- Do zones **compose with or fold in** the three existing axes? A fourth
independent axis multiplies states; absorbing `organization_posture` may be
the honest move.
- How do zones relate to **reefs**? Correlated, not identical. Say so in the
model rather than leaving readers to assume either.
```task
id: WARDEN-WP-0032-T03
status: todo
priority: high
```
**Model stance and failure mode per zone per control.** For each control:
enforced / advisory / exempt, *and* fail-closed or fail-open. The failure mode
is the part with teeth — `fail_closed` is what turns a dead tunnel into an
outage, and it is the reason `policy.enabled` was deferred.
Controls in scope at minimum: the flex-auth pre-sign gate (`policy.enabled`,
`fail_closed`), the agent read-boundary on `risk: high` lanes (`ADR-0004`), and
the `warden plan` escalation verdicts (WP-0029).
Prefer **compilation over runtime lookup** for anything flex-auth evaluates: it
is latency-critical and already consumes a built registry snapshot. Adding a
synchronous zone lookup to the decision path would be a regression dressed as an
architecture.
```task
id: WARDEN-WP-0032-T04
status: todo
priority: high
```
**Declaration format and conformance rule.** Follow `tenancy.yaml`: a per-repo
declaration, with evidence, a `reviewed` date and a `review_due`, and the §6
rule carried over — **accuracy, not altitude**. A repo declaring a stricter zone
than it can evidence is the failure mode to design against, because it is the
one that looks like progress.
Include how a zone assignment is *changed*, and how that change is observed. A
zone that can be quietly widened is not a boundary. If time-boxed exceptions
exist, their expiry must be enforced by something, not by an intention.
```task
id: WARDEN-WP-0032-T05
status: todo
priority: medium
```
**Make `policy.enabled` zone-aware and retire the global boolean.** The
successor control reads the zone of the actor being signed for and that zone's
failure mode. Ship deprecation and migration in the same change — leaving both
is the second-source-of-truth failure `ADR-0001` exists to prevent.
This closes `WARDEN-WP-0031-T05`, cancelled under `ADR-0006`. Re-run
`scripts/check_policy_caller_identity.py` first: the WP-0031 evidence
(`decision:f3f7c88f9585582a`, 2026-08-19) will be stale, and re-establishing it
is cheap precisely so this is a re-check rather than a re-do.
```task
id: WARDEN-WP-0032-T06
status: todo
priority: medium
```
**Close out honestly.** Update `SCOPE.md`, `wiki/WorkloadSecurityPosture.md`,
and `wiki/PolicyGatedSigning.md`. If the model landed in canon or in another
repo, `ADR-0006` gains a successor or an amendment recording where enforcement
scoping now lives — ops-warden follows it rather than owning it, and the ADR
must say which.
## Deliberately out of scope
- **Network segmentation.** "Zone" is an overloaded word; this model is about
*enforcement rigidity*, not routing or NetworkPolicy. Say so wherever the term
first appears, or the two will be conflated within a quarter.
- **Re-litigating the three existing axes.** They stay as they are unless T02
finds a fold-in.
- **Zones for anything ops-warden does not consume**, unless T01 hands the model
to an owner who needs the wider scope.