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,178 @@
# OpenSpec Change: network-plugin-migration
- **Change ID**: network-plugin-migration
- **Package**: `@suaveplan/network-plugin-migration` (new)
- **Status**: PROPOSED
- **Date**: 2026-05-01
---
## Summary
Implement peer state migration between meshes. When `network-plugin-assignment` rebalances a peer from an overloaded mesh to an underloaded one, or when a peer manually requests to join a different mesh, there is currently no mechanism to transfer state or maintain message continuity during the handoff. This plugin provides the migration protocol: state snapshot transfer, graceful handoff with a forwarding tunnel, and session persistence across mesh boundaries.
---
## Why
**User requirement**: *"automatically place a new connection in a tiered mesh with available spaces"* implies rebalancing, which implies migration.
**Current state**: No migration logic exists anywhere in the network suite.
**What's missing**:
- State transfer when a peer moves from Mesh A to Mesh B
- Graceful handoff: old host forwards messages to new host during transition
- Session persistence across mesh boundaries
---
## Core components
### 1. `MigrationCoordinator`
Orchestrates the end-to-end migration flow.
```ts
class MigrationCoordinator {
constructor(options: {
localPeerId: string;
localMeshId: string;
bus: NetworkBus;
});
initiateMigration(request: MigrationRequest): Promise<MigrationResult>;
acceptMigration(request: MigrationRequest): Promise<MigrationResult>;
}
interface MigrationRequest {
peerId: string;
fromMeshId: string;
toMeshId: string;
reason: string; // e.g. "rebalance", "user-request", "region-optimization"
priority: "graceful" | "urgent";
}
interface MigrationResult {
success: boolean;
peerId: string;
newMeshId: string;
transferredBytes: number;
durationMs: number;
forwardedMessages: number;
}
```
**Migration flow**:
1. **Request** — `MigrationCoordinator` sends `migration:request` to the target mesh's assignment controller.
2. **Accept** — Target mesh admits the peer via `AdmissionController`.
3. **Snapshot** — Old host serializes peer state (registry entry, topology position, session memberships) and sends it to the new host.
4. **Transfer** — New host installs the peer into its local registry and topology.
5. **Tunnel** — Old host starts a forwarding tunnel for messages addressed to the migrating peer.
6. **Cutover** — Peer disconnects from old mesh and connects to new mesh.
7. **Drain** — Old host drains the forwarding tunnel (default 30s or until empty).
8. **Complete** — Old host removes peer from its registry. `migration:completed` is emitted on both meshes' buses.
### 2. `StateTransferProtocol`
Serializes and deserializes peer state for migration.
```ts
class StateTransferProtocol {
serialize(peerId: string, registry: RegistrySnapshot, topology: TopologyPosition, sessions: SessionMembership[]): Uint8Array;
deserialize(bytes: Uint8Array): PeerStateSnapshot;
}
interface PeerStateSnapshot {
peerId: string;
registryEntry: PeerRegistryEntry;
topologyPosition: TopologyPosition;
sessionMemberships: SessionMembership[];
version: number; // monotonic, for conflict detection
}
```
Uses `@suaveplan/bitpacker` for compact binary encoding. Max snapshot size: 64 KiB (peers with larger state must use lazy rehydration).
### 3. `ForwardingTunnel`
Temporary message forwarding from old host to new host during cutover.
```ts
class ForwardingTunnel {
constructor(options: {
fromHostId: string;
toHostId: string;
peerId: string;
relay: RelayManager; // from network-plugin-relay
drainTimeoutMs: number; // default 30000
maxBufferedMessages: number; // default 1000
});
open(): void;
close(): Promise<void>;
forward(envelope: MessageEnvelope): void;
getBufferedCount(): number;
}
```
**Behaviour**:
- All messages addressed to `peerId` that arrive at the old host are forwarded to the new host via `RelayManager`.
- If the buffer exceeds `maxBufferedMessages`, oldest messages are dropped (application is notified).
- After `drainTimeoutMs`, the tunnel is closed regardless of buffer state.
- `ForwardingTunnel` is only used for `graceful` migrations. `urgent` migrations skip the tunnel and accept message loss.
---
## Error codes
```ts
const MIGRATE_CODES = defineCodes("MIGRATE", [
"TARGET_MESH_REJECTED",
"STATE_TRANSFER_FAILED",
"TUNNEL_OVERFLOW",
"TUNNEL_TIMEOUT",
"CUTOVER_FAILED",
"MIGRATION_ABORTED",
"INVALID_SNAPSHOT",
] as const);
```
`MigrationError extends SuaveplanError<MigrationErrorCode>`.
---
## Dependencies
- **Consumes**: `@suaveplan/network` (`NetworkNode`, `NetworkBus`), `@suaveplan/network-plugin-relay` (`RelayManager`, cross-mesh forwarding), `@suaveplan/network-plugin-assignment` (`AdmissionController`, `MeshBalancer`), `@suaveplan/network-plugin-registry` (`RegistrySnapshot`), `@suaveplan/network-plugin-topology` (`TopologyPosition`), `@suaveplan/network-plugin-session` (`SessionMembership`), `@suaveplan/bitpacker` (snapshot encoding), `@suaveplan/error`, `@suaveplan/types`, `@opentelemetry/api`.
- **Blocked on**: `network-core` (shipped), `network-plugin-relay`, `network-plugin-assignment`, `network-plugin-registry`, `network-plugin-topology`, `network-plugin-session`.
---
## Verification approach
- `src/coordinator/coordinator.spec-conformance.test.ts` — pins full migration flow: request → accept → snapshot → transfer → tunnel → cutover → drain.
- `src/state-transfer/state-transfer.spec-conformance.test.ts` — pins serialize/deserialize roundtrip, version tracking, size limits.
- `src/tunnel/forwarding-tunnel.spec-conformance.test.ts` — pins buffer limits, overflow drop, drain timeout.
- `tests/integration/migration.spec-conformance.test.ts` — end-to-end: peer moves from Mesh A to Mesh B, messages continue to arrive.
- 100/100/100/100 Istanbul coverage.
---
## Conformance requirements (proposed)
- `NET-99` — `MigrationCoordinator` executes a 8-step migration flow (request, accept, snapshot, transfer, tunnel, cutover, drain, complete).
- `NET-100` — `StateTransferProtocol` serializes peer registry, topology, and session state using `@suaveplan/bitpacker`.
- `NET-101` — `ForwardingTunnel` buffers messages for the migrating peer and forwards them to the new host.
- `NET-102` — `ForwardingTunnel` drops oldest messages when buffer exceeds `maxBufferedMessages`.
- `NET-103` — `ForwardingTunnel` closes after `drainTimeoutMs` regardless of buffer state.
- `NET-104` — `urgent` migrations skip the forwarding tunnel and accept message loss.
- `NET-105` — `migration:completed` is emitted on both the source and target mesh buses.
---
## Out of scope
- **Live migration without disconnect** → v2; v1 requires a brief disconnect/cutover.
- **Migration of in-flight game state** → application-level; v1 transfers session memberships only.
- **Rollback on failure** → v2; v1 reports failure and leaves application to retry.