ops-warden/workplans/WARDEN-WP-0032-security-zones.md

124 lines
4.7 KiB
Markdown
Raw Normal View History

---
id: WARDEN-WP-0032
type: workplan
title: "Security zones — scope enforcement to bands of differing rigidity"
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. This
workplan builds the thing it defers to.
## The problem in one paragraph
ops-warden has three posture axes already: environment (`dev`/`test`/`prod`,
WP-0015), workload maturity (`M0``M3`, WP-0015), and organization posture
(`build`, WP-0029). What it does not have is a way to say *"this band of the
estate is enforced, that one is advisory"* — so every enforcement control it
ships is a repo-wide boolean. `policy.enabled` is the first one to actually
become flippable, and flipping it would harden the access needed to perform the
refactors currently underway. The axes describe posture; nothing acts on them.
## What a zone has to answer
A zone is only useful if it decides something. Minimum:
- **Membership** — what puts a lane, actor, or workload in this zone? Derived
from the existing axes where possible rather than a fourth hand-maintained
list.
- **Enforcement stance per control** — for each gate (pre-sign policy, agent
read-boundary, high-risk refusal): enforced, advisory, or exempt.
- **Failure mode** — fail-closed or fail-open, per control per zone. This is the
actual bite: `fail_closed` is what makes a dead tunnel an outage.
- **Who may change it, and how it is observed** — a zone that can be quietly
widened is not a boundary.
## Open questions to settle before designing
- Is a zone a property of the **actor** (`adm`/`agt`/`atm`), the **lane**
(catalog entry), the **workload**, or the **moment** (an active refactor)? The
CoulombCore decommission suggests the last one matters and is the hardest to
model — a time-boxed relaxation is a different object than a standing zone.
- Do zones compose with the three existing axes, or replace one? A fourth
independent axis multiplies states; folding `organization_posture` in may be
the honest move.
- Is this ops-warden's model to own at all, or NetKingdom canon that ops-warden
consumes? ADR-0005 says implement narrowly and route broadly. A security zone
model that only ops-warden honours is worth much less than one flex-auth,
secrets-engine, and tenant-engine also read — but ops-warden should not
absorb an estate-wide model on its own authority either. **Settle this
first**; it changes who writes the rest.
## Tasks
```task
id: WARDEN-WP-0032-T01
status: todo
priority: high
```
**Decide ownership before designing.** Take the third open question to
net-kingdom (canon) and flex-auth (the PDP that would enforce it). If it is
canon, ops-warden drafts and offers, as it did for the WP-0015 maturity model,
and consumes the result. If it is ops-warden's, say so explicitly and record
why. Do not build a model whose owner is unsettled.
```task
id: WARDEN-WP-0032-T02
status: todo
priority: high
```
**Name the zones against reality, not in the abstract.** Walk the current
estate — the 27 catalog lanes, the actor inventory, the workloads with posture
descriptors — and see what bands actually exist. A zone model that does not
partition today's lanes cleanly is wrong, and the exceptions are the interesting
part. Include the refactor case explicitly: what zone is a lane in while the
component it fronts is being rebuilt?
```task
id: WARDEN-WP-0032-T03
status: todo
priority: high
```
**Model enforcement stance and failure mode per zone per control,** covering 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). Each must be expressible as enforced / advisory /
exempt with an explicit failure mode.
```task
id: WARDEN-WP-0032-T04
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. Ship the
migration in the same change as the deprecation — leaving both is exactly the
second-source-of-truth failure ADR-0001 exists to prevent.
```task
id: WARDEN-WP-0032-T05
status: todo
priority: medium
```
**Close WARDEN-WP-0031 T05 through this model** — enable the pre-sign gate for
whichever zone the SSH signing lane lands in, with that zone's failure mode.
Re-run `scripts/check_policy_caller_identity.py` first; the WP-0031 evidence
will be stale by then and re-establishing it is cheap by design.