5.5 KiB
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
function createBootstrapper(config: BootstrapConfig, options?: BootstrapOptions): Bootstrapper
interface Bootstrapper {
readonly state: BootstrapState
readonly peers: ReadonlyArray<BootstrapPeer>
bootstrap(signal?: AbortSignal): Promise<BootstrapResult>
abort(): void
on(event: BootstrapEvent, handler: (data: BootstrapEventData) => void): () => void
}
Configuration
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
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<BootstrapPeer>
readonly durationMs: number
readonly error?: NetworkBootstrapError
}
interface BootstrapEventData {
readonly state: BootstrapState
readonly peers?: ReadonlyArray<BootstrapPeer>
readonly seed?: SeedConfig
readonly error?: string
}
type BootstrapEvent = 'state-change' | 'peer-discovered' | 'peer-connected' | 'ready' | 'failed'
Error codes
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
- Structured
NetworkBootstrapErrorwith stableBOOTSTRAP.*codes - Zod schemas for
BootstrapConfig,SeedConfig,BootstrapOptions - FSM-backed state machine via
@suaveplan/fsm— states: idle → discovering → connecting → negotiating → ready/failed - Retry on seed discovery via
@suaveplan/retrywith injectable config - Minimum peer threshold — resolves
bootstrap()promise only whenminPeersis reached - Injectable
ClockandIdGeneratorfor deterministic tests - OTel instrumentation — span
bootstrap.run, child spans per seed, histogrambootstrap.duration_ms, counterbootstrap.peers_connected_total - Property-based tests — state machine transitions always reach a terminal state; min-peers invariant
File layout
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.