Repository navigation
Cancel, manual verify, and the monitor must commit one terminal invoice outcome - #563
woahwhattheheck wants to merge 7 commits into
Conversation
Closes Quittance-Labs#558. Legal terminal transitions live in the settlement domain and both storages enforce them. Cancel is PENDING to CANCELLED only; a loser gets a stable conflict code and does not clear payment_tx_hash. Verify and the monitor share the payment-claim lock, including muxed destinations that resolve to the seller. Late CANCELLED/EXPIRED to PAID settlement stays the AFTER_CANCEL / AFTER_EXPIRY path. Cancel proof stays Freighter-only: sellerPublicKey and signature over cancel:<invoiceId> in the JSON body. Query and header seller keys are rejected even when they match. The pay page treats CANCELLED as terminal so both surfaces show the status storage committed.
Preserve the existing terminal-settlement contribution while integrating upstream Quittance-Labs#577. Use the shared timestamped payment fixture and require stable cancellation conflict codes in both storage contract suites.
|
@CemAyyildiz The October 1 integration request is addressed on the existing branch. Current head The committed integration record links the accepted execution evidence for integration commit One acceptance-policy question remains: #558 requires CANCELLED never to become PAID, while #507 and the existing late-payment policy allow an exact ledger payment to settle after cancellation with AFTER_CANCEL history. This branch preserves the existing late-payment behavior. Please confirm which behavior should govern and identify any concrete remaining requirement on the current head. I maintain my original #558 contribution claim and request payment. Please confirm the acceptance decision, compensation amount and settlement route, preserving my authorship and all existing contributor claims. |
Summary
Closes #558.
One storage transition decides the terminal invoice status. Cancel, manual verify, and the Horizon monitor all call it; the loser receives a stable conflict code instead of overwriting the winner. Wallet identity stays Freighter-only — no login session.
Changes
backend/src/domain/invoice-settlement.ts— legal terminal transitions (PENDING→CANCELLED|PAID, lateEXPIRED|CANCELLED→PAID),InvoiceTerminalConflictError, and cancel/paid guards used by both storages.INVOICE_ALREADY_PAID/INVOICE_ALREADY_CANCELLED/INVOICE_EXPIREDwithout clearingpayment_tx_hash.sellerPublicKey+ signature overcancel:<invoiceId>). Query and header seller keys are rejected even when they match the body.markAsPaid/PaymentClaimError; race tests now cover monitor attribution and muxed destination claims.CANCELLEDis a terminal pay state so the pay surface matches the seller workspace after a lost race.shared/verification.ts— addsINVOICE_ALREADY_CANCELLED.EXPIRY-AND-LATE-PAYMENT.mdnotes the one-commit rule; late AFTER_CANCEL settlement remains per LATE_PAYMENT_POLICY.Done when
409 INVOICE_ALREADY_PAID, hash retained)TX_HASH_ALREADY_USEDpayment_tx_hashCANCELLEDterminal on pay page)Test plan
node --import tsx --test tests/invoice-terminal-settlement.test.ts tests/invoice-cancel-payment-race.test.ts tests/invoice-handlers.test.ts tests/shared-verification-contract.test.ts tests/payment-attribution.test.ts tests/invoice-payment-loop.test.ts(backend) — 159 passnode --test tests/payment-page-state.test.js tests/pay-terminal-guard.test.js tests/pay-page-status-matrix.test.js tests/verification.test.js(frontend, Node 24) — passnpm run typecheck(backend + frontend)Original contributor reward review
/claim #558
This is @woahwhattheheck's original contribution for issue #558. I affirmatively request review for any eligible GrantFox OSS contribution reward and confirmation of acceptance, reward allocation, payout method, and expected payment timing. The issue's “Maybe Rewarded” label does not establish any fixed amount or an awarded or received payment.