zone-engine/workplans/ZONE-WP-0001-security-zone-model.md
tegwick de2d8e2dda Correct the rapp count: eight declarations, not nine
An inflated count in a document whose subject is accuracy.

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

30 KiB
Raw Blame History

id type title domain repo status owner topic_slug planning_priority created updated state_hub_workstream_id
ZONE-WP-0001 workplan The security zone model — derive it from the estate, draft it as canon infotech zone-engine proposed zone-engine netkingdom P1 2026-08-19 2026-08-19 a75c8c9c-c108-4831-8d72-4343cce49879

ZONE-WP-0001 — The security zone model

Ported from WARDEN-WP-0032 (ops-warden), which deferred policy.enabled: true under ADR-0006 and named this repo as its successor. ops-warden keeps only its consumer-side task.

This workplan produces a model and a canon draft. It does not produce an API, a schema, or storage. An engine that ships a schema before it has partitioned the real estate defines the model by accident, through whatever its first wire format happened to be. Whether a runtime is warranted is an output of T02T03, not an assumption of T01.

The gap in one table

Axis Shipped Answers
Environment posture (dev/test/prod) ops-warden WP-0015 Where does this run?
Workload maturity (M0M3) ops-warden WP-0015 How ready is this workload?
organization_posture: build ops-warden WP-0029 What state is the org in?
Enforcement stance missing Is this control enforced here, and what happens when it fails?

The first three describe. Nothing decides. That is why policy.enabled is a repo-wide boolean, and why turning it on would have hardened the access needed to perform the refactors currently underway.

Do not reinvent these

net-kingdom/canon/standards/tenancy-posture_v0.1.md — the structural model to follow: orthogonal axes, graduated levels, a per-repo declaration (tenancy.yaml) with current/implemented/target vectors, evidence, and a review date; §6 conformance is accuracy, not altitude; §14 adoption stance structure, not tooling. That last one is why this workplan is shaped as it is.

Reefs (repo-manager/docs/RailianceAppDeploymentGuide.md) — reef-railiance carries a single-node/shared-control-plane residual risk requiring explicit acceptance. Substrate placement with risk attached is adjacent to a zone and must be reconciled with it, not duplicated. repo-manager's own rule — topology is not readiness — restates here as placement is not posture.

flex-auth — the PDP, service_class: latency-critical, already consuming a compiled registry snapshot built by ops-warden/scripts/build_flex_auth_registry.py. Zone membership reaches the decision point by compilation. A synchronous zone lookup in the decision path would be a regression dressed as an architecture.

flex-auth reviewed this workplan on 2026-08-19 as the PDP that would have to live with the result, and amended T01, T03, T04 and T05 in place. The three substantive changes: the "only PDP" invariant needs to bind authority and not only latency (T01); membership compiles to the registry but stance belongs in the policy package, and fail-open is not expressible by a PDP at all (T03); and flex-auth has no reload path, which decides how a time-boxed exception can possibly expire (T04). Membership itself needs no registry schema change — but do not land it on the existing trust_zone field (T05).

warden plan (ops-warden WP-0029) — already returns autonomous/founder_required/unroutable from properties of the thing, with the reasons that produced the verdict. Zone-aware enforcement extends that machinery; it does not grow a second vocabulary beside it.

Tasks

id: ZONE-WP-0001-T01
status: todo
priority: high
state_hub_task_id: "ea74316e-b711-4888-9b38-553ebc9ad856"

Confirm ownership on the record, and say what publishes where. This repo was seeded on a recommendation, not yet on agreement. Take to net-kingdom (canon) and flex-auth (the enforcing PDP): zone-engine owns the model and the exception lifecycle; canon publishes the standard, in the family of tenancy-posture_v0.1 and the *-engine boundary contracts; flex-auth stays the only PDP and consumes compiled membership.

If either disagrees, the model moves and this repo is archived rather than kept for its own sake. Record the outcome either way.

flex-auth answered 2026-08-19 (amended by flex-auth). Confirmed: zone-engine owns zone identity, membership and exception lifecycle; flex-auth stays the only PDP. But the invariant as written in GOAL.md guards the wrong property. "Never a synchronous lookup in a decision path" is a latency guarantee. It does not guarantee flex-auth remains the only decision point, because compiled data that determines an outcome is still deciding — it just decided earlier. Under the invariant as written, zone-engine could compile enforced: false for a lane and flip warden sign from deny to allow without a flex-auth policy change, and still be literally compliant.

