diff --git a/docs/ADR-001-matchmaking-platform.md b/docs/ADR-001-matchmaking-platform.md new file mode 100644 index 00000000..3bc4d98f --- /dev/null +++ b/docs/ADR-001-matchmaking-platform.md @@ -0,0 +1,75 @@ +# ADR-001: Matchmaking control-plane platform + +- Status: Accepted +- Date: 2026-08-31 +- Scope: Phase 8 matchmaking, ranked play, and per-match server allocation + +## Decision + +Build the matchmaking control plane as independently runnable Go roles backed +by PostgreSQL and Redis, deployed on provider-portable Kubernetes: + +- API: authenticated REST and revisioned WebSocket state delivery. +- Matcher: queue candidate selection and proposal creation. +- Allocator: Agones `GameServerAllocation` and assignment delivery. +- Maintenance: expiry, repair, outbox delivery, rating and result processing. +- PostgreSQL: durable identities, sessions, queue ownership, proposals, + participants, matches, ratings, results, penalties, audits and outbox. +- Redis: expiring presence and candidate indexes only; it is never an + ownership or allocation fence. +- Agones: game-server readiness, allocation and lifecycle. +- Steam Hosted Dedicated Server SDR: production player-to-server routing. + +EU and NA are the first regions. Provider-specific networking, edge, secrets, +SDR POPs and certificates live in deployment overlays. Application code must +not call a cloud-provider allocation API directly. + +The existing Godot ENet server remains a supported direct-IP/community-server +path. Allocated matches use the same authoritative simulation, but are a +separate lifecycle: one match per server process, assignment only after the +server is genuinely ready, and shutdown after result delivery. + +## Boundaries and invariants + +1. PostgreSQL is the source of truth for ownership, participation fences, + legal state transitions and idempotency. Redis indexes may be rebuilt. +2. Steam identity is verified by the secure backend. A client-supplied name or + Steam ID is never an identity or rating key. +3. The backend issues match-scoped, expiring authorisations bound to identity, + match, server, slot, protocol and connection generation. +4. Agones `Ready` means process-ready only. Assignment-ready additionally + requires the allocated manifest, signed roster and backend registration. +5. ENet/SDR carries simulation traffic; REST/WebSocket carries control-plane + traffic. No simulation state is routed through the backend. +6. Provider failure must not be represented as a player fault. Result delivery + and match-integrity failure remain separate states. + +## Rejected alternatives + +- **C#/.NET backend:** not consistent with the shipped GDScript-only project + and adds no required capability over Go. +- **Redis as the durable queue fence:** Redis failover can lose an acknowledged + write; using it as authority can split a player across proposals. +- **Provider-specific allocation SDKs in application code:** couples matching + policy and correctness to one cloud and prevents the second-provider + migration gate. +- **A custom game-server scheduler instead of Agones:** duplicates readiness, + allocation, drain and lifecycle behavior that the project needs to verify. +- **Replacing the community ENet path:** direct-IP ENet remains necessary for + LAN, CI and self-hosted servers and must not become a silent fallback for a + failed production SDR assignment. + +## Consequences + +This introduces the first non-Godot service in the project and requires +versioned API contracts, database migrations, operational security and +concurrency testing. It also gives queue ownership, ratings, reconnects and +allocation a durable authority instead of extending the Godot server with +cross-match responsibilities. SLOs and wire contracts are separate follow-up +decisions (tasks 8.2 and 8.3). + +## References + +- [`docs/MATCHMAKING.md`](MATCHMAKING.md) +- [`docs/TECH_STACK.md`](TECH_STACK.md) +- [`multiplayer-next.md`](../multiplayer-next.md) diff --git a/multiplayer-next.md b/multiplayer-next.md index 5d556874..ccafaa6e 100644 --- a/multiplayer-next.md +++ b/multiplayer-next.md @@ -29,8 +29,9 @@ product policy are in [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md). ## Phase 8 — architecture, contracts and durable data -- [ ] Lock the Go/PostgreSQL/Redis, Kubernetes/Agones, SDR, EU/NA and - provider-portability ADR; define measurable launch SLOs. +- [x] Lock the Go/PostgreSQL/Redis, Kubernetes/Agones, SDR, EU/NA and + provider-portability ADR ([ADR-001](docs/ADR-001-matchmaking-platform.md)); + measurable launch SLOs remain task 8.2. - [ ] Publish versioned OpenAPI/WebSocket contracts, stable IDs, legal state transitions, revisions and idempotency semantics. - [ ] Add PostgreSQL queue ownership/active-participation fences, durable