fix(db): widen customer_transactions.type to VARCHAR(128)

TransactionType.FIRST_SESSION_DISCOUNT ('first_session_discount', 22 chars) overflowed the VARCHAR(20) column, throwing in acceptPairingRequest AFTER the session was flipped to ACTIVE but before startSessionTimer/startSessionListener/PAIRED-notify ran. Every first-session-discount pairing thus half-completed: lost transaction row, no server-side timer, and a 500 to the mitra so its app never opened the chat. Widen the column (CREATE TABLE + idempotent ALTER). Deferred hardening (bookkeeping INSERT in the critical path) logged in TECH_DEBT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 22:27:07 +08:00
parent 6e87e9b6da
commit 495eb98787
2 changed files with 32 additions and 1 deletions

View File

@@ -10,6 +10,30 @@ to act on it without re-deriving the discussion.
## Backend
### `[2026-06-01]` Bookkeeping INSERT sits in the pairing critical path
**File:** `backend/src/services/pairing.service.js` (`acceptPairingRequest`, ~line 506)
**What happened:** the `INSERT INTO customer_transactions` runs *after* the session
is flipped to `ACTIVE` but *before* `startSessionTimer`, `startSessionListener`,
the customer `PAIRED` WS notify, and the other-mitra dismiss fan-out. A
`varchar(20)` overflow on `type = 'first_session_discount'` (22 chars) threw
there, so every first-session-discount pairing half-completed: no transaction
row, no server-side timer, no PAIRED push (customer recovered via polling), and a
500 returned to the mitra so its app never opened the chat.
**Fixed now:** column widened to `VARCHAR(128)` (migrate.js), so the INSERT no
longer throws.
**Why it's still debt:** a *bookkeeping* write can still abort *critical* pairing
steps if it ever fails again (constraint change, DB hiccup, future longer enum).
Hardening: either move the `customer_transactions` INSERT to the end of
`acceptPairingRequest`, or wrap it in a `try/catch` that logs-but-doesn't-throw,
so transaction recording can never again half-complete a pairing. Same applies to
the equivalent INSERT in `extension.service.js`.
---
### `[2026-05-11]` Public `GET /api/public/bestie/available` needs rate limiting before prod
**File:** `backend/src/routes/public/public.bestie-availability.routes.js`