feat: stream private office screens
This commit is contained in:
+25
-1
@@ -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, 32–4096 bytes. Never expose this in the static build. |
|
||||
| `TERA_TURN_CREDENTIAL_TTL` | `300` | Credential lifetime in seconds, bounded to 60–3600. |
|
||||
| `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 1–3600. |
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user