The invariant flex-auth confirms is the tighter one:

zone-engine is the authority over zone identity and membership. The effect of a zone on any decision flex-auth renders is expressed in a flex-auth policy package — versioned, fixtured, tested, and stamped into the decision record. Membership is data and is compiled. Stance is a rule and is policy.

Rationale is in T03. Please carry the tightened wording into GOAL.md; the current wording is not wrong, it is just not load-bearing.

net-kingdom answered 2026-08-19 (amended by net-kingdom, as canon owner of tenancy-posture_v0.1). Confirmed on both counts, and one part of the question is taken off this repo.

1. Enforcement stance is a separate standard, not a seventh axis of tenancy-posture. Recorded as that standard's Decision 5.6 (draft-9). The reason is structural, not territorial, and it matters for how the zone model is shaped:

  • Every one of the six axes is monotone — higher is stronger and higher is what a service wants. current/target/gap, §12's improve and guard steps, and §6's special allowance for a permanently-low level all depend on it. Enforcement stance is not monotone. ADR-0006 is precisely the finding that the top rung is the wrong answer for the SSH lane the tunnels depend on. A ladder whose top is sometimes wrong is an enumeration, and embedding one in the vector would break the six that are ladders. §8.3 refused a QoS axis on a weaker version of this test.
  • tenancy-posture is descriptive; stance is prescriptive. §6 is accuracy, not altitude, and it is safe only because the framework blocks nothing by itself. Prescription enters through Decision 8.2, where a requirer sets a minimum and a machine reconciles it against declarations. Fold stance in as an axis and an accurately declared exempt becomes conformant and exempt — a conformance rule handing out the exemption it exists to audit.

This is the same split flex-auth argued in T03, arrived at from the canon side: membership is data and is declared; stance is a rule and belongs to the control's owner. Membership behaves like a level. Stance behaves like a tier minimum.

Binding on the declaration format (this pre-empts part of T05). To avoid the parallel-framework outcome this message was sent to prevent, canon rules that zone membership is declared in tenancy.yaml under a reserved top-level zones: key — sibling to tenancy: and provider:, never inside tenancy.current. §5.4 makes that file the repo's single posture declaration surface and a second root file recreates the divergence §5.4 ended. The key is already reserved in canon/schemas/tenancy-posture_v0.1.schema.json and is deliberately unconstrained there, so the validator will not reject a combined declaration while security-zones_v0.1 is still being drafted. One file, one review cadence, one validator; two standards, because they have different owners and different conformance semantics.

On organization_posture (asked in T02 and in WARDEN-WP-0032-T01): it does not belong in a per-repo declaration 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 goes stale in as many places as there are repos. Read it as an input to stance selection; do not absorb it.

2. Reefs — zone-engine is right, and the reconciliation is not yours. Placement is not posture is correct and should stay. But the pairing has been misidentified: the unreconciled pair is not zone ↔ reef, it is reef ↔ P and V, and it is a defect in tenancy-posture, not a gap in the zone model. P grades tenant data isolation within a datastore; a reef is a named compute substrate with an accepted residual risk, and there is no rung for that. The live consequence is on V: reef-railiance is single-node with a shared control plane, which caps V for everything bound to it under Decision 4.6.1, and nothing joins those facts today. That is Decision 5.5's provider-declaration finding one layer down — a reef is a provider with nowhere to state what it makes reachable.

Recorded as tenancy-posture Decisions 8.4.1 and 8.4.2 and taken as net-kingdom's NK-WP-0027. ZONE-WP-0001 is not blocked on it. Delete the reef question from T02's list of things this model must answer; citing Decision 8.4.1 is sufficient.

One further canon ruling, because three repos had written the same rule in three vocabularies — topology is not readiness (railiance-master), placement is not posture (here), and §3.1's naming requirement. Decision 8.4.1 now states it once: the substrate a workload sits on is never, by itself, evidence for a level on any ladder. Cite it rather than restating it locally.

Ownership confirmed. zone-engine owns zone identity, membership and the exception lifecycle. Canon publishes security-zones_v0.1.md beside tenancy-posture_v0.1 and the *-engine boundary contracts, owner-driven, as WP-0015's maturity model was. The repo is not archived.

