mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-11-11 01:33:54 +01:00
fix: recover unconsumed single-game payments; make game preservation deterministic
Two disconnect-related money/UX gaps: 1. A confirmed single_game payment whose game never started (user paid, then disconnected) was money-in-nothing-given with no recovery path. recover- PendingPayments now detects confirmed single_game payments with no linked games row and grants the equivalent credits — idempotently (per-payment reason key, row-locked re-check of both the game link and prior recovery). 2. In-progress games could be dropped on disconnect when a fresh getBySocket lookup failed. The stable dbUserId is now stamped on the game at creation, so suspend/restore keys on it directly without a failure-prone disconnect- time lookup. Any game (paid or free) is preserved/reconnectable whenever a session exists; the remaining drop-branch is only the true no-session edge (e.g. DB unavailable at connect), which is logged for audit rather than masked. Adds singleGameRecovery.test.js. Full suite: 13 suites / 119 tests.
This commit is contained in:
@@ -21,7 +21,7 @@ Key: `S` ≤ half day · `M` ~1–3 days · `L` ~1 week+ · 🔴 launch-blocker
|
||||
- [x] **0.2 🔴 M — Make provably-fair real.** ✅ Per-game seeded RNG (`seedToInt`) threaded through `dungeon.js` (Digger reseed + all `Math.random()` → `rng`), `monster.js` (`seededShuffle`), `game.js` (chase + generation). `DungeonGenerator.regenerateFromSeed` + `layoutFingerprint`; `/api/verify` regenerates & returns fingerprint. Determinism test suite added (`provablyFair.test.js`). _Verifier can now reproduce the exact dungeon from the seed._
|
||||
- [x] **0.3 🔴 M — Fix batch-payout `tx_hash` collision + double-pay.** ✅ Migration 015 drops the payouts `tx_hash` unique index (batches legitimately share a tx_hash) and extends the one-per-game guard to cover `processing`. Batch completion now happens in ONE transaction via `id = ANY` (no row stranded mid-batch); BIGINT stat math (no float). Ambiguous batch failures → `needs_review` (retry service won't re-send) + operator alert. New `batchPayout.test.js` covers both paths.
|
||||
- [x] **0.4 🔴 S — Harden identity transport.** ✅ Client sends `anon_token` in handshake `auth` (not the URL query → no proxy/referer/access-log leakage); server reads `auth` first with a query-string fallback for older clients. Token is now **rotated on every resume** (`rotateToken`), so a leaked token is invalidated when the real owner reconnects; client already persists the returned token. Rotation + old-token-replay-rejection test added to `security.test.js`.
|
||||
- [ ] **0.5 🟠 S — Single-game disconnect recovery.** Extend `recoverPendingPayments` (`src/network/sessionManager.js:158`) to handle `single_game`; stop silently deleting in-progress paid games (`src/network/socketHandlers.js:787`).
|
||||
- [x] **0.5 🟠 S — Single-game disconnect recovery.** ✅ `recoverPendingPayments` now also recovers confirmed-but-unconsumed `single_game` payments (no `games.payment_id` link) by granting the equivalent credits, idempotently (per-payment reason key, row-locked). Disconnect preservation made deterministic: the stable `dbUserId` is **stamped on the game at creation**, so suspend/restore never needs a fragile disconnect-time DB lookup — every game (paid or free) is reconnectable whenever a session exists; the drop-branch is now only the genuine no-session edge. New `singleGameRecovery.test.js` (grant / consumed / idempotent).
|
||||
- [ ] **0.6 🟠 S — Client + admin XSS and CSP.** Escape chat/admin fields (`html/js/network/socketHandlers.js:291,323`; `html/admin.html`); add CSP headers.
|
||||
|
||||
## Phase 1 — Money correctness hardening (🟠)
|
||||
|
||||
Reference in New Issue
Block a user