Files
suaveplan/openspec/archive/2026-05-24-game-server-network/proposal.md
2026-05-27 23:29:53 +01:00

4.0 KiB

Migration: @suaveplan/game-server network slice (Wave B-4)

Package: @suaveplan/game-server Status: PROPOSED Type: extends-package

Why

@suaveplan/game-server shipped its core slice (errors, types, di-container) on Wave A. The network module is one of the four parallel B-wave slices that bring the package up to the broader reference surface from claude/review-game-engine-arch-Kaykr. Without a unified NetworkAdapter + reconnection driver + WebSocket/WebRTC transports, downstream session and matchmaking modules (Waves B-1…B-3, B-5) cannot wire to a transport at all — they all consume the Transport contract defined here.

The reference branch's network module (network/NetworkAdapter.ts, ReconnectionManager.ts, WebSocketTransport.ts, WebRTCTransport.ts) mixes runtime concerns (raw WebSocket / RTCPeerConnection) with framework concerns (event emitter, logger). Genesis splits those: the unified adapter contract lives here, and the actual platform-tier clients live in @suaveplan/network-transport-websockets and @suaveplan/network-transport-webrtc. The wrappers in this slice are the thin glue layer that bridges those two worlds via a structural boundary so tests can use in-process fakes instead of real sockets.

What changes

  • ADDED: src/network/network-adapter/ — unified NetworkAdapter class with single-init guard, Zod boundary validation, multi-subscriber fan-out, isolated handler errors, OTel counters (game_server.network.messages_sent_total, …messages_received_total, …errors_total).
  • ADDED: src/network/reconnection-manager/ — exponential-backoff reconnection driver via @suaveplan/retry's createExponentialBackoff + applyJitter, injectable Clock + TimersLike, OTel counter + histogram (reconnect_attempts_total, reconnect_delay_ms).
  • ADDED: src/network/websocket-transport/ — thin wrapper implementing Transport over a structural UnderlyingWebSocket boundary.
  • ADDED: src/network/webrtc-transport/ — thin wrapper implementing Transport over a structural UnderlyingWebRTC boundary, plus pass-through helpers (addIceCandidate, applyAnswer).
  • ADDED: Six new GAME_SERVER.* error codes: TRANSPORT_ALREADY_INITIALIZED, TRANSPORT_NOT_INITIALIZED, TRANSPORT_NOT_CONNECTED, INVALID_MESSAGE_FORMAT, RECONNECT_EXHAUSTED, RECONNECT_IN_PROGRESS.
  • ADDED: Subpath exports ./network/network-adapter, ./network/reconnection-manager, ./network/websocket-transport, ./network/webrtc-transport.
  • ADDED: Workspace deps @suaveplan/network-transport-websockets, @suaveplan/network-transport-webrtc, @suaveplan/retry.

Out of scope (deferred to later waves)

None. Network slice ships at full functional completeness for the NetworkAdapter + Reconnection + WebSocket + WebRTC contract pair. Real-world wiring of the underlying clients to the genesis transport packages is a downstream concern in each application; the wrappers themselves are complete.

Affected dependents

  • Downstream session and matchmaking slices (B-1, B-2, B-3, B-5) consume Transport and NetworkAdapter exclusively through their exported names; no additional change needed.

Source mapping

Genesis path Upstream reference
src/network/network-adapter/network-adapter.ts packages/universal/game-server/src/network/NetworkAdapter.ts (full rewrite into structural Transport contract, Zod boundary, OTel)
src/network/reconnection-manager/reconnection-manager.ts packages/universal/game-server/src/network/ReconnectionManager.ts (rewritten to consume @suaveplan/retry; storage persistence dropped — handled by a future state slice)
src/network/websocket-transport/websocket-transport.ts packages/universal/game-server/src/network/WebSocketTransport.ts (wraps UnderlyingWebSocket structural client instead of raw WebSocket)
src/network/webrtc-transport/webrtc-transport.ts packages/universal/game-server/src/network/WebRTCTransport.ts (wraps UnderlyingWebRTC structural client instead of raw RTCPeerConnection)