01
The plan under review
A same-day fix for a PSP webhook that credited one $1,200 top-up twice: fact-owned idempotency in the same transaction as the ledger write, an advisory lock, prove-credit-before-200, a defensive partial unique index, and reconciliation. The proposed rollout kept intake live while constraints and new code were introduced. The panel's job was to find what could still fail while the fix appeared correct.
Scenario context$340k in customer wallet top-ups in flight; one observed top-up produced two $1,200 credit rows for a single payment-intent chain.Figures as stated in the reviewed plan — no inferred savings.
02
What changed before ship
Event-delivery advisory lock
→
No advisory lock; database uniqueness is the only serialization boundary
PI/wallet partial index alone
→
Fact-owned row + UNIQUE(ledger_fact_id) + canonical PI/wallet uniqueness
Live mixed-fleet rollout
→
Quiesce every writer class, drain, reconcile, mark corrected history, validate constraints, cut over, then reopen
Compensating debits as cleanup
→
Deterministic reversal identity reversal_of:{fact_key}:{duplicate_row_id} plus coverage verification
Duplicate-row and balance counts
→
Three mathematical reopening gates: net-economic equality, canonical uniqueness, compensation coverage
Constraint-first-while-live as primary defense
→
Quiescence is primary; the canonical-default index is the fail-closed belt after bootstrap
04
Decision
Landed invariantUnanimous
Old and new credit writers are never eligible together; canonical uniqueness is installed and proven before intake reopens.
GO under the staged-then-quiesced construction only. The service binary is replaceable; the new financial invariants and compensating history are not — after cutover, the migration is forward-only.
Condition: Quiesced cutover gates: every writer class proven disabled, a finance-signed compensation set, both unique indexes valid, and zero-unexplained-mismatch reconciliation before intake reopens.