# 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 ```ts class WebRTCTransport { constructor(config: WebRTCConfig) dial(signal: SignalingChannel): Promise 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 readonly state: RTCPeerConnectionState } interface WebRTCConfig { iceServers?: RTCIceServer[] ordered?: boolean maxRetransmits?: number allowedWorkletUrls?: string[] } ``` ### Dual channel ```ts 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 ```ts 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 ```ts interface SignalingChannel { sendOffer(offer: RTCSessionDescriptionInit): Promise sendAnswer(answer: RTCSessionDescriptionInit): Promise sendIceCandidate(candidate: RTCIceCandidateInit): Promise 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 ```text 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.