Fix V2 race conditions, auth gaps, serialization bugs, and async stats
Phase 1 - Critical Fixes: - Add game_lock (asyncio.Lock) to Room class for serializing mutations - Wrap all game action handlers in lock to prevent race conditions - Split Card.to_dict into to_dict (full data) and to_client_dict (hidden) - Fix CardState.from_dict to handle missing rank/suit gracefully - Fix GameOptions reconstruction in recovery_service (dict -> object) - Extend state cache TTL from 4h to 24h, add touch_game method Phase 2 - Security: - Add optional WebSocket authentication via token query param - Use authenticated user ID/name when available - Add auth support to spectator WebSocket endpoint Phase 3 - Performance: - Make stats processing async (fire-and-forget) to avoid blocking game completion notifications Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -251,9 +251,13 @@ class TestDrawDiscardMechanics:
|
||||
player = self.game.get_player("p1")
|
||||
# Card is face down
|
||||
assert player.cards[0].face_up is False
|
||||
# to_dict doesn't reveal it
|
||||
card_dict = player.cards[0].to_dict(reveal=False)
|
||||
# to_client_dict hides face-down card details from clients
|
||||
card_dict = player.cards[0].to_client_dict()
|
||||
assert "rank" not in card_dict
|
||||
# But to_dict always includes full data for server-side caching
|
||||
full_dict = player.cards[0].to_dict()
|
||||
assert "rank" in full_dict
|
||||
assert "suit" in full_dict
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user