Commit Graph

98 Commits

Author SHA1 Message Date
Josh Creek 3985b74bcf fix(multiplayer): validate ranked season ids 2026-09-01 22:33:54 +01:00
Josh Creek ec0bc362cd fix(multiplayer): validate ranked season expiry 2026-09-01 22:33:00 +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 82691eaf80 fix(multiplayer): validate assignment expiry format 2026-09-01 22:29:45 +01:00
Josh Creek 889e30a434 fix(multiplayer): reset expiry on reauthentication 2026-09-01 22:26:39 +01:00
Josh Creek 27017043f9 feat(multiplayer): explain allocation lifecycle 2026-09-01 22:25:54 +01:00
Josh Creek fd1a4d9577 feat(multiplayer): show authoritative proposal countdown 2026-09-01 22:23:33 +01:00
Josh Creek 17e6a9bc20 fix(multiplayer): enforce opaque event resource ids 2026-09-01 22:22:34 +01:00
Josh Creek 87d43302e1 fix(multiplayer): validate event timestamps 2026-09-01 22:21:18 +01:00
Josh Creek 73e5d64ba2 test(multiplayer): cover queue conflict recovery wiring 2026-09-01 22:20:07 +01:00
Josh Creek 7534d8436c fix(multiplayer): recover queue revision conflicts 2026-09-01 22:19:02 +01:00
Josh Creek 1f05f6d524 fix(multiplayer): align resync recovery targets 2026-09-01 22:16:50 +01:00
Josh Creek cfc82bcea5 fix(multiplayer): expire client sessions proactively 2026-09-01 22:13:41 +01:00
Josh Creek 1e5825b096 fix(multiplayer): validate ticket timestamps 2026-09-01 22:08:19 +01:00
Josh Creek c08c761af3 fix(multiplayer): recover requeued tickets 2026-09-01 22:06:30 +01:00
Josh Creek 0c4ad6a5aa fix(multiplayer): preserve proposal requeues 2026-09-01 22:04:53 +01:00
Josh Creek 277ad4bf98 fix(multiplayer): validate ticket playlists 2026-09-01 22:02:01 +01:00
Josh Creek 0ce2a49419 fix(multiplayer): enforce proposal transitions 2026-09-01 22:00:37 +01:00
Josh Creek a60c1a097e fix(multiplayer): validate client revisions 2026-09-01 21:59:32 +01:00
Josh Creek f491725144 fix(multiplayer): stop recovery after completion 2026-09-01 21:58:20 +01:00
Josh Creek 0f1864f8bc fix(multiplayer): enforce client state transitions 2026-09-01 21:57:13 +01:00
Josh Creek 30a5a89164 fix(multiplayer): project complete queue lifecycle 2026-09-01 21:55:19 +01:00
Josh Creek 6ac2d0fbb1 fix(multiplayer): project accepted queue state 2026-09-01 21:54:10 +01:00
Josh Creek fa2c93ec06 fix(multiplayer): defer reconnect recovery during mutations 2026-09-01 21:53:07 +01:00
Josh Creek 51f6e19339 feat(multiplayer): expose ranked season countdown 2026-09-01 21:49:48 +01:00
Josh Creek 9240cd4b27 feat(multiplayer): preserve authoritative queue wait 2026-09-01 21:45:07 +01:00
Josh Creek 84372204fd feat(multiplayer): persist ranked arena allocations 2026-09-01 21:04:55 +01:00
Josh Creek e934bbfe44 test(training): cover wall rebound geometry 2026-09-01 17:39:53 +01:00
Josh Creek 7b2f9c26f4 feat(training): add opt-in teamplay evaluation 2026-09-01 17:30:40 +01:00
Josh Creek 6ef55affcb feat(multiplayer): add idempotent client mutation retries 2026-09-01 17:02:55 +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 334d8a26ac feat(multiplayer): enforce allocated initial connect policy 2026-09-01 16:36:26 +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 bdb3c8f4a7 fix(multiplayer): gate allocated matches on full roster 2026-09-01 16:03:43 +01:00
Josh Creek dad26a164c fix(multiplayer): recover stale proposal mutations 2026-09-01 15:31:01 +01:00
Josh Creek d081a72b9a feat(multiplayer): wire ranked profile runtime policy 2026-09-01 15:28:37 +01:00
Josh Creek f096e8ff0b test(multiplayer): verify live assignment delivery 2026-09-01 15:25:36 +01:00
Josh Creek aa93aeec95 test(multiplayer): verify two-player proposal round trip 2026-09-01 15:17:53 +01:00
Josh Creek 57fe6f4acc test(multiplayer): extend the real integration test to cover ranked profile fetch
Adds fetch_ranked_profile() right after login, asserting the expected
404 for a brand-new identity round-trips correctly through the real
RankedProfileProvider (previous commit) before proceeding to the
existing queue_create -> heartbeat -> cancel sequence. Verified stable
across 3 consecutive full runs.
2026-09-01 14:20:09 +01:00
Josh Creek f7657ad9ad test(multiplayer): extend the real integration test to cover queue cancel
Adds a fourth real round trip to control_plane_smoke.gd: heartbeat ->
cancel_queue -> CANCELLED, using the same idle-wait pattern the
heartbeat step already needed. Verified stable across 3 consecutive
full runs (real Postgres, real testkit-api, real headless Godot
client), plus the full Go and Godot unit suites clean.
2026-09-01 14:16:06 +01:00
Josh Creek 521b8122ac test(multiplayer): add a real Go+Postgres+Godot end-to-end integration test
Every existing test of the client/control-plane boundary is either a
Go unit test with a mocked HTTP layer or a GDScript unit test with no
network at all (multiplayer-next.md 8.40's own evidence names "live
multi-process control-plane/game verification" as remaining). Nothing
before this actually ran the real compiled Go binary, a real
PostgreSQL instance, and a real headless Godot process talking real
HTTP to each other -- and it immediately found a real bug (previous
commit).

server/cmd/testkit-api is a new, deliberately separate, clearly-marked
test-only binary wired identically to cmd/control-plane except for
SteamLogin: cmd/control-plane has no way to authenticate against a
real Steam Web API from this sandbox (task 8.7's own documented
blocker), so testkit-api accepts any non-empty ticket string and
derives a deterministic identity instead. This bypass is confined to
its own binary -- never a flag on cmd/control-plane, never referenced
by any Dockerfile stage or Kubernetes manifest -- specifically so it
can't become a footgun on the real one.

Game/tests/control_plane_smoke.gd drives the real ControlPlaneClient
autoload through login -> queue_create -> heartbeat against a real
server and prints SMOKE PASS/FAIL, matching the existing net_smoke.gd
convention. scripts/verify_control_plane_integration.sh orchestrates
both sides (real postgres:17-alpine, the built testkit-api binary, the
Godot client) end to end.

Two real bugs surfaced building this, both fixed and re-verified, not
just the target bug: the smoke script's own use of `go run` left a
zombie process that survived cleanup and squatting on its port
corrupted the NEXT run with a misleading "http=401 unauthorized" (now
builds and runs a real binary directly, plus a belt-and-suspenders
port-kill in cleanup); and calling heartbeat() synchronously from
within a request_succeeded handler produced a spurious "Busy" because
ControlPlaneClient's own internal resync (see previous commit) was
still in flight -- the test now waits for ControlPlaneClient to go
idle via a real Timer (call_deferred alone floods the message queue
without ever yielding a frame for the in-flight request to complete).

Verified stable across 3 consecutive full runs: real PostgreSQL
container up, migrations applied, testkit-api built and started, real
headless Godot client round-tripping login/queue/heartbeat, clean
teardown with no leftover processes, containers, or bound ports each
time.
2026-09-01 14:13:52 +01:00
Josh Creek 4fb7ddfecf docs(multiplayer): consolidate tracking into one document
multiplayer-todo.md and multiplayer-next.md tracked overlapping
information in two places. Fold everything into multiplayer-next.md
(architecture decisions, wire format, task breakdown with checkboxes,
gotchas list, testing notes) and delete multiplayer-todo.md. Section
numbers are unchanged, so existing code comments citing them by
section/task number still resolve; update every such reference to
point at the new filename.
2026-09-01 12:32:43 +01:00
Josh Creek e7c835af52 feat: add Godot Agones REST bridge 2026-09-01 09:16:41 +01:00
Josh Creek 6caf719158 feat: add allocated server readiness control 2026-09-01 09:12:10 +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