tenancy-posture draft-9: enforcement stance is not a seventh axis; reefs are canon's defect
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Answers zone-engine ZONE-WP-0001-T01.

Decision 5.6 — enforcement stance is a sibling standard, not an axis. The six
ladders are monotone and the whole current/target/guard machinery depends on it;
enforcement stance is not (ADR-0006 is the finding that the top rung is wrong for
the SSH lane). And this framework is descriptive: an accurately declared exempt
would be conformant and exempt. Membership is declared, stance belongs to the
control owner. Zone membership rides tenancy.yaml under a reserved zones: key so
the estate keeps one declaration surface; the schema permits it, unconstrained.

Decisions 8.4.1/8.4.2 — 'substrate location is not evidence' stated once instead
of three repo-local slogans, and the reef/P/V gap recorded as this document's
defect rather than zone-engine's scope. NK-WP-0027 takes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-19 22:06:20 +02:00
parent 4a915ce6c7
commit 9e041e3662
3 changed files with 512 additions and 86 deletions

View file

@ -6,11 +6,11 @@ domain: netkingdom
status: proposed
version: "0.1"
created: "2026-08-17"
updated: "2026-08-17"
updated: "2026-08-19"
scope: multi-tenancy-security-framework
revision: "draft-8"
revision: "draft-9"
owner: net-kingdom
last_reviewed: "2026-08-17"
last_reviewed: "2026-08-19"
review_interval: 6m
declaration_schema: canon/schemas/tenancy-posture_v0.1.schema.json
adr:
@ -28,7 +28,7 @@ related:
## Status
**Proposed, draft-8; ratification-ready.** Relocated from
**Proposed, draft-9; ratification-ready.** Relocated from
`the-custodian/canon/architecture` on
2026-08-17: multi-tenancy is part of the IT-security framework NetKingdom
provides, so this framework belongs in NetKingdom canon beside the IAM Profile
@ -59,6 +59,12 @@ and the tenant-engine boundary contract, not in the work-factory canon.
customer language. It also corrects the distinction between an implemented
control and an evidenced current level.
- **draft-9** answers `zone-engine`'s `ZONE-WP-0001-T01`. It rules that
enforcement stance is **not** a seventh axis (Decision 5.6) while reserving
`zones:` in `tenancy.yaml` so the estate keeps one declaration surface, and it
records the reef/`P`/`V` reconciliation as an open defect of this document
rather than of the repo that noticed it (Decision 8.4).
**Reviewed by all six. The score:** six repos found three live defects in their
own code by reading the ladders — `tenant-engine`'s unfiltered
event accessor, `audit-core`'s unfiltered read path, `flex-auth`'s
@ -583,6 +589,67 @@ it.
A provider's own `P` is `n/a`, not a number. `apps-pg` *provides* `P1`; it is
not *at* `P1`, and writing `P: 1` there would later read as an isolation claim.
**Decision 5.6 — enforcement stance is not a seventh axis, and `zones:` is
reserved in this file.** `zone-engine` asked whether *enforcement stance*
whether a given control is enforced, advisory or exempt in a given band of the
estate — should fold in here rather than become a second standard. It should
not, for a reason that is structural rather than territorial.
**Every one of the six ladders is monotone: higher is stronger, and higher is
what a service wants.** That assumption is load-bearing throughout. §12's
*improve* step moves a service up. §12's *guard* checks that none is below what
it declared. §6 has to make a special allowance for a level that is
*permanently* low by design, and §12's guard is told not to nag it — the
allowance exists because low-is-normal is the exception here.
Enforcement stance is not monotone. The correct stance for a bootstrap lane is
deliberately and permanently *below* the top rung, and the top rung is
sometimes the wrong answer outright: `ops-warden`'s `ADR-0006` is exactly the
finding that a fail-closed authorization gate on the SSH lane the tunnels
depend on is not a stronger position, it is an outage. A ladder whose top is
sometimes wrong is an enumeration, not a ladder, and putting one inside this
vector would break `current`/`target`/`gap`, the guard, and §6 for the six that
are.
§8.3 already refused an axis for a weaker reason than this one — that a QoS
level would be an unenforced claim. Enforcement stance *is* enforced. It fails
the other half of the same test.
There is a second, sharper reason. §6's conformance rule is *accuracy, not
altitude*, and it works because this framework is **descriptive**: it never
blocks anything by itself. Prescription enters only through §11 and Decision
8.2, where a **requirer** — never the declaring repo — sets a minimum level and
the two are machine-reconciled. Enforcement stance is prescriptive by nature.
Fold it in as an axis and an accurately declared `exempt` becomes conformant
*and* exempt: a conformance rule that hands out the exemption it exists to
audit. The declarer must not be the party that sets the stance.
So the split is the one `flex-auth` already argued to `zone-engine`:
**membership is data and is declared; stance is a rule and belongs to the
control's owner.** Membership is posture-shaped and behaves like a level.
Stance behaves like a tier minimum under Decision 8.2 — asserted elsewhere,
joined by machine.
**What canon rules, and it is binding on the sibling standard:**
- A security-zone standard is a **separate document** in this family, drafted
by `zone-engine` and published in NetKingdom canon beside this one and the
`*-engine` boundary contracts. It carries over §6 verbatim and §13's evidence
discipline.
- **Zone membership is declared in `tenancy.yaml`**, under a reserved top-level
`zones:` key, sibling to `tenancy:` and `provider:`*not* inside
`tenancy.current`. Decision 5.4 makes this file the repo's single posture
declaration surface, and a second root file would recreate the divergence
§5.4 was written to end. One file, one review cadence, one validator; two
standards, because the two have different owners and different conformance
semantics.
- `organization_posture` (`ops-warden` WP-0029) does **not** belong in this
file at all, under either key. It is a fleet-wide, time-varying scalar
describing the estate, not a property of the declaring service, and a
per-repo copy of a global would go stale in as many places as there are
repos. It is an *input* to stance selection and should be read by the zone
model, not absorbed into a declaration.
Worked examples after applying the evidence rule and minimum-across-paths rule
consistently:
@ -752,6 +819,46 @@ things, none of which is priority:
classes are co-resident. An unenforceable risk that nobody can see is strictly
worse than one that is stated.
### 8.4 Substrate location is not evidence — and reefs are not reconciled with `P` or `V`
**Decision 8.4.1 — location is not evidence of any property of the workload on
it.** Three repos have now written this rule locally in three vocabularies:
`railiance-master`'s *topology is not readiness*, `zone-engine`'s *placement is
not posture*, and §3.1 here, which requires every use of "isolation" to name
its axis. They are one rule. Stated once: **the substrate a workload sits on is
never, by itself, evidence for a level on any ladder in this framework.**
Binding to a reef, being on a dedicated instance, or naming a rail proves
placement and nothing else. Other repos should cite this rather than restate
it.
**Decision 8.4.2 — the reef taxonomy and this framework are not reconciled, and
that is this document's defect.** `zone-engine` asked whether canon should
reconcile reefs with the posture axes, on the assumption that this was a scope
question for the zone model. It is not: the unreconciled pair is not
zone ↔ reef, it is **reef ↔ `P` and `V`**, and it belongs to canon.
`repo-manager` owns substrate placement (`reef-railiance`, `reef-storage`) with
an explicit residual-risk acceptance attached to a binding. §7 and §8 of this
document presuppose that placement is fully described by the `P` ladder. It is
not. `P` grades **tenant data isolation within a datastore**; a reef is a named
**compute substrate carrying an accepted residual risk**. The `P` ladder has no
rung meaning "single node, shared control plane, risk accepted", and inventing
one would be the fabrication §6 prohibits.
The live consequence is on `V`, not `P`. §4.6 already warns that "a dedicated
cluster can still be a single instance on a single node", and Decision 4.6.1
makes `V` the minimum across the synchronous path. `reef-railiance` is
single-node with a shared control plane, which **caps `V` for every workload
bound to it** regardless of that workload's own replica count — which Decision
4.6.1 already says is not evidence. Nothing today joins the reef's facts to a
consumer's `V` declaration, so a rapp can declare `V2` accurately by its own
reading and be wrong by this document's own composition rule.
This is `railiance-platform`'s provider-declaration finding (Decision 5.5)
generalised one layer down. A reef is a **provider** and has nowhere to state
what it makes reachable. Tracked as `NK-WP-0027`; the fix is canon's, and the
zone model is not blocked on it.
The known escalation short of P2 is gateway-level prioritisation — ordering
submissions in a connection proxy by the requesting tenant's current
consumption. It is real, it is where the industry puts this when it must, and