1
0

feat: stream private office screens

This commit is contained in:
2026-08-11 21:31:15 -07:00
parent d841575315
commit 5ca214e4bb
28 changed files with 1754 additions and 35 deletions
+25 -1
View File
@@ -35,6 +35,7 @@ without breaking the typecheck, which is the wrong order to find out.
| `POST /api/v1/realtime/events` | — | fetch-streamed SSE, opened with a strict `ResumeRequest` | **private; never cached** |
| `POST /api/v1/realtime/pose` | — | one owned `EntityPoseSnapshot` | **private; never cached** |
| `POST /api/v1/realtime/leave` | — | session id + opaque resume token | **private; never cached** |
| `POST /api/v1/media/ice` | — | strict ICE configuration request | **private; never cached** |
| `POST /api/v1/media/join` | — | strict create or explicitly opted-in join request | **private; never cached** |
| `POST /api/v1/media/events` | — | fetch-streamed SSE opened with a strict resume request | **private; never cached** |
| `POST /api/v1/media/signal` | — | strict targeted SDP/ICE request | **private; never cached** |
@@ -42,7 +43,8 @@ without breaking the typecheck, which is the wrong order to find out.
Every body is declared once in the **root** package: ordinary feeds live in
`src/server/wire.ts`, realtime in `src/realtime`, and screen signaling in
`src/media/signalingTypes.ts`. The browser and service import the same strict
`src/media/signalingTypes.ts` and ICE configuration in `src/media/iceTypes.ts`.
The browser and service import the same strict
contracts without either transport becoming a dependency of the other.
Both location parameters are optional and omitting them answers for the default
@@ -111,6 +113,23 @@ terminate media already flowing through an established WebRTC connection;
clients must close missing/revoked peers, and the short lease bounds disconnected
clients that miss an event.
TURN is optional and fail-closed. When both `TERA_ICE_URLS` and a strong
`TERA_TURN_SHARED_SECRET` are configured, an authenticated caller may POST an
exact `IceConfigRequest` to `/api/v1/media/ice`. The service returns only
short-lived coturn REST credentials: an expiration plus a random opaque nonce
as username, and its HMAC-SHA1 password. An auth subject, email, profile id and
screen id never enter the TURN username. The shared secret stays server-only.
Partial or malformed configuration disables issuance and returns a typed 503;
the hosted browser path reports relay unavailability rather than promising a
connection that will fail across NAT. Caller-owned local screen preview remains
independent of the relay.
Allowed ICE URLs are deliberately narrow: `stun:`, `stuns:`, `turn:` and
`turns:` with a host and optional port. TURN may use only the standard exact
`?transport=udp` or `?transport=tcp` selector; userinfo, credential query
parameters and arbitrary URL syntax are rejected. Issuance is rate-limited by
the trusted proxy client address and every response remains `private, no-store`.
## Regions
**A caller's coordinate is never forwarded upstream. It only selects among the
@@ -304,6 +323,11 @@ Setting it is a licence claim you are making on the record.
| `TERA_AUTH_JWT_VERIFY` | `hs256` | Set to `jwks` for asymmetric verification. |
| `TERA_AUTH_JWKS_URL` | *(empty)* | |
| `TERA_AUTH_JWT_ISSUER` / `_AUDIENCE` | *(empty)* | Checked when set. |
| `TERA_ICE_URLS` | *(empty)* | Comma-separated credential-free STUN/TURN URLs. Must include `turn:` or `turns:` to enable issuance. |
| `TERA_TURN_SHARED_SECRET` | *(empty)* | Server-only coturn `use-auth-secret` value, 324096 bytes. Never expose this in the static build. |
| `TERA_TURN_CREDENTIAL_TTL` | `300` | Credential lifetime in seconds, bounded to 603600. |
| `TERA_ICE_RATE_ATTEMPTS` | `30` | Maximum grants per trusted client address in one rate window. |
| `TERA_ICE_RATE_WINDOW` | `60` | Rate window in seconds, bounded to 13600. |
A self-hoster gets `none`, an open office, and never creates an account
anywhere. `sso` is what Lumbridge's own deployment uses: this world holds **no