fix(multiplayer): enforce opaque event resource ids

This commit is contained in:
Josh Creek
2026-09-01 22:22:34 +01:00
parent 87d43302e1
commit 17e6a9bc20
3 changed files with 18 additions and 3 deletions
@@ -54,7 +54,7 @@ func test_session_expiry_is_checked_at_the_boundary_and_fails_closed() -> void:
func test_websocket_event_validation_requires_contract_specific_fields() -> void:
var envelope := {"event": "state_changed", "revision": 1, "resource_id": "ticket-1", "occurred_at": "2026-08-31T12:00:00Z", "state": "QUEUED"}
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")
var accepted := envelope.duplicate()
accepted["state"] = "ACCEPTED"
@@ -66,7 +66,7 @@ func test_websocket_event_validation_requires_contract_specific_fields() -> void
var bad_state := envelope.duplicate()
bad_state["state"] = "SECRET"
assert_true(not ControlPlaneClient._valid_websocket_event(bad_state), "unknown state event is rejected")
var assignment := {"event": "assignment_changed", "revision": 0, "resource_id": "match-1", "occurred_at": "2026-08-31T12:00:00Z", "match_id": "match-1", "server_id": "server-1"}
var assignment := {"event": "assignment_changed", "revision": 0, "resource_id": "match_1234567890", "occurred_at": "2026-08-31T12:00:00Z", "match_id": "match-1", "server_id": "server-1"}
assert_true(ControlPlaneClient._valid_websocket_event(assignment), "complete assignment event is accepted")
assignment.erase("server_id")
assert_true(not ControlPlaneClient._valid_websocket_event(assignment), "incomplete assignment event is rejected")
@@ -79,6 +79,12 @@ func test_websocket_event_validation_requires_contract_specific_fields() -> void
var malformed_time := envelope.duplicate()
malformed_time["occurred_at"] = "yesterday"
assert_true(not ControlPlaneClient._valid_websocket_event(malformed_time), "malformed event timestamp is rejected")
var short_resource := envelope.duplicate()
short_resource["resource_id"] = "short"
assert_true(not ControlPlaneClient._valid_websocket_event(short_resource), "short resource identifier is rejected")
var unsafe_resource := envelope.duplicate()
unsafe_resource["resource_id"] = "ticket_123456789/secret"
assert_true(not ControlPlaneClient._valid_websocket_event(unsafe_resource), "resource identifier with separators is rejected")
func test_websocket_reconnect_defers_recovery_while_http_mutation_is_in_flight() -> void: