wai.live.message and wai.live.call: conversations and calls on live rooms #493

Closed
dcharlot wants to merge 0 commits from wai/messaging-calls into main
Owner

What this is

Messaging and calls built natively on WAI rooms: two registered records, wai.live.message
and wai.live.call, specified in wai/extensions/live-messaging.md, with a reference module
in wai-rs (feature live_messaging), a byte-stable corpus, an independent verifier, a room
service mode for each, and two pages beside the room page.

  • A conversation is an end-to-end encrypted room (confidentiality) whose authority signs a
    conversation statement (WMC1). Each member publishes its messages on a messages track of
    its own, [room, member, "messages"]: each message is one object, sealed under the room's
    MLS group and signed into the member's receipt chain exactly as a media track is. The
    plaintext of each object is a signed message record (WMG1) of one of five kinds: text, a
    reply in a thread, a reaction, an edit, a retraction; the last four name their target by its
    link hash. A retraction states; it removes nothing from verification (§6.4).
  • Membership is the room's lifecycle: the clock records who the authority admits and
    removes, proposes every Add and Remove, and signs an epoch statement (WME1, chained by
    digest) naming each epoch's roster once a commit lands. In a conversation any member that a
    commit does not remove may commit, the log ordering the commits (§7.2); joule-moq-mls
    gains that rule (CommitRule::AnyMember) beside the existing lowest-leaf one.
  • Acknowledgements (WMA1): signed, cumulative per author, delivered and read.
  • The history store keeps one log per conversation on disk (a journal replayed at start):
    lifecycle records, handshake messages, epoch statements, sealed messages with their receipts,
    acknowledgements. No plaintext and no key. It answers a post only once the entry is on
    stable storage, and serves each principal only what it is owed (§9.3): membership entries up
    to its removal, content entries only at positions whose epoch lists it; not_a_member
    otherwise.
  • A call is a room with a call descriptor (WCT1) signed by its authority. Ringing is an
    invitation (WCI1) signed by the caller and held in the callee's inbox at the room service;
    accept, decline, cancel and a missed call are signed answers (WCA1), the missed one signed
    by the room's clock at the deadline. A call between two principals and a call among many are
    the same mechanism; its media is the room's own audio and video tracks.

Every record verifies offline; §11 states the whole verification of a conversation and §12
its refusal table.

What runs, and how

Piece Where How it runs
Extension text wai/extensions/live-messaging.md registry (REGISTRY.md, registry/capabilities.json, vocab/v2.ttl from wai registry export), SPEC §5, CHANGELOG, a pointer from confidentiality §5.5
Reference wai/wai-rs/src/live_messaging.rs (+ corpus.rs, bin/wai_live_messaging_vectors.rs, tests/live_messaging.rs) cargo test --features live_messaging --test live_messaging; the corpus generator regenerates every file byte for byte from its seeds
Corpus wai/live-conformance/messaging/ conversations (accepted, sealed, refused at each step), removal and history owed, calls, record vectors; every reason §12 lists is the stated outcome of at least one vector
Second implementation wai/live-conformance/live_messaging_verify.py python3 -I, written from the extension's text, sharing no code with wai-rs; agrees on every vector, and drops each of its own checks in turn to show the corpus catches it
CI .github/workflows/wai-conformance.yml live_messaging added to WAI_FEATURES, the test compiled once with the others, and a step running the generator's verify and the Python verifier
Commit rule joule-moq-mls (model.rs, group.rs), joule-moq-web (anyMemberCommits, keyProofHttp) crate tests
Room service joule-moq-room: src/messaging.rs, src/msgstore.rs, src/call.rs; [messaging] and [call] in room.example.toml tests/messaging_room.rs, tests/call_room.rs
Pages joule-moq-web/web/room/messages.{html,js}, call.{html,js}; app.js takes a grant handed to it (roomTest.enter(role, given)) e2e/messaging.e2e.mjs through e2e/run.sh --only messaging,call
Verifier in the page wai-live-web feature live_messaging (Messages, callCheck, invitationRecord, answerRecord) the pages above; crate tests

