correlation_id: e147a6ab-0644-405e-bdbd-b9dff117d7a8 reason: GH-WP-0002-T06: settle consumption ordering source: repo-manager Assistant: grok Assistant-Session: 01a04d89-aaa5-7443-945e-b3055cd4b7e4
347 lines
15 KiB
Markdown
347 lines
15 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.
|