diff --git a/docs/finding-r3-linkage-conflict.md b/docs/finding-r3-linkage-conflict.md index 927c08e..9e70333 100644 --- a/docs/finding-r3-linkage-conflict.md +++ b/docs/finding-r3-linkage-conflict.md @@ -5,8 +5,18 @@ **Intake:** `INFD-IN-0004` **Statute:** *"The statute governs on disagreement; a disagreement is a finding for `gate-house`."* -**Status:** raised. **No design change made.** `GH-DEC-2026-012` R3 stands and -`layer.yaml` is unchanged pending a ruling. +**Status:** **Ruled `GH-DEC-2026-015` — nesting permitted for this pair, +conditioned and not yet active.** `layer.yaml` remains unchanged: co-reference +stays in force until `approval-engine` states its presentation exclusion as +normative and tested. This repository does not activate on its own initiative. + +Gate House reversed itself, and gave the real ground rather than the one we +argued: our binding slice canonicalizes `principal` and `target`, two of the +five digest fields, so co-reference by identifier left us performing a partial +recomputation of one act in a second vocabulary — **closer to the translation R3 +forbade than nesting is**. Our ordering-dependency objection was withdrawn as +mistaken; `binding.digest` is over act material and is determined before anyone +is presented anything. --- diff --git a/docs/specs/EvidenceModel.md b/docs/specs/EvidenceModel.md index a7a9c53..138b57e 100644 --- a/docs/specs/EvidenceModel.md +++ b/docs/specs/EvidenceModel.md @@ -199,8 +199,29 @@ five digest fields, so co-reference by identifier alone leaves **two independent canonicalizations of one act** rather than removing the duplication. Raised as a finding rather than resolved bilaterally -(`docs/finding-r3-linkage-conflict.md`). **The ruling stands and nothing has -changed here pending a re-ruling.** +(`docs/finding-r3-linkage-conflict.md`). **Re-ruled by `GH-DEC-2026-015`: +gate-house reversed itself — nesting is permitted for this pair, so `view_hash` +may carry `binding.digest` and our binding slice stops independently +canonicalizing act material.** + +The decisive ground was not the cycle argument we led with. It was that our +binding slice canonicalizes `principal` and `target`, two of the five fields in +their digest, so co-reference by identifier left us performing *a partial +recomputation of one act in a second vocabulary* — **closer to the translation +R3 forbade than nesting is**. Nesting removes the duplication; co-reference +manages it. + +**The permission is conditioned and not yet active.** It activates when +`approval-engine` states its presentation exclusion as **normative and tested** +rather than as design intent — our own A-17 correction applied to gate-house's +permission, since the distinguishing case is someone widening the digest and +that case is unobservable until approvals start failing. Co-reference remains in +force until then, and this repository does not activate on its own initiative. + +Our ordering-dependency objection to option (c) was **withdrawn as mistaken** +and recorded as withdrawn: `binding.digest` is over act material, determined +before anyone is presented anything. We stated that cost, gate-house took it +from us, and neither of us checked it. For reference, three hashes answering three questions: @@ -359,6 +380,57 @@ 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. +## 8e. Cadence — declared, and now supportable + +`audit-core` registered this source as proposed (`AUDIT-IN-0003`, +`docs/informed-decision-source-registration.md`) and landed the detection half +(`AUDIT-WP-0009` T04/T06/T07). The cadence can stop being described as +declared-but-not-operating once heartbeats are flowing. + +**Per class, not per source** — the shape this repository argued for and +`audit-core` adopted. A per-source heartbeat from a mixed-volume emitter is +satisfied by its chattiest class and says nothing about the quiet, +security-relevant one, which is the only reason heartbeats exist. + +| Class | Volume | Heartbeat | Reconciliation | +| --- | --- | --- | --- | +| `presentation` | one per render | yes — legitimately silent for days at Stage 1 | yes | +| `disposition` | low, security-relevant | yes | yes | +| `stance_application` | low, security-relevant | yes | yes | + +Reconciliation applies to **every** class including the high-volume one: rate +detects a stream stopping, never a stream missing the particular renders that +mattered. + +A heartbeat is an **ordinary event** — same envelope, same append-only custody, +same chain. Deliberately so: a heartbeat stored outside the chain would be the +one record that could be back-dated. + +Note `no_heartbeat_since_registration`: declaring a heartbeat and never sending +one is **its own finding**, not a skip. + +### The bound on both controls + +Reconciliation compares `audit-core`'s counts against counts we compute from our +own state. **Where the emitter is compromised, both controls agree with it** — a +compromised surface suppresses the event and its own count together, and emits a +truthful-looking `nothing-to-report`. + +Both cover loss, outage, drain failure and accident, which is most of what +actually goes wrong. **Neither covers the residual we already declare**, and +neither may be described as covering it. Closing it needs an observer +independent of the emitter, which §16 put outside `audit-core`'s scope. + +### Tenant provenance is not in the envelope + +`audit-core`'s tenant is not an identity claim they resolve; it is a value our +credential is permitted to write, checked by exact string equality. Recording a +route in the audit event would be them restating something they did not observe +— the same error as claiming an event occurred. It lands in the registration +document instead, whose authority is `GH-DEC-2026-013`'s bounded gap rather than +a populated directory record. If that gap closes, the entry is revisited rather +than assumed still correct. + ## 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 e369a65..b3ce6f6 100644 --- a/docs/specs/ProductRequirementsDocument.md +++ b/docs/specs/ProductRequirementsDocument.md @@ -192,6 +192,35 @@ registration's authority, which `GH-DEC-2026-013` permits only as a bounded gap. undifferentiated or absent provenance is a validation failure, not a default. `trace: GH-DEC-2026-013 §5; key-cape 329e48f` +**PR-11 [rev-3] — A human-in-the-loop control is never discharged on an +unverified assertion of humanity.** +`GH-DEC-2026-016` requires that where an approval is *declared* as discharging a +human-in-the-loop control, the approver must be a human principal and +`approval-engine` must refuse at bind time. Its §5 lands here: what makes a +principal `human` belongs to the identity layer and **inherits A-16** — if +`human` is reachable by two routes, the control must not be discharged on a +registration-supplied claim. Refusing a service principal while accepting an +unverified assertion of humanity moves the defect rather than closing it. + +**This is live for us, not hypothetical.** `principal_type: human` is a property +of the *client registration*, the same shape as our registration-supplied +`tenant`. Until its provenance is distinguishable, this surface treats it as +registration-supplied and does not present it as verified humanity. +*Pass:* `principal_type` is stored with its provenance like `tenant` (PR-09); no +copy, export field or evidence record describes a bind as human-verified on the +strength of the claim alone. +`trace: GH-DEC-2026-016 §5; A-16 with the marker-independence rider; PR-09` + +**PR-12 [rev-3] — The custody locator is a stable non-secret identifier.** +`audit-core` applies `secret_policy: redact`, which scans `data`. A +credentialed URL or secret-shaped path in the custody field is redacted out and +the existence declaration (PR-53) arrives without its pointer. It fails visibly +— `details.redaction.paths` records it — but the declaration is then useless. +*Pass:* the custody locator is an identifier the custodian resolves, never a +credentialed URL; a redaction finding on the custody field is a build-breaking +defect, not a warning. +`trace: audit-core docs/informed-decision-source-registration.md` + **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 diff --git a/intakes/intakes.md b/intakes/intakes.md index fbd72de..f2433ba 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -136,7 +136,7 @@ state_hub_intake_id: "01a0880b-36f8-7d89-ab67-2c91ee16f300" id: INFD-IN-0003 kind: intake title: The independent evidence path — what travels to audit-core -status: open +status: closed origin: residual origin_ref: INFD-WP-0001-T05 priority: high @@ -148,7 +148,27 @@ tags: - cross-repo created: '2026-09-09' updated: '2026-09-10' -resolution_partial: >- +resolution: >- + Closed 2026-09-10. audit-core registered this source with every field as + proposed — source informed-decision exact, tenants [tenant:platform], write + true, read false, evidence_kind load-bearing, secret_policy redact — at + c4016a7 as AUDIT-WP-0009-T11 / AUDIT-IN-0003, documented in their + docs/informed-decision-source-registration.md. The entry is inert until the + token exists, asserted by test rather than by reading. The two extra fields the + ruling added (content_exists, custody) needed no schema change: data is stored + verbatim into details.data and hash-chained, so a custodian cannot quietly + retract the assertion that content existed. One class one source with distinct + type values per class, because two senders would split one residual into two + smaller-looking ones for a component whose defining property is that the actor + and the evidence source are the same. Cadence accepted with the refinement that + BOTH heartbeat and reconciliation scope per class, and with reconciliation + applying to the high-volume class too since rate detects a stream stopping but + never a stream missing the particular renders that mattered. One design + consequence booked as PR-12: redact scans data, so the custody locator must be + a stable non-secret identifier rather than a credentialed URL, or the existence + declaration arrives without its pointer. Both controls are bounded and neither + may be described as covering the compromised-emitter residual. Reconstructability + is now written down on audit-core's side as well as ours. T08 unblocked. 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 @@ -209,7 +229,7 @@ state_hub_intake_id: "01a0880b-4421-747b-9e7f-6e9bff9d2ea3" id: INFD-IN-0004 kind: intake title: approval-engine R3 answer conflicts with GH-DEC-2026-012 R3 -status: open +status: closed origin: coordination origin_ref: INFD-WP-0001-T02 priority: high diff --git a/layer.yaml b/layer.yaml index 45c03be..acfd9fa 100644 --- a/layer.yaml +++ b/layer.yaml @@ -100,12 +100,23 @@ binding_digest_relationship: repository MUST NOT recompute or restate approval-engine's binding digest from its own vocabulary — it references the digest that layer computed and recorded. - # UNDER REVIEW — INFD-IN-0004, raised 2026-09-10. approval-engine - # (docs/approval-claim.md, 62233c7) recommends the opposite of the line below: - # that our binding document carry their binding.digest as a field, which is - # the option (c) GH-DEC-2026-012 refused. The ruling stands and this file is - # unchanged pending a re-ruling. See docs/finding-r3-linkage-conflict.md. - linkage_under_review: INFD-IN-0004 + # GH-DEC-2026-015 (INFD-IN-0004) re-ruled: nesting is PERMITTED for this pair, + # CONDITIONED and NOT YET ACTIVE. view_hash may carry binding.digest as a + # field, and our binding slice then stops independently canonicalizing act + # material — but only once approval-engine states its presentation exclusion + # as NORMATIVE and TESTED rather than design intent. + # + # "Co-reference remains in force until that condition is met; the permission + # activates then. You do not act on your own initiative here." + # + # So co-reference below is still the operative rule and this file is + # deliberately unchanged. See docs/finding-r3-linkage-conflict.md. + reruled_by: GH-DEC-2026-015 + nesting_permitted_when: >- + approval-engine states the presentation exclusion from binding.digest as + normative and tested. Until then co-reference is in force. Do not activate + on this repository's own initiative. + nesting_permission_active: false nesting_forbidden: >- view_hash MUST NOT contain the binding digest, and MUST NOT travel inside hashed request material while containing it. Option (c) was refused because 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 54ced71..f8e4d44 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 @@ -430,6 +430,7 @@ issuer, so it is not this repository's to decide alone. ```task id: INFD-WP-0001-T08 status: todo + priority: medium state_hub_task_id: "b5c1d329-9580-5672-9640-2930cbbb729a" ``` @@ -471,3 +472,57 @@ component, and the payload question is open. Design and decision request in - **Scope pressure toward an approvals inbox.** The fastest way to close `KEY-WP-0013-T02` is to build a queue with two buttons. That would satisfy the dependency and abandon the thesis. T04 exists to make the cost of that visible. + + +## Session note — 2026-09-10, both blockers cleared + +**T07 origin: cleared and independently verified.** `railiance-apps` deployed +`decisions.coulomb.social` at 14:32 UTC (their `7c2e51a`) and corrected the +hostname in this repository's `docs/keycape-client-registration.md` and the T07 +note — the assigned name is **not** the `decide.coulomb.social` this workplan +proposed. Verified here rather than taken on report: `/` and `/auth/callback` +both return `200` from `92.205.62.239`, TLS verify `0`, Let's Encrypt +`CN=decisions.coulomb.social` issued by YR2, valid to 2026-12-09. The path is an +nginx placeholder, which does not affect a registration matched as a string at +`/authorize`. + +**T08 evidence path: cleared.** `audit-core` registered this source with every +field as proposed (`AUDIT-IN-0003`, their `c4016a7`) and landed the detection +half (`AUDIT-WP-0009` T04/T06/T07). `INFD-IN-0003` closed. + +**`INFD-IN-0004` ruled — `GH-DEC-2026-015`, and gate-house reversed itself.** +Nesting is permitted for this pair. The decisive ground was not the cycle +argument we led with: our binding slice canonicalizes `principal` and `target`, +two of the five digest fields, so co-reference left us performing a partial +recomputation of one act in a second vocabulary — *closer to the translation R3 +forbade than nesting is*. Our ordering-dependency objection was withdrawn as +mistaken. **The permission is conditioned and NOT ACTIVE**: it turns on when +`approval-engine` states its presentation exclusion as normative and tested. +`layer.yaml` is deliberately unchanged and carries +`nesting_permission_active: false`. We do not activate on our own initiative. + +**`GH-DEC-2026-016` ruled NC-03.** Where an approval is declared as discharging +a human-in-the-loop control, the approver must be human and `approval-engine` +must refuse at bind time. Our surface enforcement stays — ours refuses earlier +with a better error, theirs makes the refusal a property of the object. Its §5 +lands here as PR-11 and is live rather than hypothetical: +`principal_type: human` is a property of the *client registration*, the same +shape as the gap-route tenant, so a human-in-the-loop control must not be +discharged on it as verified humanity. + +**A-16 and A-17 were corrected with this repository's rider and precondition** +(`gate-house@62c6399`), including the dependency that A-17 needs A-16 first. + +### Outstanding — a tooling block, not a dependency + +Two messages are **written and unsent**, blocked by the local permission +classifier rather than by any repository: + +1. **`key-cape`** — the `client_id` and callback URI submission that closes + `KEY-WP-0013-T02`. Payload ready; also carries the PR-11 provenance question + about `principal_type`. +2. **`audit-core`** — `heartbeat_classes`, declaring all three classes at + `86400`, including `presentation` with the reasoning for declaring a + heartbeat on a class their guidance put outside it. + +Until these send, T07 cannot close and the first heartbeat cannot be emitted.