# MatrixRTC standalone publication policy (iscg policy1) ## Policy and boundary This is a narrow fork of Element's lk-jwt-service v0.9.0, upstream commit `0e176b1eca44e67b11484d0bdf56999807bf2b8e` (AGPL-3.0-only). It fixes both standalone endpoints, `/sfu/get` and `/get_token`: - Matrix OpenID verification still runs, including the subject's server name and the claimed user ID where the protocol supplies one. - Every successfully authenticated participant may publish audio/video in the requested, room-scoped session, regardless of their homeserver. - `LIVEKIT_FULL_ACCESS_HOMESERVERS=iscg.dev` still gates the server-side `CreateRoom` call and delayed-leave delegation. It is NOT widened to `astr.to` or `*`. No user's JWT gains room creation, list, recording or admin privileges. - Existing application-service membership checks, when configured, are unchanged. - The SFU MUST retain `room.auto_create: false`. Otherwise remote users can create arbitrary SFU rooms by joining, regardless of JWT-service policy. - A remote user may obtain a scoped token before a local user creates the room; the SFU rejects joining a missing room. This is intentional upstream behaviour. - Existing one-hour token TTL, SFU participant limits and container hardening are preserved. No new appservice/admin credential is introduced. **This is not Matrix room-membership authorization.** On Heather, Tuwunel 1.9.4 has no MSC4502/MSC4512 integration, and lk-jwt-service is standalone. Someone with valid Matrix OpenID and knowledge of a room ID can request an SFU token even if not a Matrix member, including for an unencrypted call. This limitation existed for subscribing before the patch and now includes publishing. Room IDs are not authorization secrets; E2EE, when enabled by clients, protects media confidentiality, not resource abuse or forged room participation. Do not advertise this deployment as membership-checked or suitable for anonymous guests. The fuller migration is homeserver-backed MSC4195/MSC4502/MSC4512 integration with scoped application-service membership checks. It requires a homeserver that supports those APIs (or a separately reviewed Tuwunel implementation), client compatibility checks and a backed-up migration. Adding `astr.to` or `*` to the full-access list does not solve membership authorization. The newer upstream `LIVEKIT_REMOTE_CAN_PUBLISH_HOMESERVERS` option applies to federated application-service requests, not to these standalone endpoints. ## Source and tests `standalone-publication.patch` changes two authorization arguments, adds a startup policy banner, regression tests and updates the two HTTP integration suites' remote publication expectations. Creation, delegation, OpenID and membership-check implementations are not replaced. The image build fails unless all root-library unit tests and both HTTP/OpenID integration suites (`get_token`, `sfu_get`) pass. Regressions cover local users, `astr.to`, an unrelated server, rejected OpenID, foreign/forged subject, room-scoped JWTs and lack of creation/admin permissions. Existing membership and delayed-event denial tests remain part of the unit suite. The upstream archive, patch and Rust builder image are SHA256-pinned, and Cargo uses `--locked`. Alpine build-tool packages are fetched from its package repository, so this is a pinned-source build recipe, NOT a claim of bit-for-bit reproducible output. Preserve the exported release image and its checksum too. ## Build (Linux amd64 / Docker) From this directory: ```sh # Run long work in tmux. No production secrets are needed by the build. sudo bash build.sh ``` The resulting image is `iscg/lk-jwt-service:0.9.0-policy1-6e21c58c02d6`. The image is local-only and Compose uses `pull_policy: never`. On a replacement host, rebuild it or load the preserved Docker image archive BEFORE starting Arion. Do not replace it with an unreviewed latest tag. Tests and compiler run in build containers; no Rust toolchain is installed on the NixOS host. ## Deployment and rollback Deploy only `matrix-rtc-jwt` with the evaluated Arion composition, after staging and health/token/media checks. No homeserver, SFU, Coturn or unrelated service restart is required. Compare the Nix source baseline to `/run/current-system` and inspect dry activation before switching so unrelated edits are not applied. The deployment receipt records the exact image ID and new Nix generation. Before deployment preserve the old generation, old composition, old image, container start-time baseline and config source. Keep release archives outside cache on Heather and Poppy. For an emergency rollback, use the saved pre-policy Arion composition: ```sh sudo arion --prebuilt-file /path/from/receipt/old-compose.yaml \ up -d --no-deps --pull never matrix-rtc-jwt ``` Then restore the pre-policy Nix generation/source selectively, retaining any subsequent unrelated edits. Do not restart the whole `heather.service`, wipe volumes, revert the homeserver database or disable TLS verification. Rejoin the call to obtain a fresh JWT; previously issued tokens do not change retroactively.