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,193 @@
# @suaveplan/drive-mesh — P2P Mesh Orchestration Capability
P2P mesh layer over `@suaveplan/drive-plugin-chunks`: peer registry, bitset
gossip, parallel chunk pull (multi-peer racing window), peer scoring, server
fallback (built-in `ServerFallback` HTTPS path — see "HTTPS chunk fetch via
ServerFallback" below), and bad-signature denylist. Consumes a pluggable list
of peer-to-peer `DriveTransport` implementations (currently WebRTC, via
`@suaveplan/drive-transport-webrtc`) without importing `@suaveplan/drive`
core directly.
## Requirements
### Requirement: Mesh orchestrator surface
The package SHALL expose a `DriveMesh` class with:
- `start(signal?)` — begin gossip + listen for chunk requests.
- `stop(reason?)` — drain in-flight, close transports. Idempotent.
- `requestChunk(fileId, chunkId, signal?): Promise<Uint8Array>` — fetch a
chunk from the mesh, falling back to the server if configured.
- `advertise(fileId, bitset)` / `unadvertise(fileId)` — push our local
availability through the gossip engine.
- `peers(): Iterable<PeerInfo>` — snapshot of the peer registry.
- `registry` — direct handle on the `PeerRegistry` for application glue.
- `tickGossip()` — manual tick (testable / configurable cadence).
- TypedEventEmitter for `chunk:*` / `peer:*` / `gossip:*` events.
### Requirement: Server is root of trust
`DriveMesh` SHALL treat the configured `serverPubKey` as the only authority
for chunk validity:
- Every chunk delivered by a peer MUST be passed through
`drive-plugin-chunks` signature verification before being returned to the
caller.
- A peer that delivers a chunk with an invalid signature MUST be added to
the registry's denylist (per-session by default, persistent if configured).
- A bad-sig peer MUST emit `peer:denied{peerId, reason: "bad-signature"}` so
upstream `NetworkBus` consumers can take action.
#### Scenario: Bad-sig peer evicted
- **WHEN** a peer delivers bytes whose signature fails
`verifyChunkSig(serverPubKey, …)`
- **THEN** `peerRegistry.recordBadSig(peerId)` MUST be called and the peer
MUST NOT be selected for subsequent chunk pulls.
### Requirement: PeerRegistry overlay
`PeerRegistry` SHALL track per-peer state including availability bitsets per
fileId, EMA latency (α=0.3), success / failure / bad-sig counts, and a
composite score for `rank(fileId, chunkId)`. The registry is an **overlay**
that consumes peer-identity events from `network-plugin-registry` (per the
`drive-network-integration` boundary spec); it MUST NOT duplicate peer-
identity storage.
### Requirement: Gossip engine
`GossipEngine` SHALL emit periodic outbound advertisements with compressed
bitsets per `fileId` (using `@suaveplan/drive-mesh-protocol` framed-bitset
helpers) and SHALL ingest inbound advertisements into the `PeerRegistry`.
### Requirement: Parallel puller with racing window
`ParallelPuller` SHALL issue chunk requests to the top-K candidates (default
3) within a configurable racing window (default 250 ms), accept the first
verified response, and abort the losers via a shared `AbortController`.
`maxParallelRequests` SHALL cap global concurrency (default 8). Failed or
timed-out attempts blacklist that peer for the specific chunkId only;
bad-signature is the only failure that escalates to a registry-wide denylist.
### Requirement: Server fallback
`ServerFallback` SHALL accept a `{ url, transport }` config and execute
equal-jitter exponential backoff retries when all peer attempts fail.
Server-delivered chunks MUST still pass signature verification.
#### Scenario: All-peers-fail with no fallback
- **WHEN** every peer attempt fails AND no `serverFallback` is configured
- **THEN** `requestChunk` MUST reject with `DriveMeshError(ALL_PEERS_FAILED)`.
### Requirement: Wire transports as plugins
`DriveMesh` SHALL accept a list of `DriveTransport` implementations through
its constructor and use them interchangeably. The structural `DriveTransport`
interface MUST expose:
- `requestChunk(peerId, fileId, chunkId, signal?): AsyncIterable<Uint8Array>`
- `advertise(peerId, fileId, bitset): Promise<void>`
- `onAdvertisement(handler): () => void`
- `peers(): Iterable<PeerInfo>`
- `dispose(): Promise<void>`
`@suaveplan/drive-transport-webrtc` satisfies this interface. The HTTPS
chunk-fetch path is NOT a `DriveTransport` plugin — see "HTTPS chunk fetch
via ServerFallback" below.
### Requirement: No network-plugin-registry import
`DriveMesh` MUST NOT import `@suaveplan/network-plugin-registry` directly.
Applications glue `peer:joined` / `peer:left` from `NetworkBus` to
`mesh.registry.addOrUpdate` / `mesh.registry.forget`. This enforces the
layering decision recorded in `openspec/specs/drive-network-integration/spec.md`.
### Requirement: Error registry
The package SHALL export `DriveMeshError extends SuaveplanError<…>` with 10
stable codes covering chunk unavailable, all-peers-fail, signature failure,
transport failure, fallback failure, invalid bitset, peer-denied paths.
### Requirement: AbortSignal threading
Every async surface (`start`, `stop`, `requestChunk`, `advertise`) SHALL
accept an optional `AbortSignal`. Pre-aborted signals reject before any
side effect. Mid-flight aborts cancel transport requests and racing
attempts cleanly.
### Requirement: Universal-tier-clean tests
Tests MUST NOT use `vi.mock` or `vi.stubGlobal`. The package SHALL ship
real-implementation fixtures (in-memory `Broker` + `FakeDriveTransport`,
real `ed25519` keypairs via `@suaveplan/crypto-curve`, real
`buildSignedChunk` from `@suaveplan/drive-plugin-chunks`, real
`encodeFramedBitset` from `@suaveplan/drive-mesh-protocol`). All test
imports come from `@suaveplan/testing/runner`.
### Requirement: Coverage + gate
`bunx turbo lint typecheck test:coverage --filter=@suaveplan/drive-mesh`
MUST be green and istanbul coverage MUST be 100% on every touched module
(statements / branches / functions / lines) before any release.
## ADDED Requirements
### Requirement: HTTPS chunk fetch via ServerFallback
The HTTPS / server-fallback chunk-fetch path SHALL be served by the
built-in `ServerFallback` module that ships inside `@suaveplan/drive-mesh`
(`./server-fallback/server-fallback`) — NOT by a separate
`DriveTransport`-shaped plugin package.
`ServerFallback` SHALL:
- Issue HTTPS `GET` to `${baseUrl}/${fileId}/${chunkId}` via an
injectable `fetchFn` (defaults to `globalThis.fetch`).
- Run every fetched chunk through `verifyChunkSig(serverPubKey, …)` from
`@suaveplan/drive-plugin-chunks` before returning bytes to the
scheduler — same root-of-trust contract as peer-served chunks.
- Apply equal-jitter exponential backoff with a caller-configurable
`maxRetries`, `backoffBaseMs`, and `backoffMaxMs`.
- Thread an `AbortSignal` through every retry.
- Surface every failure as a `DriveMeshError(FALLBACK_FAILED)` with the
underlying HTTP status / fetch error preserved in `cause`.
Bearer-token or other authentication SHALL be supplied by the consumer
through the `fetchFn` closure (e.g. wrapping `globalThis.fetch` with an
`Authorization` header) — no transport-level auth plumbing is added.
`ServerFallback` deliberately does NOT implement the
`DriveTransport` interface. Advertisement / peer-discovery / receive
semantics do not apply to a server-driven HTTPS fetch path; modelling
HTTPS as a degraded `DriveTransport` (with no-op `advertise`,
`onAdvertisement`, and a single synthetic peer) was rejected because it
adds no consumer-facing capability beyond what `ServerFallback` already
provides while doubling the surface the scheduler has to reason about.
#### Scenario: Bad-sig server chunk rejected
- **WHEN** `ServerFallback.fetchChunk(fileId, chunkId)` returns bytes whose
signature fails `verifyChunkSig(serverPubKey, …)`
- **THEN** `requestChunk` MUST reject with
`DriveMeshError(FALLBACK_FAILED)` and the chunk MUST NOT be cached.
#### Scenario: Auth wrapping happens in the consumer's fetchFn
- **WHEN** a consumer needs bearer-token authentication against the
fallback endpoint
- **THEN** the consumer SHALL pass an authenticated `fetchFn` to
`ServerFallback` (e.g. `(url, init) => fetch(url, { ...init, headers: { ...init?.headers, Authorization: 'Bearer ...' } })`)
rather than registering a separate transport.
### Requirement: No HTTPS DriveTransport plugin
There SHALL NOT be a parallel `@suaveplan/drive-transport-https` (or
similar) package implementing the `DriveTransport` interface for the
HTTPS path. The original `drive-transport-https-port` proposal was
retired on 2026-05-12 because `ServerFallback` already provides every
documented capability (HTTPS chunk fetch, signature verification,
exponential backoff with jitter, injectable `fetchFn` for tests,
`AbortSignal` threading) without inheriting the peer-shaped surface
(`advertise` / `onAdvertisement` / `peers`) that would have to be
no-ops on a unidirectional HTTPS link.