Repository navigation
Acknowledge payment receipts only after durable processing #79
Description
Problem
The listener processes receipts through a void callback, then advances checkpoint state even if local completion failed. Its error check after CompleteTransaction cannot observe that callback’s failure. Some invalid payment-method handling logs and continues, and amount conversion needs a bounded contract.
Proposed change
Validate and durably deduplicate each receipt, commit its local effect and checkpoint together, and retain/retry unresolved processing without pretending a failed event was consumed.
Acceptance criteria
- Introduce a returned processing result and stable receipt/event identity; distinguish accepted, rejected and retryable failures.
- Strictly validate method/currency/receiver/amount/expiry before effects, including uint64 values that do not fit the local amount representation.
- Inject local SQL failures, duplicate/reordered events, lost acknowledgements and crashes at cursor/effect boundaries; restart must neither skip payment nor credit twice.
- Define initial cursor/catch-up policy and reconciliation of receipts whose local intent is unavailable; do not reset or advance past uncertainty silently.
- Exercise local fake chain/checkpoint fixtures in CI; no live chain funds or outside network are required.
Current evidence
confirmed receipt/checkpoint ownership defect; source inspection only, no new runtime reproduction. Backlog classification is based on source inspection; this issue does not claim a new runtime reproduction.
- internal/dispatcher/payments/sui/listener.go: catchUp processes events without a returned per-event success result.
- internal/dispatcher/payments/sui/listener.go: Cursor advances to tip and persistence errors are only logged.
- internal/dispatcher/payments/sui/listener.go: Payment amount is converted to int64 and wrong method is logged without an immediate return.
- internal/dispatcher/payments/sui/listener.go: The void completion callback is followed by a stale err check.
- internal/dispatcher/payments/payments.go: CompleteTransaction logs failed writes instead of reporting them to its caller.
Dependencies
- #76 — Create payment intents and order rows atomically
- #78 — Commit order credits and earnings only when every write succeeds
Priority context
Required before enabling chain receipt processing; optional to the TEST-only alpha.
Activation
Optional work, deferred while the local team alpha is the priority. Development and fault injection use owned local fixtures. Production monetary operation, deployment and publication require the applicable release and operator approvals.
Validation must use owned local fixtures on supported Linux environments. Record the implementing merge request and relevant test results before closing this issue.
Imported from GitLab issue 78. Originally opened 2026-09-10. Historical GitLab links may require access to the original project.
Activity
Merge the settlement ledger branch into the receipts branch
Bound the receipt cursor by the indexer and key receipts by event
Merge the corrected settlement ledger branch into the receipts branch
ctfbruce commentedon Oct 5, 2026
Implemented by #374, with integrated recovery coverage in #384. Receipts have stable event identities, validated outcomes and atomic local payment effects; failed processing leaves the checkpoint unresolved for safe replay. Local fixtures cover duplicate and reordered events, SQL failures, indexer lag and real SQLite restart recovery without a second payment effect. Initial catch-up and unknown-intent reconciliation limits are documented. Receipt CI and rehearsal CI passed. Monetary enablement remains an operator decision.