Carry into GOAL.md: the tightened flex-auth invariant, and that the declaration surface is tenancy.yaml's zones: key rather than a new file.

id: ZONE-WP-0001-T02
status: done
priority: high
state_hub_task_id: "f1016c71-ccb0-46a7-9143-e81c7ac34cad"

Derive the zones from the real estate. Walk ops-warden's 27 catalog lanes, the adm/agt/atm actor inventory, and the workloads carrying posture descriptors. The model's test is that it partitions what exists without a residue of unexplained exceptions — and the exceptions found are the most informative output, not noise to tidy away.

Answer explicitly:

  • Is a zone a property of the actor, the lane, the workload, or the moment? The CoulombCore decommission and the issue-core move show the last is real and hardest to model. A time-boxed relaxation is a different object from a standing zone; conflating them yields a permanent hole with a temporary-sounding name.
  • How do zones relate to reefs? Struck by net-kingdom 2026-08-19. Not this model's question. Cite tenancy-posture Decision 8.4.1 — substrate location is never by itself evidence for a level — and stop there. The real unreconciled pair is reef ↔ P/V and it is canon's, tracked as NK-WP-0027.
  • Do zones compose with or fold in organization_posture? Answered by net-kingdom 2026-08-19: do not fold it in. It is a fleet-wide time-varying scalar, not a per-service property; consume it as an input to stance selection. The other two axes (environment posture, M0M3) remain an open question for this task — they are per-workload and genuinely composable.

Done 2026-08-19. Full result: docs/estate-partition-2026-08-19.md.

Corrected the same day by operator direction, recorded in §7 of that document. Policy is about the workload, not the lane; the software repo only suggests; the workload and its responsible party declare the scrutiny; and a zone requires a standard for admission — a workload qualifies to run in a zone rather than being labelled with one. This is tenancy-posture Decision 8.2's tier-minimum mechanism, which Decision 5.6 had already said stance would behave as. The four bands below survive as membership inputs, not as zones.

Four bands, each of the 27 lanes in exactly one — Decided (1, the only lane ops-warden decides), Fronted (10, owner has a front door), Covered (12, ops-warden proxies what it does not own), Signposted (4, routed, nothing flows). Derived from declared fields, not invented.

The discriminator is delegation.mode, not risk: 10 of 11 high-risk lanes are interim and 8 of those are exec_capable. A field added to answer a governance question predicts operational danger better than the one named for it.

Three results that bind the later tasks:

  • Stance is per control per zone, never per zone alone. The three existing controls cut the estate differently — pre-sign gate 1 lane, fetch gate 13, read-boundary 11, with only 8 in the overlap. They were built independently and their scopes were never reconciled.
  • Zone is a property of the lane. The caller (WARDEN_AGENT_ID) is a modifier, not the zone — collapsing them would make one lane need two. And the moment is confirmed as a separate object: nothing in the corpus represents it, and delegation.blocked_on is exactly the expiry-by-intention shape T04 must not reproduce.
  • Environment posture and M0M3 compose but cannot be joined today — they are per-workload, zones are per-lane, and no registry carries a join key. Inventing one would be fabrication under §6.

Residue, and the most valuable output: 14 of 27 lanes carry no risk value, and is_high_risk is risk == "high", so the agent read-boundary never fires for them; 5 are exec_capable. Routed to risk-nexus as RISK-F-0003. Consequence for this workplan: risk is not usable as a membership input until those lanes are graded.

id: ZONE-WP-0001-T03
status: todo
priority: high
state_hub_task_id: "7f47b750-1ae4-467d-b3c4-064f4ec07dbd"

Model stance and failure mode, per control per zone. Enforced / advisory / exempt, and fail-closed or fail-open. The failure mode is where the bite is: fail_closed is what turns a dead tunnel into an outage, and is precisely why the ops-warden flip 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 (ops-warden ADR-0004), and the warden plan escalation verdicts.

Operator direction 2026-08-19 — defaults derive from maturity, not from nothing. An ungraded lane must not inherit the safest-for-the-tool default; it should inherit the default its maturity context implies. Early or experimental context: an absent grade is tolerable and explicitly accepted. Production context: an absent grade is high, or critical where the context is critical. This is the same rule RISK-F-0003 needs and is why that finding's fix is a model question, not a cleanup.

