95 lines
5.6 KiB
Markdown
95 lines
5.6 KiB
Markdown
# OpenSpec Change: network-bootstrap
|
||
|
||
- **Change ID**: network-bootstrap
|
||
- **Package**: `@suaveplan/network-bootstrap`
|
||
- **Category**: universal
|
||
- **Target path**: `packages/network/network-bootstrap`
|
||
- **Status**: PROPOSED
|
||
- **Date**: 2026-05-11
|
||
- **Parent**: `network-transport-family` (2026-05-11) — Wave 1
|
||
- **Migration source**: `../suaveplan/packages/universal/network-bootstrap` + `../suaveplan/enterprise/network-bootstrap.md`
|
||
|
||
---
|
||
|
||
## Summary
|
||
|
||
Migrate `@suaveplan/network-bootstrap` into genesis as a universal-tier plugin providing initial-peer discovery and bootstrap orchestration for the `@suaveplan/network` mesh. Upstream ships at 99.15% coverage with a working `BootstrapPlugin`, discovery-chain, peer cache, and bootstrap middleware. This migration ports the full surface, hardens it against genesis primitives (`@suaveplan/retry`, `@suaveplan/events`, `@suaveplan/types`, OTel), and converts upstream `export *` barrels to explicit named exports per AGENTS.md §6a.
|
||
|
||
`network-bootstrap` is Wave 1 of the network migration sequence because every concrete transport in Waves 3–4 (`hyperswarm`, `libp2p`, `gundb`, …) consumes a bootstrap chain to find initial peers. Landing it first unblocks every downstream transport.
|
||
|
||
---
|
||
|
||
## Why this is needed
|
||
|
||
`@suaveplan/network` ✅ defines `NetworkPlugin` lifecycle and `NetworkBus` but does NOT define how a freshly-started node finds its first peers. Today every transport would have to roll its own initial-peer logic — duplicated code and inconsistent retry/cache semantics. `network-bootstrap` is the canonical place: pluggable discovery chain, exponential-backoff retries, persistent peer cache, deterministic peer selection.
|
||
|
||
---
|
||
|
||
## Current-state audit
|
||
|
||
Upstream surface (`../suaveplan/packages/universal/network-bootstrap/src/`):
|
||
|
||
- `core/discovery-chain/` — ordered chain of `DiscoveryStrategy` implementations, first-match-wins with fallthrough
|
||
- `core/peer-cache/` — persistent cache of known-good peer endpoints (TTL + eviction)
|
||
- `plugin/bootstrap-plugin/` — `NetworkPlugin` wrapper that wires the discovery chain into node startup
|
||
- `plugin/bootstrap-middleware/` — middleware hook for runtime augmentation of the chain
|
||
- `types/bootstrap.types.ts` — `DiscoveryStrategy`, `BootstrapResult`, `PeerCacheEntry`, options
|
||
|
||
Upstream coverage: 99.15% statement, no E2E. Upstream depends on its own ad-hoc retry/event utilities that genesis already replaces.
|
||
|
||
---
|
||
|
||
## Parity Checklist
|
||
|
||
| Capability | Upstream | Migrated | Notes |
|
||
|---|---|---|---|
|
||
| `DiscoveryStrategy` interface | ✅ | ✅ | Re-exported from `@suaveplan/types` if shared, else local. |
|
||
| `DiscoveryChain` ordered execution | ✅ | ✅ | First-success-wins, configurable fallthrough on error vs. empty result. |
|
||
| `PeerCache` with TTL + eviction | ✅ | ✅ | Backed by `@suaveplan/storage` `AbstractStorage` (universal); upstream's bespoke cache replaced. |
|
||
| `BootstrapPlugin` (NetworkPlugin lifecycle) | ✅ | ✅ | `install`/`start`/`stop`/`dispose` per `@suaveplan/network`'s contract. |
|
||
| Bootstrap middleware hook | ✅ | ✅ | Runtime augmentation of chain order/contents. |
|
||
| Retry with backoff | ✅ (ad-hoc) | ⬆️ | Replaced with `@suaveplan/retry` `RetryPolicy` + jitter. |
|
||
| Bus events on join/fail | ✅ (ad-hoc) | ⬆️ | Replaced with `@suaveplan/events` `NetworkBus` topics (`bootstrap:started`, `:peer-found`, `:exhausted`). |
|
||
| Structured errors | 🚫 (plain Error) | ⬆️ | `defineCodes("NET_BOOTSTRAP", [...])` per AGENTS.md. Codes: `CHAIN_EXHAUSTED`, `CACHE_CORRUPTED`, `STRATEGY_TIMEOUT`, `INVALID_OPTIONS`. |
|
||
| Zod boundary validation | 🚫 | ⬆️ | Every public option struct gets a Zod schema. |
|
||
| OTel instrumentation | 🚫 | ⬆️ | Spans (`bootstrap.chain.execute`), counters (`bootstrap.peers_found_total{strategy}`, `bootstrap.failures_total{strategy,code}`), histograms (`bootstrap.chain_duration_ms`). |
|
||
| AbortSignal support | 🚫 | ⬆️ | Threaded through every async path. |
|
||
| `export *` barrels | ✅ (some) | ⬆️ | Converted to explicit named exports per AGENTS.md §6a. |
|
||
| Test-runner imports | direct vitest | ⬆️ | Rewritten to `@suaveplan/testing/runner` per AGENTS.md §7. |
|
||
| 100% test coverage | 🚫 (99.15%) | ⬆️ | Bring to 100/100/100/100 per CLAUDE.md gate. |
|
||
| Property tests | 🚫 | ⬆️ | fast-check property suite on chain ordering + cache eviction. |
|
||
| Storybook stories | 🚫 (no UI) | 🚫 | Not applicable — universal-tier, no UI surface. |
|
||
|
||
No upstream capability is dropped without uplift.
|
||
|
||
---
|
||
|
||
## Available workspace deps on genesis
|
||
|
||
- `@suaveplan/network` ✅ — `NetworkPlugin`, `NetworkBus`, `MessageEnvelope`
|
||
- `@suaveplan/types` ✅ — shared interfaces (`Clock`, `Rng`, etc.)
|
||
- `@suaveplan/error` ✅ — `defineCodes`, `SuaveplanError`
|
||
- `@suaveplan/events` ✅ — typed event bus
|
||
- `@suaveplan/retry` ✅ — backoff strategies + circuit breaker
|
||
- `@suaveplan/storage` ✅ — `AbstractStorage` for the peer cache backing
|
||
- `@suaveplan/testing` ✅ — runner-agnostic test utilities + runner wrapper
|
||
|
||
All deps present; no blocking gaps.
|
||
|
||
---
|
||
|
||
## Acceptance gate
|
||
|
||
1. `bunx turbo lint typecheck test --filter=@suaveplan/network-bootstrap` green.
|
||
2. `bunx turbo test:coverage --filter=@suaveplan/network-bootstrap` at 100/100/100/100.
|
||
3. `bun run docs:check --filter=@suaveplan/network-bootstrap` green (every `.ts` has a sibling `.md`).
|
||
4. `MANIFEST.md` regen confirms dep graph has no cycles.
|
||
5. `STATUS.md` row flipped from `–` to `✅`.
|
||
|
||
---
|
||
|
||
## Out of scope
|
||
|
||
- Concrete discovery strategies for individual transports — those ship with their owning `network-discovery-*` packages (Wave 2).
|
||
- Server-tier daemons — separate `network-*-server` packages (Wave 5).
|