ADR-005 rollout step 1: value-confirmed dispense, fault screens, cash-out latch, dispense-report outbox #123
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/dispense-outcome"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The bitspire half of ADR-005 (
docs/adr/005-cash-out-dispense-outcome.md), the response to #122. Six commits, one layer each.HAL — every dispenser returns a tagged error:
errorCode(family),rawCode(78 42),errorClass(terminal/recoverable/inventory), human decode. F56 decode table seeded from sintra's exit jam and the Tejo's long-bill reject; unknown codes fail safe as terminal. Drops the borrowedstatusCode 570. First tests inpackages/hal— the bill-length table test would have caught the GTQ window months ago.State machine —
dispensed(driver boolean) →dispenseConfirmed(value equality, computed by the HAL).dispenseErrorsplits intodispenseFault(hardware error; paid, owed; 120 s with evidence) andoutOfCash(no hardware error; 30 s). A terminal fault latches cash-out off (cashOutHeld), preserved across resets, released only byCASH_OUT_RELEASED. Payment hash carried into context. 46 tests.Machine app — value confirmation in both HAL glue paths; cash-out hold persisted in
meta, restored on boot, released by arecountor a newresume_cash_outoperator op (honoured only if stamped after the hold began); hold mirrored into the cassettes-state doc and the beacon; idle Sell button disabled with the reason. A zero-dispensed report with an error now setscountsUncertainSinceinstead of being trusted. Fault/out-of-cash screens show "your payment went through", amounts, txid as QR + text, payment hash, time; raw code is not shown.Outbox —
dispense_reportstable (schema v14), written in the same SQLite transaction as thetransactionsrow, drained toreport_dispenseafter each persist, on relay reconnect, and every 60 s, acked only on OK, backing off 30 s · 2^attempts (cap 1 h). Sent on success too — the success report is what spirekeeper will capture on.Not in this PR: the spirekeeper half (ADR rollout step 2 — the
report_dispensehandler,awaiting_dispense/cash_owed, worklist + notification). Until that lands the RPC rejects as unregistered and the outbox rows simply wait with backoff; you'll see one[ATM] Dispense report … not deliveredwarning per attempt, then quiet. That is the intended shipping order.Verified: hal 20/20, state-machine 46/46, lnbits 29/29, nostr-client 43/43, clink 11/11; vue-tsc, electron tsc, preload tsc clean; full
pnpm buildof apps/machine passes (after theqrcodefix that already went todevascbff654).Behaviour changes on a machine running this: a terminal dispenser fault takes cash-out out of service until an operator recounts or publishes
resume_cash_out; customers who pay and don't receive cash see a reference screen instead of a 30 s countdown; the kiosk theme preference resets once (storage key renamed earlier today).Refs #122, #27.