Three things established while checking what this can attach to:

  • The right ladder already exists: M0M3 in ops-warden's registry/policy/security-posture.yaml. It is ordered (rank), phased (experimental-pocalpha-early-access → …), and already carries a data ceiling per rung (max_dataclass: syntheticinternal → …) plus promotion_gate. It is exactly the shape this rule needs. What it lacks is a join to lanes or repos — the gap T02 found.
  • .repo-classification.yaml category cannot carry it. It is populated estate-wide (54 project, 23 tooling, 14 product, 7 research, 4 experimental) and canon calls it "work mode, maturity, or organizational purpose" — but it is unordered, and the actual values invert the property we need: railiance-platform, which runs production OpenBao and owns three of the five lanes RISK-F-0003 exposes, is tooling; ops-warden, a production SSH CA, is tooling; net-kingdom, a canon-documentation repo, is product. Deriving a safety default from it would grade production credential infrastructure below a documentation repo. criticality exists in the rapp vocabulary (low/medium/high/critical) but is unset on every repo checked.
  • Whose maturity — the owner's, not the holder's. All 27 lanes live in ops-warden's catalog, but their owner_repo is elsewhere. Deriving from the repo that holds the pointer would give every lane ops-warden's classification, which says nothing about the credential. Membership must derive from the lane's owner or the workload it serves.

The principle validates against the data: all five lanes RISK-F-0003 exposes are owned by production-serving components, so "unclassified in a production context → high" would have caught every one.

One vocabulary caution for T05. accepted is not a grade. A grade says how dangerous a lane is; an acceptance says who agreed to carry that danger, and therefore needs an owner and a date. Putting an acceptance in a descriptive field repeats the error net-kingdom rejected when it refused stance as a tenancy axis. Model them as two fields: grade (derived, defaultable) and acceptance (asserted, owned, expiring).

Resolved by the T02 correction. Grade and acceptance are the two sides of a Decision 8.2 join: the zone asserts a floor, the workload asserts its posture, and the join is mechanical. Not two fields to invent — one join to implement.

And the join is now the critical path. ops-warden's catalog contains no workloads, so there is no subject to attach an admission standard to. M0-M3 already grades workloads, which is the side that exists; what is missing is anything declaring which workload consumes which lane. T03 cannot produce a usable stance model until that is answered, and the honest answer may be that it belongs to whatever declares workloads — not to this repo.

Corrected 2026-08-20 — the workload side exists, and most of the join with it. T02 concluded no registry carries a join key. That was too strong; it was derived from ops-warden's catalog alone, which is the one place a workload declaration would not live.

rapp-*/declarations/rapp.yaml is the workload declaration surface. Eight rapps declare workload_identity (name, principal, service_account, tenant) together with data_classification, criticality (low/medium/high/critical), readiness_state, and bound_reefs.

And the chain to maturity is already complete: ops-warden's registry/policy/security-posture.yaml carries dataclass_floor, mapping synthetic→M0, internal→M1, confidential→M2, restricted→M3. So workload → data_classification → minimum maturity is a shared vocabulary that spans two repos today, with nobody having built it for this purpose. That is the operator's maturity-derived default, already half-implemented.

criticality is the other half — it is exactly the "critical if the context is critical" axis, declared per workload, and untouched by any control so far.

Three defects in the join, which are now T03's actual work rather than a blocking unknown:

  1. The lane→workload key is derivable but fragile. path_template encodes platform/workloads/<domain>/<workload>/<bundle> for most lanes — but the convention is inconsistent: platform/workloads/rapp-qonto/keycape-client has one level fewer, so parsing yields keycape-client as a "workload" when it is a bundle. And the names do not agree: that path says rapp-qonto while the rapp declares workload_identity.name: qonto. Recommendation: add an explicit workload: field to catalog entries. Inferring identity by parsing a path string is precisely the implicit coupling that breaks quietly.
  2. Vocabulary mismatch. rapps declare public, which dataclass_floor does not map. rapp-policy-nexus is public today, so the floor cannot grade it. One of the two vocabularies must move; canon owns DataClassification.
  3. Coverage is partial. Eight workloads are declared; ops-warden's catalog yields ~17 distinct path identities. The unmatched remainder is the interesting set — it is where a lane exists for something that is not a declared workload at all.

