Problem
The checkout hard-overlap check (lib/payments/operations/checkout.ts:652-687) only blocks against isTentative: false slots, and the tentative dedup gate is keyed to the SAME user's pending payment. Two different users can hold overlapping tentative slots for the same consultant, both complete payment, and nothing at confirm time (confirmExistingAppointment, lib/payments/webhooks/handlers.ts:264) rechecks overlap before flipping isTentative=false.
Impact
Two paying customers confirmed into one consultant slot. Refund + reputation damage per occurrence. Verified launch blocker (2026-06-10 B2C audit, scenario S-B2).
Fix shape
Recheck overlap inside the confirmation tx before flipping isTentative=false: first-confirmed-wins, loser auto-refunds (or pre-payment rejection). A DB exclusion constraint is the defense-in-depth follow-up once prisma migrate lands.
Chaos test
Playwright two-context same-slot race (chaos runbook scenario 1) — must pass with exactly one confirmed slot.
Problem
The checkout hard-overlap check (
lib/payments/operations/checkout.ts:652-687) only blocks againstisTentative: falseslots, and the tentative dedup gate is keyed to the SAME user's pending payment. Two different users can hold overlapping tentative slots for the same consultant, both complete payment, and nothing at confirm time (confirmExistingAppointment,lib/payments/webhooks/handlers.ts:264) rechecks overlap before flippingisTentative=false.Impact
Two paying customers confirmed into one consultant slot. Refund + reputation damage per occurrence. Verified launch blocker (2026-06-10 B2C audit, scenario S-B2).
Fix shape
Recheck overlap inside the confirmation tx before flipping
isTentative=false: first-confirmed-wins, loser auto-refunds (or pre-payment rejection). A DB exclusion constraint is the defense-in-depth follow-up once prisma migrate lands.Chaos test
Playwright two-context same-slot race (chaos runbook scenario 1) — must pass with exactly one confirmed slot.