The layer model is now published as net-kingdom/canon/standards/security-layer-model_v0.1.md (proposed) and ratified by gate-house GH-DEC-2026-001. The note previously said the standard was not yet written. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9
187 lines
9.9 KiB
Markdown
187 lines
9.9 KiB
Markdown
# INTENT
|
||
|
||
> **NetKingdom layering review — 2026-08-28.** This repository's role was reviewed
|
||
> against the NetKingdom IT-security layer model: **Taxonomy → Tooling → Engines →
|
||
> Staff**, layered by determinism and by the kind of artifact each layer produces.
|
||
> Findings and the argument behind them:
|
||
> `gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md`.
|
||
> The model is `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed),
|
||
> ratified by `gate-house/decisions/decisions.md` GH-DEC-2026-001.
|
||
>
|
||
> The layer rule that binds every repository: **Staff never touches tooling
|
||
> directly. It acts only through engine APIs.**
|
||
>
|
||
> **This repository is Engine — currently retained as offline reference conformance.** No change to the 2026-08-23 disposition. Note that §5 of this file — *"flex-auth is the policy decision point. It stays the only one."* — is the precedent the whole review turned on, and it now generalizes: gate-house is Staff and is not a second decision point either. The falsifier in §7 ("it becomes a second decision point… it would arrive as a small convenience") is adopted estate-wide. References to flex-auth by name will need updating when the rename to access-engine lands.
|
||
>
|
||
> *This note records what should change. The body below is not yet adapted.*
|
||
|
||
> Why `zone-engine` exists and where it is going.
|
||
> What is true today is `SCOPE.md`. Checkable gates and the retirement
|
||
> condition are `GOAL.md`. This file is the argument, not the checklist.
|
||
|
||
---
|
||
|
||
## Current disposition — 2026-08-23
|
||
|
||
The argument below is retained as design history. Its desired sentence is now
|
||
sayable: the standard is in net-kingdom canon, ops-warden and flex-auth have
|
||
adopted it, the repo-wide switch is retired, and exception expiry is enforced
|
||
at each owning decision or enforcement point.
|
||
|
||
The runtime hypothesis was falsified. zone-engine is retained only as an
|
||
offline reference-conformance repository while canon v0.1 remains proposed; it
|
||
is not an engine, PDP, exception service, or consumer policy owner. Current
|
||
capability is `SCOPE.md`, and the retain/archive triggers are in `GOAL.md`.
|
||
|
||
## 1. The sentence this repo exists to make sayable
|
||
|
||
> *"This control is enforced **there**, advisory **here**, and relaxed **in this
|
||
> band until Friday** — and all three of those are written down, reviewable, and
|
||
> expire on their own."*
|
||
|
||
At inception NetKingdom could not say that. It could say how exposed a workload was
|
||
(environment posture), how ready it is (`M0`–`M3`), and what state the
|
||
organization is in (`organization_posture`). Every one of those **describes**.
|
||
None of them **decides**. So every enforcement control in the estate has been a
|
||
boolean over a whole repo.
|
||
|
||
## 2. Where that bit
|
||
|
||
ops-warden built a pre-sign authorization gate, flex-auth enforced its side, and
|
||
the gate verified clean. It was deliberately not switched on until the zone
|
||
model replaced its global scope.
|
||
|
||
`policy.enabled` is one boolean over the entire repo. With `fail_closed: true`
|
||
it makes 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. Turning it on would have been correct for a settled
|
||
production lane and wrong for an estate in the middle of decommissioning one
|
||
host and moving a service off it.
|
||
|
||
That is not a story about a flag. **Security that stops the work stops being
|
||
security and becomes an outage with good intentions** — and the reason it would
|
||
have was structural: there was nowhere to say *where* it applies. The decision
|
||
is ops-warden's `ADR-0006`; this repo is what it defers to.
|
||
|
||
## 3. What policy is about, and who decides
|
||
|
||
**Security policy is always about the actual workload.** Not the repository, not
|
||
the credential, not the lane — the running thing, and whoever answers for it.
|
||
|
||
That splits authority three ways, and the split is the model:
|
||
|
||
| Role | Who | Authority |
|
||
| --- | --- | --- |
|
||
| **Suggests** | The repo providing the software | Recommends a posture for running its software. It does not know where it will run, so it cannot determine |
|
||
| **Declares** | The workload and its responsible party | Sets the scrutiny actually applied. **The policy subject** |
|
||
| **Requires** | The zone | The standard a workload must meet to be admitted. A floor, not a label |
|
||
|
||
A workload is not *labelled* with a zone. It **qualifies** to run in one.
|
||
|
||
This is not a new prescription mechanism. `tenancy-posture_v0.1` Decision 8.2
|
||
already splits authority this way — the consuming repo owns its workload
|
||
requirements, a tier minimum is owned separately, and the two are **joined by
|
||
machine**, because *"a machine-checkable constraint must not depend on somebody
|
||
remembering to collect a signature."* Decision 5.6 then ruled that stance
|
||
*"behaves like a tier minimum under Decision 8.2."* The zone model's job is to
|
||
**be** that tier minimum, not to invent a second way of requiring things.
|
||
|
||
## 4. What a zone has to be, to be worth having
|
||
|
||
A classification that changes nothing is a label. A zone earns its keep only if
|
||
it decides something, so the model must carry:
|
||
|
||
- **Identity and membership** — an authoritative workload binding and its
|
||
responsible party's declared zone. Lanes, actors, paths and repositories are
|
||
inputs or caller context, never substitute policy subjects.
|
||
- **Admission** — a mechanical reconciliation of that declaration against the
|
||
zone floor and the workload posture. Missing identity, membership or evidence
|
||
remains `unknown`; it is never inferred into a permissive zone.
|
||
- **Stance per control** — enforced, advisory, or exempt.
|
||
- **Failure mode** — what happens when the control cannot run. This is where
|
||
the bite is; `fail_closed` is what turns a dead tunnel into an outage.
|
||
- **Exceptions that expire without anyone remembering them.**
|
||
|
||
The last was the runtime hypothesis. A standing classification needs no engine
|
||
— canon plus a declaration file covers it, which is exactly how tenancy posture
|
||
works. The implementation proved that exception state can remain with the
|
||
control owner when `not_after` is evaluated where the effect occurs. That gives
|
||
it an owner, audit trail, and enforced deadline without a central service.
|
||
|
||
## 5. The line this repo must not cross
|
||
|
||
`flex-auth` is the policy decision point. It stays the only one.
|
||
|
||
zone-engine is authority over zone **identity and membership**. The **effect**
|
||
of a zone on a decision flex-auth renders belongs in a flex-auth policy package,
|
||
because flex-auth's decision envelope stamps `matched_policy_version` and
|
||
`policy_package` — and registry content appears nowhere in that provenance. Put
|
||
stance in the registry and two decisions with the same policy version and the
|
||
same request can differ, with nothing in the audit trail explaining why.
|
||
|
||
That boundary was drawn by flex-auth on review, against a first draft of ours
|
||
that got it wrong in an instructive way: the original invariant forbade sitting
|
||
*synchronously* in a decision path, which is a latency guarantee wearing an
|
||
authority guarantee's clothes. Compiled data that determines an outcome is still
|
||
deciding; it just decided earlier.
|
||
|
||
**Held to, in one line: membership is ours, stance is theirs, and the decision
|
||
point is neither.**
|
||
|
||
## 6. What success looks like from outside
|
||
|
||
These conditions are now met for the adopted v0.1 path:
|
||
|
||
Someone who has never read this repo should be able to:
|
||
|
||
- open a service's `tenancy.yaml`, read its `zones:` key, and know which
|
||
controls bite it;
|
||
- ask "why was this relaxed?" and get a justification, an author and an expiry,
|
||
not a shrug;
|
||
- watch a relaxation lapse **without a human remembering it**;
|
||
- and find the rule published in NetKingdom canon rather than in this repo's
|
||
prose.
|
||
|
||
If a reader has to come here to understand their own posture, the model has
|
||
failed at being a standard and has succeeded only at being a service.
|
||
|
||
## 7. What would make this repo wrong
|
||
|
||
Stated up front, because a repo created on a recommendation should say what
|
||
would falsify it:
|
||
|
||
- **The exception lifecycle turns out not to need a runtime.** This falsifier
|
||
triggered. Reviewed owner records plus decision-time expiry are sufficient.
|
||
The honest outcome is canon plus offline conformance tooling, not an engine.
|
||
Retention is bounded to the proposed-standard reference need in `GOAL.md`.
|
||
- **The zones do not partition the real estate.** If the model needs a residue
|
||
of special cases to cover today's 27 routing lanes and actor inventory, it is
|
||
describing an aspiration, not a structure.
|
||
- **Nobody but the author declares one.** Two repos declaring and a third
|
||
reading is the minimum evidence of a model rather than a preference.
|
||
- **It becomes a second decision point.** The failure would not announce itself;
|
||
it would arrive as a small convenience — a stance compiled into membership
|
||
"just for now".
|
||
|
||
## 8. What this repo deliberately will not become
|
||
|
||
Not a PDP. Not network segmentation — "zone" is overloaded and the routing sense
|
||
is someone else's word. Not a placement model: reefs answer *where a thing runs*
|
||
and are `repo-manager`'s, and the fact that `reef-railiance` caps availability
|
||
for everything bound to it is a canon composition problem (`NK-WP-0027`), not
|
||
ours. Not an owner of anyone's controls — the controls stay with the repos that
|
||
enforce them; this model only says where they bite.
|
||
|
||
## 9. Direction
|
||
|
||
Model first, from the real estate. Canon standard drafted here and published by
|
||
`net-kingdom`, in the family of `tenancy-posture_v0.1`. Membership declared in
|
||
the `zones:` key that canon has already reserved. Two consumers before it is
|
||
called adopted, the first being ops-warden retiring `policy.enabled`.
|
||
|
||
A runtime only if `ZONE-WP-0001-T04` proves the exception lifecycle needs one —
|
||
and the cheaper answer is a legitimate result, not a disappointment.
|
||
|
||
That direction is delivered. `ZONE-WP-0002` hardened the offline contracts and
|
||
made canon lineage, owner provenance, revision/delta evidence, and exception
|
||
fixtures executable without reopening the runtime decision.
|