This reopens the ownership question favourably: zone-engine does not need to build a workload registry. It needs to consume rapp declarations and ops-warden's dataclass_floor, and to ask ops-warden for one explicit field.

Build stage is a positional fact, not a concession. The organization is in build; the default stance is permissive and zones tighten by admission, rather than by raising a global floor. That is what makes this model compatible with deep refactoring instead of hostile to it, and it is the same reasoning that produced ADR-0006.

Amended by flex-auth 2026-08-19 — split membership from stance. ops-warden's option (c) ("zones as policy-package data") was rejected wholesale because the model must govern two controls flex-auth does not evaluate. flex-auth agrees with the premise and disagrees with the conclusion: (c) was rejected at the wrong granularity. Where a stance is evaluated belongs with the control's enforcement point, and there are three enforcement points here, not one:

Control Enforcement point Where its per-zone stance belongs
flex-auth pre-sign gate flex-auth (PDP) + warden sign (PEP) flex-auth policy package
Agent read-boundary (ADR-0004) ops-warden CLI ops-warden — flex-auth never sees it
warden plan escalation verdicts ops-warden CLI ops-warden — flex-auth never sees it

So (b) is right for two of three controls and wrong for the one that is flex-auth's. Concretely, for the pre-sign gate:

  • Membership → compiled registry. Which zone an actor/lane is in is data, varies per resource, changes as the estate changes, and is already produced by build_flex_auth_registry.py. Compile it.
  • Stance → policy package. "In zone X the gate is advisory" is a rule about outcomes. It belongs in the artifact that already carries fixtures, rego tests, Validate(), a version, and a status.

The concrete defect in compiling stance: every flex-auth decision envelope stamps matched_policy_version, policy_package and policy_status, and the decision id is derived from policy metadata plus request (internal/decision/engine.go:358). Registry content is not in that provenance. If zone stance lives in the registry, a stance change alters the verdict while the decision record still reports the same policy version — two decisions, same version, same request, different effect, and nothing in the audit trail explains why. That breaks flex-auth's reproducibility contract for exactly the control this workplan exists to make safe.

Second correction: flex-auth cannot express fail-open. A PDP returns an effect. "Fail-open" describes what the caller does when flex-auth is unreachable — that is a property of ops-warden's client (fail_closed in warden.yaml), and no zone data compiled into flex-auth can influence it. Model the failure-mode axis as PEP-side, owned by each consumer's declaration, not as something the PDP carries. enforced/advisory/exempt is expressible by flex-auth (as effect plus an advisory annotation in the envelope); fail-open is not, and a model that implies otherwise will be built and then not work.

id: ZONE-WP-0001-T04
status: todo
priority: high
state_hub_task_id: "1c542ca5-2b82-4778-a3e4-c76e932423c9"

Design the time-boxed exception — this is the load-bearing task. A standing classification needs no engine; canon plus a declaration file covers it. An exception with an expiry is state, and state wants an owner. Whether this repo earns a runtime is decided here.

Must specify: who may grant, against which zone and control, for how long, with what recorded justification; how expiry is enforced rather than intended; how an active exception is visible to someone who did not grant it; and what happens at expiry — auto-revert, or block until renewed.

If T04 concludes the lifecycle can live as reviewed declarations in git, say so plainly and drop the runtime. That is a valid and cheaper outcome.

Hard constraint from flex-auth 2026-08-19 — the PDP has no reload path. cmd/flex-auth/main.go:447 calls registry.LoadFile once at process start. There is no watcher, no SIGHUP, no reload endpoint. Both the registry snapshot and the policy package are baked into the container image and the production pins are digest-pinned (values/ops-warden.yaml, sha256:138aa347…). Changing either means: rebuild image → new digest → helm upgrade → pod restart.

This is the input T04 most needs, and it kills one design outright:

  • An exception compiled as inert registry data cannot have an enforced expiry. It expires when a human rebuilds and redeploys. That is expiry by intention — precisely what this task says it must not be.
  • An exception carrying its own not_after timestamp, evaluated against decision time in rego, does have an enforced expiry. OPA has a clock (time.now_ns()); the grant costs a redeploy but the lapse is automatic and needs nobody. The zone widens by deploy and narrows by itself, which is the correct asymmetry.

