approval-engine raised APPROVAL-IN-0002: secrets-engine's PEP validator expects a flex-auth ActionAuthorization but fetches the approval-claim endpoint that GH-DEC-2026-003 names as step 1. Two objects on one path. GH-IN-0002 records the intake; GH-DEC-2026-005 resolves it. The claim is the step-1 artifact and always was — ActionAuthorization is unratified, has no valid_now field, and cannot be served from a step-1 call. The addition beyond confirmation is doctrine: a PEP validates each artifact against the layer that owns its data, and no PIP republishes the PDP's decision. The provenance.authority == "state-hub" requirement is struck; State Hub is a read model and holds no runtime approval authority. docs/contracts/approval-consumption.md carries the amendment at the sequence itself so implementers find it there. 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
25 KiB
Decision records
GH-DEC-2026-001 — NetKingdom security layer model, the gate-house re-cut, and the access-engine reframing
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-engineis the only policy decision point, generalizing to the whole estate the ruling first drawn inzone-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(/authorizeskeleton).GH-WP-0001is rewritten against the re-cut before it is promoted to active.
What approval does not authorize
- The
flex-auth→access-enginerename 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
proposedtoaccepted. - 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:
- flex-auth — Engine framing, the rename, and the authoring/evaluation split.
- 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
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-enginefailing a revoke (and any other mutation) when its own store cannot insert the outbox row.- Continuing to revoke while
audit-coreis down, with the row draining later. - Treating emit-after-commit, a second non-local queue, or a sync
audit-corecall insideBEGIN…COMMITas 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
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:
- Allow never consumed — PEP duty to consume; PDP lifetime bounds the
window; a stale ALLOW without a matching
useis a finding, not a consume. - Double consumption —
approval-engineCAS; the PEP that receives conflict does not act. - 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-engineexposingPOST /v1/approvals/{id}/consumeagainst this contract, including the digest column the internal CAS does not yet store.FLEX-WP-0017-T05requiring the PEP (secrets-engine, for that task) to consume before the OpenBao call.- Canon
T-06consume-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
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-guardowns 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-canonto adopt, revise, or contest the generic contract and create its own owning work record. - Requesting
net-kingdomto adopt, revise, or contest the security profile and create its own owning work record. - Sources such as
qonto-assistant,approval-engine, andsecrets-enginepublishing 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-assistantremains 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
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.