open-standards/joule-code/joule-code-rs/crates/joule-moq-relay/relay.example.toml
Transaction Science c86b75ac52 The service binaries are wai-relay, wai-room and wai-ingest; the crates keep their names
WAI toolchain decision 11: joule-moq-relay builds wai-relay, joule-moq-room wai-room, and
joule-moq-ingest wai-ingest. wai dev finds them by those names (WAI_RELAY_BIN, WAI_ROOM_BIN),
and the quickstart archive, the release workflow, the examples' workflow, the browser
tests, the interop scripts, the example host script, the Scoop manifest and the crates'
READMEs and example configurations name them so. Wire and record identifiers that carry a
crate's name (joule-moq-relay/session-summary/2, joule-moq-ingest/session/1, the relay's
MOQT implementation string) and the log variables (JOULE_MOQ_*_LOG) are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 04:52:31 -04:00

156 lines
6.8 KiB
TOML

# wai-relay (crate joule-moq-relay): an example configuration. Every field is optional; these are the
# defaults unless a comment says otherwise. Nothing secret belongs here: keys are files
# the operator provides, and tokens are named by their SHA-256.
# Native QUIC (ALPN moqt-22) and WebTransport over HTTP/3 (ALPN h3), one UDP port.
quic_listen = "127.0.0.1:4443"
# The WebSocket fallback (plain HTTP upgrade; put TLS in front of it).
websocket_listen = "127.0.0.1:4480"
# The path of the WebTransport CONNECT and of the WebSocket upgrade.
path = "/moq"
# The New Session URI a shutdown GOAWAY names; empty reuses the current one.
goaway_uri = ""
[tls]
# cert_path = "/etc/joule-moq-relay/fullchain.pem"
# key_path = "/etc/joule-moq-relay/key.pem"
# Without files: a development certificate for these names, its SHA-256 printed.
dev_names = ["localhost", "127.0.0.1", "::1"]
[cache]
max_bytes = 268435456
[limits]
max_sessions = 4096
max_requests = 256
max_uni_streams = 1024
max_request_updates = 16
max_auth_token_cache_size = 16384
max_rendezvous_ms = 30000
upstream_timeout_ms = 5000
fill_timeout_ms = 2000
write_concurrency = 8
max_object_bytes = 16777216
unknown_alias_wait_ms = 1000
goaway_timeout_ms = 5000
# 0 for each of these: no limit. A session at max_session_ms is closed; one sending past
# max_ingress_kbps (averaged over ingress_burst_ms) is closed; the binary exits with status
# 70 past max_resident_mb. A rule with `unlimited = true` exempts its sessions from the first
# two.
max_session_ms = 0
max_ingress_kbps = 0
ingress_burst_ms = 4000
max_resident_mb = 0
# The most relays a request may have passed through (its RELAY_PATH), and the wait before an
# upstream link is dialed again, doubled on each failure to 30 s.
max_relay_hops = 8
upstream_reconnect_ms = 1000
websocket_buffer_bytes = 67108864
idle_timeout_ms = 30000
quic_send_window_bytes = 1048576
quic_stream_window_bytes = 16777216 # a stream's flow-control window: more than the largest group a door holds
quic_connection_window_bytes = 67108864 # a session's, all its streams together: what bounds the bytes it leaves unread; never below the stream window
[receipts]
receipts_track_suffix = "_receipts"
# Check objects in this namespace against their receipts at the door (example; not a
# default). An empty trust list accepts any key whose signature verifies. A field "*"
# matches any field; `trust_field = 1` with `prefix = ["*", "*", "video"]` would accept, in
# each room, the key its namespace's second field names (WAI live-rooms §6.1).
[[receipts.door]]
prefix = ["example", "live"]
trust = []
hold_ms = 2000
[summary]
# key_path = "/etc/joule-moq-relay/summary-seed"
# out_path = "/var/log/joule-moq-relay/sessions.jsonl"
# The relay's own energy in its per-hop session records (WAI live-metering §8): "auto"
# reads the counter the host offers (macOS: the relay process's CPU energy; Linux: the CPU
# packages' RAPL energy, only with dedicated_host = true, the statement that this host runs
# the relay alone); "off" reads none, and every record carries the unmetered marker.
[metering]
energy = "auto"
dedicated_host = false
# The room grants tokens carry, for the per-hop session records of WAI rooms (an example;
# not a default): a session whose SETUP presents this token runs under this grant.
[[metering.grants]]
token_sha256 = "1df4b07d05b9b3b1115b4b6b22af319a2f99564a2fa2573a34896063c7513c10"
grant = "0000000000000000000000000000000000000000000000000000000000000001"
joules_ceiling_micro = 5000000
funds_ceiling = 500
currency = "EUR"
[auth]
required = false
# An example grant; the hash below is of the placeholder string "replace-me".
[[auth.grants]]
prefix = ["example"]
token_sha256 = "1df4b07d05b9b3b1115b4b6b22af319a2f99564a2fa2573a34896063c7513c10"
publish = true
subscribe = true
# true: the token is a room grant's record (WAI live-rooms §4.1), honoured only on a
# session whose SETUP proved possession of its principal's key (§10.5.2).
proof = false
# true: a session presenting this token is exempt from max_session_ms and max_ingress_kbps.
unlimited = false
# true: the token may seek back, fetching a track below its live edge (WAI live-rooms
# §10.6). A room grant from an authority below seeks back when its powers hold seek.
seek = false
# The DVR store (an example; not a default): a window of the tracks under each prefix, kept
# on disk with their receipts and served to FETCH below the live edge (WAI live-recording
# §8). Groups go oldest first, whole, past max_age_s (at most 86400, 24 hours) or past
# max_bytes for the window's tracks together. The store survives a restart: on start every
# object is checked against its receipt again, and one that does not verify is dropped,
# counted, and never served. `room_keys` are the room authorities and clocks whose decision
# events withhold what they deny or redact (WAI live-moderation §6.3). `takedown_keys` are the
# services whose signed takedowns the store honours (WAI takedown §10.1): it forgets what each
# covers and signs a purge under purges/ with the summary key.
[dvr]
path = "/var/lib/joule-moq-relay/dvr"
room_keys = []
takedown_keys = []
[[dvr.window]]
prefix = ["*"]
max_age_s = 900
max_bytes = 4294967296
# The floor of WAI rooms (WAI co-performance §6): the relay reads each room's turn schedules
# and handovers from the events tracks it forwards, and does not forward a media object a
# performer publishes out of turn under a schedule that refuses. A schedule is honoured from a
# room key (these, and the keys of `auth.authorities`) or from a principal whose session proved
# a grant with the direct power. Absent: the relay holds no floor. The relay counts each
# author's audience inputs in the order of its chain (co-performance §7.3): an input that arrives
# ahead of a gap in its author's chain waits up to `hold_ms` for the gap to fill, and is refused
# `input_out_of_order` if it has not.
[floor]
room_keys = []
hold_ms = 2000
# A room authority (an example; not a default): every WRG1 grant its key signs is honoured,
# beside its proof and within its window, with the rights live-rooms §10.2 gives it. `rooms`
# narrows it to these room ids; empty, every room it grants.
# [[auth.authorities]]
# key = "<the authority's Ed25519 key, hex>"
# rooms = []
# Relays this one dials (relay-to-relay cascading): a SUBSCRIBE, FETCH or TRACK_STATUS for a
# track no session here publishes, under one of `prefixes`, goes to the first whose session is
# open; namespaces published here under them are published there. Trust is one of ca_path,
# cert_sha256 (a pinned certificate) and native_roots; ws:// takes none. The token is read from
# token_path and must hash to token_sha256.
#
# [[upstream]]
# name = "home"
# url = "wss://home.example/moq"
# transport = "websocket"
# prefixes = [["*"]]
# native_roots = true
# token_sha256 = "<64 hex digits>"
# token_path = "/etc/joule-moq-relay/home.token"