From 889e30a434673e2e7383bd18dff305316d7153df Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Tue, 1 Sep 2026 22:26:39 +0100 Subject: [PATCH] fix(multiplayer): reset expiry on reauthentication --- Game/scripts/control_plane_client.gd | 1 + Game/tests/cases/test_control_plane_client.gd | 7 +++++++ multiplayer-next.md | 2 ++ 3 files changed, 10 insertions(+) diff --git a/Game/scripts/control_plane_client.gd b/Game/scripts/control_plane_client.gd index 7898cfbc..f6377f4f 100644 --- a/Game/scripts/control_plane_client.gd +++ b/Game/scripts/control_plane_client.gd @@ -87,6 +87,7 @@ func configure(url: String, token: String) -> bool: return false base_url = normalized access_token = normalized_token + session_expires_at = "" auth_expired = false if _websocket != null: connect_event_stream() diff --git a/Game/tests/cases/test_control_plane_client.gd b/Game/tests/cases/test_control_plane_client.gd index 534b8e46..15465e29 100644 --- a/Game/tests/cases/test_control_plane_client.gd +++ b/Game/tests/cases/test_control_plane_client.gd @@ -53,6 +53,13 @@ func test_session_expiry_is_checked_at_the_boundary_and_fails_closed() -> void: assert_true(not ControlPlaneClient.is_valid_rfc3339_timestamp("2026-08-31T12:00:00"), "timezone-less timestamp is rejected") +func test_reconfiguration_discards_the_previous_session_expiry() -> void: + var client := ControlPlaneClient.new() + client.session_expires_at = "1970-01-01T00:00:01Z" + assert_true(client.configure("https://match.example", "new-session:opaque-token"), "new session configures successfully") + assert_eq(client.session_expires_at, "", "new credentials do not inherit the old expiry") + + func test_websocket_event_validation_requires_contract_specific_fields() -> void: var envelope := {"event": "state_changed", "revision": 1, "resource_id": "ticket_123456789", "occurred_at": "2026-08-31T12:00:00Z", "state": "QUEUED"} assert_true(ControlPlaneClient._valid_websocket_event(envelope), "valid state event is accepted") diff --git a/multiplayer-next.md b/multiplayer-next.md index 2ff9d97f..b4e7d88c 100644 --- a/multiplayer-next.md +++ b/multiplayer-next.md @@ -1570,3 +1570,5 @@ The Go event hub now enforces the same resource-ID allowlist before publication, The matchmaking UI now displays the authoritative proposal countdown from the server expiry epoch, clamped at zero and retaining compatible copy when older responses omit expiry metadata. Adversarial countdown tests cover delayed and missing-expiry responses. The UI now provides explicit detail copy for every non-terminal allocation and connection phase (`ACCEPTED` through `LIVE`), so server progress remains understandable throughout assignment and transport startup. + +Reconfiguring the client with new credentials now clears the prior session expiry, preventing an expired session’s timestamp from invalidating a fresh authentication. A re-authentication regression test covers the boundary.