houserules/packages/server/src
Joey Yakimowich-Payne 4819676d84
fix(net): sync customModifiers to late-joiners + reconnects in game.state
T3 audit gap 2 (CRITICAL). The server's Room kept registered custom
modifier descriptors in a per-room Map but the game.state snapshot
carried no field for them. Impact:
  - Client A registers 'custom:shield' → server broadcasts
    custom-modifier.registered → A + any currently-connected B see it.
  - Client C joins AFTER the registration → receives game.state →
    has no knowledge of 'custom:shield'.
  - Client C's engine applies a profile with kind='custom:shield' →
    registry-dispatch fallback silently no-ops → apparent cosmetic
    modifier mismatch between A/B and C.

Symmetric fix across the wire:
  - GameStatePayloadSchema (server + client types) gains an optional
    customModifiers: CustomModifierDescriptorWire[] field.
  - Both emit sites in broadcast.ts (late-joiner path +
    reconnect-with-buffered-deltas path) include the room's registered
    descriptors.
  - PredictionManager.applyFullState mirrors received descriptors
    onto the fresh engine's customModifiers registry before handing
    control to the UI. Unknown descriptor shapes are accepted as-is
    (the wire-shape cast at the single boundary bridges the Zod v3/v4
    type split same as the custom-modifier.registered subscriber).

E2E regression guard (Oracle Q4.1 recommendation): new scenario
'late-joiner + reconnect receive registered custom modifiers in
game.state'. Host creates + registers, opponent joins AFTER
registration, asserts opponent's game.state carries the descriptor.
Would have caught the pre-fix behaviour as a test failure instead of
a manual audit find.

1393 unit + 19/19 custom-modifiers e2e green.
2026-04-20 16:58:48 -06:00
..
broadcast.test.ts feat(server): add reconnection with 60s grace + snapshot resume (P4.7) 2026-04-16 17:38:26 -06:00
broadcast.ts fix(net): sync customModifiers to late-joiners + reconnects in game.state 2026-04-20 16:58:48 -06:00
game-session.test.ts feat(server): add authoritative game session per room (P4.5) 2026-04-16 17:17:42 -06:00
game-session.ts feat(server): turn-boundary queue for modifier profile updates 2026-04-19 09:06:15 -06:00
index.ts feat(server): add reconnection with 60s grace + snapshot resume (P4.7) 2026-04-16 17:38:26 -06:00
layouts.test.ts feat(server): layout-aware room.create + resolved layout echoes (Phase C) 2026-04-18 20:01:01 -06:00
layouts.ts feat(server): layout-aware room.create + resolved layout echoes (Phase C) 2026-04-18 20:01:01 -06:00
logger.ts feat(server): scaffold Bun HTTP+WS server with health + logging (P4.1) 2026-04-16 17:03:42 -06:00
logging.test.ts feat(server): add reconnection with 60s grace + snapshot resume (P4.7) 2026-04-16 17:38:26 -06:00
logging.ts feat(server): add reconnection with 60s grace + snapshot resume (P4.7) 2026-04-16 17:38:26 -06:00
middleware.test.ts feat(server): add rate-limit, origin allow-list, message-size cap (P4.4) 2026-04-16 17:11:40 -06:00
middleware.ts feat(server): add rate-limit, origin allow-list, message-size cap (P4.4) 2026-04-16 17:11:40 -06:00
protocol.test.ts fix(server): widen ModifierKindIdSchema to accept custom modifier ids 2026-04-20 16:43:38 -06:00
protocol.ts fix(net): sync customModifiers to late-joiners + reconnects in game.state 2026-04-20 16:58:48 -06:00
reconnect.test.ts feat(server): add reconnection with 60s grace + snapshot resume (P4.7) 2026-04-16 17:38:26 -06:00
reconnect.ts feat(server): add reconnection with 60s grace + snapshot resume (P4.7) 2026-04-16 17:38:26 -06:00
room.create-profile.test.ts feat(server): room-create accepts profile 2026-04-18 22:55:24 -06:00
rooms.test.ts feat(server): add room registry with codes + tokens (P4.3) 2026-04-16 17:09:43 -06:00
rooms.ts feat(server): custom-modifier.register WS handler 2026-04-19 20:01:11 -06:00
ws.custom-modifier-register.test.ts feat(server): custom-modifier.register WS handler 2026-04-19 20:01:11 -06:00
ws.modifier-profile-consent.test.ts test(server): two-player consent flow (T3) 2026-04-19 09:25:48 -06:00
ws.modifier-profile-update.test.ts feat(server): turn-boundary queue for modifier profile updates 2026-04-19 09:06:15 -06:00