flex-auth/docs/stance-register-review.md
tegwick 92981698d8
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Close FLEX-WP-0029 second edition; correct cadence.yaml; block human/external-gated workplans
FLEX-WP-0029: publish the second stance-register edition across five rows
(a third scope axis, not a converging two — tenant-engine scopes on
engine-reachability, not security-zone), record Finding 1 as resolved by
gate-house doctrine rather than by either side, and note Finding 3 as still
open in secrets-engine's file. First edition marked superseded, not amended.
SCOPE.md's G3 gap closed accordingly.

FLEX-WP-0031: correct cadence.yaml to declare one heartbeat per rare
load-bearing class instead of a single combined class (tests pass unchanged).
Acknowledged audit-core's AUDIT-IN-0006 reply on T02 and recorded its
corrections; the remaining work (drain, reconciliation, PVC rollout, G2
closure) stays wait/blocked pending the founder's attended OpenBao mint and
gate-house's atomicity ruling, so the workplan moves to blocked.

FLEX-WP-0027: marked blocked — the sole remaining task needs the operator's
own signed-in account, an irreducible human action.

FLEX-WP-0020: recorded net-kingdom's T04 update (NK-WP-0039-T02 done,
runtime.yaml digests current) and replied with no objection to their
ADR-0015 values-pointer proposal for the drifted runtime.yaml reference.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 250108@bnt-lap001
Assistant-Session: bab3d5bd-b0bb-42d0-bf80-94ed6fc2b08a
2026-09-27 22:12:35 +02:00

104 lines
5 KiB
Markdown

# Stance-register review — the register has a second row
Status: superseded — see `docs/stance-register-review-second-edition.md`
(2026-09-27, `FLEX-WP-0029`). This edition stays as written; it is not
amended to match the five-row register (`FLEX-DEC-2026-008`'s rule that a
correction a reader cannot see is not a correction).
Date: 2026-09-06
Standard: `security-layer-model_v0.7` §6.4 obligation 3, §13.1
Reviewer: flex-auth (Engine / PDP)
## Why flex-auth is writing this
In the 2026-08-29 alignment review flex-auth told gate-house it is "the
repository positioned to notice when the aggregate of consumer stances diverges
from what the policy packages say," and then recorded that the claim was sound
but unexercised: §13.1's register existed with **one row**, and one row cannot
diverge from anything.
It now has two. This is that claim being exercised for the first time, and
flex-auth is reporting a divergence it found rather than waiting to be asked.
## The two published maps
| | `ops-warden` | `secrets-engine` |
| --- | --- | --- |
| File | `pep-stance.yaml` | `pep-stance.yaml` |
| Rule of record | `ADR-0009` | `INTENT.md` / `layer.yaml` |
| Protected action | SSH certificate issuance | OpenBao metadata/KV lifecycle and delivery |
| Scope axis | `security-zone` | `catalog-stage` |
| Pinned to code by test | yes (`PolicyConfig.failure_modes`) | yes (`SHIPPED_STANCE`) |
Both are §6.4-conformant. Both are total over their axis, both publish rather
than bury the map, both carry no implicit default, and both are asserted equal
to the shipped value by a test — which is the property that makes a published
map worth relying on at all.
## Finding 1 — the two maps take opposite stances on `unknown`
| | `unknown` |
| --- | --- |
| `ops-warden` | `fail_open` — explicit, versioned build profile, `ADR-0009` |
| `secrets-engine` | `fail_closed` |
Both are defensible and neither is a defect. `ops-warden`'s `unknown` is a
build-profile artifact on a path whose z3 rows are closed; `secrets-engine`
treats an unmapped stage as production-shaped. But the estate's only two
published maps disagree about the case that, by construction, is the one nobody
planned for.
That is the aggregate divergence flex-auth said it would notice. It is reported
as an observation for gate-house's register, **not** as a request that either
repository change. A PDP does not get to set a consumer's stance — §9.3's
two-owner split is flex-auth's own finding and it cuts this way too.
What is worth deciding, and it is gate-house's to decide, is whether §6.4 should
say anything about `unknown` specifically. Today it requires only that the map
be total; totality is satisfied by either answer.
## Finding 2 — the rows are not comparable, and the register cannot say so
`ops-warden` scopes by `security-zone`; `secrets-engine` scopes by
`catalog-stage`, explicitly "the equivalent scope until security-zone
membership arrives as a claim on the decision." §6.4's "per zone or equivalent"
permits both.
The consequence is that the register cannot answer the question an inventory
exists to answer. "What is the estate's stance for a `z2-protected` workload?"
has no answer for `secrets-engine`, because that repository has no zone axis —
and the mapping between a catalog stage and a zone is not published anywhere.
This is a property of the register rather than a fault in either map. It is
worth recording before a third row arrives, because the cost of two
incommensurable axes is small and the cost of five is not.
flex-auth holds a relevant boundary here, unchanged from 2026-08-19: zone
**membership** compiles into the registry snapshot flex-auth already consumes,
while per-zone **stance** belongs to the consumer. If zone membership becomes a
claim on the decision, `secrets-engine`'s axis can converge onto zones without
either side inventing a mapping.
## Finding 3 — `secrets-engine`'s map cites a shelved artifact
`pep-stance.yaml` defines `fail_closed` as "no protected side effect without a
durable access-engine / `ActionAuthorization` record."
`ActionAuthorization` was shelved on the PEP consumption path by
`GH-DEC-2026-005`, which flex-auth accepted in `FLEX-DEC-2026-006` — arguing
against its own proposal. The step-1 artifact is `approval-engine`'s
approval-claim; the step-2 artifact is flex-auth's `DecisionEnvelope`.
The stance itself is unaffected: `fail_closed` still means no protected side
effect without a durable record, and the records exist. Only the name of the
artifact is stale. Because this file is read at runtime and pinned by test, the
stale name is more durable than a comment would be, which is why it is worth a
line rather than being left.
## What flex-auth is not claiming
- No stance is wrong. flex-auth cannot express fail-open at all, and does not
get to grade a consumer's residue.
- No change is requested of `ops-warden`. Its `unknown: fail_open` is
documented, versioned, and reasoned.
- This is not a §13.1 register. gate-house owns the register; this is one
reviewer's reading of the two rows now in it.