wai.live.e2ee in the browser: a page member in WebAssembly, frames sealed before publish and opened before decode, a room service carrying the group's messages (L10b) #366

Merged
dcharlot merged 17 commits from joule-moq/e2ee-web into main 2026-10-20 17:33:22 -04:00

2026-10-20

Transaction Science
Merge remote-tracking branch 'origin/main' into joule-moq/e2ee-web
Some checks failed
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 5s
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 18s
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, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
jouleclaw fabrics / metal (macOS, Apple GPU) (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, every target (pull_request) Has been cancelled
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-relay, every target (pull_request) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
# Conflicts:
#	joule-code/CHANGELOG.md
#	joule-code/joule-code-rs/Cargo.toml
2026-10-20 17:21:44 -04:00
Transaction Science
Merge remote-tracking branch 'origin/main' into joule-moq/e2ee-web
All checks were successful
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m20s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 1m32s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 12s
WAI conformance / does this change touch it (pull_request) Successful in 13s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 1m41s
WAI energy receipts / does this change touch it (pull_request) Successful in 11s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 23s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 3m43s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 11s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 29s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m35s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 8m15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 16m54s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 23m34s
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 5s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 3m9s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m1s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m4s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m10s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 28s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 13m2s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 19s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 42s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 4m43s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 9m44s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 21m58s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 8m42s
# Conflicts:
#	wai/CHANGELOG.md
2026-10-20 13:21:41 -04:00
Transaction Science
e2e e2ee: count what reaches the decode path by envelopes that do not read, not decoder errors
A decoder reports the delta frame after a dropped one, which refers to it; that is not
the dropped object reaching a decoder. Sealed bytes handed to the decode path never read
as a WAI1 envelope, which this counts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 09:35:46 -04:00
Transaction Science
2026-10-20 09:31:24 -04:00
Transaction Science
joule-moq-web: in an end-to-end encrypted room a frame is numbered only when it is sent
Before the room's group keys the page nothing is sent; numbering those frames left a gap
below a track's first group, and a late joiner's FETCH from group 0 asked the relay for
groups it never had, which it passed to the publisher. A track's groups now run from 0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 09:11:52 -04:00
Transaction Science
joule-moq-web: a late joiner in an end-to-end encrypted room does not present again a group it received live
Its FETCH copy is the same location, which §6 step 8 refuses as a replay.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:53:18 -04:00
Transaction Science
confidentiality §15: a member in a browser, and a room service as the carrier of a room's MLS messages; READMEs, CHANGELOGs, CI
§1's scope now covers the browser and states what a browser member does not do in this
revision (§15.3): watch without being a member, ingest by WHIP or WebRTC, seek back. §15.2
makes the carrier's order binding on a member's own create and commit: applied only when the
log returns it, dropped when another's commit for the epoch comes first.

CI: joule-moq-room and joule-moq-web run on a joule-moq-mls change; the conformance job runs
joule-moq-web's tests with feature e2ee, which run only with it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:47:05 -04:00
Transaction Science
joule-moq-web: the room page in an end-to-end encrypted room, and the e2ee scenario (WIP)
The page checks the room's record, loads the e2ee build, leaves a KeyPackage, follows the
room service's log (web/room/e2ee.js), seals each frame before it is signed and published,
and opens each object through §6 before it is decoded; objects of an epoch not yet reached
wait. It shows the room is end-to-end encrypted, its epoch and its roster; no watching and
no seeking back in such a room. The session hands each object's property list to a sink.
wai-live-web's roomDescriptor gives the recording mode the record is checked against.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:43:46 -04:00
Transaction Science
joule-moq-room: end-to-end encrypted rooms — the record, the clock as the MLS group's external sender, and the room's log
[room] e2ee = true gives every room a WRE1 record the authority signs (suite 0x0004,
recording mode 0 as the descriptor already states) and a joule-moq-mls Clock. The service
is the room's carrier of MLS messages (confidentiality §5.1): one log per room holding the
clock's lifecycle records as signed, its proposals, and every GroupInfo, commit and Welcome
a member posts, in the order the clock took them.

- GET /mls?room&from[&wait_ms]: the log from an entry, held up to 8 s while nothing is new;
- POST /mls/key-package: kept for the principal's Add, from a principal the room granted;
- POST /mls/post: a GroupInfo, or a commit and its Welcome, checked by the clock as every
  member checks it; refused (409) and not carried otherwise;
- GET /room carries the record.

Tests: the record and the log on a room (unit), and the service on a relay with two
members keying through HTTP as a page does: create, Add, Welcome, refused posts not
carried, each opens the other's sealed object, a leave removed by the next commit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:34:41 -04:00
Transaction Science
joule-moq-web: feature e2ee, the member of an end-to-end encrypted room for a page
E2eeMember wraps joule-moq-mls's RoomMember: KeyPackage, lifecycle events and MLS
messages in the carrier's order, staged create and commit, seal of an encoded frame
(inner digest, envelope flag in the Immutable Properties, delivery timeout beside them)
and open through the §6 checks, with the reason or the epoch to wait for. TrackSigner
signs a sealed object's receipt over its sealed bytes (signSealed, no WAI_RECEIPT), and
UniItem gives an object's property list as it was carried. e2eeCheckRecord checks WRE1.

The e2ee build is a second wasm (joule_moq_web_e2ee) that a page loads for such a room
alone; [profile.wasm] (release, LTO, one codegen unit, opt-level s) keeps it smaller.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:28:26 -04:00
Transaction Science
joule-moq-mls: a member behind an ordering carrier — stages its create and commit, follows the group before its Welcome; feature js for wasm32
A room service that carries the room's messages in one order (confidentiality §5.1) is
how a browser member is reached. A member that applied its own commit before the carrier
ordered it could fork from a commit another member made for the same epoch, so:

- stage_create / stage_commit hold the member's GroupInfo or commit until the carrier
  returns it (receive applies it then, checked as every member checks it); another's
  first, or a refusal, withdraws it. create and commit still apply at once.
- before its Welcome a principal follows the group from its public handshake messages,
  as the clock does (the code is now shared), so its model knows whether a group exists
  and who is in it; a Welcome for another and a GroupInfo of a group it holds are ignored.
- feature js: openmls's js (getrandom 0.4 wasm_js, web-time) and getrandom 0.2's js for
  the crypto provider's generator; the crate builds for wasm32-unknown-unknown.

Tests: a room carried in one order (create, follow, commit, Welcome, removal), two
commits for one epoch where the carrier's first wins, a commit overtaken by another, and
a staged create the carrier refuses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:28:19 -04:00
Transaction Science
joule-moq secure_objects: a keyring holds the locations it opened by epoch, and forgets them with the epoch's keys
An object presented again carries the same KID, so its epoch's set holds it; a set goes
when its epoch's keys are deleted, after which every object of that epoch is refused
epoch_not_joined anyway. A page in a long room keeps memory bounded by the epochs it holds.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:28:18 -04:00