gate-house/workplans/GH-WP-0003-statute-v08-amendment-set.md

247 lines
12 KiB
Markdown
Raw Normal View History

---
id: GH-WP-0003
type: workplan
title: "Security layer model v0.8 amendment set"
domain: infotech
repo: gate-house
status: finished
owner: codex
topic_slug: infotech
created: "2026-09-05"
updated: "2026-09-09"
state_hub_workstream_id: "a331dc88-c9bc-5d2a-9ff1-2aa7e837c3bb"
---
# Security layer model v0.8 amendment set
## Goal
Land the queued amendments to security-layer-model as v0.8: the §9.7.3 consume-ordering protocol clarification, the §11 emission-guarantee declaration check, the §13/§13.1 register disposition against maturity-engine, the §9.5 posture/maturity recomputability boundary, and the GH-DEC-2026-005 split-validation doctrine. Each is currently doctrine held in a gate-house contract or decision rather than in the accepted statute.
2026-09-06 08:11:45 +02:00
**Normative text for A1A6 is drafted at
`docs/amendments/v0.8-amendment-set.md`.** That file is the reviewable unit: each
amendment carries its own wording, defect statement, and authority, so it can be
argued before anything touches a cut document. T06 assembles from it.
## Why now
`security-layer-model_v0.7.md` is accepted and must not be patched in place. Since
its acceptance, five separate rulings have been made that belong in the statute and
are currently held in gate-house contracts, decision records, or a reply in another
repository's inbox. Each was correctly kept out of v0.7; together they are now a
version.
The risk of leaving them scattered is not that any one is wrong — each was argued
where it was made. It is that a reader of the accepted statute gets an answer that
the estate no longer holds, and that the register sections (§13, §13.1) are
accumulating rows in a document that four repositories have said should be a
pointer.
Gate House authors the amendment set. `net-kingdom` publishes. Nothing here edits
v0.7.
```task
id: GH-WP-0003-T01
status: done
priority: high
state_hub_task_id: "330d9739-f172-536d-82f6-74eec03902e0"
```
**§9.7.3 — consume ordering.** v0.7 reads as if the protected action must precede
the consume call. `GH-DEC-2026-003` and `docs/contracts/approval-consumption.md`
establish the opposite: the PEP MUST obtain a successful consume before the side
effect, because act-then-consume lets CAS prevent only the second *record* and not
the second *side effect*. Carry the clarification into §9.7.3 without retracting the
forensic claim that consumption MUST NOT be inferred from a decision record.
```task
id: GH-WP-0003-T02
status: done
priority: high
state_hub_task_id: "fe278b70-8c05-539c-9f41-4019c3c35520"
```
**§11 — emission-guarantee declaration check.** Add the conformance check drafted as
the last section of `docs/contracts/approval-emission-detection.md`: a load-bearing
evidence source declares a local outbox plus heartbeat-or-reconciliation; an
attributive non-atomic source declares the trade and does not claim completeness.
This exists so the next engine catalogued as an evidence source cannot reintroduce
the `GH-IN-0001` gap silently.
```task
id: GH-WP-0003-T03
status: done
priority: high
state_hub_task_id: "6d5efa1a-54d9-5995-bfac-d2a9f5291469"
```
**§13 and §13.1 — register disposition.** `maturity-engine` (MAT-WP-0001) holds the
§13 gap-register snapshot and the §13.1 stance-map inventory as queryable data, with
`ASM-0``ASM-6` registered as data owned by gate-house and `pep-stance-publication`
owned by ops-warden. Four repositories have offered §13.1 rows —
`user-engine/pep-stance.yaml`, `tenant-engine/pep-stance.yaml`, ops-warden published,
ops-mason unpublished.
Decide whether §13 becomes a pointer to `maturity-engine` or stays a table. The
argument for the pointer is that a hand-maintained table in a statute is a register
that drifts, and that transcribing rows is exactly the manual step the engine exists
to remove. The argument against is that a statute must be readable without a live
query. Both are real; settle it as a decision record rather than by editing.
Settled as `GH-DEC-2026-006`: the registers become pointers, and not before
`maturity-engine` publishes a committed, versioned export readable without a live
query. Publication is the precondition, not the follow-up. Until it lands the tables
stay and rows are transcribed, so the four outstanding stance-map offers are
inventoried in v0.8 either way — `user-engine`, `tenant-engine`, `ops-warden`
(published) and `ops-mason` (unpublished).
```task
id: GH-WP-0003-T04
status: done
priority: medium
state_hub_task_id: "89ffd56e-5abf-5003-889e-1d00c3453b23"
```
**§9.5 — the posture/maturity boundary.** `kings-guard` (KG-DEC-2026-002,
`kings-guard/docs/PostureMaturityBoundary.md`) argues that the discriminator is
recomputability, not volatility: given the same criteria and the same evidence, if
you MUST get the same answer it is maturity and belongs in an engine; if you CANNOT
promise the same answer it is posture and belongs in Staff. The argument is that
volatility describes the two things without partitioning them, and every case it does
not obviously cover becomes an argument at exactly the boundary §6 says must not be
open to argument.
Adopt the recomputability boundary as GH-DEC-2026-007 GH-WP-0003-T04. kings-guard's answer to KG-IN-0003 is adopted: the posture/maturity line is recomputability, not volatility. Their argument holds — volatility describes the two categories without partitioning them, and every case it does not obviously cover becomes an argument at exactly the boundary §6 exists to keep out of argument. The test is §9.5's own determinism clause pointed where it had not been pointed. Added one clause they did not propose, because their framing opens a loophole: recomputability is assessed over the stated criteria, so a criterion that dereferences a judgment is deterministic in form and inferential in substance, and would put an opinion inside an engine wearing a rule's clothes. A criterion MUST bottom out in evidence about the subject, not in another party's conclusion about it. A recorded judgment is evidence that the judgment was made, never that the thing judged is so — the same distinction §9.6 draws about archives and GH-DEC-2026-005 draws about valid_now. All three kings-guard consequences carried, including the constraint they volunteered against themselves (readiness is not an input to posture) and their honest limit, which makes §17 load-bearing for the rule. 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
2026-09-06 08:08:32 +02:00
Disposed as `GH-DEC-2026-007`: **adopted**, with one added clause. Recomputability
is assessed over the stated criteria, so a criterion that dereferences a judgment
("level 2 iff the reviewer marked it adequate") is deterministic in form and
inferential in substance. A criterion MUST therefore bottom out in evidence about the
subject, not in another party's conclusion about it. All three kings-guard
consequences are carried, including the constraint they volunteered against
themselves — capability readiness MUST NOT be an input to posture — and their honest
limit, that "the same evidence" is undefined until §17, is recorded in the statute
beside the test rather than left in the commentary.
```task
id: GH-WP-0003-T05
status: done
priority: medium
state_hub_task_id: "087d3f67-66ef-59a3-8d4b-26ebfa5b2d00"
```
**Split validation as statute.** `GH-DEC-2026-005` states that a PEP validates each
artifact against the layer that owns its data and that a PIP MUST NOT republish the
PDP's decision. That is a general property of the layer model, not a fact about the
approval path, and it currently lives only in a decision record and a contract.
Place it in the statute where §8's three-way split is stated.
```task
id: GH-WP-0003-T06
status: done
priority: medium
state_hub_task_id: "ecc01a7b-22df-5a9c-a29b-eb7559713ca7"
```
**Assemble, circulate, publish.** Cut `security-layer-model_v0.8.md`, circulate for
assent as v0.6 and v0.7 were, and hand to `net-kingdom` for publication. Record
dispositions of the returned findings. v0.7 stays accepted and unedited until v0.8
is accepted in its place.
```task
id: GH-WP-0003-T07
status: done
priority: low
state_hub_task_id: "d68be07d-2528-52a2-8de5-909890eb7758"
```
**§17 — refresh the ownership paragraph.** §17 closes with "Ownership is proposed,
not assigned… Neither has assented." `GH-DEC-2026-004` assigned the split and both
`info-tech-canon` (`ITC-WP-0018`, `ITC-EMISSION-CADENCE 0.1` in canon 0.7.0) and
`net-kingdom` (`NK-WP-0035`, `emission-cadence-security-profile_v0.1.md`) have
accepted in their own voice. Replace the paragraph with the settled ownership and
cite the decision; keep §17's drafter credit to `kings-guard`.
Surfaced by `docs/conformance/2026-09-06-v06-findings-audit.md`, which also confirms
that all fifteen v0.6 review findings are dispositioned in v0.7 — this is the one
paragraph a later decision made stale, not a missed finding.
Close the binding-correspondence gap as GH-DEC-2026-008 access-engine raised, and declined to solve locally, a hole in the split GH-DEC-2026-005 ruled on. approval-claim verification item 4 is a disjunction and neither limb delivers "approved for THIS request" on the PDP path: limb one requires translating between two engines' vocabularies and no mapping is published, limb two (pdp_digest) is optional. Where the digest is absent a consumer can hold valid_now true, receive an ALLOW, consume and act with nothing establishing that approval and decision concern the same action and target. Ruled: the PDP digest is the correspondence and is required on that path; a claim without one fails closed; the native limb survives only for consumers already in approval-engine's vocabulary, including T-06. No mapping is published — a translation can be wrong while still producing a confident answer, it fails open, it would be owned by neither engine, and recomputing another layer's binding is the re-derivation GH-DEC-2026-005 already forbids. The cost is stated: an approval issued without a bound CheckRequest is unusable on this path, which is correct behaviour. Also: adopted hub row b606e8ce as canonical for GH-DEC-2026-005 rather than registering a duplicate; recorded approval-engine's narrowing of the approver-threshold consequence (distinctness is a UNIQUE storage invariant, so the PEP stopped checking that the engine applied its own invariant, not whether dual control could be forged); and drafted A7/T08, a §11 marking obligation and §12 consumer rule for derived summaries, after four instances in one week across four repositories. 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
2026-09-06 09:32:20 +02:00
```task
id: GH-WP-0003-T08
status: done
priority: medium
state_hub_task_id: "ce6a814f-f854-52af-8e3c-205bf240f487"
Close the binding-correspondence gap as GH-DEC-2026-008 access-engine raised, and declined to solve locally, a hole in the split GH-DEC-2026-005 ruled on. approval-claim verification item 4 is a disjunction and neither limb delivers "approved for THIS request" on the PDP path: limb one requires translating between two engines' vocabularies and no mapping is published, limb two (pdp_digest) is optional. Where the digest is absent a consumer can hold valid_now true, receive an ALLOW, consume and act with nothing establishing that approval and decision concern the same action and target. Ruled: the PDP digest is the correspondence and is required on that path; a claim without one fails closed; the native limb survives only for consumers already in approval-engine's vocabulary, including T-06. No mapping is published — a translation can be wrong while still producing a confident answer, it fails open, it would be owned by neither engine, and recomputing another layer's binding is the re-derivation GH-DEC-2026-005 already forbids. The cost is stated: an approval issued without a bound CheckRequest is unusable on this path, which is correct behaviour. Also: adopted hub row b606e8ce as canonical for GH-DEC-2026-005 rather than registering a duplicate; recorded approval-engine's narrowing of the approver-threshold consequence (distinctness is a UNIQUE storage invariant, so the PEP stopped checking that the engine applied its own invariant, not whether dual control could be forged); and drafted A7/T08, a §11 marking obligation and §12 consumer rule for derived summaries, after four instances in one week across four repositories. 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
2026-09-06 09:32:20 +02:00
```
**Derived summaries must be marked (A7).** Four instances in one week, in four
repositories, of a repository acting on a derived summary rather than the
authoritative body — a stale revisit trigger here, a change log read for section text
here, a dual-control rule written against an assumed schema in `access-engine`, a
fixture read for contract prose in `secrets-engine`. Proposed by `approval-engine` on
the observation that at four instances it is a property of how the estate publishes
rather than four separate lapses: authoritative bodies with derived summaries beside
them and no staleness marker on the derivatives.
Strengthen A7 to two tiers on approval-engine's proposal The summary-for-body pattern reached six instances in four repositories in one week. approval-engine escalated it with a concrete split: the half that is mechanically checkable and the half that is doctrine. §11 gains an example-validates-against-schema check, with the clause that matters most — where a field is optional but load-bearing, examples must cover both its presence and its absence. That clause is instance six: approval-engine's own claim examples omitted pdp_digest and contradicted its schema, found while implementing GH-DEC-2026-008, by the repository making the argument. An example set that silently omits an optional field teaches every reader the field does not exist. §12 gains the convention half, which no test can cover: derivatives marked with source and derivation version, and dated review records marked as status-as-of-date rather than current state. The tally is recorded in full because it is the argument. Four of six were self-reported and one was committed by the proposer, so the case is that the publishing shape makes the error the default — not that four repositories were careless. A control depending on repositories volunteering corrections is not a control. 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
2026-09-06 14:21:29 +02:00
Now six instances in four repositories, and A7 is drafted in two tiers on
`approval-engine`'s proposal: a §11 mechanical check (published examples validate
against the schema they exemplify, and cover both shapes of an optional load-bearing
field) and a §12 convention (derivatives marked with source and derivation version;
dated review records marked as status-as-of-date). Four of the six were self-reported
and one was committed by the repository arguing for the rule, which is the argument
that the publishing shape makes the error the default rather than that four
repositories were careless. The limit is stated in the draft: the mechanical half
catches example drift, the convention half makes prose staleness visible without
detecting it.
Rule on unknown and the scoping axis as GH-DEC-2026-009 access-engine exercised the divergence capability it claimed in the v0.6 round, on the first occasion §13.1 held two rows. ops-warden resolves unknown to fail_open, secrets-engine to fail_closed; both conformant, both total, both test-pinned, disagreeing about the one case that by construction nobody planned for. They also scope over different axes, so the register cannot answer what an inventory exists to answer. Ruling 1: unknown is not a zone and MUST fail closed. §9.3 permits trading availability for openness per zone — and that trade requires knowing the zone. Where the scope is unknown the trade cannot have been made for it, so a permissive unknown does not extend a considered decision, it invents the most permissive one. An unreachable engine is a known request in a degraded system; an unclassified subject is not. unknown is the cheapest state for an attacker to induce, so failing open on it makes being unclassifiable a privilege escalation requiring no credential, which §8's asymmetry forbids wherever it appears. Ruling 2: each map declares its scoping axis and its relation to zone. Forcing everyone onto zones would make secrets-engine assert a zone it cannot know, and a fiction in a runtime-read test-pinned file is worse than an honest incommensurability. The register records the axes and states that cross-axis aggregation is unavailable. ops-warden acquires one non-conformant cell at v0.8. It did everything asked — published first, built the reference form, offered it estate-wide — so this goes to the assent round rather than being imposed quietly. 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
2026-09-06 14:18:36 +02:00
```task
id: GH-WP-0003-T09
status: done
priority: high
state_hub_task_id: "e3a7dfb7-f6ea-5dcf-ad02-602aca969449"
Rule on unknown and the scoping axis as GH-DEC-2026-009 access-engine exercised the divergence capability it claimed in the v0.6 round, on the first occasion §13.1 held two rows. ops-warden resolves unknown to fail_open, secrets-engine to fail_closed; both conformant, both total, both test-pinned, disagreeing about the one case that by construction nobody planned for. They also scope over different axes, so the register cannot answer what an inventory exists to answer. Ruling 1: unknown is not a zone and MUST fail closed. §9.3 permits trading availability for openness per zone — and that trade requires knowing the zone. Where the scope is unknown the trade cannot have been made for it, so a permissive unknown does not extend a considered decision, it invents the most permissive one. An unreachable engine is a known request in a degraded system; an unclassified subject is not. unknown is the cheapest state for an attacker to induce, so failing open on it makes being unclassifiable a privilege escalation requiring no credential, which §8's asymmetry forbids wherever it appears. Ruling 2: each map declares its scoping axis and its relation to zone. Forcing everyone onto zones would make secrets-engine assert a zone it cannot know, and a fiction in a runtime-read test-pinned file is worse than an honest incommensurability. The register records the axes and states that cross-axis aggregation is unavailable. ops-warden acquires one non-conformant cell at v0.8. It did everything asked — published first, built the reference form, offered it estate-wide — so this goes to the assent round rather than being imposed quietly. 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
2026-09-06 14:18:36 +02:00
```
**`unknown` and the scoping axis (A8).** `access-engine` exercised the divergence
capability it claimed in the v0.6 round, on the first occasion §13.1 held two rows.
`ops-warden` resolves `unknown` to `fail_open` and `secrets-engine` to `fail_closed`;
both maps are conformant, total and test-pinned, and they disagree about the case
nobody planned for. The two maps also scope over different axes, so the register
cannot answer the question an inventory exists to answer.
Settled as `GH-DEC-2026-009` and drafted as A8: `unknown` is not a zone and fails
closed, because the §9.3 trade requires knowing the zone and a permissive `unknown`
makes being unclassifiable a privilege escalation needing no credential; and each map
declares its axis and its relation to zone, with the register stating what it cannot
answer rather than implying it can. `ops-warden` acquires one non-conformant cell at
v0.8 and it goes to the assent round rather than being imposed.
---
## T06 status
**Round closed 2026-09-09; publication handed to `net-kingdom`.**
`security-layer-model_v0.8.md` remains `status: proposed` at `net-kingdom@64394e9`.
The acceptance flip and publication are `net-kingdom`'s and it has confirmed it will
run them on round close. `security-layer-model_v0.7.md` stays `accepted` and in force
until then, unpatched.
Four repositories returned text reviews — `access-engine` (four findings),
`approval-engine` (one partial plus three), `ops-warden` (two findings and one
agreement), and `net-kingdom` (§17 confirmed, §11 corrected in place at `da7747d`).
All are dispositioned in `docs/conformance/2026-09-06-v08-assent-round.md`.
Nine corrections landed in the text during circulation, listed as §15 items 1220. Two
rulings were substantive enough to carry their own records:
- **`GH-DEC-2026-010`** — a PEP must be able to *attribute* a decision to
`access-engine`, and obligation 2's digest test does not discharge obligation 1.
Fail-closed protects against a decision point that is absent, not against one that
lies. Carried as a declared §13 gap with `access-engine` as owner.
- **`GH-DEC-2026-011`** — `ops-warden`'s asked-for transitional `unknown: fail_open` is
**declined**; §13.1 records a dated classification-coverage figure beside each stance
instead. Also settles that a map must enumerate its axis and that an `absent` scope is
distinguishable from an `unknown` one — closing the §16 question this version opened.
**`kings-guard` and `audit-core` did not return a review.** §14 records that as *not
claimed*. The sections they were asked to attack — §9.5's criteria-grounding clause and
§12's step-four paragraph; §11's emission-guarantee wording — carry no assent from the
repository best placed to test them. That is a gap in the round, not a defect in the
text, and it does not block publication.