mirror of
https://code.gri.mw/GUI/grim.git
synced 2026-07-15 11:18:55 +00:00
e9f0c3f0e2
Closes the buyer's double-send window. When a Nostr-rail send carries order context, the plain kind-17 status=sent receipt used to publish at finalize alongside the encrypted proof. With an offline merchant, finalize can be hours away, so the buyer stared at a scannable QR for a payment already made: maximum double-send temptation. The receipt now publishes at S1 dispatch, the same moment the payment envelope is accepted by a relay and the wallet UI flips to "sent", through the same crash-safe reconcile queue. The event shape is unchanged (same tags, kind, content); only the timing moves earlier, so magick's status=sent matcher is unaffected. The encrypted PROOF delivery stays at finalize (the proof does not exist before then). Idempotency: a new receipt_sent flag on TxNostrMeta gates the receipt to exactly one publish per tx, so finalize never duplicates it. deliver_proof no longer touches the receipt; the reconcile pass gets an independent receipt-retry path for the crash/offline case. Decision logic is factored into pure predicates (receipt_due_at_dispatch, receipt_retry_due, proof_delivery_due) used by the live paths and covered by three tests: dispatch-publish decision, no-duplicate-at-finalize, and proof-still-at-finalize. Full lib + i18n drift green.