open-standards/joule-code/joule-code-rs/crates/joule-moq-room
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science cebfe2801a
Some checks failed
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m26s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 8s
WAI conformance / does this change touch it (pull_request) Successful in 9s
WAI energy receipts / does this change touch it (pull_request) Successful in 8s
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Successful in 7s
WAI neural sink gates / does this change touch it (pull_request) Successful in 7s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 1m51s
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Successful in 8s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 7s
wai-quantum command line / does this change touch it (pull_request) Successful in 6s
wai-quantum CUDA member / does this change touch it (pull_request) Successful in 6s
wai-quantum dataflow member / does this change touch it (pull_request) Successful in 6s
wai-quantum signal processor / does this change touch it (pull_request) Successful in 6s
wai-quantum HIP member / does this change touch it (pull_request) Successful in 6s
wai-quantum FPGA member / does this change touch it (pull_request) Successful in 7s
wai-quantum Metal member / does this change touch it (pull_request) Successful in 6s
wai-quantum npu-cores member / does this change touch it (pull_request) Successful in 6s
wai-quantum neural-processor member / does this change touch it (pull_request) Successful in 6s
wai-quantum OpenCL member / does this change touch it (pull_request) Successful in 6s
wai-quantum-qpu / does this change touch it (pull_request) Successful in 6s
wai-quantum service / does this change touch it (pull_request) Successful in 7s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 6s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 6s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 5s
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 7s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 5s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m38s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 2m45s
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Successful in 5s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 7s
wai-web wasm32 / does this change touch it (pull_request) Successful in 7s
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Successful in 20s
wai-quantum npu-cores member / member · npu-cores, neural processor (framework-128gb silicon) (pull_request) Successful in 1m12s
wai-quantum OpenCL member / member · OpenCL GPU (framework-128gb) (pull_request) Successful in 13s
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Successful in 8s
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Successful in 11s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 7m48s
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Successful in 28s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Successful in 27s
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Successful in 20s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 20s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 50s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 5m44s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m24s
wai-pack / wai-pack · macos (pull_request) Successful in 1m7s
wai-quantum command line / command line · macos (pull_request) Successful in 37s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Successful in 20s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 4m21s
wai-quantum Metal member / member · Metal (macos) (pull_request) Successful in 29s
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Successful in 1m13s
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Successful in 23s
wai-quantum service / service · macos (pull_request) Successful in 45s
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Successful in 11s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 16m8s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m31s
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Successful in 15s
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Successful in 14s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m41s
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 19m9s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 2m31s
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Successful in 9m23s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 20s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 7m17s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 15s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 30s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m52s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 8m27s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m19s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 16m37s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Failing after 16m15s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 26s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 23s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 23s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 18s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m8s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m22s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 5s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 10s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m50s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 1m58s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 3m2s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 1m34s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 3m32s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 5m6s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 5m43s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 11m41s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 3m57s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 3m54s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 5m51s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 7s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 3m56s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m20s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 30s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 9m26s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m52s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 7m13s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m22s
wai-pack / wai-pack · linux (pull_request) Successful in 1m44s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 2m22s
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Successful in 27s
wai-quantum command line / command line · linux (pull_request) Successful in 1m15s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Successful in 3m37s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Successful in 4m1s
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Successful in 21s
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Successful in 26s
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Successful in 21s
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Successful in 24s
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Successful in 23s
wai-quantum service / service · linux (pull_request) Successful in 1m11s
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Successful in 19s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 2m28s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Successful in 14m21s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Successful in 31s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Successful in 19s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 8m4s
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Successful in 26s
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Successful in 31s
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Successful in 16s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Successful in 16s
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Successful in 19s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Successful in 3m9s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 5m24s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 2m15s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m23s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m37s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m53s
wai-quantum 0.6.15 and wai-quantum-cli 0.1.3: generators, the workbench, and a program's history
This carries OpenQASM 3 generators, the specification-and-evaluator
workbench, the Studio's Workbench pane and a program's attributed history
to the package registry.

- wai-quantum 0.6.15: qasm::parse_with, qasm::inputs and
  qasm::instantiate; engine::discover, with equiv::same_state for the
  prepares task; engine::energy, moved from the job service;
  job::lint_with and critique::critique_with, which read a generator at
  its inputs; and engine::versions.
- wai-quantum-cli 0.1.3 requires it: --input on every command, instance,
  discover new | search | eval | submit | show | verify, history start |
  commit | changes | propose | merge | log | blame | verify, --history on
  run, submit and verify, and the MCP's discover and history tools.
