joule-moq-relay: relay-to-relay cascading, one live room across relays, the WAI evidence at every hop #475

Closed
dcharlot wants to merge 0 commits from wai/relay-cascade into main
Owner

What this is

Relay-to-relay cascading for joule-moq-relay, so one WAI live room can span relays in
different places: the home relay behind an HTTP-only tunnel that carries WebSocket alone, and
an edge relay with public UDP. On main a publisher and its subscribers must reach the same relay
process. With this, each relay dials the upstreams its configuration names, routes the namespace
prefixes it is given there, and carries the room's tracks both ways, with every WAI check made
again at every hop.

Configuration: [[upstream]]

url (moqt:// native QUIC, https:// WebTransport, wss:///ws:// the WebSocket binding),
transport, prefixes (namespace prefixes, * per field), trust (exactly one of ca_path,
cert_sha256 for a pinned leaf, native_roots; none for ws://), token_sha256 with
token_path (the token is read from the file and must hash to the SHA-256 named in the config;
the relay refuses to start otherwise), and an optional relay_key the upstream must declare.
New limits: max_relay_hops (8, at most 15) and upstream_reconnect_ms (1 s, doubling to 30 s).

Behaviour, on draft-ietf-moq-transport-22's relay rules

  • Forwarded once, cached, fanned out (§7.4): a SUBSCRIBE, FETCH or TRACK_STATUS for a track no
    session of the relay publishes goes upstream on the first open link that routes it; the
    subscription it makes is the relay's own upstream subscription, so every local subscriber is
    served from it. A RENDEZVOUS_TIMEOUT goes upstream with the time left.
  • Namespaces both ways (§4, §7.6): every namespace published to a relay under a link's
    prefixes, by PUBLISH_NAMESPACE or as the namespace of a track sent by PUBLISH, is published on
    the link, so a publisher on either relay reaches subscribers on the other; a SUBSCRIBE_NAMESPACE
    is forwarded on the links it overlaps and the answers merged with the relay's own.
  • Loops: a relay-id path, which the draft allows only as a negotiated extension. The draft
    defines neither a path nor a hop limit (§4.1: namespace publication "does not protect against
    loops"; §7: relay interconnection out of scope), and an unknown Message Parameter closes the
    session (§9.20) — but §9.20 also admits one "negotiated via Setup Options". So both ends of a
    link declare the Setup Option RELAY_ID (0x3A4F, odd, bytes: the relay's summary key), the
    dialer proving it with a GRANT_PROOF naming no grant over the listener's challenge, and every
    request between relays then carries the Message Parameter RELAY_PATH (0x3A51): the relays
    passed, the sender last. A relay never forwards back on the session a request came from, to a
    relay on its path, or past the hop limit; a request naming the relay that receives it is
    refused relay_loop, past the limit relay_hops_exceeded; RELAY_PATH on a session that did not
    negotiate it closes the session PROTOCOL_VIOLATION. A path, not a bare hop limit: it stops a
    request at the first relay it would repeat, and its length is the hop limit.
  • Failover and a typed refusal: links are tried in the configuration's order; one that is
    down, refuses for unavailability (TIMEOUT, INTERNAL_ERROR, GOING_AWAY, EXCESSIVE_LOAD)
    or does not answer is passed over; with none up, REQUEST_ERROR TIMEOUT reason no_upstream
    (after waiting within a requested rendezvous).
  • GOAWAY across hops (§6.6.1, §7.6.1, §9.2): an upstream's GOAWAY moves the link to a
    session at the URI it names (else the link's own), re-subscribes there every track held through
    the old one (duplicates deduplicated, §7.3), re-publishes the namespaces, and closes the old
    session; it is never passed downstream. The relay's own GOAWAY on a session it dialed names no
    URI (a client's). A GOAWAY from a relay that dialed this one stops new requests to it.

WAI evidence across hops (and the spec text)

  • Receipts at every door — jwp-receipts.md §4.1: a relay holds what another relay forwards
    to its own door, and refuses an object that does not verify though the relay before forwarded it.
  • A per-hop record per hop, chaining by track — live-metering.md §3.10 (new), §8: each relay
    signs its own WMH1; a hop link is counted in both ends' track entries and in neither's
    subscriber sessions nor ledger, so each subscriber is counted once and a grant's consumption is
    what the relays serving its sessions state; each hop's energy is its own figure with its class,
    summed only within a class. The record layout, receipt and corpus do not change.
  • Grants per hop — live-rooms.md §10.7 (new): each relay holds its own sessions to §10
    (rights, the seek power, a rated track's threshold); a hop link runs under its operator's token,
    never a principal's grant; a FETCH or fill of a track whose live edge the relay does not know
    learns it upstream (TRACK_STATUS) and is held to §10.6 before anything is forwarded.
  • Co-performance, the floor — co-performance.md §8: the floor and the audience inputs are
    decided at the relay the performer's or author's session publishes to; over a hop link they are
    forwarded as decided, in arrival order, and the events are read for their statements alone.
    This keeps #462's chain-order counting exactly where the author publishes.
  • The DVR window — live-recording.md §8.3: a window at one relay is fetched through another
    as an upstream FETCH, the seek power held at the viewer's relay.
  • Energy: the relay already labels its own figure unmetered per session; nothing sums across
    hops or classes. Each relay's summary of a link names the other relay (peer).

Design decisions

  • A link is an ordinary -22 session in which the relay is the client (session::dial_session),
    so every existing rule (door, DVR, floor, dedup, scheduler, summaries) applies to it unchanged.
  • Announcements flow from the dialer to the listener; routes from the dialer's config. Either
    relay can dial the other, which covers both directions: the edge dials the home relay's
    wss:// endpoint through its tunnel, or the home relay dials an edge's UDP port.
  • Peering is -22 only: the -18/-16 bridges have no form for RELAY_PATH and refuse it by name.
  • A rated room is not carried across a hop link (the link's threshold is 0): fail-closed until
    peer trust for thresholds is decided.
  • The floor is decided once: re-deciding at a downstream relay by its own arrival time would
    refuse objects the first relay forwarded, and re-deciding inputs there would refuse them for want
    of the author's grant.
  • New dependency tokio-rustls 0.26 (ring, no default features) for wss:// with the relay's own
    verifier, and rustls-native-certs (already in the lock). Lockfiles: additions only.

Checks

Check Command (through rb unless noted) Result
relay crate, every target cargo test --locked -p joule-moq-relay -- --test-threads=2 all pass: 48 unit, cascade 12, and every existing integration test
cascade suite, looped cargo test --locked -q -p joule-moq-relay --test cascade ×6 (full), ×15 (the three summary-based tests) 6/6 and 15/15 pass (an earlier loop found a race in the chain test: a session leaves the table before its summary is signed; the tests now wait for every summary)
codec cargo test --locked -p joule-moq all pass (round-trip generator covers RELAY_PATH)
dependents of the codec cargo build --locked -p joule-moq-web -p joule-moq-ingest -p joule-moq-mls -p joule-moq-interop; cargo check --locked in examples/transport-moqt build
room service (own workspace) cargo test --locked in crates/joule-moq-room all pass (12 unit + 3 integration targets)
clippy cargo clippy --locked -p joule-moq -p joule-moq-relay --all-targets zero notes in any file this PR touches (the remaining notes are on main, in joule-moq/src/receipt.rs and others)
lockfiles cargo metadata --locked --offline --format-version 1 in joule-code-rs and crates/joule-moq-room (and examples/transport-moqt, unchanged) valid; additions only (tokio-rustls 0.26.6 and the relay's two edges)
wai-rs tests that read the changed specs cargo test --locked --features live_room,live_metering,co_performance,live_record,ai_usage,bearer_receipts --test live_room --test live_metering --test co_performance --test live_record --test ai_usage --test bearer_receipts all pass
independent verifiers of the changed specs (local) python3 -I live_metering_verify.py metering, co_performance_verify.py coperformance, live_rooms_verify.py rooms, live_record_verify.py recordings all PASS
repo checks (local) check-tests-in-ci.py, check-workflow-concurrency.sh, check-spec-refs.py, check-wai-section-refs.py, check-no-vanity-metrics.sh, test-public-text-checks.sh, check-comparative-prose.sh, check-orphan-sources.py all exit 0
public names (local) check-public-names.sh on the 30 changed files; commit messages and this body against the same patterns clean
workflows none touched wfsteps/YAML parse not needed

Falsifications

Committed first; each mutation applied to the worktree, the named test run on the build host,
the file restored (git diff --quiet after).

Rule broken Test Exit
sender-side path check (may_forward lets a request go toward a relay on its path) a_loop_of_relays 101
receiver-side check (a request naming the receiving relay accepted) a_relay_path_is_checked_where_it_arrives 101
door trusts what a peer forwarded receipts_are_checked_at_every_door 101
a hop link counted as a subscriber session in the per-hop record three_relays_in_a_chain 101
the floor held again over a hop link the_floor_is_held_once_where_the_performer_publishes 101
audience inputs decided again over a hop link co_performance_votes_are_counted_once_in_chain_order 101
failover: only the first link tried an_upstream_that_is_down_is_passed_over 101
no_upstream: a down upstream read as no route an_upstream_that_is_down_is_passed_over 101
GOAWAY: subscriptions not moved an_upstream_goaway_moves_the_subscriptions 101
seek: a FETCH through a link not held to the learned live edge the_home_dvr_window_is_fetched_from_the_edge 101
seek: a fill not held once the upstream's SUBSCRIBE_OK brings the live edge the_home_dvr_window_is_fetched_from_the_edge 101
a PUBLISHed track's namespace not published upstream the_floor_is_held_once_where_the_performer_publishes 101
announcements published toward a relay on their path a_loop_of_relays 101

The first run showed the loop test passing with the sender-side check removed: the receiver-side
check stopped the loop one hop later. The test now asserts which relay refuses (the one whose
link leads back, before sending), and both checks fail it when broken.

Not done

  • The per-hop record names no peer hop. A link is counted in the track entries at both ends,
    so the chain is read by track (in at one hop against out at the one before), not by link, and
    the room-session receipt's verifier does not check it. Link entries naming the peer hop would be
    a new WMH1 version with wai-rs, corpus and Python-verifier changes.
  • A rated room is not carried across a hop link: the link proves no grant, so its threshold is
    0 and the upstream serves it nothing rated above 0 (fail-closed).
  • A FETCH piped through from upstream is checked against its receipts by the subscriber, not at
    the door of the relay piping it (as on main for any upstream fetch). Live objects are checked at
    every door.
  • Statements by a participant with the direct power (a schedule or window it states) are
    honoured downstream of a hop link only when a room key states them: the downstream relay does not
    hold that participant's grant. Room-key statements and turn holders' handovers carry.
  • Routes are the configured prefixes: a namespace an upstream names in NAMESPACE routes nothing
    by itself.
  • GOAWAY moves are tested over the WebSocket binding; QUIC and WebTransport links share the
    code path but have no GOAWAY test of their own.
  • Nothing is deployed. A viewer reaches an edge relay only from a page served on the edge's
    origin (the room page takes a relay on its own origin alone).
  • CI runs for this PR are cancelled, as asked; the checks above ran on the build host.

🤖 Generated with Claude Code


Closed: Landed on main through merge train E (#499, merge bf39ec9a); verified by content: this PR's head is in main

## What this is Relay-to-relay cascading for `joule-moq-relay`, so one WAI live room can span relays in different places: the home relay behind an HTTP-only tunnel that carries WebSocket alone, and an edge relay with public UDP. On main a publisher and its subscribers must reach the same relay process. With this, each relay dials the upstreams its configuration names, routes the namespace prefixes it is given there, and carries the room's tracks both ways, with every WAI check made again at every hop. ### Configuration: `[[upstream]]` `url` (`moqt://` native QUIC, `https://` WebTransport, `wss://`/`ws://` the WebSocket binding), `transport`, `prefixes` (namespace prefixes, `*` per field), trust (exactly one of `ca_path`, `cert_sha256` for a pinned leaf, `native_roots`; none for `ws://`), `token_sha256` with `token_path` (the token is read from the file and must hash to the SHA-256 named in the config; the relay refuses to start otherwise), and an optional `relay_key` the upstream must declare. New limits: `max_relay_hops` (8, at most 15) and `upstream_reconnect_ms` (1 s, doubling to 30 s). ### Behaviour, on `draft-ietf-moq-transport-22`'s relay rules - **Forwarded once, cached, fanned out** (§7.4): a SUBSCRIBE, FETCH or TRACK_STATUS for a track no session of the relay publishes goes upstream on the first open link that routes it; the subscription it makes is the relay's own upstream subscription, so every local subscriber is served from it. A RENDEZVOUS_TIMEOUT goes upstream with the time left. - **Namespaces both ways** (§4, §7.6): every namespace published to a relay under a link's prefixes, by PUBLISH_NAMESPACE or as the namespace of a track sent by PUBLISH, is published on the link, so a publisher on either relay reaches subscribers on the other; a SUBSCRIBE_NAMESPACE is forwarded on the links it overlaps and the answers merged with the relay's own. - **Loops: a relay-id path, which the draft allows only as a negotiated extension.** The draft defines neither a path nor a hop limit (§4.1: namespace publication "does not protect against loops"; §7: relay interconnection out of scope), and an unknown Message Parameter closes the session (§9.20) — but §9.20 also admits one "negotiated via Setup Options". So both ends of a link declare the Setup Option `RELAY_ID` (`0x3A4F`, odd, bytes: the relay's summary key), the dialer proving it with a `GRANT_PROOF` naming no grant over the listener's challenge, and every request between relays then carries the Message Parameter `RELAY_PATH` (`0x3A51`): the relays passed, the sender last. A relay never forwards back on the session a request came from, to a relay on its path, or past the hop limit; a request naming the relay that receives it is refused `relay_loop`, past the limit `relay_hops_exceeded`; RELAY_PATH on a session that did not negotiate it closes the session PROTOCOL_VIOLATION. A path, not a bare hop limit: it stops a request at the first relay it would repeat, and its length is the hop limit. - **Failover and a typed refusal**: links are tried in the configuration's order; one that is down, refuses for unavailability (`TIMEOUT`, `INTERNAL_ERROR`, `GOING_AWAY`, `EXCESSIVE_LOAD`) or does not answer is passed over; with none up, `REQUEST_ERROR TIMEOUT` reason `no_upstream` (after waiting within a requested rendezvous). - **GOAWAY across hops** (§6.6.1, §7.6.1, §9.2): an upstream's GOAWAY moves the link to a session at the URI it names (else the link's own), re-subscribes there every track held through the old one (duplicates deduplicated, §7.3), re-publishes the namespaces, and closes the old session; it is never passed downstream. The relay's own GOAWAY on a session it dialed names no URI (a client's). A GOAWAY from a relay that dialed this one stops new requests to it. ### WAI evidence across hops (and the spec text) - **Receipts at every door** — `jwp-receipts.md` §4.1: a relay holds what another relay forwards to its own door, and refuses an object that does not verify though the relay before forwarded it. - **A per-hop record per hop, chaining by track** — `live-metering.md` §3.10 (new), §8: each relay signs its own `WMH1`; a hop link is counted in both ends' track entries and in neither's subscriber sessions nor ledger, so each subscriber is counted once and a grant's consumption is what the relays serving its sessions state; each hop's energy is its own figure with its class, summed only within a class. The record layout, receipt and corpus do not change. - **Grants per hop** — `live-rooms.md` §10.7 (new): each relay holds its own sessions to §10 (rights, the seek power, a rated track's threshold); a hop link runs under its operator's token, never a principal's grant; a FETCH or fill of a track whose live edge the relay does not know learns it upstream (TRACK_STATUS) and is held to §10.6 before anything is forwarded. - **Co-performance, the floor** — `co-performance.md` §8: the floor and the audience inputs are decided at the relay the performer's or author's session publishes to; over a hop link they are forwarded as decided, in arrival order, and the events are read for their statements alone. This keeps #462's chain-order counting exactly where the author publishes. - **The DVR window** — `live-recording.md` §8.3: a window at one relay is fetched through another as an upstream FETCH, the seek power held at the viewer's relay. - **Energy**: the relay already labels its own figure unmetered per session; nothing sums across hops or classes. Each relay's summary of a link names the other relay (`peer`). ## Design decisions - **A link is an ordinary -22 session in which the relay is the client** (`session::dial_session`), so every existing rule (door, DVR, floor, dedup, scheduler, summaries) applies to it unchanged. - **Announcements flow from the dialer to the listener; routes from the dialer's config.** Either relay can dial the other, which covers both directions: the edge dials the home relay's `wss://` endpoint through its tunnel, or the home relay dials an edge's UDP port. - **Peering is -22 only**: the -18/-16 bridges have no form for RELAY_PATH and refuse it by name. - **A rated room is not carried across a hop link** (the link's threshold is 0): fail-closed until peer trust for thresholds is decided. - **The floor is decided once**: re-deciding at a downstream relay by its own arrival time would refuse objects the first relay forwarded, and re-deciding inputs there would refuse them for want of the author's grant. - New dependency `tokio-rustls` 0.26 (ring, no default features) for `wss://` with the relay's own verifier, and `rustls-native-certs` (already in the lock). Lockfiles: additions only. ## Checks | Check | Command (through `rb` unless noted) | Result | |---|---|---| | relay crate, every target | `cargo test --locked -p joule-moq-relay -- --test-threads=2` | all pass: 48 unit, `cascade` 12, and every existing integration test | | cascade suite, looped | `cargo test --locked -q -p joule-moq-relay --test cascade` ×6 (full), ×15 (the three summary-based tests) | 6/6 and 15/15 pass (an earlier loop found a race in the chain test: a session leaves the table before its summary is signed; the tests now wait for every summary) | | codec | `cargo test --locked -p joule-moq` | all pass (round-trip generator covers RELAY_PATH) | | dependents of the codec | `cargo build --locked -p joule-moq-web -p joule-moq-ingest -p joule-moq-mls -p joule-moq-interop`; `cargo check --locked` in `examples/transport-moqt` | build | | room service (own workspace) | `cargo test --locked` in `crates/joule-moq-room` | all pass (12 unit + 3 integration targets) | | clippy | `cargo clippy --locked -p joule-moq -p joule-moq-relay --all-targets` | zero notes in any file this PR touches (the remaining notes are on main, in `joule-moq/src/receipt.rs` and others) | | lockfiles | `cargo metadata --locked --offline --format-version 1` in `joule-code-rs` and `crates/joule-moq-room` (and `examples/transport-moqt`, unchanged) | valid; additions only (`tokio-rustls` 0.26.6 and the relay's two edges) | | wai-rs tests that read the changed specs | `cargo test --locked --features live_room,live_metering,co_performance,live_record,ai_usage,bearer_receipts --test live_room --test live_metering --test co_performance --test live_record --test ai_usage --test bearer_receipts` | all pass | | independent verifiers of the changed specs (local) | `python3 -I live_metering_verify.py metering`, `co_performance_verify.py coperformance`, `live_rooms_verify.py rooms`, `live_record_verify.py recordings` | all PASS | | repo checks (local) | `check-tests-in-ci.py`, `check-workflow-concurrency.sh`, `check-spec-refs.py`, `check-wai-section-refs.py`, `check-no-vanity-metrics.sh`, `test-public-text-checks.sh`, `check-comparative-prose.sh`, `check-orphan-sources.py` | all exit 0 | | public names (local) | `check-public-names.sh` on the 30 changed files; commit messages and this body against the same patterns | clean | | workflows | none touched | wfsteps/YAML parse not needed | ## Falsifications Committed first; each mutation applied to the worktree, the named test run on the build host, the file restored (`git diff --quiet` after). | Rule broken | Test | Exit | |---|---|---| | sender-side path check (`may_forward` lets a request go toward a relay on its path) | `a_loop_of_relays` | 101 | | receiver-side check (a request naming the receiving relay accepted) | `a_relay_path_is_checked_where_it_arrives` | 101 | | door trusts what a peer forwarded | `receipts_are_checked_at_every_door` | 101 | | a hop link counted as a subscriber session in the per-hop record | `three_relays_in_a_chain` | 101 | | the floor held again over a hop link | `the_floor_is_held_once_where_the_performer_publishes` | 101 | | audience inputs decided again over a hop link | `co_performance_votes_are_counted_once_in_chain_order` | 101 | | failover: only the first link tried | `an_upstream_that_is_down_is_passed_over` | 101 | | `no_upstream`: a down upstream read as no route | `an_upstream_that_is_down_is_passed_over` | 101 | | GOAWAY: subscriptions not moved | `an_upstream_goaway_moves_the_subscriptions` | 101 | | seek: a FETCH through a link not held to the learned live edge | `the_home_dvr_window_is_fetched_from_the_edge` | 101 | | seek: a fill not held once the upstream's SUBSCRIBE_OK brings the live edge | `the_home_dvr_window_is_fetched_from_the_edge` | 101 | | a PUBLISHed track's namespace not published upstream | `the_floor_is_held_once_where_the_performer_publishes` | 101 | | announcements published toward a relay on their path | `a_loop_of_relays` | 101 | The first run showed the loop test passing with the sender-side check removed: the receiver-side check stopped the loop one hop later. The test now asserts which relay refuses (the one whose link leads back, before sending), and both checks fail it when broken. ## Not done - **The per-hop record names no peer hop.** A link is counted in the track entries at both ends, so the chain is read by track (in at one hop against out at the one before), not by link, and the room-session receipt's verifier does not check it. Link entries naming the peer hop would be a new `WMH1` version with `wai-rs`, corpus and Python-verifier changes. - **A rated room is not carried across a hop link**: the link proves no grant, so its threshold is 0 and the upstream serves it nothing rated above 0 (fail-closed). - **A FETCH piped through from upstream** is checked against its receipts by the subscriber, not at the door of the relay piping it (as on main for any upstream fetch). Live objects are checked at every door. - **Statements by a participant with the direct power** (a schedule or window it states) are honoured downstream of a hop link only when a room key states them: the downstream relay does not hold that participant's grant. Room-key statements and turn holders' handovers carry. - **Routes are the configured prefixes**: a namespace an upstream names in NAMESPACE routes nothing by itself. - **GOAWAY moves** are tested over the WebSocket binding; QUIC and WebTransport links share the code path but have no GOAWAY test of their own. - **Nothing is deployed.** A viewer reaches an edge relay only from a page served on the edge's origin (the room page takes a relay on its own origin alone). - CI runs for this PR are cancelled, as asked; the checks above ran on the build host. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- **Closed:** Landed on main through merge train E (#499, merge bf39ec9a); verified by content: this PR's head is in main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
joule-moq-room: its lockfile gains tokio-rustls and two edges, nothing else re-resolved
Some checks failed
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-relay, every target (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Has been cancelled
43c87c8c07
Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot closed this pull request 2026-10-26 20:58:54 -04:00
Some checks failed
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-relay, every target (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!475
No description provided.