That is a third argument for stance-in-policy independent of the audit one in T03, and it also bears on whether this repo earns a runtime: if expiry is evaluated at decision time from a compiled timestamp, the lifecycle needs a record and a review, not a service. flex-auth's read is that this points at the cheaper outcome, but it is T04's call.

id: ZONE-WP-0001-T05
status: todo
priority: medium
state_hub_task_id: "f4556ca0-cb26-46ed-9351-d00270bd2309"

Declaration format and conformance rule. Follow tenancy.yaml: per-repo, with evidence, reviewed, and review_due; carry over accuracy, not altitude. Include how a zone assignment changes and how that change is observed — a zone that can be quietly widened is not a boundary.

Carrier file settled by net-kingdom 2026-08-19 (see T01). The declaration rides tenancy.yaml under a reserved top-level zones: key, not a new root file. The key is already permitted and deliberately unconstrained in net-kingdom/canon/schemas/tenancy-posture_v0.1.schema.json, so this task defines the shape inside zones: and nothing else. What remains open here is unchanged: the trust_zone collision, and whether membership rides the subject or the resource.

Two carrier facts from flex-auth 2026-08-19 (no schema change needed). Compiled zone membership is expressible in flex-auth's registry format today, with zero Go changes. Every registry entity carries metadata; api.Resource additionally carries labels, owner, attributes and trust_zone, and internal/decision/engine.go:275 flattens all of them into input.resource.attributes before evaluation. subject.metadata and subject.claims are flattened the same way (engine.go:257). A compiler writing "security_zone": "..." into a resource's attributes makes it readable from rego as input.resource.attributes.security_zone. Nothing to build.

Two things to decide anyway, and both belong in this task:

  1. Do not reuse trust_zone — this collision has already happened inside the PDP. api.Resource.TrustZone is a first-class field, is surfaced into rego input, and ops-warden/scripts/build_flex_auth_registry.py:77 sets it to the hardcoded constant "platform" on every ssh-certificate resource. No policy package reads it. It is a dormant, plausibly-named, semantically-empty field sitting exactly where a reader would expect zone membership to go. SCOPE.md warns that "zone" is overloaded and names network segmentation as the hazard; the actual live collision is this one. Name the new concept security_zone explicitly, or deliberately repurpose trust_zone and say so loudly — but do not let both exist meaning different things.

  2. Say whether membership rides the subject or the resource. In the ops-warden registry an actor appears as both: as a subject (agt-state-hub-bridge) and as a per-actor resource (ssh-cert:actor/agt-state-hub-bridge). If T02 concludes a zone is a property of the actor, the compiler must be told which record carries it — or write both and make that the contract. Leaving it implicit produces two compilers that disagree. This is a compiler contract, not a schema change.

id: ZONE-WP-0001-T06
status: todo
priority: medium
state_hub_task_id: "8a000c18-6ee7-4328-99c7-53c490435316"

Draft the canon standard and offer it. security-zones_v0.1.md for net-kingdom/canon/standards/, drafted here, published there. Owner-driven landing, as ops-warden's WP-0015 maturity model was.

id: ZONE-WP-0001-T07
status: todo
priority: medium
state_hub_task_id: "c7ea24df-8aa9-4ead-ba3a-033aa5201c21"

Prove it on two consumers. A model only its author honours is not adopted. The first is ops-warden: retire policy.enabled for a zone-aware control, closing WARDEN-WP-0031-T05. Re-run ops-warden/scripts/check_policy_caller_identity.py first — the 2026-08-19 evidence (decision:f3f7c88f9585582a) will be stale, and re-establishing it is cheap by design. The second consumer comes from T01.

  • ops-warden ADR-0006 — enforcement is zone-scoped, never a global flag
  • ops-warden WARDEN-WP-0032 — the ops-warden-side stub this was ported from
  • ops-warden WARDEN-WP-0031 — the deferred flip, and the readiness evidence
  • flex-auth FLEX-WP-0016 — the enforcing pin with no enforcing consumer
  • net-kingdom/canon/standards/tenancy-posture_v0.1.md — draft-9 Decisions 5.6, 8.4.1, 8.4.2 are net-kingdom's answer to T01
  • net-kingdom NK-WP-0027 — the reef ↔ P/V reconciliation, taken off this repo
  • repo-manager/docs/RailianceAppDeploymentGuide.md — reefs