6.6 KiB
OpenSpec Change: network-transport-libp2p
- Change ID: network-transport-libp2p
- Package:
@suaveplan/network-transport-libp2p - Category: universal (browser + server)
- Target path:
packages/network/network-transport-libp2p - Status: PROPOSED
- Date: 2026-05-11
- Parent:
network-transport-family(2026-05-11) — Wave 4 - Migration source:
../suaveplan/packages/browser/network-libp2p+../suaveplan/enterprise/network-libp2p.md - Supersedes: the original name reservation in this folder (2026-05-11)
Summary
Migrate @suaveplan/network-libp2p into genesis as @suaveplan/network-transport-libp2p — a universal-tier Transport over the libp2p stack (TCP, WebSockets, WebRTC, Noise, Yamux, identify, ping, mDNS, bootstrap, circuit-relay-v2). Largest single migration in the network family — the upstream package is the most complex transport with ≈1.1k LOC of source, 18+ external deps, and a 749-line React demo that must be extracted. Last in Wave 4 because every other transport landing first proves the patterns this migration consolidates.
Why this is last in Wave 4
- Surface size. 9 source files, 18+ libp2p subpackage deps, real test coverage gaps.
- Demo extraction. Upstream
libp2p-demo.tsxis 749 LOC of React, violating the 300-line cap and adding React runtime deps to a universal-tier package. - Dep-graph risk. libp2p brings transitive deps that may conflict with already-shipped packages. Landing it last surfaces conflicts after lighter Wave-4 work has stabilised the catalog.
Current-state audit
Upstream source layout (../suaveplan/packages/browser/network-libp2p/src/lib/):
| File | LOC | Notes |
|---|---|---|
network-libp2p.ts |
213 | Libp2pTransport class |
libp2p-connection.ts |
205 | node create + connect |
libp2p-messaging.ts |
167 | stream messaging |
libp2p.types.ts |
119 | |
send-to-peer.ts |
73 | |
stream-handler.ts |
60 | protocol handler registration |
peer-message.ts |
45 | wire format |
libp2p-demo.tsx |
749 ❌ | React UI — over 300-line cap and brings React runtime dep into universal package |
libp2p-demo.stories.tsx |
211 | |
network-libp2p.test.ts |
505 | over 500-line test cap |
network-libp2p.spec.ts |
56 | duplicate test file using vitest globals |
Tests: only top-level Libp2pTransport is covered. libp2p-connection, libp2p-messaging, send-to-peer, stream-handler, peer-message have no dedicated tests.
Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
Transport contract impl |
partial | ⬆️ | NEW conformant adapter. |
NetworkPlugin wrapper |
🚫 | ⬆️ | Mirrors WebRTCPlugin shape. |
| TCP transport | ✅ | ✅ | Server tier only. |
| WebSockets transport | ✅ | ✅ | Universal. |
| WebRTC transport | ✅ | ✅ | Browser tier — composes shipped network-transport-webrtc ✅ where applicable. |
| Noise encryption | ✅ | ✅ | |
| Yamux muxer | ✅ | ✅ | |
| Identify / ping protocols | ✅ | ✅ | |
| mDNS discovery | ✅ | ✅ | Server tier only. |
| Bootstrap node list | ✅ (defaults present) | ⬆️ | Bootstrap list REQUIRED in options; no public-bootstrap fallback. Constructor throws INVALID_OPTIONS if missing. |
| Circuit-relay-v2 | ✅ | ✅ | |
| Stream-based request/response | ✅ | ✅ | |
| Wire-format peer message | ✅ | ✅ | Re-use @suaveplan/serialize. |
749-line libp2p-demo.tsx |
✅ | 🚫 | Extracted to a separate companion package @suaveplan/react-network-libp2p-demo (Wave 7). This migration drops it from the transport package. |
Storybook .stories.tsx |
✅ | 🚫 | Extracted with the demo. |
| React/react-dom runtime deps | ✅ ❌ | 🚫 | Removed — universal-tier package must not pull React. |
Duplicate .spec.ts test file |
❌ | 🚫 | DELETED. .spec.ts reserved for Playwright per CLAUDE.md. |
505-line network-libp2p.test.ts |
❌ (over cap) | ⬆️ | Split by responsibility into ≤500-line files. |
Unit tests for libp2p-connection/-messaging/send-to-peer/stream-handler/peer-message |
🚫 | ⬆️ | All authored fresh. |
| Structured errors | 🚫 | ⬆️ | defineCodes("NET_LIBP2P", [...]): BOOTSTRAP_FAILED, DIAL_FAILED, STREAM_FAILED, PROTOCOL_NOT_SUPPORTED, IDENTIFY_REJECTED, INVALID_OPTIONS. |
| Zod boundary validation | 🚫 | ⬆️ | Every public option struct. |
| OTel metrics | partial (Libp2pMetrics type unused) |
⬆️ | Counters libp2p.connections_opened_total{outcome}, streams_opened_total, bytes_total{direction}; histograms libp2p.dial_ms, libp2p.stream_ttfb_ms. |
| AbortSignal | 🚫 | ⬆️ | Threaded everywhere. |
export * barrels |
check | ⬆️ | Convert to explicit named exports per §6a. |
| Test-runner imports | direct vitest globals | ⬆️ | Rewrite to @suaveplan/testing/runner per §7. |
| 100% test coverage | 🚫 | ⬆️ | Bring to 100/100/100/100. |
examples/ (if present) |
check | ✅ | Keep — lint-cleaned. |
Available workspace deps on genesis
@suaveplan/network✅@suaveplan/network-plugin-transport-manager✅@suaveplan/network-transport-webrtc✅ (composes forwebrtclibp2p sub-transport)@suaveplan/serialize✅@suaveplan/error,@suaveplan/types,@suaveplan/events,@suaveplan/retry,@suaveplan/timing✅@suaveplan/testing✅- External (add to root catalog under
network-transport):libp2p@libp2p/tcp(server-only)@libp2p/websockets@libp2p/webrtc@libp2p/bootstrap@libp2p/circuit-relay-v2@libp2p/echo@libp2p/identify@libp2p/interface@libp2p/mdns(server-only)@libp2p/ping@chainsafe/libp2p-noise@chainsafe/libp2p-yamux@multiformats/multiaddr
NOT added: react, react-dom — demo lives in a separate package.
Acceptance gate
bunx turbo lint typecheck test --filter=@suaveplan/network-transport-libp2pgreen.bunx turbo test:coverage --filter=@suaveplan/network-transport-libp2p100/100/100/100.bun run docs:checkgreen.- No file > 300 LOC source (impl) or > 500 LOC tests.
- Zero React imports in this package's
src/. - Integration test: 2-peer dial across the
webrtcsub-transport + 2-peer dial acrosswebsocketssub-transport; both complete envelope round-trips. STATUS.mdrow flipped.
Out of scope
- The 749-line React demo — moves to
@suaveplan/react-network-libp2p-demoin a future Wave-7 proposal. - libp2p bootstrap node hosting (deployment concern; user supplies bootstrap list).
- IPFS / Kademlia DHT integration (separate proposal if needed).