Skip to main content

max / makenotwork

1022 B · 16 lines History Blame Raw
1 -- Pay-S1 (ultra-fuzz Run 9): add an in-flight `refunding` state to transactions.
2 --
3 -- The self-service refund endpoint only checked `status = 'completed'` before
4 -- calling Stripe, and the row stayed `completed` until the async `refund.created`
5 -- webhook flipped it to `refunded`. A rapid double-submit therefore passed the
6 -- guard twice; on a shared-cart PaymentIntent the second refund consumed another
7 -- line's refundable balance. The fix claims the row `completed -> refunding`
8 -- atomically before the Stripe call (released back to `completed` on Stripe
9 -- error); the webhook then finalizes `refunding -> refunded`.
10 --
11 -- Widen the status CHECK to admit the new interim value. The constraint was
12 -- created inline in 001_initial_schema.sql and auto-named `transactions_status_check`.
13 ALTER TABLE transactions DROP CONSTRAINT IF EXISTS transactions_status_check;
14 ALTER TABLE transactions ADD CONSTRAINT transactions_status_check
15 CHECK (status IN ('pending', 'completed', 'failed', 'refunded', 'refunding'));
16