diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 1dfa2b6..b553aac 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -20,7 +20,7 @@ | workplan | RAILIANCE-WP-0016 | finished | — | workplans/RAILIANCE-WP-0016-apps-pg-resource-evidence.md | | workplan | RAILIANCE-WP-0016 | finished | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | | workplan | RAILIANCE-WP-0017 | finished | — | workplans/RAILIANCE-WP-0017-consumption-mode-enforcement.md | -| workplan | RPF-WP-0018 | proposed | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| workplan | RPF-WP-0018 | active | — | workplans/RPF-WP-0018-policy-surface-alignment.md | | task | RAILIANCE-WP-0005-T01 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md | | task | RAILIANCE-WP-0005-T02 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md | | task | RAILIANCE-WP-0005-T03 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md | @@ -81,10 +81,10 @@ | task | RAILIANCE-WP-0016-T04 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | | task | RAILIANCE-WP-0016-T05 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | | task | RAILIANCE-WP-0017-T01 | done | — | workplans/RAILIANCE-WP-0017-consumption-mode-enforcement.md | -| task | RPF-WP-0018-T01 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | -| task | RPF-WP-0018-T02 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | -| task | RPF-WP-0018-T03 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | -| task | RPF-WP-0018-T04 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | -| task | RPF-WP-0018-T05 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | -| task | RPF-WP-0018-T06 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | -| task | RPF-WP-0018-T07 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T01 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T02 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T03 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T04 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T05 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T06 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | +| task | RPF-WP-0018-T07 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md | diff --git a/docs/tenancy-posture.md b/docs/tenancy-posture.md index 29fad61..df1db9e 100644 --- a/docs/tenancy-posture.md +++ b/docs/tenancy-posture.md @@ -14,6 +14,19 @@ levels below are `0`. None of them is an admission of weakness, and §6 is explicit that a declared low level is conformant while an unevidenced high level is not. +**Every level below carries what §13 requires of it.** §13.1: a level is +claimed only with its evidence artifact present. §13.1a: at or below the +"no control" rung, a declaration requires a **stated reason** instead, because +there is nothing to overclaim at the bottom of a ladder. Floor claims here +carry `reason:`; claims above the floor carry `evidence:`. A claim with +neither would be the overclaim §6 prohibits. + +Where `target` equals `current`, that is a **settled position, not a stalled +trajectory** — §6 permits a low level to be permanent by design, on the +`flex-auth` precedent (`I1` forever, because verifying its own inputs would +make it the identity provider its scope refuses to be). Those lines carry +`permanent: true` so §12's guard does not nag them. + ## Why this is a vector *set* and not a vector §5 asks a **service** for one level per axis. `railiance-platform` is an OAS @@ -84,28 +97,65 @@ tenancy: tenancy: service: openbao role: credential-provider - current: { I: 0, A: 2, E: 0, P: 0, R: 0 } - target: { I: 0, A: 2, E: 0, P: 0, R: 1 } + current: { I: 0, A: 0, E: 0, P: 0, R: 0 } + target: { I: 0, A: 0, E: 0, P: 0, R: 1 } + permanent: [I, A, E] service_class: latency-critical reviewed: "2026-08-17" + reason: + I: "No tenant concept. OpenBao authenticates workloads via Kubernetes + auth; it never receives, parses or validates a NetKingdom tenant + identifier. Permanent by design — a secrets engine that resolved + tenant identity would be duplicating tenant-engine." + A: "No tenant context is carried, so there is nothing to bind. Permanent + by design, on the §6 flex-auth precedent." + E: "No tenant-keyed data. OpenBao holds workload secrets, not tenant + records." + P: "One instance, every consumer shares it. Single-node rail; §17 + scaling demands apply." + R: "No retention position on audit device output or on KV version + history." gap: - R: "No retention position on audit device output or on KV version history. - R1 (platform default) is reachable cheaply and is not yet declared." - notes: - - "A2 is claimed on the consumer boundary, not a tenant boundary: policy - per workload path, bound once, centrally, in OpenBao's own policy - engine. It is NOT delegated to flex-auth, so A3 is not claimed and is - not currently a target — a PDP in the credential path would put - flex-auth on OpenBao's availability path and OpenBao on flex-auth's." - - "E is 0 on the TENANT axis and that number is misleading without this - sentence: consumer separation in OpenBao is structural — a workload - token's policy cannot address another workload's path at all, which is - E4-shaped machinery. It scores 0 because the axis measures the tenant - boundary and OpenBao has no tenant dimension. See the provider note." - - "P0 is accurate and deliberate: one instance, every consumer shares it. - Single-node rail; §17 scaling demands apply." + R: "R1 (platform default) is reachable cheaply and is not yet declared. + The only line here with a real trajectory." ``` +**Correction, 2026-08-17.** This vector first declared `A: 2`. That was +wrong twice over and both errors are worth recording rather than quietly +editing. + +*It was internally incoherent.* `E: 0` was justified on the ground that +OpenBao has no tenant dimension. §4.2's `A2` reads "a single local +authorization boundary; **tenant context** bound once, centrally" — the same +dimension. A declaration cannot invoke the absence of tenant context to claim +the floor on one axis and ignore it to claim a rung on the next. + +*It was unevidenced at the moment of claiming.* §13.1 requires the artifact to +be present when the level is claimed, and none was cited. §13.1a would not +have rescued it: the table defines an artifact from `A2` upward, so `A2` is +precisely the first rung where the exemption stops applying. + +The irony is the point. This repo routed a finding about unevidenced claims +in the same week it made one. + +**What the corrected zeros conceal, and why the provider note below exists.** +`A: 0` now reads as though OpenBao performs no authorization. It performs a +great deal, it is central, and it is mechanically evidenced — +`scripts/openbao-verify-token-grants.py` mints a scoped child token, asserts +it *can* sign with `ssh/sign/agt-role`, and asserts it *cannot* read policy +metadata, then revokes by accessor. That is exactly the shape §13 asks for at +`A2`: choke point identified, unbound request refused. It is pointed at the +**consumer** boundary, and none of the five axes has anywhere to put it. + +That evidence is therefore cited under the provider statement rather than +against a consumer axis. Consumer separation in OpenBao is structural — a +workload token's policy cannot address another workload's path at all, which +is `E4`-shaped machinery — and the framework's honest application scores it +`0`. + +`A3` is not a target: a PDP in the credential path would put `flex-auth` on +OpenBao's availability path and OpenBao on `flex-auth`'s. + ### `platform-pg` — policy relationship only Declared by `rapp-postgres`. This repo does not restate it. What this repo @@ -131,6 +181,18 @@ plus the provider statement is the accurate form. This is routed as a finding. **The five ladders describe a consumer of storage. They do not describe a provider of it.** +**Narrowed on re-reading, 2026-08-17.** An earlier version of this finding +claimed the framework had no way to say "this zero is structural, not weak". +That was wrong: §6 says exactly that, and §13.1a supplies the mechanism — +`target` equal to `current` with a stated reason is a settled position, on the +`flex-auth` `I1`-forever precedent. This declaration now uses it. Half of the +finding is withdrawn. + +What survives is the other half, and it is not expressible: a provider cannot +state **what level it makes reachable for the workloads it holds**, nor record +a control that is real, mechanically evidenced, and simply not on any of the +five consumer axes. + Every service above scores at or near zero on I, A and E, and in each case for the same structural reason rather than for a weakness: a storage or credential platform has no tenant dimension of its own. It is exactly as strong or weak as