diff --git a/SCOPE.md b/SCOPE.md index 06905ef..db13283 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -103,13 +103,26 @@ Stated here because a scope file that only lists capabilities overstates them. - **`view_hash` is not inside the approval entry.** `POST /entries` discards its body by design. Correlation is `(approval_id, subject, approved_at)`, so an auditor holding only the approval object cannot reach the presentation. +- **Commitment-only evidence is not reconstructability.** `GH-DEC-2026-014` + granted it for Stage 1 and bounded it: it satisfies non-alteration, and moves + integrity out of our control while leaving *availability* entirely inside it. + The party that can withhold the content is the party the evidence is about. + Narrowed by the required existence assertion; not closed. +- **The registration-bound tenant is a declared bounded gap**, not the terminal + state. `GH-DEC-2026-013` ruled directory-sourced terminal and admitted + `key-cape`'s shape because its distinguishing case fails closed. Build to it + as transitional. - **Nothing is deployed**, so nothing is observed in production and nothing is contained automatically. ## Open -- **Human token tenant** — blocks `T07`. A human access token cannot carry - `tenant:platform` today. Registration-bound versus directory-sourced; not this - repository's to decide alone. -- **The independent evidence path** — mechanism unchosen; required by limit 3 - before `T08` ships. +- **The deployed origin** — the one remaining input to `T07`. `client_id` and + the callback URI must name a real origin, since redirects match exactly. +- **`audit-core` registration and cadence** — the payload is ruled + (commitment-only, with the existence assertion); the sender registration and + whether reconciliation-plus-heartbeat suits a mixed-volume source are still + `audit-core`'s to answer. Required before `T08` ships. + +*Closed 2026-09-10:* the human token tenant (`GH-DEC-2026-013`, `key-cape` +`329e48f`) and the evidence payload question (`GH-DEC-2026-014`). diff --git a/docs/evidence-path-design.md b/docs/evidence-path-design.md index c31cca0..22dd9a1 100644 --- a/docs/evidence-path-design.md +++ b/docs/evidence-path-design.md @@ -7,6 +7,10 @@ **Governing:** `GH-DEC-2026-012` limit **L3-independent-evidence-path** **Addressed to:** `audit-core` (registration and payload), `gate-house` (the content question, if it is doctrine) +**Ruled:** `GH-DEC-2026-014` split it — the payload is `audit-core`'s custody +question; what may be *claimed* from a record of this shape is doctrine. +Commitment-only is **granted for Stage 1**, with the §4 condition below, which +this repository did not propose. --- @@ -96,6 +100,11 @@ recomputable. ### (c) Split — commitment to `audit-core`, content to a separate evidence store +*Refusal endorsed by `GH-DEC-2026-014`, with an addition worth carrying: an +evidence store owned by the party whose conduct it evidences is not an evidence +store, whatever its integrity properties. **The ownership objection is prior to +the custody one.*** + (a)'s payload to `audit-core`, plus the full bundle to a store that is neither `audit-core` nor us. @@ -118,10 +127,12 @@ Reasoning: 2. It does not silently expand what `audit-core` holds. Expanding that is a decision for its owner, and (b) presented as a fait accompli would be exactly the drift we asked gate-house to prevent in a different context. -3. It is honest about what it does not close: **we can still erase the - content.** That residual is adjacent to the one `layer.yaml` already declares - (a compromised surface presents X and attests Y) and belongs in the same - place — declared, tracked, not claimed as closed. +3. It is honest about what it does not close. Our first wording — "we can still + erase the content" — **understated it**, and `GH-DEC-2026-014` corrected us: + commitment-only moves **integrity** out of our control and leaves + **availability** entirely inside it. *The party that can withhold the content + is the party the evidence is about.* That is the condition limit 3 exists to + prevent, reduced and not removed. 4. (b) remains available and is a payload change, not a redesign, if the estate later decides a commitment is insufficient. @@ -129,6 +140,42 @@ Reasoning: content question is `audit-core`'s to answer as its custodian, or `gate-house`'s as doctrine. If it is doctrine and the ruling is (b), we will implement (b). +## 4a. The existence assertion — required, and not ours + +`GH-DEC-2026-014` granted commitment-only **on a condition we did not propose**, +and it is the condition that makes the grant safe. + +**Non-production must be detectable as a finding, not present as an absence.** + +If the independent path holds only a commitment, a reviewer who asks for content +and gets nothing cannot distinguish *erased*, *withheld*, *lost*, and *never +held*. The absence reads as an unremarkable blank. + +So the emitted record MUST carry, alongside the commitment: + +| Field | Meaning | +| --- | --- | +| `content_exists` | An assertion that committed content exists | +| `custody` | Where custody of that content sits | + +such that **failure to produce at retrieval is a conformance failure +attributable to the custodian** — here, this repository. + +> A commitment with no assertion that something is being committed to is +> indistinguishable from a commitment to nothing. + +**Not a reversal candidate.** If it proves expensive, the answer is a cheaper +mechanism for the same property, never the property's removal. + +Two limits travel with the grant and belong in `audit-core`'s design too: + +- It satisfies **non-alteration**. It does **not** satisfy + **reconstructability**, and must not be described as doing so in any document + or conformance claim on either side. +- The residual is not closed and this repository is not credited with closing + it. The existence assertion narrows the erasure gap by making non-production + attributable; it does not produce the missing thing. + ## 5. Cadence Presentation evidence is declared load-bearing, so §9.6 requires a cadence and diff --git a/docs/specs/ArchitectureBlueprint.md b/docs/specs/ArchitectureBlueprint.md index a8b264d..07cb2cc 100644 --- a/docs/specs/ArchitectureBlueprint.md +++ b/docs/specs/ArchitectureBlueprint.md @@ -62,12 +62,28 @@ and `scope`, and an `assurance` object. restating the shape, so it cannot drift. `at` is authentication time, not token mint time; consumers needing freshness compare `at` rather than assuming it. -**Open — blocking T07.** A human access token cannot carry `tenant:platform` -today: the tenant claim on human tokens resolves from the directory user record, -which no adapter populates, so tokens fall back to `tenant:coulomb`. -`approval-engine` compares by exact equality and refuses near-misses. Resolution -is registration-bound (preferred here) or directory-sourced; it is not this -repository's alone to decide. See §7. +**Resolved.** `key-cape` implemented registration-bound tenancy on 2026-09-09 +(`329e48f`), deliberately correct under both candidate rulings: a declared zone +applies where the directory places the user nowhere, agreement passes, and a +declared zone **conflicting** with a directory assignment refuses issuance with +`403 tenant_binding` rather than relabelling. `GH-DEC-2026-013` then ruled +directory-sourced the terminal state and granted the registration-bound shape as +a **declared bounded gap** — admissible precisely because its distinguishing +case fails closed. + +**Build to it knowing it is transitional.** Two obligations land here: + +- **Do not declare a tenant the directory record does not carry** unless + prepared to say so in the record. Declaring one asserts a fact about a person + on this registration's authority, which the ruling permits only as a gap. +- **Record the tenant claim's provenance.** `key-cape` emits `tenant` as a bare + string, so a consumer cannot distinguish a directory-asserted tenant from a + registration-supplied one. `GH-DEC-2026-013` §5 requires the claim to carry + provenance; until it does, this surface records which route the value arrived + by rather than storing an undifferentiated string. + +**And do not use the `tenant` claim as the act-scope.** `binding.target` is the +act-scope and is committed in `view_hash`. See `EvidenceModel.md` §8c. ### 2.2 `access-engine` — the decision, consumed @@ -235,17 +251,23 @@ gated on the tenant question in §7. ## 7. Open and blocking -**O-01 — Human token tenant.** Blocks T07. Registration-bound (this -repository's stated preference, as the tenant is then a property of the surface -and its registration — which is exactly what the pre-sign binding slice commits) -versus directory-sourced (which makes tenant a property of the person and -changes it everywhere). Not ours alone; raised with `key-cape`, -`approval-engine` and `gate-house`. If registration-bound is chosen, the -condition that it holds *only* because registrations are static and -deployment-owned should be written into the contract, not left as reasoning in a -message. +**~~O-01 — Human token tenant.~~ Closed 2026-09-10** by `GH-DEC-2026-013` and +`key-cape` `329e48f`. Our binding-versus-awareness argument was accepted and +written into the ruling as its §6 — and it did not change the outcome, it +sharpened the defect: two different facts (act-scope, and the principal's +membership) were sharing one field. The condition we asked for is now in +`key-cape`'s `docs/tenant-claim-contract.md`, strengthened from "must be +revisited" to **void** if the dynamic-registration exclusion is lifted, and +enforced by a test asserting the capability and the exclusion together. See +§2.1 for the two obligations that land on us. -**O-02 — The independent evidence path.** Design and decision request written: +**O-02 — The independent evidence path.** *Payload ruled: commitment-only +granted for Stage 1 by `GH-DEC-2026-014`, on the condition that the record carry +an assertion that content exists and where custody sits, so non-production is a +finding attributable to us rather than an unremarkable blank. It satisfies +non-alteration, not reconstructability, and must not be described otherwise. The +registration and cadence remain with `audit-core`.* Design and decision request +written: `docs/evidence-path-design.md`, filed as `INFD-IN-0003`. Read independence and the local transactional outbox are settled; the open question is **what travels**, because a presentation record carries the brief and packet material @@ -275,3 +297,7 @@ with no obvious `approval-engine` counterpart. Stage 1 scope undecided. - A polling loop against `approval-engine` synthesising an inbox. - A fail-closed outcome recorded as an approver's decline. - Describing the decision path as validated while `GH-DEC-2026-010` is open. +- Describing commitment-only evidence as reconstructability + (`GH-DEC-2026-014`). +- Using the token's `tenant` claim as the act-scope, or storing it without its + provenance (`GH-DEC-2026-013` §5). diff --git a/docs/specs/EvidenceModel.md b/docs/specs/EvidenceModel.md index 3475f58..83bbcfc 100644 --- a/docs/specs/EvidenceModel.md +++ b/docs/specs/EvidenceModel.md @@ -236,6 +236,105 @@ by reading that field. Never infer it from the shape of `subject_id` — a namin convention is not a verified claim. Entries written before v4 are `null` and must not be read as `human`. +## 8c. Act-scope is not membership — `GH-DEC-2026-013` §5 + +Gate House made the sharpest observation anyone has made about this object +model, and it is worth carrying in full because it changes what we record even +though it changes no field. + +Two different facts are being asked to travel in one claim named `tenant`: + +| Fact | Property of | Who needs it | +| --- | --- | --- | +| Which scope is this act being entered into | the **act** | this repository's binding slice | +| Which tenant is this person a member of | the **principal** | `approval-engine`'s exact-match admission | + +> *"A binding slice that must commit the scope being entered should commit THAT +> SCOPE, not borrow a membership claim to stand in for it."* + +**Our schema already does the right thing.** `binding.target` is the act-scope: +the tenant, environment and system being entered, committed in the binding +document and therefore inside `view_hash`. It is not derived from, and must +never be replaced by, the token's `tenant` claim. + +What was missing is not a field but a **statement and a record**: + +- `binding.target` is the authoritative act-scope commitment. The `tenant` claim + is a membership fact about the principal and is **not** the act-scope. +- The two must never be collapsed. Where they agree, that agreement is itself a + fact worth recording; where they disagree, issuance is refused upstream + (`key-cape` `329e48f`) and this surface records the refusal rather than + choosing a winner. +- **The `tenant` claim's provenance is recorded.** `key-cape` emits `tenant` as + a bare string, so a consumer cannot tell a tenant the *directory asserted about + the person* from one a *registration supplied about the client they came + through*. `GH-DEC-2026-013` §5 requires the claim to carry its provenance; + until it does, this surface records which route the value arrived by rather + than storing an undifferentiated string. + +This is the same rule as `unknown` versus `absent` in the stance map and +`erased` versus `never held` in §8d: **wherever a system reaches one appearance +by two routes, the record must say which route**, or the safer reading becomes +unavailable to everyone. + +## 8d. What commitment-only does and does not establish — `GH-DEC-2026-014` + +Commitment-only emission is **granted for Stage 1**. It is granted on the test +`GH-DEC-2026-013` set: its distinguishing case fails closed. A reviewer who +cannot obtain the content gets **no** reconstruction rather than a **wrong** one. + +**It satisfies non-alteration. It does not satisfy reconstructability, and must +not be described as doing so** — not here, not in `audit-core`'s documents, and +not in any conformance claim. + +A commitment-only record is weaker than an archive in a specific way. An archive +proves records were not altered or truncated after arrival, never that one was +never sent (§2, E-04). A commitment additionally **does not carry what it commits +to**. It establishes that the commitment was made when it says and has not +changed. About *what was committed to* it establishes nothing — except +conditionally: **if** a document is later produced, whether it is the one. + +### The gap, in the right words + +An earlier draft of ours said commitment-only "leaves us able to erase the +content". That understates where the problem sits, and Gate House corrected it: + +> **Commitment-only moves *integrity* out of our control and leaves +> *availability* entirely inside it. The party that can withhold the content is +> the party the evidence is about.** + +That is the condition limit 3 exists to prevent, **reduced and not removed**. The +reduction is real. It is not sufficient alone — which is why the grant carries +the condition below. + +### The condition that makes the grant safe + +**Non-production must be detectable as a finding, not present as an absence.** + +If the independent path holds only a commitment, a reviewer who asks for content +and gets nothing cannot distinguish *erased*, *withheld*, *lost*, and *never +held*. The absence reads as an unremarkable blank. + +So the evidence path must carry, alongside the commitment: + +1. an assertion that committed content **exists**, and +2. **where custody sits**, + +such that failure to produce at retrieval is a **conformance failure +attributable to the custodian**. + +> *A commitment with no assertion that something is being committed to is +> indistinguishable from a commitment to nothing.* + +This is **not a reversal candidate**. If it proves expensive, the answer is a +cheaper mechanism for the same property, never removal of the property. + +### Residual, again + +Not closed, not credited. The existence assertion narrows the erasure gap — a +detectable non-production tells a reviewer something is missing and who owed it. +It does not produce the missing thing. + ## 9. Signed attributes (L4+, horizon) When AES/QES arrives, the signed attributes carry `memo_id`, `memo_version`, diff --git a/docs/specs/ProductRequirementsDocument.md b/docs/specs/ProductRequirementsDocument.md index 963578d..e369a65 100644 --- a/docs/specs/ProductRequirementsDocument.md +++ b/docs/specs/ProductRequirementsDocument.md @@ -170,6 +170,28 @@ context. ### 3.2 Presentation +**PR-08 [rev-2] — The act-scope is committed; the membership claim is not +borrowed to stand in for it.** +`binding.target` — the tenant, environment and system being entered — is the +authoritative act-scope and is inside `view_hash`. The token's `tenant` claim is +a membership fact about the *principal* and is never used as the act-scope. +*Pass:* no code path derives `binding.target` from the token's `tenant` claim; +changing `binding.target` changes `view_hash` (existing isolation vector 3). +`trace: GH-DEC-2026-013 §5; EvidenceModel §8c` + +**PR-09 [rev-2] — The `tenant` claim is stored with its provenance.** +`key-cape` emits `tenant` as a bare string, so a consumer cannot distinguish a +tenant the *directory asserted about the person* from one a *registration +supplied about the client they came through*. Until the claim carries its own +provenance, this surface records which route the value arrived by. + +This surface must not declare a tenant the directory record does not carry +without saying so in the record — doing so asserts a fact about a person on this +registration's authority, which `GH-DEC-2026-013` permits only as a bounded gap. +*Pass:* every stored tenant value carries a provenance marker; a value with an +undifferentiated or absent provenance is a validation failure, not a default. +`trace: GH-DEC-2026-013 §5; key-cape 329e48f` + **PR-10 — A memo renders question, requested act, binding level, brief and consequences before any action control is reachable.** *Pass:* the disposition controls are not operable until the brief region has @@ -327,6 +349,26 @@ tampering, not a compromised surface presenting X and attesting Y. *Pass:* the residual appears in `EvidenceModel.md` and in the bundle metadata. `trace: gate-house decision request §3; approval-engine's equivalent residual` +**PR-53 [rev-2] — Emitted evidence asserts that content exists and where custody +sits.** +Commitment-only emission carries, alongside the hashes, an assertion that the +committed content exists and the custodian holding it, so that failure to +produce at retrieval is a **conformance failure attributable to the custodian** +rather than an unremarkable blank. Without it, a reviewer cannot distinguish +*erased*, *withheld*, *lost* and *never held*. +*Pass:* every emitted commitment carries `content_exists` and `custody`; a +retrieval failure produces a finding naming the custodian. +`trace: GH-DEC-2026-014 §4 — a granting condition, not a reversal candidate` + +**PR-54 [rev-2] — Commitment-only evidence is never described as +reconstructability.** +It satisfies **non-alteration**. It does not carry what it commits to, and +establishes what was committed to only conditionally — if a document is later +produced, whether it is the one. +*Pass:* no document, export field or conformance claim in this repository +describes the independent evidence path as reconstructing content. +`trace: GH-DEC-2026-014` + ### 3.7 Locale and accessibility **PR-60 — German and English, with German as a first-class source language.** diff --git a/intakes/intakes.md b/intakes/intakes.md index 076104c..6c9e304 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -62,7 +62,7 @@ state_hub_intake_id: "01a08610-f458-7fd5-b284-26a65d1d73c2" id: INFD-IN-0002 kind: intake title: Human access tokens cannot carry tenant:platform -status: open +status: closed origin: coordination origin_ref: INFD-WP-0001-T07 priority: high @@ -74,7 +74,32 @@ tags: - cross-repo - blocker created: '2026-09-09' -updated: '2026-09-09' +updated: '2026-09-10' +resolution: >- + Resolved 2026-09-10. key-cape had already implemented registration-bound + tenancy on 2026-09-09 (329e48f), deliberately correct under both candidate + rulings: a declared zone applies where the directory places the user nowhere, + agreement passes, and a declared zone conflicting with a directory assignment + refuses issuance with 403 tenant_binding rather than relabelling. So the risk + that a client registered now fails closed at first use was already retired. + GH-DEC-2026-013 then ruled directory-sourced the terminal state and granted + the registration-bound shape as a declared bounded gap — admissible precisely + because its distinguishing case fails closed. This repository's + binding-versus-awareness argument was accepted and written into the ruling as + its §6; it did not change the outcome but sharpened the defect, which is that + two different facts share one field named tenant: the act-scope (a property of + the act, which our binding slice commits) and the principal's membership (a + property of the person, which approval-engine exact-matches). Gate House's + correction of our position is adopted: a binding slice that must commit the + scope being entered should commit that scope, not borrow a membership claim to + stand in for it — and binding.target already does, so no field was added, only + a statement and a provenance record. The condition we asked for is in + key-cape's docs/tenant-claim-contract.md, strengthened from "must be revisited" + to void if the dynamic-registration exclusion is lifted, and enforced by a test + asserting the capability and the exclusion together. Two obligations land here + and are booked as PR-08 and PR-09: do not use the tenant claim as the + act-scope, and record the claim's provenance since key-cape emits it as a bare + string. T07 unblocked. description: >- Raised by key-cape (KEY-WP-0013-T05) while reviewing the approver client shape, and it blocks INFD-WP-0001-T07. The tenant claim on a human token @@ -122,7 +147,32 @@ tags: - decision-request - cross-repo created: '2026-09-09' -updated: '2026-09-09' +updated: '2026-09-10' +resolution_partial: >- + Doctrine half ruled 2026-09-10 as GH-DEC-2026-014; the payload remains + audit-core's custody question and the intake stays open for it. Commitment-only + is GRANTED for Stage 1, on the GH-DEC-2026-013 test that its distinguishing + case fails closed — a reviewer who cannot obtain the content gets no + reconstruction rather than a wrong one — and the data-protection reason was + accepted as a reason of the right kind, since doctrine forcing L4 contract text + into an audit fabric trades one control for a breach of another. Two limits: + it satisfies non-alteration and NOT reconstructability, and must not be + described otherwise in any document or conformance claim on either side; and + our wording of the gap was corrected — commitment-only moves integrity out of + our control and leaves availability entirely inside it, so the party that can + withhold the content is the party the evidence is about, which is limit 3's + condition reduced rather than removed. The grant carries a condition we did not + propose (§4): the path must carry an assertion that committed content exists + and where custody sits, so that non-production is a finding attributable to the + custodian rather than an unremarkable blank — a commitment with no assertion + that something is being committed to is indistinguishable from a commitment to + nothing. Not a reversal candidate. Our refusal of a separate evidence store was + endorsed, with the addition that an evidence store owned by the party whose + conduct it evidences is not an evidence store whatever its integrity + properties, the ownership objection being prior to the custody one. Booked as + PR-53 and PR-54 and EvidenceModel §8d. Still open for audit-core: sender + registration, and whether reconciliation plus heartbeat suits a mixed-volume + source. description: >- GH-DEC-2026-012 limit L3 requires the evidence copy to reach audit-core independently of informed-decision, because here the actor being audited and diff --git a/workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md b/workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md index 6994289..db3c4c9 100644 --- a/workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md +++ b/workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md @@ -352,7 +352,21 @@ registration is accepted by `approval-engine`'s verifier; `KEY-WP-0013-T02` is unblocked. **This is the task that discharges the gap that created this repository.** -2026-09-09: blocked on `INFD-IN-0002`. `key-cape` found that a human access +2026-09-10 — **unblocked.** `INFD-IN-0002` closed: `key-cape` had already +implemented registration-bound tenancy (`329e48f`) correct under both candidate +rulings, and `GH-DEC-2026-013` granted the shape as a declared bounded gap. Two +obligations land here and are booked as PR-08/PR-09: never use the token's +`tenant` claim as the act-scope (`binding.target` is, and already was), and +record the claim's provenance, since `key-cape` emits it as a bare string and a +consumer cannot otherwise tell a directory-asserted tenant from a +registration-supplied one. Build to the registration-bound shape knowing it is +transitional. + +The one remaining input is the **deployed origin**. Redirects match exactly, so +`client_id` and the callback URI must name a real origin — the reason not to +publish is now solely that, and no longer the tenant. + +Superseded context: 2026-09-09: blocked on `INFD-IN-0002`. `key-cape` found that a human access token cannot carry `tenant:platform` today — the tenant claim resolves from a directory record no adapter populates, so every human token falls back to `tenant:coulomb`, which `approval-engine` refuses by exact match. Registering