Local Cap’n Web over WebRTC
Cursors can now carry the same ephemeral Cap’n Web capability session over an ordered, reliable RTCDataChannel. This is a custom transit underneath Cap’n Web—not a replacement protocol and not a change to signed Cursors records.
The default configuration deliberately has no STUN or TURN servers. It is useful immediately for same-device and LAN-reachable peers, and it cannot silently join a public network. Supplying traversal infrastructure is an explicit caller decision.
Immediate browser proof
Run an actual two-peer loopback in the cockpit console:
await globalThis.__cursorsAppRuntime.capnWebWebRtc.loopback()
The result comes through an RTCDataChannel and pipelines the peer description plus its fabric status without an intermediate await.
Two browsers with manual rendezvous
On the offering browser:
const offering = await globalThis.__cursorsAppRuntime.capnWebWebRtc.offer()
copy(offering.offer)
Pass that offer through a channel you already trust. On the answering browser:
const answering = await globalThis.__cursorsAppRuntime.capnWebWebRtc.answer(PASTE_OFFER)
copy(answering.answer)
Return the answer to the offering browser:
await offering.acceptAnswer(PASTE_ANSWER)
const peer = await offering.remote
await peer.describe()
An SDP offer or answer may contain network-address information. Treat it as short-lived rendezvous material and share it only with the intended peer. It is not a Cursors identity, grant, durable locator, or bearer capability.
What the server already provides
The existing opt-in CurveMailbox Durable Object already has the Bugout-like coordination pieces:
- short-lived opaque signaling rows in SQLite;
- admission and per-mailbox quotas;
- hibernatable WebSocket relay frames;
- retained envelopes and receipts;
- explicit remote kill/fail-closed behavior.
The next bridge can carry these same offer/answer values as encrypted signaling records. The server remains rendezvous/relay only: peers still verify signed identities and grants at effect boundaries.
Limits and failure behavior
- 64 KiB maximum Cap’n Web message before JSON parsing;
- 256 KiB data-channel buffered high-water mark;
- ordered, reliable channel label
cursors-capnweb-v1only; - Cap’n Web depth 32 and bigint digit limit 256;
- exported peer capability is read-only and reports only bounded fabric status;
- channel close breaks all live stubs and emits a visible transport event;
- no persistence of object tables, promises, callbacks, or stub IDs;
- CURSO/0 signed records remain canonical and byte-compatible;
- HTTP batch remains the universal browser fallback when WebRTC is absent.