# OpenSpec Change: enterprise-network-testing - **Change ID**: enterprise-network-testing - **Package**: `@suaveplan/network-testing` - **Category**: universal/network - **Target path**: `universal/network/network-testing` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/network-testing.md` --- ## Summary Deliver `@suaveplan/network-testing` on the genesis branch from scratch at enterprise quality. The package provides network testing utilities: in-memory transport implementations, fake WebSocket adapters, network condition simulators (latency, jitter, packet loss, bandwidth), test peer factories, clock-controlled timing helpers for network scenarios, and assertion utilities for network events. Genesis adds structured errors via `@suaveplan/error`, Zod schemas for condition simulators, OTel integration for verifying instrumentation in tests, and a comprehensive test harness API. --- ## Current-state audit (genesis) The package does not exist on genesis yet — this is a fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | Base class for `NetworkTestingError`; stable error codes | | `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock`, `EventBusLike` — all injectable | | `@suaveplan/events` (`workspace:^`) | Real `EventBus` for test event capture | | `@suaveplan/testing` (`workspace:^`) | `FakeClock`, `MemoryStore`, testing helpers | | `zod` (`catalog:forms`) | Zod schemas for condition simulator config | | `@opentelemetry/api` (`catalog:observability`) | OTel no-op for instrumentation testing | | `tslib` (`catalog:build`) | Runtime helpers | Dev deps: `vitest`, `@vitest/coverage-istanbul` (all `catalog:testing`). --- ## Public API surface ### In-memory transport ```ts function createMemoryTransport(options?: MemoryTransportOptions): MemoryTransportPair interface MemoryTransportPair { readonly client: MemoryTransport readonly server: MemoryTransport connect(): void disconnect(): void } interface MemoryTransport { readonly id: string readonly state: TransportState send(message: unknown, signal?: AbortSignal): Promise connect(signal?: AbortSignal): Promise disconnect(): void on(event: string, handler: (data: unknown) => void): () => void messages: unknown[] // captured sent messages } ``` ### Fake WebSocket adapter ```ts function createFakeWebSocketAdapter(options?: FakeWebSocketOptions): FakeWebSocketAdapter interface FakeWebSocketAdapter { connect(url: string, protocols?: string[]): FakeWebSocketHandle simulateMessage(data: string | Uint8Array): void simulateError(error: Error): void simulateClose(code?: number, reason?: string): void readonly connections: ReadonlyArray<{ url: string; handle: FakeWebSocketHandle }> } interface FakeWebSocketHandle { readonly readyState: number readonly sentMessages: ReadonlyArray send(data: string | Uint8Array): void close(code?: number, reason?: string): void onopen: (() => void) | null onclose: ((code: number, reason: string) => void) | null onmessage: ((data: string | Uint8Array) => void) | null onerror: ((error: Error) => void) | null } ``` ### Network condition simulator ```ts function createConditionSimulator(conditions: NetworkConditions): ConditionSimulator interface NetworkConditions { latencyMs?: number | LatencyDistribution jitterMs?: number packetLossRate?: number // 0–1 bandwidthBps?: number disconnectAfterMs?: number } interface LatencyDistribution { min: number max: number distribution: 'uniform' | 'normal' | 'bimodal' } interface ConditionSimulator { wrap Promise }>(transport: T): T setConditions(conditions: Partial): void reset(): void readonly stats: SimulationStats } interface SimulationStats { readonly sentMessages: number readonly droppedMessages: number readonly totalLatencyMs: number readonly avgLatencyMs: number } ``` ### Test peer factory ```ts function createTestPeer(options?: TestPeerOptions): TestPeer interface TestPeer { readonly id: string readonly address: string readonly capabilities: string[] asRegistryEntry(): RegistryEntry asBootstrapSeed(): SeedConfig withCapabilities(capabilities: string[]): TestPeer withRegion(region: string): TestPeer withHealth(healthy: boolean, latencyMs?: number): TestPeer } interface TestPeerOptions { id?: string address?: string capabilities?: string[] region?: string clock?: Clock } ``` ### Network event assertions ```ts function createNetworkEventCapture(eventBus: EventBusLike): NetworkEventCapture interface NetworkEventCapture { events: unknown[] waitFor(event: string, timeout?: number): Promise assertEventEmitted(event: string, predicate?: (data: unknown) => boolean): void assertEventCount(event: string, count: number): void clear(): void } ``` ### Options and error codes ```ts interface MemoryTransportOptions { latencyMs?: number clock?: Clock } interface FakeWebSocketOptions { autoConnect?: boolean clock?: Clock } type NetworkTestingErrorCode = | 'NET_TEST_TIMEOUT' | 'NET_TEST_EVENT_NOT_EMITTED' | 'NET_TEST_CONNECT_FAILED' function registerNetworkTestingErrorCodes(): void ``` --- ## Genesis additions 1. **Structured `NetworkTestingError`** with stable `NET_TEST.*` codes 2. **Zod schemas** for `NetworkConditions`, `MemoryTransportOptions` 3. **`MemoryTransportPair`** — bidirectional in-process transport for unit tests 4. **`FakeWebSocketAdapter`** — injectable into `@suaveplan/network-websockets` clients 5. **`ConditionSimulator`** — wraps any transport and injects latency/jitter/packet-loss via injectable `Clock` and `Rng` 6. **`TestPeer` factory** — fluent builder compatible with `@suaveplan/network-registry` and `@suaveplan/network-bootstrap` 7. **`NetworkEventCapture`** — wraps an `EventBus` to capture and assert emitted events in tests --- ## File layout ```text universal/network/network-testing/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/ index.ts types/ common.ts common.md transports/ memory-transport/ memory-transport.ts memory-transport.md memory-transport.test.ts index.ts fake-websocket/ fake-websocket.ts fake-websocket.md fake-websocket.test.ts index.ts simulators/ condition-simulator/ condition-simulator.ts condition-simulator.md condition-simulator.test.ts index.ts factories/ test-peer/ test-peer.ts test-peer.md test-peer.test.ts index.ts assertions/ event-capture/ event-capture.ts event-capture.md event-capture.test.ts index.ts tests/ integration.test.ts ``` --- ## Impact **Workspace dep prerequisites**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/testing` must be published.