Persist review evidence and deliver audit records transactionally

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-10 23:27:19 +02:00
parent 0e48355b9f
commit 2cc32168ac
14 changed files with 1474 additions and 22 deletions

View file

@ -526,6 +526,48 @@ before a UI retry. `/readyz` deliberately remains 503 and browser entry routes
are absent until this protected path is wired. The task remains `progress`.
See `docs/browser-authentication.md`.
2026-09-10 — **durable evidence and receiver integration implemented.**
`store.py` / `records.py` persist packet bytes, immutable memo versions and
presentations, explicit append-only acknowledgments, dispositions, submission
correlation and a same-transaction evidence outbox in private SQLite storage.
The new G_ACTOR guard refuses use of another person's presentation. The two
older tests with mismatched placeholder actors were corrected; a dedicated
negative regression now pins the real guard. Return/discuss remain local acts.
Operation ids and atomic reservation prevent double submission. Lost engine
responses and unknown duplicates remain unresolved and cannot be attached to a
new presentation or silently retried. A confirmed correlation retrieves the
original acknowledgment snapshot; later acks do not strengthen earlier evidence.
Revisions cannot race in-flight/unresolved submissions. Backup/restore preserves
the evidence and pending delivery state.
`audit.py` uses the current Audit Core ingestion contract, stable event ids and
bytes, scoped metadata-only envelopes, receiver references, retry/backoff and
visible blocked records. Writer-only reconciliation and a separate auditor read
were exercised against the actual receiver. Heartbeats are per class and do not
mask undelivered evidence. The receiver counts by accepted_at, while the source
counts by occurred_at: the report now carries both, and delayed acceptance is
not automatically called a loss. Exact window shape came from the real API,
not from a local fixture assumption.
258 tests pass (52 added), including process death before commit, injected
outbox failures, concurrent clicks/reservations, restore, lost engine response
and receiver deduplication. Actual Approval Engine and Audit Core APIs are
exercised with synthetic identities and development custody. Evidence:
`docs/evidence/2026-09-10-durable-review-evidence.json`. No native policy, human
login, production audit custody, deployed binding UI or factory run is claimed.
**Next within T08:** define/admit the exact PDP read/bind request and caller,
then connect protected review/ack/accept/return/discuss routes to this store and
its original-entry recovery rules. Persist the obtained policy observation and
retain decision_attributable=false while its upstream gap remains. No Informed
Decision package/registration was found in Flex Auth's checked examples,
registry or docs at `88b3543`; a local allow rule is not a replacement.
Schedule and admit audit draining/heartbeats, account for acceptance-time delay
in reconciliation, supply native custody and registered human/deployed-engine
proof. These remain live work in this task; `/readyz` stays 503 and browser bind
routes remain absent. Details: `docs/durable-review-evidence.md`.
## Known risks
- **T02 is a hard gate.** Writing the blueprint before the layer ruling risks