38 lines
3.0 KiB
Markdown
38 lines
3.0 KiB
Markdown
# API and transport
|
||
|
||
All API paths are same-origin. Mutations and WebSocket upgrades require an `Origin` matching `WEBKA_ORIGIN` or an explicit `WEBKA_ALLOWED_ORIGINS` entry exactly. JSON requests use `Content-Type: application/json`. Authentication is the signed `webka_session` cookie. Error responses are `{ "error": "translationKey" }`; framework validation errors are shown as a translated generic error by the frontend.
|
||
|
||
| Method | Path | Access | Result |
|
||
|---|---|---|---|
|
||
| GET | `/api/bootstrap` | Public | `{ needs_setup }` |
|
||
| POST | `/api/bootstrap` | Setup token, first run only | `{ username, password, setup_token }` → 201 |
|
||
| POST | `/api/login` | Public, throttled | `{ username, password }` → signed cookie |
|
||
| POST | `/api/logout` | Signed in | Deletes current session and closes its transport |
|
||
| GET | `/api/session` | Signed in | `{ id, username, role, session_id }`; refreshes activity |
|
||
| GET/POST | `/api/accounts` | Admin | List accounts / create viewer `{ username, password }` |
|
||
| DELETE | `/api/accounts/:id` | Admin | Delete viewer and cascade sessions; admin protected |
|
||
| POST | `/api/accounts/:id/password` | Admin | `{ password }`; revokes all target sessions |
|
||
| GET | `/api/sessions` | Admin | Active sessions and last activity |
|
||
| DELETE | `/api/sessions/:id` | Admin | Force revoke session |
|
||
| GET | `/api/status` | Signed in | Live state, uptime origin, count, share URL; identities visible only to admin |
|
||
| GET upgrade | `/api/signal?mode=host\|viewer` | Signed in; host mode admin only | WebSocket JSON signaling |
|
||
|
||
One active host and one transport per login session. Up to 32 sockets, 64 KiB per WebSocket message, 120 signaling messages per second per socket; API bodies capped at 8 KiB. Roles are always enforced server-side. Login/setup permit ten attempts per IP per minute. Argon2 work is limited to two concurrent blocking jobs.
|
||
|
||
Signaling is not a media relay. The browser uses `RTCPeerConnection({ iceServers: [] })`, video-only tracks, trickle ICE and peer-to-peer encrypted WebRTC. The server chooses the sender identity from the authenticated connection; it never accepts a claimed `peer` field from a client.
|
||
|
||
Server events:
|
||
|
||
- `welcome { peer, live }`
|
||
- `viewer-joined { peer }`, `viewer-left { peer }` (host only)
|
||
- `host-online`, `host-offline` (viewers)
|
||
- `error { error }` (capacity/session/host conflict)
|
||
|
||
Routed messages: `{ type, target, data }` become `{ type, peer, data }`.
|
||
|
||
- Host → its viewers: `offer` (SDP), `ice` (ICE candidate).
|
||
- Viewer → current host: `answer`, `ice`, `renegotiate`.
|
||
- Viewer-to-viewer and forged role messages are dropped.
|
||
|
||
The server revalidates the session before each inbound signal and every two seconds. Logout, account deletion, password reset and session revocation remove affected connections and notify the host/viewers to close media peers. The frontend clears peers when signaling disconnects, retries with 1–10 second exponential backoff, and rechecks authentication before reconnecting. There is no recording or server-side video storage.
|