feat(co-host): server-side multi-controller (owner promotes peers to drive)

Generalizes host-only from a single host to a controller SET. The owner (creator)
can promote/demote peers; in host-only mode the relay gate allows any controller,
not just the owner. Single-host is now the special case controllers={owner}, so
existing behavior/tests are unchanged.

- shared: CAPABILITIES.CO_HOST enabled; new SET_PEER_ROLE event; CONTROL_MODE
  payload carries controllers.
- server: room.controllers Set (always incl. owner), advertised in ROOM_DATA;
  gate checks controllers.has(peerId); SET_PEER_ROLE handler (owner-only, target
  must be present, MAX_CONTROLLERS=10 cap, re-sync on reject); controlModePayload
  helper for consistent emits; owner-leave resets controllers + falls back to
  everyone, co-host-leave broadcasts the updated list (dedup/reconnect guarded).
- WS test: promote→drive, plain guest still gated, non-owner can't promote,
  demote→re-gated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
KoalaDev
2026-06-28 03:36:22 +02:00
parent de518ac205
commit a326087ca5
3 changed files with 135 additions and 20 deletions
+4 -3
View File
@@ -35,7 +35,8 @@ export const EVENTS = {
// Host Control Mode
SET_CONTROL_MODE: "set_control_mode", // Client -> Server: host sets room control mode ('everyone' | 'host-only')
CONTROL_MODE: "control_mode", // Server -> Client: room control mode changed { controlMode, hostPeerId }
CONTROL_MODE: "control_mode", // Server -> Client: control mode/role changed { controlMode, hostPeerId, controllers }
SET_PEER_ROLE: "set_peer_role", // Client -> Server: owner promotes/demotes a peer { peerId, controller }
// Media Control
PLAY: "play",
@@ -75,8 +76,8 @@ export const CONTROL_MODES = {
// relays (unknown/absent list → feature treated as unavailable) and old clients
// simply ignore the field. Add a flag here as each server-gated feature lands.
export const CAPABILITIES = {
HOST_CONTROL: 'host-control'
// Future: CO_HOST: 'co-host' // owner promotes guests to additional controllers
HOST_CONTROL: 'host-control',
CO_HOST: 'co-host' // owner promotes guests to additional controllers
};
export const HEARTBEAT_INTERVAL = 15000; // 15s