Files
2026-05-27 23:29:53 +01:00

5.7 KiB

OpenSpec Change: network-plugin-session

  • Change ID: network-plugin-session
  • Package: @suaveplan/network-plugin-session (new)
  • Status: PROPOSED
  • Type: new-package
  • Date: 2026-04-29

Why

The tiered mesh network provides peer-to-peer connectivity, but it has no concept of logical player groupings — sessions. A session is a scope within which peers see each other, exchange state, and interact. Sessions can be nested: a parent session (free-roam open world) contains child sessions (missions, heists, races), which may contain further nested sessions (mission phases, instanced interiors). This is the pattern used by GTA V Online, Destiny, The Division, and many other multiplayer games.

Without session management, every peer in the mesh receives every message from every other peer. Sessions provide:

  • Visibility isolation — peers only receive state from peers in their session branch
  • Nested hierarchies — missions inside free-roam, phases inside missions
  • Session-scoped host nomination — each session elects its own host for state authority
  • Capacity enforcement — hard caps per session type (free-roam: 30, mission: 4, race: 8)
  • Graceful transitions — joining/leaving sessions without dropping mesh connection
  • Parent state inheritance — sub-sessions can optionally receive read-only state from parent (weather, time, world events)

What changes

  • ADDED: SessionPlugin class implementing NetworkPlugin.
  • ADDED: SessionManager — maintains the session tree, handles create/destroy/join/leave/move operations.
  • ADDED: Session — represents one session node in the tree: id, parentId, hostId, peers[], capacity, rules, state.
  • ADDED: SessionRouter — intercepts outgoing messages and filters delivery to peers in the target session scope only.
  • ADDED: SessionHostElection — per-session host nomination, independent of mesh Tier 0 host. A peer can be host of multiple sessions.
  • ADDED: SessionTransitionManager — handles join/leave/move with state snapshot transfer and forwarding tunnel.
  • ADDED: ParentStateBridge — optionally replicates read-only parent state into child sessions (e.g., world time, weather).
  • ADDED: SessionCapacityEnforcer — rejects joins when capacity exceeded; can trigger session split.
  • ADDED: SessionRegistry — tracks all known sessions in the mesh, their hosts, and their peer counts.
  • ADDED: NETWORK_SESSION_CODES — frozen error registry.

Session hierarchy model

Mesh (all connected peers)
└── Session: "freeroam-01" (capacity: 30, host: Peer-A)
    ├── Peer-A (host)
    ├── Peer-B
    ├── Peer-C
    ├── Peer-D
    └── Session: "mission-heist-01" (capacity: 4, host: Peer-B)
        ├── Peer-B (host)
        ├── Peer-C
        ├── Peer-D
        └── Session: "phase-drill" (capacity: 2, host: Peer-C)
            ├── Peer-C (host)
            └── Peer-D

Rules:

  • A peer can be in exactly one leaf session at a time.
  • A peer implicitly belongs to all ancestor sessions (for parent state bridge).
  • Messages sent within a session are delivered only to peers in that session or its descendants.
  • Messages sent "upward" (to parent) are delivered to the parent session host only.
  • Each session has its own host, elected independently via the same governance scoring.

Out of scope

  • Game-specific state replication (entities, physics, AI) → gaming packages (gaming-ecs, gaming-r3f-networking).
  • Matchmaking (finding which session to join) → gaming-lobby, gaming-matchmaking.
  • Party system (persistent friend group) → gaming-party.
  • Persistence (saving session state to disk) → future network-plugin-session-persistence.

Source mapping

This change derives from the session concepts in ../suaveplan/enterprise/game-server.md (§sessions) and ../suaveplan/enterprise/lobby.md, but is a new design — suaveplan has no equivalent network-layer session plugin.

Requirement Source lines Notes
Session management game-server/README.md §Sessions reworded; suaveplan had session stubs in game-server, not network layer
Session host game-server/README.md §Sessions reworded; host per session, not per mesh
Capacity limits lobby/README.md §Capacity reworded; per-session, not per-lobby

Requirements with no source line

Requirement Justification
Session-scoped message routing Defensive — prevents free-roam state flooding mission peers
Nested session hierarchies Required for GTA V-style missions-within-free-roam
Parent state bridge Required so mission players still see world time/weather
Per-session host election Required so mission host can be closest to mission peers, not free-roam host
Session transition with snapshot Required for seamless join/leave without mesh disconnect

Verification approach

  • src/session/session.spec-conformance.test.ts — pins create, destroy, join, leave, move.
  • src/router/router.spec-conformance.test.ts — pins message delivery scope, upward routing, parent bridge.
  • src/election/election.spec-conformance.test.ts — pins per-session host election, independent of mesh host.
  • src/transition/transition.spec-conformance.test.ts — pins join/leave/move with state snapshot.
  • src/capacity/capacity.spec-conformance.test.ts — pins capacity enforcement, rejection, split trigger.
  • src/registry/session-registry.spec-conformance.test.ts — pins session tree tracking, peer counts.
  • tests/dep-graph.test.ts — pins no direct import of webrtc or gaming packages.

Migration impact

None — additive only.