Commit Graph

17 Commits

Author SHA1 Message Date
Josh Creek b8bcc1f3c1 feat(join-auth): add key-ID rotation to signed join authorisations
Prerequisite for wiring the allocator to publish rosters. The signing
key is a shared HMAC secret mounted into both the allocator and the
allocated game server; without a key ID, rotating it would invalidate
every authorisation already issued for an in-flight match, because a
server holding only the new key cannot verify a token signed with the
old one.

Add KeyID to JoinAuthorisation and append it to the canonical claim
bytes, so it is covered by the signature and cannot be repointed at a
different key than the one that actually signed. Allocated servers now
hold a set of currently-valid keys and select by ID: a rotation
publishes the new key alongside the old, and the old is dropped once no
live match can still reference it.

The key file becomes a JSON map of key ID to base64 key. A file of raw
key bytes is still accepted as a single key under the empty ID, which is
what an unrotated deployment and the kind fixture use.

Game/scripts/match_net.gd builds the canonical bytes independently, so
it changes in lockstep; the cross-language golden token in
test_match_net.gd is regenerated from the Go implementation and now
carries a key ID. Added tests cover accepting either key mid-rotation,
rejecting a retired key ID, and rejecting a token whose key ID was
swapped to name a key the server does hold.

Go suite and 223 Godot tests pass.
2026-09-05 10:36:06 +01:00
Josh Creek 8c28374eb4 fix(multiplayer): harden reconnect lifecycle fencing 2026-09-03 13:24:52 +01:00
Josh Creek d59e0017f7 fix(multiplayer): lock signed team assignments 2026-09-02 19:05:45 +01:00
Josh Creek 0bca441ca1 fix(multiplayer): enforce drain at admission 2026-09-02 19:04:56 +01:00
Josh Creek 807aaa4478 fix(multiplayer): validate match admission context 2026-09-01 22:51:15 +01:00
Josh Creek d819658ace fix(multiplayer): reject typed claim coercion 2026-09-01 22:32:05 +01:00
Josh Creek 4d8638e62f fix(multiplayer): harden join expiry validation 2026-09-01 22:30:36 +01:00
Josh Creek 4e88ea80f3 feat(multiplayer): handle planned shutdowns on clients 2026-09-01 16:43:47 +01:00
Josh Creek b24f9fc448 feat(multiplayer): notify clients before server shutdown 2026-09-01 16:42:15 +01:00
Josh Creek 80d6ee8cf5 fix(multiplayer): validate allocated roster shape 2026-09-01 16:18:31 +01:00
Josh Creek 69a8402f11 fix(multiplayer): honor assigned team and slot 2026-09-01 16:17:10 +01:00
Josh Creek b4ea50d76a fix(multiplayer): reclaim slots by signed identity 2026-09-01 16:08:01 +01:00
Josh Creek 3aad68a6e6 feat: fence expired allocated reconnects 2026-09-01 08:52:12 +01:00
Josh Creek e25d61d80e feat: verify allocated join authorisations with hmac 2026-09-01 08:48:48 +01:00
Josh Creek 4b01b7fc88 fix: prevent concurrent join token reuse 2026-09-01 08:41:38 +01:00
Josh Creek 68d832f7bc feat: enforce allocated join roster admission 2026-09-01 08:39:56 +01:00
Josh Creek 4533da34e0 feat(multiplayer): Phase 1 transport, connection, and lobby
Lands tasks 1.0-1.8 of multiplayer-todo.md: the pure-function test runner,
net_codec (wire format quantizers/pack-unpack), NetworkManager (ENet
transport, manual polling, min-RTT clock sync), MatchNet (handshake,
protocol/tick-rate gating, roster with team+ready state), lobby.tscn (team
columns, switch team, ready toggle), server_boot.tscn (headless dedicated
server with structured logging and an overrun watchdog), and main_menu.gd's
Host/Join-by-IP UI (connecting overlay, cancel, bounded failure path).

Followed by an adversarial review (Opus subagent) that found and fixed two
real bugs - an unvalidated player_name broadcast that let one client's
oversized name head-of-line-block the reliable channel for everyone, and a
server-side roster leak across a host/re-host cycle - plus three gaps in
the test suite itself where a claim of "verified" wasn't actually backed
by what the test checked. All five two-process smoke tests plus the
pure-function suite are green with the strengthened assertions in place.
2026-08-20 08:18:59 +01:00