Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
# 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](https://libp2p.io) 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.tsx` is 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 for `webrtc` libp2p 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
1. `bunx turbo lint typecheck test --filter=@suaveplan/network-transport-libp2p` green.
2. `bunx turbo test:coverage --filter=@suaveplan/network-transport-libp2p` 100/100/100/100.
3. `bun run docs:check` green.
4. No file > 300 LOC source (impl) or > 500 LOC tests.
5. Zero React imports in this package's `src/`.
6. Integration test: 2-peer dial across the `webrtc` sub-transport + 2-peer dial across `websockets` sub-transport; both complete envelope round-trips.
7. `STATUS.md` row flipped.
---
## Out of scope
- The 749-line React demo — moves to `@suaveplan/react-network-libp2p-demo` in a future Wave-7 proposal.
- libp2p bootstrap node hosting (deployment concern; user supplies bootstrap list).
- IPFS / Kademlia DHT integration (separate proposal if needed).

View File

@@ -0,0 +1,73 @@
# Tasks — network-transport-libp2p
## Phase 1: Scaffold
- [ ] 1.1 Create `packages/network/network-transport-libp2p/` with feature-module layout.
- [ ] 1.2 `package.json` at `0.1.0`, `"sideEffects": false`, universal-tier (no `browser` restriction, no React deps).
- [ ] 1.3 Test config via `createTestConfig()`; `tests/dep-graph.test.ts`.
- [ ] 1.4 Add 14 libp2p subpackages to root catalog under `network-transport` group.
## Phase 2: Demo extraction (PRE-WORK)
- [ ] 2.1 Open Wave-7 proposal `react-network-libp2p-demo` reserving the destination package.
- [ ] 2.2 Do NOT port `libp2p-demo.tsx` or `libp2p-demo.stories.tsx` into this package.
- [ ] 2.3 Verify package has zero `react` / `react-dom` references.
## Phase 3: Types + errors
- [ ] 3.1 Port `libp2p.types.ts` → `src/types/types.ts` + sibling `.md`.
- [ ] 3.2 `defineCodes("NET_LIBP2P", [...])`: `BOOTSTRAP_FAILED`, `DIAL_FAILED`, `STREAM_FAILED`, `PROTOCOL_NOT_SUPPORTED`, `IDENTIFY_REJECTED`, `INVALID_OPTIONS`.
- [ ] 3.3 Zod schemas for `Libp2pConfig` + sub-transport configs.
- [ ] 3.4 Reject construction without explicit `bootstrap` list (throws `INVALID_OPTIONS`).
## Phase 4: Core libp2p stack
- [ ] 4.1 Port `libp2p-connection.ts` — node create + dial lifecycle.
- [ ] 4.2 Port `libp2p-messaging.ts` — stream-based request/response.
- [ ] 4.3 Port `peer-message.ts` — wire format over `@suaveplan/serialize`.
- [ ] 4.4 Port `send-to-peer.ts` — addressed-send helpers.
- [ ] 4.5 Port `stream-handler.ts` — protocol handler registration.
## Phase 5: Transport + plugin
- [ ] 5.1 Author `Libp2pTransport implements Transport`.
- [ ] 5.2 Author `Libp2pPlugin implements NetworkPlugin`.
- [ ] 5.3 Conformance tests for both contracts.
## Phase 6: Test refactor
- [ ] 6.1 DELETE upstream duplicate `network-libp2p.spec.ts` (`.spec.ts` is Playwright-only per CLAUDE.md).
- [ ] 6.2 Split upstream 505-line `network-libp2p.test.ts` into ≤500-line files by responsibility.
- [ ] 6.3 Author unit tests for `libp2p-connection`, `libp2p-messaging`, `send-to-peer`, `stream-handler`, `peer-message`.
## Phase 7: Observability
- [ ] 7.1 Counters `libp2p.connections_opened_total{outcome}`, `streams_opened_total`, `bytes_total{direction}`.
- [ ] 7.2 Histograms `libp2p.dial_ms`, `libp2p.stream_ttfb_ms`.
- [ ] 7.3 Bus emissions `transport:libp2p:dial`/`:identify`/`:stream`.
## Phase 8: Tests + docs
- [ ] 8.1 fast-check property tests on multiaddr parsing + peer-ID round-trip.
- [ ] 8.2 Integration test: 2-peer webrtc dial + 2-peer websockets dial, both round-trip envelope.
- [ ] 8.3 100/100/100/100 coverage gate.
- [ ] 8.4 Sibling `.md` per `.ts` impl file.
- [ ] 8.5 No file > 300 LOC source or > 500 LOC test.
- [ ] 8.6 Root `README.md` with sub-transport selection examples.
## Phase 9: Verification
- [ ] 9.1 `bunx turbo lint typecheck test --filter=@suaveplan/network-transport-libp2p` green.
- [ ] 9.2 `bunx turbo test:coverage --filter=@suaveplan/network-transport-libp2p` 100/100/100/100.
- [ ] 9.3 `bun run docs:check` green.
- [ ] 9.4 Zero React imports in `src/`.
- [ ] 9.5 `MANIFEST.md` regen.
- [ ] 9.6 `STATUS.md` row flipped.
## Pre-archive checklist
- [ ] Row 1 — Phase 9 green.
- [ ] Row 2 — Demo extraction confirmed (no React in this package).
- [ ] Row 3 — Integration test against real libp2p stack passes.
- [ ] Row 4 — `openspec/specs/network-transport-libp2p/spec.md` written.
- [ ] Row 5 — Folder archived.