# OpenSpec Change: enterprise-network-observability - **Change ID**: enterprise-network-observability - **Package**: `@suaveplan/network-observability` - **Category**: universal/network - **Target path**: `universal/network/network-observability` - **Status**: SUPERSEDED-BY-GENESIS-WAVE - **Date**: 2026-04-24 --- ## Summary Deliver `@suaveplan/network-observability` on the genesis branch from scratch at enterprise quality. The package provides network metrics collection and distributed tracing instrumentation: RTT measurements, bandwidth estimation, connection health scoring, packet loss tracking, span propagation across network hops, and structured event emission for network anomalies. Genesis adds structured errors via `@suaveplan/error`, Zod schemas for all metric types, deep OTel integration (this package is specifically about observability), `AbortSignal` on collection tasks, injectable `Clock` for measurement timestamps, and event-bus emission for threshold breaches. --- ## 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 `NetworkObservabilityError`; stable error codes | | `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock`, `EventBusLike` | | `@suaveplan/events` (`workspace:^`) | Event bus for threshold breach notifications | | `@suaveplan/logger` (`workspace:^`) | Structured logging | | `@suaveplan/timing` (`workspace:^`) | Stopwatch and throttle for measurement intervals | | `zod` (`catalog:forms`) | Zod schemas for all public metric types | | `@opentelemetry/api` (`catalog:observability`) | Deep OTel integration — this package enriches OTel spans | | `tslib` (`catalog:build`) | Runtime helpers | Dev deps: `vitest`, `@vitest/coverage-istanbul`, `fast-check` (all `catalog:testing`). --- ## Public API surface ### Core ```ts function createNetworkMonitor(options?: NetworkMonitorOptions): NetworkMonitor interface NetworkMonitor { start(signal?: AbortSignal): Promise stop(): void snapshot(): NetworkSnapshot history(limit?: number): ReadonlyArray on(event: NetworkEvent, handler: (data: NetworkSnapshot) => void): () => void } ``` ### Metric types ```ts interface NetworkSnapshot { readonly timestamp: number readonly rtt: RttMetrics readonly bandwidth: BandwidthMetrics readonly packetLoss: PacketLossMetrics readonly health: NetworkHealthScore } interface RttMetrics { readonly current: number readonly min: number readonly max: number readonly avg: number readonly p50: number readonly p95: number readonly p99: number readonly samples: number } interface BandwidthMetrics { readonly downloadBps: number readonly uploadBps?: number readonly estimatedAt: number } interface PacketLossMetrics { readonly rate: number // 0–1 readonly total: number readonly lost: number } interface NetworkHealthScore { readonly score: number // 0–100 readonly grade: 'excellent' | 'good' | 'fair' | 'poor' | 'critical' readonly factors: ReadonlyArray } interface HealthFactor { readonly name: string readonly weight: number readonly score: number readonly impact: 'positive' | 'negative' | 'neutral' } ``` ### Span propagation ```ts function injectTraceContext(headers: Record): Record function extractTraceContext(headers: Record): SpanContext | null function withNetworkSpan(name: string, fn: () => Promise, attributes?: NetworkSpanAttributes): Promise interface NetworkSpanAttributes { url?: string method?: string statusCode?: number requestSize?: number responseSize?: number } ``` ### Options ```ts interface NetworkMonitorOptions { measureIntervalMs?: number historySize?: number rttTargetUrl?: string thresholds?: NetworkThresholds logger?: LoggerLike clock?: Clock eventBus?: EventBusLike } interface NetworkThresholds { maxRttMs?: number minBandwidthBps?: number maxPacketLossRate?: number minHealthScore?: number } type NetworkEvent = 'snapshot' | 'threshold-breach' | 'recovery' ``` ### Error codes ```ts type NetworkObservabilityErrorCode = | 'NET_OBS_MEASUREMENT_FAILED' | 'NET_OBS_MONITOR_ALREADY_RUNNING' | 'NET_OBS_ABORT' function registerNetworkObservabilityErrorCodes(): void ``` --- ## Genesis additions 1. **Structured `NetworkObservabilityError`** with stable `NET_OBS.*` codes 2. **Zod schemas** for all metric types and options 3. **Health scoring algorithm** — weighted composite of RTT, packet loss, bandwidth; grades A–F 4. **W3C Trace Context propagation** helpers (`injectTraceContext`, `extractTraceContext`) 5. **Threshold alerting** — emits event-bus events when thresholds are breached or recovered 6. **Injectable `Clock`** for deterministic timestamp tests 7. **OTel deep integration** — this package is the entry point for network-layer OTel spans --- ## File layout ```text universal/network/network-observability/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/ index.ts types/ common.ts common.md core/ monitor/ monitor.ts monitor.md monitor.types.ts monitor.test.ts index.ts health/ health.ts health.md health.test.ts index.ts tracing/ propagation.ts propagation.md propagation.test.ts index.ts metrics/ rtt.ts rtt.md rtt.test.ts bandwidth.ts bandwidth.md bandwidth.test.ts tests/ integration.test.ts property.test.ts ``` --- ## Impact **Workspace dep prerequisites**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/logger`, `@suaveplan/timing` must be published.