Checks

Head 01f3aac11fa8e78381c7c15ad9304c0fa493aae6. Rust and Python on the Framework box (x86_64 Linux) through the build-host
snapshot of this head; the browser end-to-end tests on the M3 Ultra Mac Studio; text checks on
the dev machine (no builds there).

Check Host Result
wai-rs: cargo test --locked --no-default-features --features "$WAI_FEATURES" --test live_messaging (CI's feature set) Framework 3 passed
wai-rs: --lib codecs::registry with CI's features Framework 15 passed
wai-rs: --features live_messaging --lib (the feature alone) Framework 613 passed
wai_live_messaging_vectors verify ../live-conformance/messaging Framework every file regenerates byte for byte from its seeds; every case gets its stated outcome
wai registry export --check Framework clean
python3 -I live-conformance/live_messaging_verify.py live-conformance/messaging Framework PASS, and its mutation self-test catches every dropped check
every other live-conformance/*_verify.py on its corpus Framework all PASS (dred_verify.py skipped: needs the draft's weights file; bearer_verify.py has no corpus row in the README)
wai-live-web: cargo test --locked --lib Framework 8 passed
joule-moq-mls: cargo test --locked -p joule-moq-mls Framework 15 + 4 passed
joule-moq-web: cargo test --locked -p joule-moq-web --features e2ee Framework 11 passed
joule-code-collab (depends on joule-moq-mls): cargo check --locked --all-targets Framework builds
joule-moq-room: cargo test --locked --all-targets (incl. messaging_room, call_room) Framework every target passes
clippy --all-targets: wai-rs (live_messaging), wai-live-web, joule-moq-mls + joule-moq-web (e2ee), joule-moq-room Framework no note in a file this PR touches (the notes left are in joule-moq and joule-moq-room/src/epoch.rs, unchanged here and the same on main)
cargo metadata --locked --offline for every touched lockfile (wai-rs, wai-live-web, joule-code-rs, joule-moq-room) Framework ok
browser e2e: e2e/run.sh --only messaging,call,service,e2ee (host Chrome, fake camera and microphone) Mac Studio messaging and call: 17 of 17 checks ok; the room scenarios beside them (service, e2ee, on the changed app.js): 74 of 74 ok
ruby YAML parse of .github/workflows/*.yml dev all parse
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 dev all clean
check-public-names.sh over every changed file, the commit messages and this text dev clean

What the room-service tests cover, against the brief: three members key through the log and
open each other's messages; one member is offline while the others thread, reply and react,
the service stops and starts again from its store, and the member catches up through both
epochs; edits and retractions verify (a retraction stated, its target kept); a removed member
reads nothing written after its removal, is refused not_a_member, and a message it sealed
before its removal and posted after is refused by the store (not_a_member) and by a verifier
(sender_not_member); a 1:1 call rings, is accepted, and carries audio and video through the
relay under the call's grants; in a call among three, one invitee declines and the other's
invitation is recorded missed at its deadline, signed by the clock; every record read back
verifies offline with wai-rs. The store's files are checked to hold
no plaintext.

Falsifications

Committed first (head 01f3aac11), then on the Framework box, through the build-host snapshot:
each guard broken alone by an edit whose anchor matched exactly once, the guarding tests run,
the file restored with git checkout -- <file>, and the same tests run again.

Guard broken File Mutated Restored
1a. accept a message from a removed member: drop check_post's roster check (sender_not_member) wai-rs/src/live_messaging.rs --test live_messaging: both corpus tests fail (exit 101); messaging_room fails at "a verifier refuses a removed member's message" (exit 101) 3 of 3 and 2 of 2 pass
1b. accept a message from a removed member: drop the store's admission check on a post joule-moq-room/src/messaging.rs messaging_room fails: the held-back post is not refused not_a_member (exit 101) 2 of 2 pass
2a. serve history to a non-member: drop owed's not_a_member wai-rs/src/live_messaging.rs both corpus tests fail (exit 101) 3 of 3 pass
2b. serve history to a non-member: the store's log serves every position when nothing is owed joule-moq-room/src/messaging.rs messaging_room fails at "bob reads what he is owed up to his removal, then nothing: not_a_member" (exit 101) 2 of 2 pass
3. skip an invitation's signature wai-rs/src/live_messaging.rs both corpus tests fail; call_room fails: the service takes a mis-signed invitation ({"ok":true,"rung":1}) (exit 101 each) 3 of 3 and 1 of 1 pass
4. let an edit change another author's message wai-rs/src/live_messaging.rs both corpus tests fail (exit 101) 3 of 3 pass
5. let a retraction remove its target from verification (the message dropped from the view) instead of stating it retracted wai-rs/src/live_messaging.rs both corpus tests fail; messaging_room fails (exit 101 each) 3 of 3 and 2 of 2 pass

The independent verifier, which shares no code with the mutated module, passes on the committed
corpus throughout; its own mutation self-test drops each of its checks in turn and shows the
corpus catches every one. The snapshot's tree was clean after the run.

Relation to the open live-room PRs

This branch is off main and carries no commit of #482 or #489. A trial merge of each into this
head (git merge-tree) conflicts in the lines both sides add to the same lists: the
CHANGELOG's top, the room service's module list and Cargo.toml features, e2e/run.sh's
scenario split, the workflow comments and path filters, and (with #489) app.js's entry
point. Each is a keep-both resolution; after it, wai registry export and the lockfiles are
regenerated and checked. The merge train for those PRs was not on the forge when this was
opened, so it is not merged here.

Not done

  • The messages tracks are carried by the room service, not by a relay: a member posts each
    sealed message to the service's store over HTTP and reads the log there. The track naming,
    the objects and the receipts are the relay's (§4), so a relay could carry them unchanged, but
    no page publishes them on a relay yet.
  • Retention (§9.4) is specified, not enforced: the store keeps everything.
  • Inboxes are in memory: a service restart loses ringing calls (the conversation's log is the
    durable part).
  • A page's MLS state lives in its memory: a member that closes the page and opens it again is a
    new member (§7.5 says what a device would need to keep).
  • One conversation per service, and one call at a time per service.
  • A removed member is not admitted again under the same key.
  • Grants are good for up to fourteen days and renewed by joining again.
  • If the journal write fails after the in-memory log changed, the service needs a restart to
    return to what is on disk.

Decisions for the owner

  1. Any member commits, in a conversation (§7.2). Confidentiality §5.5's lowest-leaf rule
    would hold every change back while the lowest member is offline, and a conversation has no
    presence leave to heal it. This PR keeps lowest-leaf for live rooms and uses any-member
    for conversations; the log makes two commits for one epoch impossible to apply.
  2. Acknowledgements are in the clear in the store (signed, not sealed): the store checks
    them, and they carry only positions. Sealing them would hide read state from the store at
    the cost of the store's checks.
  3. Browser member persistence: whether a page should keep its group state (and its key)
    across reloads, and where.
  4. Service-carried or relay-carried messages: whether the next step publishes the messages
    tracks through a relay, with the store as a subscriber.

🤖 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 Messaging and calls built natively on WAI rooms: two registered records, `wai.live.message` and `wai.live.call`, specified in `wai/extensions/live-messaging.md`, with a reference module in `wai-rs` (feature `live_messaging`), a byte-stable corpus, an independent verifier, a room service mode for each, and two pages beside the room page. - **A conversation** is an end-to-end encrypted room (confidentiality) whose authority signs a conversation statement (`WMC1`). Each member publishes its messages on a messages track of its own, `[room, member, "messages"]`: each message is one object, sealed under the room's MLS group and signed into the member's receipt chain exactly as a media track is. The plaintext of each object is a signed message record (`WMG1`) of one of five kinds: text, a reply in a thread, a reaction, an edit, a retraction; the last four name their target by its link hash. A retraction states; it removes nothing from verification (§6.4). - **Membership** is the room's lifecycle: the clock records who the authority admits and removes, proposes every Add and Remove, and signs an epoch statement (`WME1`, chained by digest) naming each epoch's roster once a commit lands. In a conversation any member that a commit does not remove may commit, the log ordering the commits (§7.2); `joule-moq-mls` gains that rule (`CommitRule::AnyMember`) beside the existing lowest-leaf one. - **Acknowledgements** (`WMA1`): signed, cumulative per author, delivered and read. - **The history store** keeps one log per conversation on disk (a journal replayed at start): lifecycle records, handshake messages, epoch statements, sealed messages with their receipts, acknowledgements. No plaintext and no key. It answers a post only once the entry is on stable storage, and serves each principal only what it is owed (§9.3): membership entries up to its removal, content entries only at positions whose epoch lists it; `not_a_member` otherwise. - **A call** is a room with a call descriptor (`WCT1`) signed by its authority. Ringing is an invitation (`WCI1`) signed by the caller and held in the callee's inbox at the room service; accept, decline, cancel and a missed call are signed answers (`WCA1`), the missed one signed by the room's clock at the deadline. A call between two principals and a call among many are the same mechanism; its media is the room's own audio and video tracks. Every record verifies offline; §11 states the whole verification of a conversation and §12 its refusal table. ## What runs, and how | Piece | Where | How it runs | |---|---|---| | Extension text | `wai/extensions/live-messaging.md` | registry (`REGISTRY.md`, `registry/capabilities.json`, `vocab/v2.ttl` from `wai registry export`), SPEC §5, CHANGELOG, a pointer from confidentiality §5.5 | | Reference | `wai/wai-rs/src/live_messaging.rs` (+ `corpus.rs`, `bin/wai_live_messaging_vectors.rs`, `tests/live_messaging.rs`) | `cargo test --features live_messaging --test live_messaging`; the corpus generator regenerates every file byte for byte from its seeds | | Corpus | `wai/live-conformance/messaging/` | conversations (accepted, sealed, refused at each step), removal and history owed, calls, record vectors; every reason §12 lists is the stated outcome of at least one vector | | Second implementation | `wai/live-conformance/live_messaging_verify.py` | `python3 -I`, written from the extension's text, sharing no code with `wai-rs`; agrees on every vector, and drops each of its own checks in turn to show the corpus catches it | | CI | `.github/workflows/wai-conformance.yml` | `live_messaging` added to `WAI_FEATURES`, the test compiled once with the others, and a step running the generator's `verify` and the Python verifier | | Commit rule | `joule-moq-mls` (`model.rs`, `group.rs`), `joule-moq-web` (`anyMemberCommits`, `keyProofHttp`) | crate tests | | Room service | `joule-moq-room`: `src/messaging.rs`, `src/msgstore.rs`, `src/call.rs`; `[messaging]` and `[call]` in `room.example.toml` | `tests/messaging_room.rs`, `tests/call_room.rs` | | Pages | `joule-moq-web/web/room/messages.{html,js}`, `call.{html,js}`; `app.js` takes a grant handed to it (`roomTest.enter(role, given)`) | `e2e/messaging.e2e.mjs` through `e2e/run.sh --only messaging,call` | | Verifier in the page | `wai-live-web` feature `live_messaging` (`Messages`, `callCheck`, `invitationRecord`, `answerRecord`) | the pages above; crate tests | ## Checks Head `01f3aac11fa8e78381c7c15ad9304c0fa493aae6`. Rust and Python on the Framework box (x86_64 Linux) through the build-host snapshot of this head; the browser end-to-end tests on the M3 Ultra Mac Studio; text checks on the dev machine (no builds there). | Check | Host | Result | |---|---|---| | `wai-rs`: `cargo test --locked --no-default-features --features "$WAI_FEATURES" --test live_messaging` (CI's feature set) | Framework | 3 passed | | `wai-rs`: `--lib codecs::registry` with CI's features | Framework | 15 passed | | `wai-rs`: `--features live_messaging --lib` (the feature alone) | Framework | 613 passed | | `wai_live_messaging_vectors verify ../live-conformance/messaging` | Framework | every file regenerates byte for byte from its seeds; every case gets its stated outcome | | `wai registry export --check` | Framework | clean | | `python3 -I live-conformance/live_messaging_verify.py live-conformance/messaging` | Framework | PASS, and its mutation self-test catches every dropped check | | every other `live-conformance/*_verify.py` on its corpus | Framework | all PASS (`dred_verify.py` skipped: needs the draft's weights file; `bearer_verify.py` has no corpus row in the README) | | `wai-live-web`: `cargo test --locked --lib` | Framework | 8 passed | | `joule-moq-mls`: `cargo test --locked -p joule-moq-mls` | Framework | 15 + 4 passed | | `joule-moq-web`: `cargo test --locked -p joule-moq-web --features e2ee` | Framework | 11 passed | | `joule-code-collab` (depends on `joule-moq-mls`): `cargo check --locked --all-targets` | Framework | builds | | `joule-moq-room`: `cargo test --locked --all-targets` (incl. `messaging_room`, `call_room`) | Framework | every target passes | | clippy `--all-targets`: `wai-rs` (`live_messaging`), `wai-live-web`, `joule-moq-mls` + `joule-moq-web` (`e2ee`), `joule-moq-room` | Framework | no note in a file this PR touches (the notes left are in `joule-moq` and `joule-moq-room/src/epoch.rs`, unchanged here and the same on main) | | `cargo metadata --locked --offline` for every touched lockfile (`wai-rs`, `wai-live-web`, `joule-code-rs`, `joule-moq-room`) | Framework | ok | | browser e2e: `e2e/run.sh --only messaging,call,service,e2ee` (host Chrome, fake camera and microphone) | Mac Studio | messaging and call: 17 of 17 checks ok; the room scenarios beside them (`service`, `e2ee`, on the changed `app.js`): 74 of 74 ok | | `ruby` YAML parse of `.github/workflows/*.yml` | dev | all parse | | `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` | dev | all clean | | `check-public-names.sh` over every changed file, the commit messages and this text | dev | clean | What the room-service tests cover, against the brief: three members key through the log and open each other's messages; one member is offline while the others thread, reply and react, the service stops and starts again from its store, and the member catches up through both epochs; edits and retractions verify (a retraction stated, its target kept); a removed member reads nothing written after its removal, is refused `not_a_member`, and a message it sealed before its removal and posted after is refused by the store (`not_a_member`) and by a verifier (`sender_not_member`); a 1:1 call rings, is accepted, and carries audio and video through the relay under the call's grants; in a call among three, one invitee declines and the other's invitation is recorded missed at its deadline, signed by the clock; every record read back verifies offline with `wai-rs`. The store's files are checked to hold no plaintext. ## Falsifications Committed first (head `01f3aac11`), then on the Framework box, through the build-host snapshot: each guard broken alone by an edit whose anchor matched exactly once, the guarding tests run, the file restored with `git checkout -- <file>`, and the same tests run again. | Guard broken | File | Mutated | Restored | |---|---|---|---| | 1a. accept a message from a removed member: drop `check_post`'s roster check (`sender_not_member`) | `wai-rs/src/live_messaging.rs` | `--test live_messaging`: both corpus tests fail (exit 101); `messaging_room` fails at "a verifier refuses a removed member's message" (exit 101) | 3 of 3 and 2 of 2 pass | | 1b. accept a message from a removed member: drop the store's admission check on a post | `joule-moq-room/src/messaging.rs` | `messaging_room` fails: the held-back post is not refused `not_a_member` (exit 101) | 2 of 2 pass | | 2a. serve history to a non-member: drop `owed`'s `not_a_member` | `wai-rs/src/live_messaging.rs` | both corpus tests fail (exit 101) | 3 of 3 pass | | 2b. serve history to a non-member: the store's log serves every position when nothing is owed | `joule-moq-room/src/messaging.rs` | `messaging_room` fails at "bob reads what he is owed up to his removal, then nothing: not_a_member" (exit 101) | 2 of 2 pass | | 3. skip an invitation's signature | `wai-rs/src/live_messaging.rs` | both corpus tests fail; `call_room` fails: the service takes a mis-signed invitation (`{"ok":true,"rung":1}`) (exit 101 each) | 3 of 3 and 1 of 1 pass | | 4. let an edit change another author's message | `wai-rs/src/live_messaging.rs` | both corpus tests fail (exit 101) | 3 of 3 pass | | 5. let a retraction remove its target from verification (the message dropped from the view) instead of stating it retracted | `wai-rs/src/live_messaging.rs` | both corpus tests fail; `messaging_room` fails (exit 101 each) | 3 of 3 and 2 of 2 pass | The independent verifier, which shares no code with the mutated module, passes on the committed corpus throughout; its own mutation self-test drops each of its checks in turn and shows the corpus catches every one. The snapshot's tree was clean after the run. ## Relation to the open live-room PRs This branch is off main and carries no commit of #482 or #489. A trial merge of each into this head (`git merge-tree`) conflicts in the lines both sides add to the same lists: the CHANGELOG's top, the room service's module list and `Cargo.toml` features, `e2e/run.sh`'s scenario split, the workflow comments and path filters, and (with #489) `app.js`'s entry point. Each is a keep-both resolution; after it, `wai registry export` and the lockfiles are regenerated and checked. The merge train for those PRs was not on the forge when this was opened, so it is not merged here. ## Not done - The messages tracks are carried by the room service, not by a relay: a member posts each sealed message to the service's store over HTTP and reads the log there. The track naming, the objects and the receipts are the relay's (§4), so a relay could carry them unchanged, but no page publishes them on a relay yet. - Retention (§9.4) is specified, not enforced: the store keeps everything. - Inboxes are in memory: a service restart loses ringing calls (the conversation's log is the durable part). - A page's MLS state lives in its memory: a member that closes the page and opens it again is a new member (§7.5 says what a device would need to keep). - One conversation per service, and one call at a time per service. - A removed member is not admitted again under the same key. - Grants are good for up to fourteen days and renewed by joining again. - If the journal write fails after the in-memory log changed, the service needs a restart to return to what is on disk. ## Decisions for the owner 1. **Any member commits, in a conversation** (§7.2). Confidentiality §5.5's lowest-leaf rule would hold every change back while the lowest member is offline, and a conversation has no presence `leave` to heal it. This PR keeps lowest-leaf for live rooms and uses any-member for conversations; the log makes two commits for one epoch impossible to apply. 2. **Acknowledgements are in the clear** in the store (signed, not sealed): the store checks them, and they carry only positions. Sealing them would hide read state from the store at the cost of the store's checks. 3. **Browser member persistence**: whether a page should keep its group state (and its key) across reloads, and where. 4. **Service-carried or relay-carried messages**: whether the next step publishes the messages tracks through a relay, with the store as a subscriber. 🤖 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
extensions/live-messaging.md: a conversation is an end-to-end encrypted room
with a conversation statement (WMC1); each member's messages track carries
sealed message records (WMG1: text, reply in a thread, reaction, edit,
retraction, each target named by its link hash) signed into the member's
receipt chain; the clock's epoch statements (WME1) name each epoch's roster;
acknowledgements (WMA1); a history store's contract; calls (WCT1, WCI1, WCA1).

wai-rs feature live_messaging: every record, sealing and opening per
confidentiality §4, the conversation verifier a store uses for its checks,
what a principal is owed, the call verifier, and the corpus generator
(live-conformance/messaging/vectors.json).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
live_messaging_verify.py reads descriptors with live_rooms_verify.py, Key IDs,
keys, AES-GCM and plaintexts with e2ee_verify.py, and implements the rest:
every record, the receipts-track object of jwp-receipts' binary form, a
conversation entry by entry, what a principal is owed, and calls. It agrees
with wai-rs on every vector, fails every mutated copy of the corpus, and
catches each of its own checks dropped. The corpus gains receipt-level and
plaintext-level controls, a conversation under AES_256_GCM_SHA512_128, and
history requests that state whether the requester is admitted (§9.3).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
CommitRule::AnyMember (WAI live-messaging §7.2) beside the room's lowest-leaf
rule (confidentiality §5.5, the default): RoomMember and Clock check commits by
the rule their model holds, and a page's E2eeMember opts in with
anyMemberCommits(). A model test holds both rules.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
[messaging]: the service keeps one conversation, an end-to-end encrypted room,
in a history store on disk (conversation.json and an append-only journal, each
append on stable storage before the answer, a torn tail dropped). Members join
by a proof of their key, key through the service's log with any member
committing, post sealed messages and acknowledgements that wai-rs's
Conversation checks before they are taken, and read the log as live-messaging
§9.3 owes it. A restart replays the journal and checks every regenerated
proposal and epoch statement against it.

[call]: a call descriptor the authority signs, invitations the caller signs held
in each callee's inbox, answers checked by wai-rs's Call, the clock's missed
call at each deadline, and grants for the caller and each callee that accepts.

tests/messaging_room.rs and tests/call_room.rs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
web/room/messages.html: a member of a conversation in a page. It joins with a
proof of its own key, keys through the service's log with joule_moq_web_e2ee's
member (any member commits), seals each message before it is signed into its
receipt chain and posted, opens and verifies every message (wai_live_web's
Messages, live-messaging §11), shows threads, reactions, edits and
retractions, and acknowledges what it read.

web/room/call.html: a page's inbox, each invitation checked with its call
before it rings (callCheck); placing a call, ringing, accepting, declining and
cancelling; the call's media through the room page in a frame, which now takes
a grant handed to it (enter(role, { seed, answer })).

wai-live-web: the messaging records, receipts, acknowledgements, invitations
and answers a page signs, and Messages, verified against the corpus in its
tests. joule-moq-web: keyProofHttp, a proof naming no grant.

e2e/messaging.e2e.mjs (run by e2e/run.sh): the messaging scenario and the call
scenario.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai.live.message and wai.live.call registered as records, their seven magics as
wire identifiers, and the export regenerated. SPEC §5 says what each is;
confidentiality §5.5 names the conversation's commit rule. wai-conformance runs
tests/live_messaging.rs and live_messaging_verify.py; joule-moq-web's job
requires the messaging and call scenarios to pass. joule-moq-room's README and
example configuration describe [messaging] and [call].

Co-Authored-By: Claude Opus 5.5 <[email protected]>
live messaging: regenerate the corpus, a removed member's held-back message
Some checks failed
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
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 / each feature of the independent verifiers' steps compiles alone (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
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
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
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
01f3aac11f
The corpus is regenerated from its seeds since history entries name whether
the principal was admitted. The room test now has a removed member post a
message it sealed before its removal: the service refuses it (not_a_member)
and a verifier refuses it (sender_not_member). The crate README names the
messages and call pages and their e2e scenarios. Clippy notes in the slice's
files are resolved.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot closed this pull request 2026-10-26 20:59:49 -04:00
Some checks failed
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 4s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 8s
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
wai-quantum studio and desktop / does this change touch it (pull_request) Has been cancelled
wai-quantum studio and desktop / studio · browser (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
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 / each feature of the independent verifiers' steps compiles alone (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
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
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
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (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!493
No description provided.