The page makes its own Ed25519 key, asks the room service for a grant for it
(a publisher's or a viewer's) from its Join and Watch buttons, presents the
grant with a proof by that key over the WebSocket binding (WebTransport not
tried), and takes the lifecycle from the service's clock, reading the room's
grants again when someone joins under a grant it did not hold
(wai-live-web's Room.setGrants). Leave, a typed human caption, the session's
end, and a proof by another key (tryWrongKey) for the tests.
e2e: the service scenario runs the relay (WebSocket only, trusting the
service's authority, its door holding each publisher to its own key), the
room service and a same-origin proxy on loopback; with --base it runs against
a deployment.
Co-Authored-By: Claude Opus 5.5 <[email protected]>