# Capability Spec: network-session ## Capability ID `network-session` ## Status PROPOSED ## Description Logical session overlay on top of the tiered mesh network. Sessions provide player visibility scopes, nested hierarchies (free-roam → mission → phase), per-session host nomination, capacity enforcement, and seamless join/leave transitions. ## Interfaces ### `Session` ```typescript interface Session { readonly id: SessionId; readonly parentId: SessionId | null; readonly hostId: string; readonly peers: ReadonlyArray; readonly capacity: number; readonly rules: SessionRules; readonly state: SessionState; readonly depth: number; } ``` ### `SessionManager` ```typescript interface SessionManager { createSession(parentId: SessionId, config: SessionConfig): Session; destroySession(sessionId: SessionId): void; join(sessionId: SessionId, peerId: string): Promise; leave(sessionId: SessionId, peerId: string): Promise; move(peerId: string, fromSessionId: SessionId, toSessionId: SessionId): Promise; getSession(peerId: string): Session | undefined; getSessionPath(sessionId: SessionId): ReadonlyArray; } ``` ### `SessionRouter` ```typescript interface SessionRouter { send(sessionId: SessionId, envelope: MessageEnvelope): void; broadcast(sessionId: SessionId, envelope: MessageEnvelope): void; sendToParent(sessionId: SessionId, envelope: MessageEnvelope): void; } ``` ### `SessionHostElection` ```typescript interface SessionHostElection { nominate(sessionId: SessionId): Promise; getHost(sessionId: SessionId): string | undefined; } ``` ## Behaviors ### NET-SESS-01 — Session tree Sessions form a tree with exactly one root session per mesh. Each session has exactly one parent (except root). Cycles are impossible. ### NET-SESS-02 — Leaf membership A peer belongs to exactly one leaf session at any time. The peer implicitly belongs to all ancestor sessions for parent-state-bridge purposes. ### NET-SESS-03 — Session-scoped routing Messages sent within a session scope are delivered only to peers in that session or its descendants. Peers outside the scope do not receive the message. ### NET-SESS-04 — Upward routing Messages with `scope: 'parent'` are delivered only to the parent session's host. This is used for child-to-parent state reporting (e.g., "mission complete"). ### NET-SESS-05 — Broadcast within branch Messages with `scope: 'broadcast'` are delivered to all peers in the target session and all descendant sessions. ### NET-SESS-06 — Per-session host election Each session nominates its own host independently. The election uses the same scoring algorithm as mesh governance but scoped to session peers. A peer can host multiple sessions simultaneously. ### NET-SESS-07 — Host independence from mesh The session host can be different from the mesh Tier 0 host. If the mesh host and session host are the same peer, that peer hosts both layers. ### NET-SESS-08 — Join with state snapshot When a peer joins a session, the session host provides a state snapshot. The peer transitions through `requesting → syncing → active` before receiving live messages. ### NET-SESS-09 — Leave with cleanup When a peer leaves a session, the session host cleans up peer state and notifies remaining peers. The leaving peer is moved to the parent session. ### NET-SESS-10 — Move with forwarding tunnel When a peer moves from session A to session B, a temporary forwarding tunnel routes in-flight messages from A's host to B's host until the peer is fully synced. ### NET-SESS-11 — Capacity enforcement `join()` is rejected when the session is at capacity. The rejection includes `session:capacity-exceeded` on the bus. ### NET-SESS-12 — Parent state bridge Child sessions optionally receive read-only state from parent sessions (e.g., world time, weather). Child peers cannot send messages to parent. ## Error codes - `NET_SESSION_NOT_FOUND` — Session does not exist - `NET_SESSION_PEER_NOT_FOUND` — Peer not in session - `NET_SESSION_CAPACITY_EXCEEDED` — Session at capacity - `NET_SESSION_CYCLE_DETECTED` — Attempted to create session cycle - `NET_SESSION_HOST_UNREACHABLE` — Session host not responding - `NET_SESSION_TRANSITION_TIMEOUT` — Join/move/sync timed out - `NET_SESSION_INVALID_SCOPE` — Unknown message scope ## Dependencies - `@suaveplan/network` - `@suaveplan/error` - `@suaveplan/types` - `@suaveplan/events` - `@suaveplan/fsm` - `@suaveplan/timing` - `@opentelemetry/api` - `zod` ## Notes - Session depth should be bounded (suggested max: 4) to prevent routing overhead. - Session state is in-memory only; persistence is deferred to `network-plugin-session-persistence`. - The root session typically maps 1:1 with the mesh group.