Files
suaveplan/openspec/archive/2026-05-12-drive-transport-webrtc-port/proposal.md
2026-05-27 23:29:53 +01:00

2.3 KiB

OpenSpec Change: drive-transport-webrtc-port

  • Change ID: drive-transport-webrtc-port
  • Package: @suaveplan/drive-transport-webrtc (new)
  • Status: PROPOSED
  • Date: 2026-04-28

Summary

WebRTC datachannel implementation of the DriveTransport interface for browser-to-browser chunk transfer. Wraps RTCPeerConnection + RTCDataChannel, frames chunks for transmission, handles backpressure via bufferedAmount watermark, and integrates with a signalling channel (typically WebSocket via @suaveplan/network-websockets once ported, or any caller-supplied signaller).

API surface

const transport = webrtcTransport({
    signaller: SignallerClient,        // injectable
    iceServers: RTCIceServer[],
    dataChannel: { ordered: true, maxRetransmits: 0 },  // configurable
});
// Implements DriveTransport
transport.requestChunk(peerId, fileId, chunkId): AsyncIterable<Uint8Array>;
transport.advertise(peerId, fileId, bitset);
transport.onAdvertisement(handler);
transport.peers(): Iterable<PeerInfo>;

Wire framing

Each datachannel message is a length-prefixed frame:

[4 B uint32 BE  frameLen]
[1 B uint8     frameType]   // 0x01 chunk-request, 0x02 chunk-response, 0x03 advertisement
[frameLen-1 B  payload]
  • Chunk request: fileId(32) ‖ chunkId(4).
  • Chunk response: raw 164+payloadLen byte chunk.
  • Advertisement: fileId(32) ‖ gzipped-bitset.

Datachannel messages may be fragmented by the WebRTC stack; receiver buffers until frameLen bytes are accumulated.

Backpressure

  • High-water mark: bufferedAmount > 16 MiB → pause sends, await bufferedamountlow event.
  • Low-water mark: bufferedAmount < 4 MiB → resume.
  • Configurable via transport.bufferThresholds.

Dependencies

  • Consumes: @suaveplan/drive-mesh (interface), @suaveplan/error, @suaveplan/types, @suaveplan/streams, @opentelemetry/api, zod.
  • Blocked on: drive-mesh-port. Will integrate with @suaveplan/network-webrtc once that is ported (provides RTCPeerConnection lifecycle helpers).

Out of scope

  • Signalling protocol details — caller supplies the SignallerClient.
  • TURN credential rotation — handled by iceServers provider.
  • DataChannel encryption beyond DTLS — chunk payload is already AEAD+sig-protected by the chunks plugin.