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
@@ -24,6 +24,16 @@ reading the code, not yet by watching them behave on each site.
Deferred by decision (see §8): host grace period on disconnect (EC-10).
### Capability detection (forward-compat hook)
The relay advertises `capabilities: ['host-control']` in `ROOM_DATA`
(`SERVER_CAPABILITIES` in server, `CAPABILITIES` in shared/constants). The client
enables host-control UI/behavior only when the flag is present, so the feature
degrades cleanly on an older relay (absent → off) and old clients ignore the
field. This is the extensible hook for the planned **co-host** feature (owner
promotes guests to additional controllers): it will add a `'co-host'` capability
+ events without a protocol bump or breaking older relays/clients. Add new flags
to `CAPABILITIES` / `SERVER_CAPABILITIES` as features land.
### Pre-test self-audit (fixed)
- **Popup remote buttons froze for guests** — in host-only a guest's Play/Pause/SYNC
click was gated server-side but the button stuck on "Playing"/disabled with no
+83
View File
@@ -0,0 +1,83 @@
# Host Control Mode — Beta Testing Guide
> Temporary doc for branch `feature/host-control-mode`. Remove before merge.
> The feature needs the **server** half too — the official relay
> (`wss://syncserver.koalastuff.net`) doesn't run it yet, so test against a beta
> server first.
## 1. Run the beta relay (Docker)
The branch publishes the server image to GHCR under non-production tags
(`:beta` = newest branch build, `:sha-<commit>` = immutable pin). `:latest` is
never touched.
```bash
# Log in (the package is private → PAT with read:packages)
echo "$GHCR_PAT" | docker login ghcr.io -u <your-gh-user> --password-stdin
# Pull + (re)create — NOTE: `docker restart` does NOT pick up a new image,
# you must remove and re-run (or use compose / Watchtower).
docker pull ghcr.io/shik3i/koalasync:beta
docker rm -f koala-beta 2>/dev/null || true
docker run -d --name koala-beta -p 3000:3000 \
-e SERVER_SALT='choose-your-own-salt' \
ghcr.io/shik3i/koalasync:beta
```
To always run the newest beta automatically, point **Watchtower** at the
container — it does the pull → recreate whenever `:beta` moves.
The `OFFICIAL_SERVER_TOKEN` is baked into `shared/constants.js`, so no token env
is needed. Set `SERVER_SALT` (used for room-password hashing).
## 2. Connect the extension to it
⚠️ The client **force-upgrades `ws://` to `wss://` for any non-localhost host**
(see background.js "Upgraded to wss:// for remote host"). So a bare
`ws://your-server:3000` will fail without TLS. Two options:
- **Quick (no TLS):** SSH-tunnel the port so it counts as local:
```bash
ssh -L 3000:localhost:3000 your-beta-server
```
then in the popup → **Manual Connect / Advanced → Custom →** `ws://localhost:3000`.
- **Proper:** put the container behind a TLS reverse proxy (Caddy does automatic
HTTPS) → `wss://beta.yourdomain`.
Then create/join a room.
## 3. ⚠️ Use two *new* clients
Test with **two browser profiles both running this branch build** (load unpacked
from `extension/`, or install the built zip). A stock release client as a guest
will be correctly gated by the server but has none of the content-side code, so
it silently desyncs with no dialog/snap-back — that's expected degradation, not a
bug, but it looks like one during testing.
## 4. Verification checklist
| # | Step | Expect |
|---|------|--------|
| 1 | Create a room (host) | Host Control card shows **Host** + the toggle |
| 2 | Second profile joins | Guest sees no card while mode is "everyone" |
| 3 | Host enables "Only I can control" | Guest's Play/Pause/SYNC buttons lock; card shows **Guest** |
| 4 | Guest presses pause/space on the video | Brief flicker, snaps back to host position |
| 5 | Guest pauses again | Dialog: "Stay in sync" / "Watch on my own" |
| 6 | Guest → "Watch on my own" | Persistent "Solo" badge; host's peer list shows **Solo** |
| 7 | Guest → "Resync" | Snaps back to host; Solo badge clears on both sides |
| 8 | Guest tries Force-Sync / seek spam | Nothing propagates to the room |
| 9 | Host disables host-only | Card hides for guest; controls unlock |
| 10 | Host leaves the room | Room falls back to "everyone"; a remaining peer becomes host |
| 11 | Reload the guest's page while desynced | Still shows Solo (state survives reload) |
| 12 | Switch the popup language | Dialog/badge text is localized |
## 5. Capability detection
The relay advertises `capabilities: ['host-control']` in `ROOM_DATA`. The client
only enables the feature when that flag is present, so:
- against this beta server → feature on;
- against the old official server → feature cleanly hidden (no errors).
This is the extensible hook for the planned **co-host** feature (owner promotes
guests to additional controllers) — it'll add a `'co-host'` capability + events
without breaking older relays/clients.