docs(route): define pragmatic LiveKit trust boundary

This commit is contained in:
AAA committed 2026-08-23 01:51:36 +08:00
1 parent 6b0b1a37e3
commit 1fc89b51ae
4 files changed
+42 -6

No files matched your search

@@ -227,11 +227,19 @@ do not prove target-network latency, quality, capacity, or interoperability.
## Security and privacy
Media authority is room-, role-, session-, share-, revision-, and
connection-bound. Server-assisted credentials are short-lived, scoped,
memory-only, and never placed in URLs, logs, browser persistence, or SQLite.
Route and signaling authority is room-, role-, session-, share-, revision-, and
connection-bound. LiveKit media credentials are short-lived and bound to the
room, role, share, and publication generation so healthy media may survive a
signaling reconnect. Server-assisted credentials remain memory-only and never
appear in application page URLs, browser persistence, or SQLite. LiveKit places
its short-lived JWT in the WebSocket transport request target, which must not be
logged; no credential may enter application or proxy logs.
Ordinary SFU transport terminates DTLS-SRTP at the SFU; the product must not
claim application E2EE unless key distribution and real media evidence exist.
Authenticated Hosts and shipped clients are trusted media participants in the
current private-room threat model. Stale route-control sessions remain
unauthorized; a retired media generation remains charged during bounded drain
until deletion of its exact room prevents re-entry.
## Consequences
+1
View File
@@ -5,6 +5,7 @@ Last updated: 2026-08-23
## Current Product Truth
- Build private, low-latency game screen sharing for one broadcaster and a small group of trusted friends. Public or large broadcasts belong on OBS/Twitch-class services.
- Authenticated Hosts and shipped clients are trusted media participants in these private rooms; route authority, generation fencing, and server admission remain fail-closed.
- Web is the current delivery target. Viewers join from desktop or mobile browsers; a packaged or native sender is a later optimization.
- Keep routing automatic and media distributed. Direct/peer UDP is preferred; centralized media is fallback infrastructure, not the default topology.
- Every non-server endpoint uses one server-authoritative steady outbound media-copy capacity: default `2`, statically configurable as `1`, `2`, or `3`. A peer child or the Host publication consumes one slot; upstream receive is free, selected TURN replaces the same copy's transport, and SFU subscriber egress is accounted at the server. Browser role/UA/visibility does not create a separate tier, and clients cannot raise the deployment value.
+28 -1
View File
@@ -533,6 +533,28 @@ the server must. Redundancy can improve recovery but costs traffic and
coordination; removing redundancy leaves a recovery interval after a relay is
lost.
## Self-Hosted LiveKit Trust Boundary
Pinned LiveKit 1.13.5 treats `canPublishSources` as a source allowlist, not a
per-participant or per-source publication-count limit. `limit.num_tracks` gates
node-wide `NumTracksIn + NumTracksOut` admission, while
`subscription_limit_video/audio` caps each participant's concurrent subscribed
tracks by kind and leaves excess requests pending; neither is an SFU bandwidth
budget.
Self-hosted `RemoveParticipant` closes the current participant but does not
invalidate a still-valid join token. With `room.auto_create: false`, such a
token cannot recreate an absent room. Screener's exact-generation room names
include an unguessable publication generation and are never reused, so room
deletion plus absence proof fences an old media generation rather than revoking
every token immediately.
Screener sizes ingress and egress for its shipped clients in private rooms where
authenticated Hosts are trusted media participants. Exact-generation room
lifecycle, short-lived scoped tokens, source grants, selective subscription,
and deployment isolation remain required. The pinned upstream LiveKit release
is sufficient for that boundary.
## Route Screening
| Route | Where copies are emitted | Endpoint cost | Evidence status |
@@ -608,7 +630,7 @@ The measurable gates and exact staged experiments are in
## Sources And License Boundary
Primary sources accessed on 2026-08-19, 2026-08-21, and 2026-08-22:
Primary sources accessed on 2026-08-19, 2026-08-21, 2026-08-22, and 2026-08-23:
- [Pion WebRTC](https://github.com/pion/webrtc) - MIT; no code copied.
- [Pion WebRTC v4 API](https://pkg.go.dev/github.com/pion/webrtc/v4) - API
@@ -672,6 +694,11 @@ Primary sources accessed on 2026-08-19, 2026-08-21, and 2026-08-22:
reference, with no code copied into this research change.
- [LiveKit 1.13.5 configuration sample](https://github.com/livekit/livekit/blob/v1.13.5/config-sample.yaml),
[pinned configuration source](https://github.com/livekit/livekit/blob/v1.13.5/pkg/config/config.go),
[node track-limit selection](https://github.com/livekit/livekit/blob/v1.13.5/pkg/routing/selector/utils.go),
[participant publication checks](https://github.com/livekit/livekit/blob/v1.13.5/pkg/rtc/participant.go),
[subscription-limit handling](https://github.com/livekit/livekit/blob/v1.13.5/pkg/rtc/subscriptionmanager.go),
[room allocation](https://github.com/livekit/livekit/blob/v1.13.5/pkg/service/roomallocator.go),
[room-service lifecycle](https://github.com/livekit/livekit/blob/v1.13.5/pkg/service/roomservice.go),
[ports/firewall](https://docs.livekit.io/transport/self-hosting/ports-firewall/),
[deployment/embedded TURN](https://docs.livekit.io/transport/self-hosting/deployment/),
and [benchmark guidance](https://docs.livekit.io/transport/self-hosting/benchmark/)
+2 -2
View File
@@ -26,7 +26,7 @@ SFU/TURN 的 publication、subscription、transport、server-resource accounting
- 一对多观看:房间 admission 与端点下游容量分别配置,超额加入必须明确拒绝。Production 当前默认 8、显式接受 1 至 16;未来默认值和上限是独立产品决策,必须经过相应资源、质量、深度和恢复验收,不能从端点 cap 或一次短跑推导。
- 端点发送容量:所有非服务器端点使用同一个服务端权威稳态 outbound media-copy capacity,由唯一部署项 `ENDPOINT_MEDIA_COPY_CAPACITY` 配置,默认 `2` 且只接受 `1`、`2` 或 `3`;不读取旧键或保留第二套 tier。peer child 或 Host 的唯一 SFU publication 各消耗一份,上游接收不消耗该预算,committed selected TURN 只替换同一份 logical edge 的 transport。客户端只能声明不高于部署值的可用容量,角色、浏览器、UA、设备类型和页面可见性不产生不同上限。服务端在每次 `authenticated` 权威快照中返回最终 `endpointMediaCopyCapacity`;普通非 peer-assisted 模式也只授权稳定加入顺序中的至多 `C` 个 Host child,超额 Viewer 保持入房等待并在槽位释放后提升,信令不能绕过该集合。Web 与 Native 严格校验该值,Native Host 的普通 Viewer admission、peer-assisted child assignment 和实际发送槽位都使用同一值,且不得从独立的房间 `maxViewers` 推导。并行产生媒体的 candidate 必须持有唯一的 `TransitionOverlapSlot`,并在 commit 后回到稳态上限;SFU subscriber egress 与 TURN allocation 由独立 server admission 记账。该不兼容能力变化与单一 signaling wire 原子升级;缺失或非法 cap 与旧客户端都在取得房间或 route authority 前 fail closed。
- P2P 优先:每条普通逻辑媒体边先尝试 direct/peer UDP,服务器不得默认中转可直连媒体。更多观看者优先沿满足统一端点容量的无环 peer 图分布;每名 Viewer 同时至多一个 active upstream,失败时只影响需要重选的分支。
- NAT 与传输边界:STUN 必须可用,所有 ordinary peer `RTCPeerConnection` 只接收 STUN ICE servers,普通边不得预发 TURN candidate。所有恢复和候选授权必须绑定 exact room/share generation、endpoint session、route/assignment generation 与 connection identity;成功即停止,失败、超时或绑定失效即撤销,全部可用路径耗尽后明确等待或失败。已接受的顺序是保持既有 logical edge,必要时 direct/STUN 后使用 exact selected TURN;只有 logical ingress 不可用时才使用当前 Host publication 的 SFU subscription。Host 无 direct first-level path 时优先一条可经 TURN 的 Host-SFU publication,而不是逐 Viewer 建 Host-TURN peer 边。凭据不得进入 URL、日志、浏览器持久化或 SQLite;HTTPS/WSS 继续独立使用 TLS/TCP。
- NAT 与传输边界:STUN 必须可用,所有 ordinary peer `RTCPeerConnection` 只接收 STUN ICE servers,普通边不得预发 TURN candidate。所有恢复和候选授权必须绑定 exact room/share generation、endpoint session、route/assignment generation 与 connection identity;成功即停止,失败、超时或绑定失效即撤销,全部可用路径耗尽后明确等待或失败。已接受的顺序是保持既有 logical edge,必要时 direct/STUN 后使用 exact selected TURN;只有 logical ingress 不可用时才使用当前 Host publication 的 SFU subscription。Host 无 direct first-level path 时优先一条可经 TURN 的 Host-SFU publication,而不是逐 Viewer 建 Host-TURN peer 边。凭据不得进入应用页面 URL、日志、浏览器持久化或 SQLite;TURN 凭据和 Screener route grant 不进入任何 URL,LiveKit join JWT 仅按协议进入不得记录的 WebSocket request target。HTTPS/WSS 继续独立使用 TLS/TCP。
- 质量控制:保留 1080p60(8 Mbps)、1080p30(5 Mbps)、720p30(3 Mbps)三档推荐上限,三档与高级设置初始值统一采用 `balanced`(平衡)与 `automatic`(自动编码),`maintain-resolution`(清晰优先)、`maintain-framerate`(流畅优先)和 H.264/VP8 保留为显式选择。分享期间可直接换视频档位和 64/128/256 kbps 音频 sender ceiling,不重新选择来源或重建健康连接;视频 codec 首个可交付切换边界是在分享已显式暂停时执行有界重协商,未暂停热切换是后续复用同一事务的扩展。Peer-assisted relay 与已配置的 SFU 必须接收同一个严格校验的房间级权威设置,覆盖当前和以后建立的 sender;普通 P2P 信令结构保持不变。任何设置都只是浏览器上限和偏好,具体降级由浏览器决定;必须读回实际 sender 参数并通过 stats 观测结果、显示参数拒绝、改写和持续受限原因。不做自定义动态 FPS、综合评分或周期性全房间调档。
- 路径隔离双表示:direct/peer 继续使用每条 PeerConnection 独立的 stock WebRTC GCC,不把任何 viewer 反馈合成全房目标。每条 SFU path 从 `HIGH` ceiling 开始;优先用 pinned LiveKit 2.22.0/1.13.5 的标准两层 screen-share simulcast,在 Dynacast off 下常驻 exactly `HIGH+LOW`,让内建 per-subscriber BWE 独立降层和恢复。若该 gate 通过,Screener 不实现媒体层 selector。首 gate 使用 zero-descendant SFU leaf;root-with-children 的自动 downshift 与有界迁移是 default-on 前独立硬门。只有内建选择不满足门槛时才用标准 subscriber quality 显式限制,常驻成本不合格时再测标准 sender 手动启停。`LOW` 停编只是资源优化;active representation/layer 硬上限为二,禁止按 viewer 增长。必须实测实际接收层、硬件编码证据、游戏 FPS/p1 low、CPU/GPU、区间 encode cost、上传和分层 bytes。当前 Web P2P simulcast 缺少 receiver 选 RID 和跨 PeerConnection shared-encode 契约;当前 Web/LiveKit SVC 也缺少 direct/peer 独立选层与可移植硬件保证,且 pinned screen share 强制三层 temporal-only `L1T3`,二者按现契约静态 no-go。全部标准路径失败后才考虑 custom/native dual encode。没有合格 hardware/power-efficient 路径或额外表示破坏游戏/上传预算时 fail closed:保护健康路径并明确显示弱路径降级或不可用。
- 路径级质量状态:应用的 `HIGH`/`FALLBACK` 非对称窗口只决定拓扑资格和诊断,不命令正常的媒体层切换,也不计算综合分数。`EdgeHealth(parent, child)` 只控制该 child 的换父;`RelayEligibility(parent)` 仅适用于 relay parent,按 `eligible -> suspect -> draining -> ineligible` 控制其是否接收新 child 以及是否排空现有 children。质量 owner 根据不同 downstream edges 的当前可观察证据和端点容量要求足够的独立关联;同一 edge 的 C+B 只处理该 child。relay parent 自身 ingress 失败先触发本地修复并进入 `suspect`,只有修复失败、明确 sender/resource failure 或独立 downstream edges 确认转发仍失效时才 drain,不等待不存在的第二个 child;Host source 走 publication repair/child migration,不走 parent reparent。退位时仍健康的 ingress 保留,失效 ingress 在同一 bounded target 中替换或移除;无目标 child 进入有界等待或失败,更长的稳定证明和 cooldown 后才恢复 `eligible`。Viewer 请求必须鉴权、限频、去重,并由 sender 的 GCC/Transport-CC、实际码率、RTT、丢包、重传、编码限制、协商 codec/profile/parameters 与 viewer 解码、丢帧、冻结证据交叉验证;不能仅凭自报生效,也不得上传 raw SDP、candidate 地址或原始设备/网络标识。
@@ -71,7 +71,7 @@ SFU/TURN 的 publication、subscription、transport、server-resource accounting
- 启播:观看者请求观看后,除用户授权耗时外,3 秒内出现首帧;从请求开始到首帧期间持续显示真实、稳定且可访问的连接阶段,不用黑屏、`playing` 事件或 ICE `connected` 冒充已播放。
- 流畅性:选择 60 fps 档位时,不能在没有降档或提示的情况下连续 5 秒低于 50 个解码帧每秒。
- 成本:direct/peer UDP 不经过应用服务器。SFU/TURN 的 ingress、egress、allocation 和并发上限由整体路由模型明确配置;验收逐 hop 记录 Host、peer、SFU、TURN 和供应商计费的真实 bytes,不得用普通端点 child 数或有效载荷近似代替中央资源准入。
- 安全:应用控制面全程 HTTPS/WSS;site access、Host token 与 room-scoped Viewer grant 权限正交,任何一个 Viewer grant 只授予一个房间的观看角色。P2P/TURN 边在 WebRTC 端点间使用 DTLS-SRTP,普通 SFU 是逐跳 DTLS-SRTP;只有另行实现并验收应用层 E2EE 才能对 SFU operator 保持媒体端到端机密。仓库、数据库、日志和错误不得包含明文密码或 grant。
- 安全:应用控制面全程 HTTPS/WSS;site access、Host token 与 room-scoped Viewer grant 权限正交,任何一个 Viewer grant 只授予一个房间的观看角色。P2P/TURN 边在 WebRTC 端点间使用 DTLS-SRTP,普通 SFU 是逐跳 DTLS-SRTP;只有另行实现并验收应用层 E2EE 才能对 SFU operator 保持媒体端到端机密。仓库、数据库、日志和错误不得包含明文密码或 grant。已鉴权 Host 与 shipped clients 是当前私密房间中的可信媒体参与者;越权房间、角色和未授权 subscription 必须拒绝。旧 generation 不得重新取得 route authority,并在有界 drain 后由 exact-room 删除阻止再次加入。
- 隐私:P2P 会向房间内好友暴露网络地址,首版威胁模型仅覆盖可信熟人;若要求隐藏 IP,必须切换为服务器转发。
- 可维护性:代码、需求、调研、项目记忆、`AGENTS.md` 和 `.codex/` 均在 Git 中跟踪;开发配置不得依赖单一操作系统的绝对路径。
- 迁移完整性:同一 release 的客户端、服务端和部署配置原子迁移;canary 结束后删除被替代的配置、wire、parser、双写与测试,不为无当前消费者的旧版本保留兼容层或第二套架构。Git 历史承担旧实现追溯。