GH-WP-0003-T03. maturity-engine holds the §13 gap register and the §13.1 stance-map inventory as queryable data and proposed the statute tables become pointers. Two things are true at once: a statute should not carry state, and a standard must be readable on its own. The registers become pointers, and not before maturity-engine publishes a committed, versioned export readable without a live query. Publication is the migration's precondition, not its follow-up — pointing an auditor at a live engine is not a register they can read, and would repeat in the other direction the exact defect §13.1 was created to fix. Until the export lands the tables stay and rows are transcribed, so user-engine, tenant-engine, ops-warden and ops-mason are inventoried in v0.8 either way rather than waiting on the condition. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WtJBr77gMFLrN93iEevqQJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 425128@bnt-lap001 Assistant-Session: f5944d8b-dac4-4e1a-87eb-8b3d8f314a63
693 lines
31 KiB
Markdown
693 lines
31 KiB
Markdown
# Decision records
|
|
|
|
## GH-DEC-2026-001 — NetKingdom security layer model, the gate-house re-cut, and the access-engine reframing
|
|
|
|
```yaml
|
|
id: GH-DEC-2026-001
|
|
kind: decision
|
|
title: NetKingdom security layer model, the gate-house re-cut, and the access-engine
|
|
reframing
|
|
status: resolved
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.1.md
|
|
source_note: history/2026-08-28-security-layer-model-and-gate-house-recut.md
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- flex-auth
|
|
- ops-warden
|
|
- ops-mason
|
|
- kings-guard
|
|
- whitehat-security
|
|
- net-kingdom
|
|
- zone-engine
|
|
created: '2026-08-28T19:15:15.607849Z'
|
|
updated: '2026-08-28T19:16:01.456127Z'
|
|
rationale: 'Approved in session on 2026-08-28. The three rulings were taken interactively:
|
|
Staff as the layer name, net-kingdom canon as the model''s home, and access-engine
|
|
as the rename target with the lane/rule demarcation accepted as its cost. Approval
|
|
covers the doctrine and documents only; the flex-auth rename remains a separate
|
|
governed migration, and the standard stays proposed pending assent from flex-auth,
|
|
kings-guard, and ops-warden.'
|
|
decided_by: Bernd Worsch
|
|
decided_at: '2026-08-28T19:16:01.456127Z'
|
|
state_hub_decision_id: "2d6509d0-ffd2-4209-89ab-bf68a4945ada"
|
|
```
|
|
|
|
## Context
|
|
|
|
The security estate acquired overlapping claims to the same responsibility, and
|
|
the overlap was invisible in each repository's own documents. `gate-house` was
|
|
seeded as a deterministic authority plane — a policy decision point with an
|
|
`/authorize` API, grant storage, and a revocation service — while `flex-auth`
|
|
already described itself as the authorization control plane and was actively
|
|
delivering `FLEX-WP-0017`, an approval contract binding approvals to action,
|
|
actor, target, and validity window. Neither repository's INTENT named the other.
|
|
`zone-engine` had already been ruled against on the same question.
|
|
|
|
Full review and evidence: `history/2026-08-28-security-layer-model-and-gate-house-recut.md`.
|
|
|
|
## Decision requested
|
|
|
|
Ratify three linked rulings. They are one decision because the second does not
|
|
hold without the first, and the third is the first applied to the repository
|
|
that was already right.
|
|
|
|
### Ruling 1 — Adopt the NetKingdom security layer model
|
|
|
|
The estate is layered **Taxonomy → Tooling → Engines → Staff**, distinguished by
|
|
determinism and by the kind of artifact each layer produces. The top layer is
|
|
named **Staff** — the general-staff sense of plans and doctrine without
|
|
execution — not "Helpers", which undersold a layer holding architecture,
|
|
controlling, and change.
|
|
|
|
The model is published as `net-kingdom/canon/standards/security-layer-model_v0.1.md`,
|
|
owned by gate-house, status `proposed`. It belongs in net-kingdom canon rather
|
|
than info-tech-canon because it is NetKingdom-flavored security architecture,
|
|
not general semantic contract.
|
|
|
|
It carries two normative rules:
|
|
|
|
- **Staff never touches Tooling directly. It acts only through Engine APIs.**
|
|
- **`access-engine` is the only policy decision point**, generalizing to the
|
|
whole estate the ruling first drawn in `zone-engine/INTENT.md` §5.
|
|
|
|
### Ruling 2 — Re-cut gate-house as the doctrine council
|
|
|
|
Gate House is Staff: the council where NetKingdom's security and defence
|
|
doctrine is established, documented, taught, and supervised. It holds no
|
|
runtime position.
|
|
|
|
The decisive argument is gate-house's own: **a decision point inside gate-house
|
|
would place the deterministic authority boundary inside the non-deterministic
|
|
management layer, violating INV-02 — the first invariant the repository exists
|
|
to defend.** The repository would have been the clearest available
|
|
counterexample to the canon it hosts.
|
|
|
|
Boundary: *the mandate and the operating mode are gate-house's; the decision is
|
|
access-engine's; the credential is secrets-engine's; the perimeter is
|
|
ops-mason's and ops-warden's.*
|
|
|
|
gate-house keeps what no other repository owns — the operating modes, the
|
|
principal/actor/runtime triple, mandates and authority ceilings, the change
|
|
dynamics envelope, the MCP doctrine, the posture asymmetry, the assurance
|
|
specifications, and the curriculum. It gives up `/authorize`, policy evaluation,
|
|
policy engine selection, grant storage, and revocation.
|
|
|
|
### Ruling 3 — Reframe flex-auth as an Engine and rename it access-engine
|
|
|
|
`flex-auth` is Engine-layer and remains the only policy decision point. It is
|
|
renamed **`access-engine`**. `auth-engine` was rejected: key-cape owns
|
|
authentication, and `auth-` preserves the ambiguity the rename exists to remove.
|
|
`permission-engine` was rejected as ageing badly against a future `role-engine`.
|
|
|
|
The name's one cost is that "access" is already spoken for operationally by
|
|
ops-warden and ops-mason. It is paid by a demarcation, now normative in §8 of
|
|
the standard: **ops-warden and ops-mason own access lanes — how a worker reaches
|
|
a host; access-engine owns access rules — whether they may.**
|
|
|
|
Sequence is binding: **reframe the INTENT first, rename second**, as a governed
|
|
migration. The rename touches `FLEX-WP` prefix ownership, State Hub identifiers,
|
|
ops-warden's routing tables, zone-engine's binding boundary text, and
|
|
secrets-engine integrations.
|
|
|
|
The reframing also splits a responsibility flex-auth currently holds whole:
|
|
**authoring and governing policy is Staff work (gate-house); evaluating it
|
|
deterministically and in-path is access-engine's, exclusively.** This is the
|
|
constructive resolution of the `FLEX-WP-0017` overlap — gate-house designs the
|
|
approval contract, access-engine validates approvals at decision time.
|
|
|
|
## What approval authorizes
|
|
|
|
- Publication of the layer model as a proposed net-kingdom standard.
|
|
- The gate-house INTENT re-cut, already applied at `7f13f72`.
|
|
- The layering review notes placed at the top of twelve estate INTENT files.
|
|
- Starting the flex-auth INTENT reframe.
|
|
- Retiring the gate-house artifacts that describe an engine: ADR-003 (policy
|
|
engine selection), milestones M0, M3, and M4, and `GH-WP-0001-T04`
|
|
(`/authorize` skeleton). `GH-WP-0001` is rewritten against the re-cut before
|
|
it is promoted to active.
|
|
|
|
## What approval does not authorize
|
|
|
|
- The `flex-auth` → `access-engine` rename itself. That is a separate governed
|
|
migration with its own record, and it must not begin before the INTENT
|
|
reframe lands.
|
|
- Any change to `zone-engine`'s 2026-08-23 disposition.
|
|
- Promoting the standard from `proposed` to `accepted`.
|
|
- Any change to another repository's workplans. Work structure stays with the
|
|
repository doing the work.
|
|
|
|
## Assent still required
|
|
|
|
Two adaptations move vocabulary away from repositories that currently use it,
|
|
and follow the estate's precedent that a boundary is drawn on review by the
|
|
other side rather than asserted — as flex-auth did to zone-engine:
|
|
|
|
1. **flex-auth** — Engine framing, the rename, and the authoring/evaluation split.
|
|
2. **kings-guard** and **ops-warden** — releasing "control plane" and the
|
|
security curriculum respectively to the layers that own them.
|
|
|
|
## Reversal
|
|
|
|
The rulings are documents; nothing executable depends on them yet, and no code
|
|
exists in gate-house. Reversal is reverting the INTENT and standard commits.
|
|
The falsifiers that should trigger reconsideration are in
|
|
`gate-house/INTENT.md` § "What Would Make This Repository Wrong" — principally
|
|
gate-house becoming a paper generator whose conformance loop never turns, or
|
|
the estate declining to adopt the authority vocabulary.
|
|
|
|
## GH-DEC-2026-002 — Revocation fails closed only when approval-engine's own store is down
|
|
|
|
```yaml
|
|
id: GH-DEC-2026-002
|
|
kind: decision
|
|
title: Revocation fails closed only when approval-engine's own store is down
|
|
status: resolved
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|
source_note: history/2026-08-29-approval-evidence-integrity-contracts.md
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- approval-engine
|
|
- audit-core
|
|
- flex-auth
|
|
created: '2026-08-29T12:50:04.747439Z'
|
|
updated: '2026-08-29T12:50:58.873684Z'
|
|
rationale: 'Approved as GH-WP-0002-T03. Local-outbox fail-closed is the only remaining
|
|
closed path: if approval-engine cannot insert the outbox row, the revocation does
|
|
not commit. An audit-core outage must not block a revocation. Synchronous emission
|
|
inside the mutation is forbidden even though it is atomic. Proceed-with-gap is rejected
|
|
for load-bearing approval evidence.'
|
|
decided_by: Bernd Worsch
|
|
decided_at: '2026-08-29T12:50:58.873684Z'
|
|
```
|
|
|
|
## Context
|
|
|
|
`GH-IN-0001` (from `audit-core`) required that the revocation failure mode be a
|
|
recorded decision rather than an implementation accident. Both sides are
|
|
defensible on their own: fail-closed makes an audit dependency into an
|
|
availability risk on the revocation path; proceed-with-gap needs a detectable
|
|
marker so the gap is visible rather than silent.
|
|
|
|
v0.5's local-outbox rule already narrowed this. With the queue in
|
|
`approval-engine`'s own store, fail-closed triggers only when that store is
|
|
down — where the change could not have been recorded anyway — and an
|
|
`audit-core` outage does not block a revocation. Satisfying atomicity by
|
|
emitting synchronously to `audit-core` inside the mutation is also atomic, and
|
|
turns an audit outage into an inability to revoke: the operation least
|
|
tolerable to block during an incident.
|
|
|
|
The statute states the locality rule at §9.4. This record is the decision the
|
|
workplan still owed, so an implementer cannot pick the other side by accident.
|
|
|
|
Wire: `docs/contracts/approval-outbox.md`.
|
|
|
|
## Decision
|
|
|
|
**If the local outbox insert cannot commit, the revocation does not commit.**
|
|
The same rule applies to issuance, use, and supersession.
|
|
|
|
**An `audit-core` outage MUST NOT block a revocation.** Drain is asynchronous
|
|
and at-least-once. `audit-core` dedupes on `event_id`.
|
|
|
|
**Synchronous emission to `audit-core` inside the state-change transaction is
|
|
forbidden**, even though it is atomic.
|
|
|
|
Proceed-with-gap is rejected for load-bearing approval evidence. A revocation
|
|
that succeeds while its event is lost is the exact case `AUDIT-IN-0001`
|
|
conditioned assent on.
|
|
|
|
## What this authorizes
|
|
|
|
- `approval-engine` failing a revoke (and any other mutation) when its own
|
|
store cannot insert the outbox row.
|
|
- Continuing to revoke while `audit-core` is down, with the row draining later.
|
|
- Treating emit-after-commit, a second non-local queue, or a sync `audit-core`
|
|
call inside `BEGIN`…`COMMIT` as out of contract.
|
|
|
|
## What this does not authorize
|
|
|
|
- Claiming the outbox closes adversarial omission. Atomicity prevents crash;
|
|
cadence and reconciliation detect suppression after the fact (§9.6).
|
|
- A validity query on `audit-core`.
|
|
- Any change to another repository's workplans.
|
|
|
|
## Reversal
|
|
|
|
Revert this record and the outbox contract. The falsifier is operational: if
|
|
failing closed on the local store removes the ability to revoke during the
|
|
incidents this engine exists for, the trade needs revisiting — but the
|
|
alternative is a silent evidence gap on the event an attacker most wants
|
|
missing, which is worse.
|
|
|
|
## GH-DEC-2026-003 — The PEP consumes an approval before the protected side effect
|
|
|
|
```yaml
|
|
id: GH-DEC-2026-003
|
|
kind: decision
|
|
title: The PEP consumes an approval before the protected side effect
|
|
status: resolved
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|
source_note: docs/contracts/approval-consumption.md
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- approval-engine
|
|
- flex-auth
|
|
- secrets-engine
|
|
- ops-warden
|
|
created: '2026-08-29T12:50:06.944092Z'
|
|
updated: '2026-08-29T12:51:01.355583Z'
|
|
rationale: Approved as GH-WP-0002-T06. The PEP consumes by compare-and-swap before
|
|
the protected side effect; the PDP never mutates; there is no unconsume. Same request
|
|
digest is idempotent success; a different digest against a consumed object is conflict.
|
|
This closes the three named races and unblocks APPROVAL-WP-0001-T05 and FLEX-WP-0017-T05.
|
|
decided_by: Bernd Worsch
|
|
decided_at: '2026-08-29T12:51:01.355583Z'
|
|
```
|
|
|
|
## Context
|
|
|
|
Statute §16 left open who marks an approval consumed, and at what point
|
|
relative to the decision. `flex-auth` named three failure modes neither engine
|
|
closes alone: an ALLOW never consumed; a double consumption by racing callers;
|
|
consumption after a failed action. `approval-engine` performs the mutation
|
|
because `access-engine` never mutates, and refused to wire a public consume by
|
|
guessing the contract. `APPROVAL-WP-0001-T05` and `FLEX-WP-0017-T05` are wait
|
|
on this record.
|
|
|
|
§9.7.3 forbids inferring consumption from a decision record. That stands. The
|
|
same paragraph currently reads as if the action must precede the consume call.
|
|
That reading cannot enforce single use: two racing PEPs can both act, and CAS
|
|
then prevents only the second record.
|
|
|
|
## Decision
|
|
|
|
**The PEP-shaped consumer consumes, by compare-and-swap, before the protected
|
|
side effect.** The PDP never mutates. Staff never calls consume.
|
|
|
|
**There is no unconsume and no reserve/release.** An approval authorizes one
|
|
attempt, not one success. A consume followed by a failed action spends the
|
|
object; retry is a new approval.
|
|
|
|
**Same `request_digest` against an already-consumed object is idempotent
|
|
success** (a retry of one logical request). A different digest is conflict,
|
|
and the PEP MUST NOT act.
|
|
|
|
The three failure modes have owners:
|
|
|
|
1. *Allow never consumed* — PEP duty to consume; PDP lifetime bounds the
|
|
window; a stale ALLOW without a matching `use` is a finding, not a consume.
|
|
2. *Double consumption* — `approval-engine` CAS; the PEP that receives
|
|
conflict does not act.
|
|
3. *Consumed then the action fails* — accepted as the cost of closing (2).
|
|
|
|
Protocol: `docs/contracts/approval-consumption.md`. Statute v0.8 will replace
|
|
the §9.7.3 implication that action precedes the consume call; until then this
|
|
record governs the blocked implementers.
|
|
|
|
## What this authorizes
|
|
|
|
- `approval-engine` exposing `POST /v1/approvals/{id}/consume` against this
|
|
contract, including the digest column the internal CAS does not yet store.
|
|
- `FLEX-WP-0017-T05` requiring the PEP (secrets-engine, for that task) to
|
|
consume before the OpenBao call.
|
|
- Canon `T-06` consume-side replay (a second, different digest against a
|
|
consumed object) becoming in-scope once the endpoint exists.
|
|
|
|
## What this does not authorize
|
|
|
|
- The PDP consuming, or inferring consumption from a decision record.
|
|
- Unconsume, reserve, or any path that returns a consumed object to `approved`.
|
|
- A consume that is a decision ("may this actor do X").
|
|
- Any change to another repository's workplans. Work structure stays with the
|
|
repository doing the work.
|
|
|
|
## Reversal
|
|
|
|
Revert this record and the consumption contract. The falsifier is operational:
|
|
if spending an approval on a failed attempt makes the estate unable to
|
|
complete the actions this object exists for, a reserve/commit protocol can be
|
|
raised then. Unconsume is not the alternative — it reopens replay.
|
|
|
|
## GH-DEC-2026-004 — Layer emission-cadence ownership between Info Tech Canon and Net Kingdom
|
|
|
|
```yaml
|
|
id: GH-DEC-2026-004
|
|
kind: decision
|
|
title: Layer emission-cadence ownership between Info Tech Canon and Net Kingdom
|
|
status: resolved
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|
source_note: kings-guard/specs/EmissionCadenceDeclaration.md
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- info-tech-canon
|
|
- net-kingdom
|
|
- kings-guard
|
|
- qonto-assistant
|
|
created: '2026-09-04T00:55:29Z'
|
|
updated: '2026-09-04T00:55:29Z'
|
|
rationale: >-
|
|
Approved interactively on 2026-09-04. The layered split gives each artifact
|
|
one owner: ecosystem-wide semantics belong to info-tech-canon; NetKingdom-
|
|
specific MUST/SHOULD rules and the low-volume load-bearing heartbeat-plus-
|
|
reconciliation profile belong to net-kingdom. This avoids both a Staff-local
|
|
consumer schema and competing Taxonomy definitions.
|
|
decided_by: Bernd Worsch
|
|
decided_at: '2026-09-04T00:55:29Z'
|
|
state_hub_decision_id: "89c73f45-d07b-40ea-b428-5a7375ce4b09"
|
|
```
|
|
|
|
## Context
|
|
|
|
Security-layer-model v0.7 §§9.6 and 17 require evidence sources to declare an
|
|
expected emission cadence so silence can become a finding. King's Guard is the
|
|
only current consumer and drafted `EmissionCadenceDeclaration.md` against the
|
|
real `qonto-assistant` source, but correctly declined to keep a Staff-local
|
|
schema. The standard left ownership between the two Taxonomy repositories:
|
|
`info-tech-canon` for ecosystem-wide semantic contracts and `net-kingdom` for
|
|
NetKingdom standards of record.
|
|
|
|
Treating that as joint ownership would leave version authority ambiguous.
|
|
Giving the entire artifact to either repository would instead conflate a
|
|
reusable evidence/observability contract with the security obligations of one
|
|
estate. The split is therefore made by artifact, with one owner for each.
|
|
|
|
## Decision
|
|
|
|
**`info-tech-canon` owns the versioned, ecosystem-wide
|
|
`EmissionCadenceDeclaration` semantic contract.** It owns the generic forms,
|
|
fields, vocabulary, validation semantics, compatibility rules, and evolution
|
|
of the contract.
|
|
|
|
**`net-kingdom` imports that contract and owns the NetKingdom security
|
|
profile.** It owns which evidence classes MUST or SHOULD declare cadence, the
|
|
rule that rate monitoring is forbidden for rare load-bearing classes, and the
|
|
heartbeat-plus-reconciliation obligations that satisfy security-layer-model
|
|
§9.6.
|
|
|
|
The remaining ownership boundaries are unchanged:
|
|
|
|
- each source repository owns its declaration instance and emission behavior;
|
|
- `kings-guard` owns stream evaluation and silence findings, not the schema;
|
|
- Gate House owns doctrine and conformance supervision, not publication or
|
|
runtime behavior.
|
|
|
|
The King's Guard draft remains the provenance and handover input. Once the
|
|
Taxonomy artifacts are published, it becomes historical rather than a second
|
|
contract.
|
|
|
|
## What this authorizes
|
|
|
|
- Requesting `info-tech-canon` to adopt, revise, or contest the generic
|
|
contract and create its own owning work record.
|
|
- Requesting `net-kingdom` to adopt, revise, or contest the security profile
|
|
and create its own owning work record.
|
|
- Sources such as `qonto-assistant`, `approval-engine`, and `secrets-engine`
|
|
publishing instances against the eventual canonical contract and profile.
|
|
- King's Guard replacing its draft-shaped fixture with the published contract
|
|
without changing its consumer ownership.
|
|
|
|
## What this does not authorize
|
|
|
|
- Joint ownership or two independently versioned definitions of the generic
|
|
schema.
|
|
- Gate House or King's Guard retaining the schema as a local contract.
|
|
- Gate House creating workplans in either Taxonomy repository.
|
|
- Treating ownership as source conformance: `qonto-assistant` remains
|
|
incomplete until it publishes and emits the required positive claim.
|
|
|
|
## Assent and completion
|
|
|
|
The ownership ruling is resolved. Publication is complete only when both
|
|
Taxonomy owners reply in their own voice and publish or explicitly schedule
|
|
their respective artifacts. Until then the prior handover residual remains
|
|
open, now with an unambiguous requested disposition.
|
|
|
|
## Reversal
|
|
|
|
Supersede this record if the generic contract proves inseparable from the
|
|
NetKingdom security profile, or if Info Tech Canon cannot provide a stable
|
|
cross-domain contract boundary. Reversal must still name one owner for every
|
|
artifact; returning to undifferentiated "Taxonomy ownership" is not an
|
|
acceptable outcome.
|
|
|
|
## GH-DEC-2026-005 — The approval-claim is the step-1 artifact on the PEP consumption path
|
|
|
|
```yaml
|
|
id: GH-DEC-2026-005
|
|
kind: decision
|
|
title: The approval-claim is the step-1 artifact on the PEP consumption path
|
|
status: resolved
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|
source_note: docs/contracts/approval-consumption.md
|
|
origin: GH-IN-0002
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- approval-engine
|
|
- flex-auth
|
|
- secrets-engine
|
|
- ops-warden
|
|
rationale: 'Confirmed, with one addition. GH-DEC-2026-003 already named step 1 by
|
|
endpoint and by field; the approval-claim is what that endpoint serves and valid_now
|
|
is its field. ActionAuthorization is a proposed, unratified shape carrying no doctrine
|
|
standing here. The addition is that the split validation is stated as doctrine rather
|
|
than left implicit: each artifact is checked by the consumer against the layer that
|
|
owns its data, and no PIP republishes a PDP decision. The state-hub authority requirement
|
|
in the secrets-engine validator is struck because State Hub is a read model and
|
|
holds no runtime approval authority.'
|
|
decided_by: Bernd Worsch
|
|
created: '2026-09-05T23:28:23.931441Z'
|
|
updated: '2026-09-05T23:28:23.931441Z'
|
|
```
|
|
|
|
## Context
|
|
|
|
`GH-DEC-2026-003` settled the consumption sequence and named step 1 by endpoint and
|
|
by field: `GET /v1/approvals/{id}/claim` → `valid_now` (a fact, not permission).
|
|
`approval-engine` serves the approval-claim at that endpoint
|
|
(`approval-engine/docs/approval-claim.md`). `secrets-engine`'s PEP validator
|
|
(`validate_action_authorization`, `src/secrets_engine/authorization.py`) calls the
|
|
same endpoint but expects a flex-auth `ActionAuthorization`. Two different objects
|
|
were being assumed on one path, and the divergence would have surfaced at first live
|
|
consume rather than at deployment.
|
|
|
|
`ActionAuthorization` originates in `flex-auth/docs/action-bound-authorization-contract.md`
|
|
as a proposed shape for durable approval storage that the same document assigns to
|
|
`approval-engine`. It was never ratified, appears nowhere in this repository's
|
|
doctrine, and has no `valid_now` field. `GH-DEC-2026-003` was issued after it without
|
|
reference to it. There is therefore nothing to reconcile: the claim was the step-1
|
|
artifact all along, and this record says so where implementers will find it.
|
|
|
|
`approval-engine` raised the question rather than guessing, which is the behaviour
|
|
§12 asks for. The three substantive assertions in the request were checked here
|
|
independently before confirmation.
|
|
|
|
## Decision
|
|
|
|
**1. The approval-claim is the step-1 artifact on the `GH-DEC-2026-003` path.**
|
|
It carries the approval fact: binding digest, validity window, consumption state,
|
|
observation freshness, and issuer. Holding one with `valid_now: true` remains not
|
|
authority to act.
|
|
|
|
**2. `ActionAuthorization` is not required on that path.** `approval-engine` is not
|
|
expected to serve it and MUST NOT serve it from the claim endpoint. A step-1 response
|
|
cannot contain a step-2 decision; any composed post-decision artifact would be a new
|
|
artifact at a new endpoint. The proposal is shelved on this path, not withdrawn.
|
|
|
|
**3. A PEP validates across the two artifacts it already fetches.** The claim is
|
|
checked for the approval fact; the flex-auth `DecisionEnvelope` from step 2 is checked
|
|
for exact `CheckRequest` match and policy package/version pin. This is doctrine, not
|
|
merely an implementation convenience: **each artifact is validated against the layer
|
|
that owns its data.** A PIP republishing the PDP's decision would put a copy of the
|
|
authority decision in a repository that did not render it — the same shape of error
|
|
the re-cut removed from Gate House itself. No safety property is lost, because
|
|
`ActionAuthorization` is a bundle of exactly these two checks.
|
|
|
|
**4. The `provenance.authority == "state-hub"` requirement is struck.** State Hub is
|
|
a read model. It is not the runtime approval authority and never was; flex-auth's own
|
|
contract says so. A validator that requires it would fail closed against every
|
|
correctly issued claim. `secrets-engine` removes the constant with the validator split.
|
|
|
|
Consequent changes: `approval-engine` none — the claim schema stands as published;
|
|
`secrets-engine` splits its validator and drops the authority constant; `flex-auth`
|
|
records that the proposal is shelved on this path. Nothing here gates
|
|
`APPROVAL-WP-0002-T03` — `secrets-engine` is fail-closed until its own gates land,
|
|
and this record governs first live consume, not deployment.
|
|
|
|
## Deferred
|
|
|
|
A ratified post-decision `ActionAuthorization` — one composed, signed, forwardable
|
|
object — remains coherent and is recorded here so it is not rediscovered as new. It
|
|
is not adopted now because it has no named issuer or lifecycle owner and the sequence
|
|
is already settled without one. Revisit on any of: a third or fourth PEP-shaped
|
|
consumer; a requirement for a single signed forwardable artifact (offline
|
|
verification, or an audit that must replay one object rather than a join); resolution
|
|
of flex-auth's open G3 finding by composition rather than by adding a lifetime to the
|
|
envelope; or assent of the statute §17 Taxonomy request-claim schema
|
|
(`APPROVAL-IN-0001`) — in which case converge there and do **not** revive this
|
|
separately.
|
|
|
|
Also rejected, so they are not re-proposed: serving `ActionAuthorization` at the claim
|
|
endpoint (structurally impossible for step 1, and it would assert an authority
|
|
`approval-engine` does not hold); and extending the claim with `approvals.required_count`
|
|
or `entries` (publishing approver identities is a deliberate least-disclosure non-goal,
|
|
and it would still not satisfy the validator).
|
|
|
|
## Reversal
|
|
|
|
Revert this record and the amendment to `docs/contracts/approval-consumption.md`. The
|
|
falsifier is a demonstrated check that two-artifact validation cannot perform and a
|
|
single composed artifact can — most plausibly offline or forwarded verification with
|
|
no access to the PDP. That is a trigger for the deferred option above, not for
|
|
returning `ActionAuthorization` to the claim endpoint, which stays forbidden on
|
|
structural grounds regardless.
|
|
|
|
## GH-DEC-2026-006 — The §13 registers become pointers only once maturity-engine publishes a readable export
|
|
|
|
```yaml
|
|
id: GH-DEC-2026-006
|
|
kind: decision
|
|
title: The §13 registers become pointers only once maturity-engine publishes a readable
|
|
export
|
|
status: resolved
|
|
owner: Bernd Worsch
|
|
repo: gate-house
|
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
|
source_note: workplans/GH-WP-0003-statute-v08-amendment-set.md (T03)
|
|
requested_dispositions:
|
|
- approved
|
|
- revised
|
|
- rejected
|
|
affects:
|
|
- gate-house
|
|
- net-kingdom
|
|
- maturity-engine
|
|
- ops-warden
|
|
- ops-mason
|
|
- user-engine
|
|
- tenant-engine
|
|
- access-engine
|
|
rationale: 'A statute of record should not carry state, and §13 and §13.1 are state:
|
|
they change without the doctrine changing, and a hand-maintained table inside a
|
|
standard is a register that drifts. maturity-engine is the right holder. But a pointer
|
|
is only an improvement once there is something readable to point at — a standard
|
|
that can only be understood by querying a live engine has traded one defect for
|
|
a worse one, and it would make the statute unreadable to exactly the auditor it
|
|
exists for. The migration is therefore conditioned on a committed, versioned export
|
|
rather than declared outright. Until that export exists the tables stay and rows
|
|
are transcribed, so no repository is left without an answer while the condition
|
|
is outstanding.'
|
|
decided_by: Bernd Worsch
|
|
created: '2026-09-05T23:38:49.777532Z'
|
|
updated: '2026-09-05T23:38:49.777532Z'
|
|
```
|
|
|
|
## Context
|
|
|
|
`security-layer-model` v0.7 §13 holds the open-gap register and §13.1 the PEP
|
|
stance-map register. Both were created because the obligations above them named a
|
|
register that did not exist — §9.1's own logic, that a requirement whose register is
|
|
missing is a capability catalogued without a surface. They did their job.
|
|
|
|
`maturity-engine` (MAT-WP-0001) now holds both as queryable data: the §13 snapshot
|
|
with state and owner-status intact, the §13.1 inventory, `ASM-0`…`ASM-6` registered
|
|
as data owned by gate-house, `pep-stance-publication` owned by ops-warden, and
|
|
blocked-clean scored equal to conforming by test. It proposes that the statute table
|
|
become a pointer.
|
|
|
|
Four repositories are waiting behind the answer. `user-engine` and `tenant-engine`
|
|
have published stance maps and asked for §13.1 rows; ops-warden is published and
|
|
ops-mason is not. §6.4 obliges every PEP-shaped consumer to publish and obliges those
|
|
maps to be inventoried. Each week the question stays open, the register either
|
|
accumulates transcription or accumulates silence.
|
|
|
|
## Decision
|
|
|
|
**§13 and §13.1 become pointers to `maturity-engine`, and not before it publishes a
|
|
committed, versioned export of both registers that is readable without a live query.**
|
|
|
|
Two things are true at once and the ruling holds both.
|
|
|
|
**A statute should not carry state.** §13 and §13.1 change without the doctrine
|
|
changing. A table maintained by hand inside a standard of record drifts, and every
|
|
row transcribed into it is the manual step `maturity-engine` exists to remove. This
|
|
is the same rule as `GH-DEC-2026-005`: the artifact is held by the layer that owns
|
|
its data, and a repository that neither computes nor owns a fact should not be its
|
|
register of record.
|
|
|
|
**A standard must be readable on its own.** A pointer to a live engine is not a
|
|
register an auditor can read; it is an instruction to run software. Whatever else the
|
|
statute is, it must be legible in git, at a version, to a reader with no cluster
|
|
access — including a reader auditing the estate precisely because they do not trust
|
|
its running systems. Replacing a drifting table with an unreadable reference trades a
|
|
known defect for a worse one.
|
|
|
|
The condition reconciles them. `maturity-engine` computes and remembers; it also
|
|
publishes the result as a committed artifact at a stated path and version, and the
|
|
statute cites that path. The rows are then computed rather than transcribed, and
|
|
still readable without a query. **Publication is the migration's precondition, not
|
|
its follow-up.**
|
|
|
|
### What happens meanwhile
|
|
|
|
The tables stay, and rows continue to be transcribed into §13.1 at each version cut.
|
|
No repository waits on the export to get an answer. `user-engine`, `tenant-engine`,
|
|
ops-warden and ops-mason are inventoried in v0.8 whether or not the export has
|
|
landed by then.
|
|
|
|
This is deliberately the slower path. The alternative — strike the tables now and
|
|
point at the engine — would close four open requests immediately and leave the
|
|
statute stating an obligation whose register no reader can open, which is the exact
|
|
defect §13.1 was created to fix. Repeating a defect in the other direction is not
|
|
progress.
|
|
|
|
### What is asked of `maturity-engine`
|
|
|
|
Not a new capability, a published form of one it has. The export must be a file in
|
|
the repository, versioned, generated rather than hand-edited, carrying the same
|
|
fields the statute tables carry today (§13: capability, kind, declarer, owner, state,
|
|
owner-status; §13.1: consumer, stance map path, shape), and regenerable so drift
|
|
between the export and the engine's own state is detectable. `layer.yaml` and
|
|
`pep-stance.yaml` are the shape to follow: published, machine-readable, and asserted
|
|
equal to shipped behaviour by a test. §6.4 obligation 3 already requires that
|
|
equality of every PEP; a register of those maps should not hold itself to less.
|
|
|
|
When it exists, the §13 and §13.1 tables are replaced by a citation of it, and
|
|
`maturity-engine` becomes the register of record.
|
|
|
|
## Reversal
|
|
|
|
Revert to tables if the export proves to drift from the engine's computed state
|
|
faster than a hand-maintained table drifted from reality — that is, if generation and
|
|
publication decouple. The falsifier is mechanical: a regeneration that changes the
|
|
committed export without any underlying evidence having changed, or an underlying
|
|
change that does not reach the export.
|