# Architecture (friends edition)

React 19 + Vite frontend → same-origin Express API and Socket.IO gateway → PostgreSQL.

- Email OTP with securely hashed challenge, 5-minute expiry, max 5 wrong attempts, resend cooldown; password is optional Argon2id. Session and CSRF protected.
- TableEngine performs room mutations in a per-room queue, with each change persisted in a single SQL transaction. **Deploy only one API instance**; multi-node requires distributed locks and socket adapters.
- `wallets` and `wallet_transactions` maintain append-only virtual-chip ledger; `rooms.state.members[].tableChips` tracks unused chips on a specific table. Deposit/withdraw atomically change wallet and table stack. A pot consists of ante/bet chips previously removed from unused stack and is awarded back to winner's stack on completion. `round_actions` and `rounds` maintain game history.
- `safeRoom()` is the ONLY general room serializer and never gives live opponent cards to participants. Separate `/api/admin/rooms/:id/spectate` endpoint requires admin + room owner + private opt-in spectator mode + round active + owner not participating.
- `ownerSpectator` setting is only allowed for admin-owner-created private rooms; every new player must explicitly consent when joining. Owner sits out and does not count against max 3–6 active seats. If owner leaves, spectator setting is removed.
- Player identities are represented by a UUID internally and a separate unique `game_id` (`TP...`) for owner search and Telegram request messages. Free-chip requests are tracked in `chip_requests`; admin decision and wallet credit commit together in a row-locked PostgreSQL transaction. Optional Telegram notification is outbound-only; owner approvals happen in-app.
- Backend routes: `/api/chip-requests`, `/api/admin/chip-requests`, `/api/admin/players/:id/set-balance`, `/api/admin/rooms/:id/actions`, `/api/auth/*`, `/api/rooms`, `/api/rooms/join`, `/api/rooms/:id/chips`, `/api/rooms/:id/leave`, `/api/admin/*`, `/api/rewards/*`, `/api/wallet`.
- No payment services or bank/UPI interfaces exist.
