feat(host-control-mode): explicit server capabilities for feature detection

Replace the implicit "hostPeerId present ⇒ feature supported" heuristic with an
explicit capabilities list the relay advertises in ROOM_DATA. Cleaner, self-
documenting, and the extensible hook for the planned co-host feature (owner
promotes guests to extra controllers) — a future 'co-host' capability + events
slot in without a protocol bump.

- shared: CAPABILITIES { HOST_CONTROL }.
- server: SERVER_CAPABILITIES advertised in ROOM_DATA.
- background: track serverCapabilities (empty against older relay), serverSupports(),
  thread hostControlSupported through GET_STATUS / GET_CONTROL_MODE / CONTROL_MODE.
- popup: gate the host-control card on the explicit capability instead of hostPeerId.

Backwards-compatible both ways: old relay omits the field → feature stays hidden
(no errors); old client ignores the field. WS test asserts ROOM_DATA advertises
the capability. Adds docs/host-control-mode-TESTING.md (beta-server setup, wss
caveat, two-new-clients note, verification checklist).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
KoalaDev
2026-06-27 04:48:45 +02:00
parent 9feafab617
commit 9963da2ebc
7 changed files with 143 additions and 14 deletions
+10
View File
@@ -69,6 +69,16 @@ export const CONTROL_MODES = {
HOST_ONLY: 'host-only' // only the host drives the room
};
// Server feature capabilities, advertised to clients in ROOM_DATA. Lets a client
// detect what the relay actually supports instead of inferring it from the
// presence of a data field — so new server features degrade cleanly on older
// 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
};
export const HEARTBEAT_INTERVAL = 15000; // 15s
export const FORCE_SYNC_TIMEOUT = 8500; // 8.5s timeout for force sync ACKs (must be > content.js poll timeout of 8s)
export const EPISODE_LOBBY_TIMEOUT = 60000; // 60s timeout for episode lobby