Skip to content

Claim Ledger

Marcus Richards edited this page Oct 6, 2026 · 1 revision

Claim Ledger

An in-memory, append-only, SHA-256 hash chain of receipts. Code: permit/ledger.py.

Receipt

Field Notes
seq 0-based position
prev_hash Hash of the previous receipt. Genesis is 64 zeros
event_type See the table below
payload Event data (JSON)
timestamp UTC ISO-8601
hash sha256 of canonical JSON (sort_keys, compact separators) over the five fields above

Verification

verify_chain() walks every receipt. It checks the sequence, the prev_hash link, and a recomputed hash, so it catches reordering, gaps and payload tampering. The release-verifier calls it before every capture. A broken chain refuses the capture and voids the hold.

Event types written by the code

Group Events
Permit lifecycle GRANTED, DELEGATED, TIGHTEN, E-STOP, REVOKED_CASCADE, CARVE_RELEASED
Gate ALLOWED, BLOCKED
Approvals APPROVAL_REQUESTED, APPROVAL_PENDING, APPROVAL_DECIDED
Settlement AUTHORIZED, CAPTURED, VOIDED, REFUSED, FAILED, UNKNOWN, CLEANUP_PENDING

A successful capture writes two CAPTURED receipts: one at the permit layer (reserved → captured) and one at the settlement layer (with the PayPal capture id). An e-stop void of a registered escrow writes two VOIDED receipts in the same way.

Reading it

  • HTTP: GET /api/ledger returns chain: {ok, reason} and receipts with seq, event, the first 12 hex characters of hash, and payload.
  • Dashboard: GET /api/state on the dashboard port.

Boundaries (stated in the repo)

  • Not durable. A restart loses it.
  • Not signed. VERIFIED means the list in this process is internally consistent. It is not a PayPal signature.
  • Cannot detect removal of the final entries without an external checkpoint.
  • Duplicate claim ids: whether the ledger rejects them is Unknown per docs/scenarios.md. The code has no dedupe check.

Clone this wiki locally