# OpenSpec Change: enterprise-network-bootstrap - **Change ID**: enterprise-network-bootstrap - **Package**: `@suaveplan/network-bootstrap` - **Category**: universal/network - **Target path**: `universal/network/network-bootstrap` - **Status**: SUPERSEDED-BY-GENESIS-WAVE - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/network-bootstrap.md` --- ## Summary Deliver `@suaveplan/network-bootstrap` on the genesis branch from scratch at enterprise quality. The package provides network bootstrap and initialization: seed peer discovery, initial topology negotiation, connection establishment sequencing, bootstrap state machine, retry-with-backoff on seed failure, and a readiness signal when the minimum peer threshold is met. Genesis adds structured errors via `@suaveplan/error`, Zod schemas for all bootstrap configuration types, OTel instrumentation on every bootstrap phase, `AbortSignal` on the full bootstrap sequence, injectable `Clock` and `IdGenerator`, event-bus integration for phase transitions, and property-based tests for state machine invariants. --- ## 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 `NetworkBootstrapError`; stable error codes | | `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock`, `IdGenerator`, `EventBusLike` | | `@suaveplan/events` (`workspace:^`) | Event bus for bootstrap phase transitions | | `@suaveplan/logger` (`workspace:^`) | Structured logging | | `@suaveplan/retry` (`workspace:^`) | Retry with exponential backoff on seed discovery | | `@suaveplan/fsm` (`workspace:^`) | FSM for bootstrap state machine | | `zod` (`catalog:forms`) | Zod schemas | | `@opentelemetry/api` (`catalog:observability`) | Spans + counters on bootstrap phases | | `tslib` (`catalog:build`) | Runtime helpers | Dev deps: `vitest`, `@vitest/coverage-istanbul`, `fast-check` (all `catalog:testing`). --- ## Public API surface ### Core ```ts function createBootstrapper(config: BootstrapConfig, options?: BootstrapOptions): Bootstrapper interface Bootstrapper { readonly state: BootstrapState readonly peers: ReadonlyArray bootstrap(signal?: AbortSignal): Promise abort(): void on(event: BootstrapEvent, handler: (data: BootstrapEventData) => void): () => void } ``` ### Configuration ```ts interface BootstrapConfig { seeds: SeedConfig[] minPeers?: number maxPeers?: number topology?: TopologyHint timeout?: number } interface SeedConfig { id?: string address: string port: number priority?: number tags?: string[] } type TopologyHint = 'mesh' | 'star' | 'ring' | 'tree' interface BootstrapOptions { retry?: RetryOptions logger?: LoggerLike clock?: Clock idGenerator?: IdGenerator eventBus?: EventBusLike } ``` ### State types ```ts type BootstrapState = | 'idle' | 'discovering' | 'connecting' | 'negotiating' | 'ready' | 'failed' | 'aborted' interface BootstrapPeer { readonly id: string readonly address: string readonly port: number readonly connectedAt: number readonly latencyMs?: number readonly capabilities?: string[] } interface BootstrapResult { readonly success: boolean readonly peers: ReadonlyArray readonly durationMs: number readonly error?: NetworkBootstrapError } interface BootstrapEventData { readonly state: BootstrapState readonly peers?: ReadonlyArray readonly seed?: SeedConfig readonly error?: string } type BootstrapEvent = 'state-change' | 'peer-discovered' | 'peer-connected' | 'ready' | 'failed' ``` ### Error codes ```ts type NetworkBootstrapErrorCode = | 'BOOTSTRAP_NO_SEEDS' | 'BOOTSTRAP_SEED_UNREACHABLE' | 'BOOTSTRAP_TIMEOUT' | 'BOOTSTRAP_MIN_PEERS_NOT_MET' | 'BOOTSTRAP_NEGOTIATION_FAILED' | 'BOOTSTRAP_ABORT' function registerNetworkBootstrapErrorCodes(): void ``` --- ## Genesis additions 1. **Structured `NetworkBootstrapError`** with stable `BOOTSTRAP.*` codes 2. **Zod schemas** for `BootstrapConfig`, `SeedConfig`, `BootstrapOptions` 3. **FSM-backed state machine** via `@suaveplan/fsm` — states: idle → discovering → connecting → negotiating → ready/failed 4. **Retry on seed discovery** via `@suaveplan/retry` with injectable config 5. **Minimum peer threshold** — resolves `bootstrap()` promise only when `minPeers` is reached 6. **Injectable `Clock` and `IdGenerator`** for deterministic tests 7. **OTel instrumentation** — span `bootstrap.run`, child spans per seed, histogram `bootstrap.duration_ms`, counter `bootstrap.peers_connected_total` 8. **Property-based tests** — state machine transitions always reach a terminal state; min-peers invariant --- ## File layout ```text universal/network/network-bootstrap/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/ index.ts types/ common.ts common.md core/ bootstrapper/ bootstrapper.ts bootstrapper.md bootstrapper.types.ts bootstrapper.test.ts index.ts discovery/ discovery.ts discovery.md discovery.test.ts index.ts negotiation/ negotiation.ts negotiation.md negotiation.test.ts index.ts tests/ integration.test.ts property.test.ts ``` --- ## Impact **Workspace dep prerequisites**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/logger`, `@suaveplan/retry`, `@suaveplan/fsm` must be published.