- The desktop app requires 0.6.15 too, for discover, instantiate and the
  history.
- Every lockfile that holds wai-quantum or wai-quantum-cli moves with
  them, so a --locked build still reads its own.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 02:03:20 -04:00
..
src age × co: the room's own service is not held to the serving rule 2026-10-22 07:08:25 -04:00
tests joule-moq-relay: count each author's audience inputs in its chain's order, not in arrival order 2026-10-25 03:56:05 -04:00
Cargo.lock wai-quantum 0.6.15 and wai-quantum-cli 0.1.3: generators, the workbench, and a program's history 2026-10-26 02:03:20 -04:00
Cargo.toml Merge #432 (co-watch) into the live-room train 2026-10-22 05:26:53 -04:00
README.md age × co: the room's own service is not held to the serving rule 2026-10-22 07:08:25 -04:00
room.example.toml Merge #432 (co-watch) into the live-room train 2026-10-22 05:26:53 -04:00

joule-moq-room

A room service for WAI live rooms (wai/extensions/live-rooms.md) over joule-moq-relay. It holds one room's authority and clock keys and:

  • issues grants. A visitor's page makes an Ed25519 key and asks for a grant for it (POST /grant). The service signs a short-lived WRG1 grant: a publisher's (its own audio and video, one of the room's places) or a viewer's (the room to watch). A grant is public, so it is useless without its key: the relay, configured with the authority's key ([[auth.authorities]]), honours it only beside a proof of possession over the relay's own challenge (§10.5), which only the page that holds the key can make. Grants are bounded per client address and overall, and publishers per room. Every role, and so every grant, holds the seek power (live-rooms §3.3, bit 4): a visitor may fetch a track below its live edge (§10.6), from the relay's cache or its DVR window, as a late joiner does for the groups before it joined. A relay refuses such a fetch to a grant without it.

  • authors the lifecycle (§7.2). The service's clock is a session on the relay. It watches each publisher's video track (a SUBSCRIBE that asks for no objects): when the track appears the clock signs join and publish for the publisher on its events track (live-events §8.1), and when the relay ends the track (the publisher's session closed) it signs leave. Pages author none of it.

  • serves the room. GET /room gives the signed descriptor, the composition descriptor and the publishers' grants, which a page verifies the room with (live-rooms §9).

  • keeps end-to-end encrypted rooms ([room] e2ee = true, WAI extensions/confidentiality.md). Each room then has a confidentiality record (WRE1) the authority signs, and one MLS group whose only external sender is the room's clock: the clock proposes the Add of each publisher it records joining and the Remove of each it records leaving, and follows the group from its public messages, holding no key. The service is the room's carrier of MLS messages (§5.1, §15.2): one log per room holding the clock's lifecycle records, its proposals, and every GroupInfo, commit and Welcome a member posts, in the order the clock took them; a post the clock refuses (§5.5) is not carried.

  • admits by age ([age], WAI extensions/age-assurance.md §5.6), as the Privacy Pass origin of RFC 9577. Each room then has an age policy (§4) naming the configured issuers with one key per threshold, and a rating (§3), a room claim, both signed by the authority. A grant request without a token is answered 401 with a PrivateToken challenge for each key (WWW-Authenticate, RFC 9577 §2.1.2): its redemption context HMAC-SHA-256 over the room and a window of token_window_s under a key drawn at start (a restart turns outstanding challenges away), its origin_info the service's server name (origin, else the request's Host). A request with Authorization: PrivateToken token="…" has the token checked by wai-rs's §5.2 against the room's age, and its grant states the token's threshold in age (§5.4), from which the relay holds every track to the serving rule (§5.5). The nonces redeemed are kept for the current window and the one before, at most max_nonces a window (past it, 503 and nothing spent), and dropped as a window ages out. Each admission is counted by its window, issuer and threshold, and nothing else of it is kept: GET /age/receipt gives the room's wai-age-admissions receipt so far (§7), signed by the clock, every count under 50 suppressed, and with receipts_out each window's is appended there as it closes, and the rest of a room's when it ends. The room's rating rides the clock's events track and the grant answer's room, which a publisher's page carries on its tracks (§5.7). The clock's own session proves both room keys in its SETUP (a GRANT_PROOF naming no grant, §5.5), so the relay serves it the room's rated tracks as the room's own service: it follows each publisher and, with [co], logs every performer's objects. Operating an issuer, or the attester that establishes an age, is not the service's.

  • keeps co-performance ([co], WAI extensions/co-performance.md). With audience_input above 0, every viewer's grant carries the audience-input power (the attribute audience_input, the most inputs it may send to one selection window) and may send meta events and reactions, and the viewers' grants are listed with the room (co.audience) so a page verifies their inputs; with latency_budget_ms above 0, every publisher's grant carries that budget. Either gives the room a co-performance policy (WPP1) the authority signs (co.policy), its publishers meta events (their intents), a lead role with the direct power for the first publisher (lead), and, with ai, a grant marked as an AI participant's for a page that asks ("ai": <model digest>). The clock then keeps what only it knows (src/co.rs, co-performance §8): it records each audience member joining when its events track appears, holds the room as a verifier does (every member's chain, by FETCH where it has a gap), logs each publisher's media objects with their arrival and their due instant (GET /co/objects, the objects a verifier is given), and signs a mark (WPM1) for each object out of turn under a schedule that marks or later than its budget, the commitment (WPK1) and selection (WPS1) of each window once it closes, and the periodic fidelity statement (WPF1). A page asks the clock for a turn schedule (WPT1), a handover (WPH1) or a window (WPW1) over HTTP (POST /co/...), with its grant and a proof of possession over a challenge the service issued (live-rooms §10.5.3); its powers decide what it may ask. The relay holds the floor and the audience's inputs (its [floor], which relay-lines prints commented out).

  • keeps watch rooms ([room] watch_source, WAI extensions/co-watch.md). Each room then watches that file together: the authority signs a co-watch policy (WXP1) naming it, an object sequence of one object, by the SHA-256 of its bytes and its duration, and the service serves the bytes. A visitor enters the room's co-watch log by a proof of its grant's key over a challenge the service issued, for the request it makes (live-rooms §10.5.3), and the clock signs its join; every grant carries watch_control, the actions its principal may control. The service is the room's carrier of its viewers' events: one log per room, holding every record of the clock's chain and every control and presentation statement a viewer posts, each carried only when a verifier would accept it (its chain, its signature, its grant's policy and rate, and co-watch §5 and §7.2). Each window, the clock signs the skew statements of co-watch §8.4 from what the log holds; and a viewer silent for four seconds, or whose grant has ended, leaves. A watch room is never end-to-end encrypted (its source is served in the clear), admitted by age (its source is served without a grant) or a room with co-performance: the service refuses such a configuration.

A room lasts while anyone publishes in it. When the last publisher has left, the next one starts a new room: a new descriptor at a new t0, under the same authority and clock, so each room's grants and chain hold one stretch of company.

Running it

joule-moq-room keygen <keys.toml>       new keys (mode 0600, never over a file); prints the
                                        relay configuration lines that trust them
joule-moq-room relay-lines <keys.toml>  those lines again
joule-moq-room --config <room.toml>     serve (room.example.toml shows every field)

The keys file must be readable by its owner alone; the service refuses it otherwise. Keys has no Debug, so that no log prints a seed.

The relay needs, beside its listener and limits, the lines relay-lines prints:

[[auth.authorities]]
key = "<authority>"

[[auth.grants]]                  # the clock's events track, in any room
prefix = ["*", "<clock>", "events"]
token_sha256 = "<SHA-256 of the clock's token>"
publish = true
unlimited = true                 # no session or ingress limit for the clock's session

[[auth.grants]]                  # the clock watches the publishers
prefix = []
token_sha256 = "<SHA-256 of the clock's token>"
subscribe = true

and a door that holds each publisher's media to its own key:

[[receipts.door]]
prefix = ["*", "*", "video"]
trust_field = 1

HTTP

Request Answer
GET /, GET /health {"ok", "relay": the clock's session is open, "room"}
GET /room the room: room, t0_us, descriptor, compose, grants (hex), present, publishers, max_publishers, e2ee ({"record": <hex>, "log"}, or null), and co ({"policy": <hex>, "audience": [<hex>]}, or null)
POST /grant {"principal": <64 hex>, "role": "publisher" | "viewer"} {"grant", "digest", "exp", "role", "room": <as GET /room>}; 409 full or busy; 429 rate with retry_after_s; 503 relay while the clock has no session
GET /mls?room=<id>&from=<n>[&wait_ms=<ms>] an end-to-end encrypted room's log from entry n: {"room", "entries": [{"seq", "event" or "mls": <hex>}], "next", "end"}, held up to 8 s while nothing is past n; 410 for a room since replaced, 404 for a room that is not end-to-end encrypted
POST /mls/key-package {"room", "key_package": <hex>} kept for the principal's Add: {"ok", "principal"}; 403 for a principal the room has not granted
POST /mls/post {"room", "frames": [<hex>]} a GroupInfo, or a commit and its Welcome, checked by the clock as a member checks it, then carried: {"ok", "seq"}; 409 {"error": <reason>} when the clock refuses it
POST /grant in a room that admits by age without a token: 401 {"error": "token_required", "age"} and a WWW-Authenticate: PrivateToken challenge=…, token-key=…, max-age=… for each key; with Authorization: PrivateToken token="…": the grant, its age the token's threshold, or 403 {"error": <age-assurance §11's reason>} and the challenges again; 503 busy when the window's nonces are at their bound. GET /room's age is {"policy", "ratings", "age", "token_window_s"}
GET /age/receipt {"receipt", "policy"}: the room's admission receipt so far, signed by its clock
GET /watch/time a watch room: {"now_us", "t0_us"}, the service's clock, for a page's estimate of the room clock
GET /watch/source a watch room's source, its bytes whole, of its media type
GET /watch/challenge {"challenge": <hex>}: single-use, good for a minute
POST /watch/join {"room", "grant": <hex>, "proof": <hex>} the proof (live-rooms §10.5.1) over a challenge, for POST //<host><public_prefix>/watch/join; the clock signs the principal's join: {"ok", "t"}; 401 {"error": <reason>} for a proof that fails
POST /watch/post {"room", "events": [<hex>]} (at most 8) the viewer's events, each checked and carried in order: {"ok", "carried", "log"}; 409 {"error": <reason>, "carried"} at the first refused
GET /watch?room=<id>&from=<n>[&wait_ms=<ms>] the watch room's log from entry n: {"room", "entries": [{"seq", "event": <hex>}], "next", "end"}, held up to 8 s while nothing is past n
GET /watch/room the room as a co-watch verifier is given it (descriptor, grants, chains, policies, sources), the latest window's skew statements read, and the refusals by reason

Every answer is JSON with Cache-Control: no-store. The client's address is CF-Connecting-IP, else the first X-Forwarded-For, else the connection's: the service listens on loopback behind the front that sets them.

Tests

cargo test (this crate is a workspace of its own, with its own lock file, since it builds on wai-rs): the keys file, the grants checked against the descriptor and read by the relay's reader, the places, the limiter, and tests/room_service.rs, the service against a relay on loopback: a grant and its proof open a session and the clock announces the publisher, the grant alone opens none, the room verifies, a third publisher is refused, clients are bounded, and a new room starts when the last publisher has left; and an end-to-end encrypted room on a relay, two members keying through the service as pages do (a GroupInfo, the clock's Add, a commit and its Welcome), the posts the clock refuses not carried, each opening what the other seals, and a member that leaves removed by the next commit. Admission by age: unit tests of src/age.rs over published RSA test keys (tests/common/rfc_test_keys.rs: RFC 7517 A.2's, RFC 9500's testRSA2048 and RFC 9578 A.2's), whose tokens they sign directly, as the blind protocol's output is the same signature: the challenges by window, a token admitted once and at the room's age, the window before accepted and the one before that, another origin's and another service's challenge refused, the nonces bounded and dropped by window, and the receipt's cells the reference's and its signature the clock's; and tests/age_admission.rs, the service with [age] and a relay: the 401 and its challenges, tokens at 16 and 18 admitted and their grants' age read by the relay, one of 13 refused below_threshold, one spent twice token_replayed, one for another origin token_wrong_challenge, one that does not read token_malformed, a publisher challenged too, the relay serving the viewer at 16 the audio and refusing it the video the publisher rates 18, and the receipt read and checked by wai-rs. A room with co-performance: its policy, the audience-input power and the budgets on its grants, and two viewers' votes in a window the clock opens, commits and selects, verified as co-performance §9 verifies a room. A watch room against a relay on loopback: its source served and named by its policy, viewers admitted by a proof for the request they make (a proof for another target, or presented again, refused), their controls and statements carried and a control in the past refused, the clock's skew statements of each window, each viewer's leave once silent, and the room the log carries verified as co-watch §11 verifies it, every viewer in sync.

Licence

Apache-2.0.