--- id: GH-WP-0002 type: workplan title: "Approval evidence integrity" domain: infotech repo: gate-house status: finished origin: GH-IN-0001 state_hub_workstream_id: "393d46ad-4f8c-5578-b63d-91cb0e8b9502" updated: "2026-08-29" --- # Approval evidence integrity Promoted from `GH-IN-0001`, raised by `audit-core` with a drafted five-task plan. It escalates correction 2 of the `AUDIT-IN-0001` assent from a caveat in a reply to tracked work, because it must land before `approval-engine` is built rather than after. **The gap.** A hash chain proves accepted records were not altered or truncated. It proves nothing about an event never emitted. Every `approval-engine` event class degrades gracefully under omission except one: a suppressed **revocation** leaves the chain intact, the attestation matching, and the record showing an approval that was never revoked. The evidence half would look sound and not be. Doctrine now at `net-kingdom/canon/standards/security-layer-model_v0.5.md` §9.6. ```task id: GH-WP-0002-T01 status: done priority: high state_hub_task_id: "538f0417-2d71-578c-8cf3-e7077fa410af" ``` Amend §9.4 so it does not rest on `audit-core`'s principle 6 omission claim. Done in v0.4; §9.6 generalizes it estate-wide and v0.5 adds the load-bearing versus attributive distinction. ```task id: GH-WP-0002-T02 status: done priority: high state_hub_task_id: "73a8feb0-02bd-5191-bdfd-82bcc42c6756" ``` Specify the transactional-outbox contract for `approval-engine`: same transaction as the object mutation, queue local to the engine, at-least-once into the outbox since `audit-core` dedupes on event id and a replay does not fork the chain. Done — `docs/contracts/approval-outbox.md` adopts `approval-engine`'s wire (`docs/outbox-contract.md`) as Gate House doctrine. ```task id: GH-WP-0002-T03 status: done priority: high state_hub_task_id: "1fc8fd3c-7af4-50e7-a07c-f45016f8b1f3" ``` Decide the revocation failure mode explicitly: fail closed, or proceed with a detectable gap. Done — GH-DEC-2026-002. Fail-closed only when `approval-engine`'s own store cannot insert the outbox row. An `audit-core` outage MUST NOT block a revocation. Synchronous emission inside the mutation is forbidden. Proceed-with-gap is rejected for load-bearing approval evidence. ```task id: GH-WP-0002-T04 status: done priority: medium state_hub_task_id: "3d62dbf9-786e-58c1-bd87-fb43658ca865" ``` Give the gap a detection surface: outbox depth and age, or reconciliation of `approval-engine` object counts against `audit-core` event counts per class. Done — `docs/contracts/approval-emission-detection.md`. Form is heartbeat plus reconciliation, not rate monitoring; lag bounds on outbox depth and age. `approval-engine/cadence.yaml` is the reference source declaration. `kings-guard` remains the observer; until it reports watching in production, the declaration is still required. ```task id: GH-WP-0002-T05 status: done priority: medium state_hub_task_id: "2a2a73ea-2778-59d2-94ef-7a70a22bb169" ``` Add a §11 conformance check so the next engine catalogued as an evidence source declares its emission guarantee rather than reintroducing this silently. Done as doctrine — the check is the last section of `docs/contracts/approval-emission-detection.md`. Queued for statute v0.8 §11 rather than patched into accepted v0.7. Load-bearing sources declare a local outbox plus heartbeat-or-reconciliation; attributive non-atomic sources declare the trade and do not claim completeness. ```task id: GH-WP-0002-T06 status: done priority: high state_hub_task_id: "250cb9b3-713d-5607-ad1b-225e339693bf" ``` Settle the consumption ordering contract between `approval-engine` and `access-engine` — who signals consumed, at what point relative to the decision, and the handling of an allow never consumed, a double consumption by racing callers, and consumption after a failed action. Done — GH-DEC-2026-003 and `docs/contracts/approval-consumption.md`. The PEP consumes by CAS before the side effect; the PDP never mutates; there is no unconsume. Unblocks `APPROVAL-WP-0001-T05` and `FLEX-WP-0017-T05`.