Co-watch merged by meaning onto the integrated live room (#428): - joule-moq-room: one config reader, `Config::settings()`, now fallible, carries `age`, `audience_input`, `latency_budget_ms`, `lead`, `ai` and the watch room's `watch` (from `watch_source`/`watch_duration_ms`), `watch_control` and `watch_window_ms`; one `public_prefix`. A watch room is refused together with `e2ee`, `[age]` or `[co]`. - One path for the clock's records: co-performance's `Item` (`Life`/`Meta`) and `emit_items`, with the clock's rate kept; co-watch's skew statements go out as `emit_meta`, its leaves through `emit_after` (a least `t`), and every record of the clock's chain reaches the watch log through `watch_record`. The separate `Lifecycle::Meta` is dropped. - Roles and grants: `meta` for participants in a room with co-performance or a watch room, `WATCHER_KINDS` for a watch room's viewers, `watch_control` the last attribute in key order. - Page: the co-watch mode beside co-performance and the binding; the e2e suite gains `cowatch` and keeps every scenario; run.sh runs all five node test files. - Workflows: each step whole, `paths:` unioned. CHANGELOG and REGISTRY rows kept from both; capabilities.json and v2.ttl regenerated by `registry export`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
90 lines
4.5 KiB
TOML
90 lines
4.5 KiB
TOML
# joule-moq-room: an example configuration. Nothing secret belongs here: the keys are a
|
|
# file of their own (`joule-moq-room keygen <path>` makes it, mode 0600), outside every
|
|
# repository, and the relay knows the clock's token by its SHA-256 alone.
|
|
|
|
# The HTTP service, on loopback behind the front that serves the room's page.
|
|
listen = "127.0.0.1:9682"
|
|
# The path the front serves the service under, when it strips it (`/room-api`): a grant's proof
|
|
# over HTTP, and a watch room's join proof, name the path the page addressed.
|
|
public_prefix = "/room-api"
|
|
keys = "/path/to/keys.toml"
|
|
# The relay's WebSocket endpoint, for the clock's own session (loopback).
|
|
relay_url = "ws://127.0.0.1:9681/moq"
|
|
# Exit with status 70 past this resident memory (MiB), for the supervisor to restart it.
|
|
max_resident_mb = 256
|
|
|
|
[room]
|
|
# Publishers at once, those whose grants are still waited for among them; the composition
|
|
# lays out this many tiles.
|
|
max_publishers = 4
|
|
max_present = 16
|
|
# A grant's life, in seconds.
|
|
publisher_grant_s = 1200
|
|
viewer_grant_s = 1800
|
|
# How long a publisher's grant holds its place before its tracks appear.
|
|
join_wait_s = 90
|
|
# Grants one room takes; then a new room starts once it is empty.
|
|
max_grants = 64
|
|
# Every room end-to-end encrypted (WAI confidentiality): a confidentiality record, an MLS
|
|
# group whose external sender is the clock, and the room's log of MLS messages. Such a room
|
|
# is never recorded, and its viewers are not members of its group.
|
|
e2ee = false
|
|
# Every room watches this file together (WAI co-watch): served whole, named by the room's
|
|
# co-watch policy, with its duration in milliseconds. Empty for rooms that watch nothing. A
|
|
# watch room is not also end-to-end encrypted, admitted by age or a room with co-performance.
|
|
watch_source = ""
|
|
watch_duration_ms = 0
|
|
# The actions every principal of a watch room may control: 1 play, 2 pause, 4 seek, 8 rate.
|
|
watch_control = 15
|
|
# The skew window the clock states, in milliseconds: a whole number of seconds.
|
|
watch_window_ms = 5000
|
|
|
|
[co]
|
|
# Co-performance (WAI co-performance): either value above 0 gives each room a co-performance
|
|
# policy the authority signs, served with the room. The audience-input power every viewer's
|
|
# grant carries: the most inputs it may send to one selection window (1 to 255; 0: none).
|
|
audience_input = 0
|
|
# Every publisher's latency budget in milliseconds: a later object is marked, never mixed
|
|
# unmarked (0: none).
|
|
latency_budget_ms = 0
|
|
# Which publishers hold the direct power, to state turn schedules, hand any turn over and open
|
|
# selection windows: "first" (the room's first publisher), "publishers" or "none".
|
|
lead = "first"
|
|
# Whether a publisher may ask for a grant that marks it an AI participant (its `ai` attribute).
|
|
ai = true
|
|
# How often the clock states each participant's fidelity, in seconds (0: when a lead asks).
|
|
fidelity_every_s = 30
|
|
# How long after a window closes the clock commits to it, for inputs still in flight (ms).
|
|
commit_after_ms = 1500
|
|
# How far ahead a schedule a page asks for starts, and a handover takes effect, at least (ms).
|
|
lead_ms = 300
|
|
# The objects the clock logs in one room; past it, it still marks, and logs no more.
|
|
max_objects = 200000
|
|
# The relay holds the floor and the audience's inputs once its configuration has the `[floor]`
|
|
# lines `relay-lines` prints (commented out there).
|
|
|
|
[rate]
|
|
# Grants per client address: this many at once, then one more every this many seconds.
|
|
client_burst = 6
|
|
client_every_s = 20
|
|
# And for everyone together.
|
|
global_burst = 120
|
|
global_every_s = 10
|
|
|
|
# Every room admits by age (WAI age-assurance §5.6): a grant request carries a Privacy Pass
|
|
# token (RFC 9577, type 0x0002 of RFC 9578), and the grant states its threshold. Absent: rooms
|
|
# admit anyone. The keys are the issuers' public keys, RFC 9578 §6.5's SubjectPublicKeyInfo in
|
|
# hexadecimal; operating an issuer, and its attester, is not the service's.
|
|
# [age]
|
|
# window_s = 3600 # the windows an admission receipt counts in
|
|
# token_window_s = 600 # a challenge's redemption context holds for this window and the next
|
|
# max_nonces = 65536 # nonces kept a window; past it, no further token of that window
|
|
# origin = "room.example" # the service's server name; absent, the request's Host
|
|
# receipts_out = "/path/to/age-receipts.jsonl"
|
|
# [[age.issuers]]
|
|
# name = "issuer.example"
|
|
# keys = [{ threshold = 16, spki = "<hex>" }, { threshold = 18, spki = "<hex>" }]
|
|
# [[age.ratings]] # the room's rating: one entry per scheme
|
|
# scheme = "https://ratings.example/scheme"
|
|
# value = "16"
|
|
# min_age = 16
|