Files
2026-05-27 23:29:53 +01:00

6.8 KiB

OpenSpec Change: enterprise-browser-network-webrtc

  • Change ID: enterprise-browser-network-webrtc
  • Package: @suaveplan/network-webrtc
  • Category: browser
  • Target path: browser/network/network-webrtc
  • Status: SUPERSEDED-BY-GENESIS-WAVE
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/network-webrtc.md

Summary

Deliver @suaveplan/network-webrtc on the genesis branch from scratch at enterprise quality. The package provides the browser-side WebRTC transport for @suaveplan/network: a WebRTCTransport wrapping RTCPeerConnection + RTCDataChannel, a dual-channel system for reliable + unreliable messaging, a ChannelRouter dispatching by topic, and a first-class SignalingChannel interface with Memory / WebSocket / WebTorrent implementations. No React dependencies — demo UI moves to a React companion package.


Current-state audit (genesis)

The package does not exist on genesis yet — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/network (workspace:^) Transport interface, NetworkError, connection lifecycle types
@suaveplan/error (workspace:^) Typed WebRTC errors
@suaveplan/types (workspace:^) LoggerLike, EventBusLike
@suaveplan/events (workspace:^) EventEmitter for transport event maps
@suaveplan/serialize (workspace:^) Structured message encoding/decoding
@suaveplan/schema-registry (workspace:^) Register signalling Zod schemas
zod (catalog:forms) Schemas for signalling message types
@opentelemetry/api (catalog:observability) WebRTC metrics
tslib (catalog:build) Runtime helpers

Dev deps: vitest, @vitest/coverage-istanbul, @playwright/test (catalog:testing), @suaveplan/testing workspace:^.


Preserved public API surface (from main branch)

Core transport

class WebRTCTransport {
  constructor(config: WebRTCConfig)
  dial(signal: SignalingChannel): Promise<void>
  close(): void
  send(data: Uint8Array | string): void
  sendUnreliable(data: Uint8Array | string): void
  onMessage(handler: (data: Uint8Array | string) => void): void
  onClose(handler: () => void): void
  getStats(): Promise<RTCStatsReport>
  readonly state: RTCPeerConnectionState
}

interface WebRTCConfig {
  iceServers?: RTCIceServer[]
  ordered?: boolean
  maxRetransmits?: number
  allowedWorkletUrls?: string[]
}

Dual channel

class DualChannel {
  constructor(connection: RTCPeerConnection, config?: DualChannelConfig)
  sendReliable(data: Uint8Array | string): void
  sendUnreliable(data: Uint8Array | string): void
  onMessage(handler: (data: Uint8Array | string, reliable: boolean) => void): void
  close(): void
}

Channel router

class ChannelRouter {
  register(channelId: string, handler: ChannelHandler): void
  unregister(channelId: string): void
  route(message: ChannelMessage): void
  send(channelId: string, payload: unknown): void
}

interface ChannelMessage { channelId: string; payload: unknown; reliable?: boolean }
type ChannelHandler = (payload: unknown) => void

Signalling interface

interface SignalingChannel {
  sendOffer(offer: RTCSessionDescriptionInit): Promise<void>
  sendAnswer(answer: RTCSessionDescriptionInit): Promise<void>
  sendIceCandidate(candidate: RTCIceCandidateInit): Promise<void>
  onOffer(handler: (offer: RTCSessionDescriptionInit) => void): void
  onAnswer(handler: (answer: RTCSessionDescriptionInit) => void): void
  onIceCandidate(handler: (candidate: RTCIceCandidateInit) => void): void
  close(): void
}

class MemorySignalingChannel implements SignalingChannel { ... }
class WebSocketSignalingChannel implements SignalingChannel { constructor(url: string) }

New additions for genesis

1. Structured errors via @suaveplan/error

Error codes: WEBRTC_DIAL_FAILED, WEBRTC_ICE_FAILED, WEBRTC_CHANNEL_CLOSED, WEBRTC_SIGNALING_TIMEOUT, WEBRTC_INVALID_STATE.

2. Perfect-negotiation pattern

PeerConnection implements "polite peer" logic — avoids offer/answer glare on simultaneous negotiation.

3. ICE-restart policy

Detect iceConnectionState === 'failed'; auto-restart ICE; surface as typed event 'ice:restart'.

4. Flow control + back-pressure

DualChannel.sendReliable tracks RTCDataChannel.bufferedAmount; blocks or queues when buffer exceeds a configurable watermark.

5. OTel metrics

Counters webrtc.dial_total, webrtc.bytes_in_total, webrtc.bytes_out_total; histogram webrtc.ice_gather_ms, webrtc.rtt_ms.

6. Signalling message Zod schemas

Schemas for offer/answer/ICE-candidate messages registered in @suaveplan/schema-registry.

7. STUN/TURN configuration helpers

Curated iceServers bundles with validation helper; TURN_CONFIG constants for common providers.


File layout

browser/network/network-webrtc/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    webrtc/
      peer-connection/
        peer-connection.ts        (RTCPeerConnection wrapper + ICE restart + perfect negotiation)
        peer-connection.md
        peer-connection.test.ts
        index.ts
      data-channel/
        data-channel.ts
        data-channel.md
        data-channel.test.ts
        index.ts
      signaling-handlers/
        signaling-handlers.ts
        signaling-handlers.md
        signaling-handlers.test.ts
        index.ts
      webrtc-transport/
        webrtc-transport.ts
        webrtc-transport.md
        webrtc-transport.types.ts
        webrtc-transport.test.ts
        index.ts
    dual-channel/
      dual-channel/
        dual-channel.ts
        dual-channel.md
        dual-channel.test.ts
        index.ts
    channel-router/
      channel-router/
        channel-router.ts
        channel-router.md
        channel-router.test.ts
        index.ts
    signaling/
      signaling-channel/
        signaling-channel.ts      (interface + MemorySignalingChannel)
        signaling-channel.md
        signaling-channel.test.ts
        index.ts
      websocket-signaling/
        websocket-signaling.ts
        websocket-signaling.md
        websocket-signaling.test.ts
        index.ts
    config/
      ice-servers/
        ice-servers.ts
        ice-servers.md
        index.ts
  tests/
    integration.test.ts
  e2e/
    webrtc.spec.ts                (Playwright two-browser offer/answer/ICE/dial/send)
  examples/                       (NOT in package.json "files")
    basic-usage.ts
    memory-signaling.ts

Impact

Downstream: @suaveplan/drive-webrtc, @suaveplan/network-discovery-webtorrent, WebRTC-based game networking.

Breaking changes: react removed from runtime deps (demo moved to companion); examples moved out of published tarball.

Prerequisites: @suaveplan/network, @suaveplan/serialize, @suaveplan/error, @suaveplan/events on Verdaccio.