# Capability Spec Delta: network-plugin-migration (complete-network-plugins) **Package**: `@suaveplan/network-plugin-migration` **Status**: PROPOSED > Every requirement below carries a `**Verified by:**` line at authoring time. First canonical spec for this package. ## ADDED Requirements ### Requirement: MigrationCoordinator orchestrates node migration end-to-end The package SHALL export `MigrationCoordinator`, `MigrationCoordinatorConfig`, `MigrationRequest`, `MigrationResult`, and `MigrationDestination`. The coordinator SHALL drive the migration through four phases — prepare, state-transfer, cutover, drain — and SHALL throw `MigrateError(MIGRATION_REJECTED)` when the destination refuses the request. #### Scenario: destination refuses the migration - **WHEN** `coordinator.migrate(request)` is called and the destination returns a refusal - **THEN** the call throws `MigrateError` with `code === "NET_MIGRATE.MIGRATION_REJECTED"` and the source node retains ownership **Verified by:** `src/coordinator/coordinator.spec-conformance.test.ts::"throws MIGRATION_REJECTED when destination refuses"` --- ### Requirement: MigrationCoordinator enforces a deadline The coordinator SHALL accept a `timeoutMs` and SHALL throw `MigrateError(MIGRATION_TIMEOUT)` when the migration does not complete within the deadline. #### Scenario: deadline elapses - **WHEN** state transfer exceeds `timeoutMs` - **THEN** the coordinator throws `MigrateError(MIGRATION_TIMEOUT)` and aborts in-flight work **Verified by:** `src/coordinator/coordinator.spec-conformance.test.ts::"throws MIGRATION_TIMEOUT when deadline elapses"` --- ### Requirement: StateTransferProtocol serializes and transports snapshots The package SHALL export `StateTransferProtocol`, `StateTransferProtocolConfig`, `MigrationSnapshot`, and `SnapshotSerializer`. The protocol SHALL stream a snapshot from source to destination using the supplied serializer and SHALL throw `MigrateError(STATE_TRANSFER_FAILED)` on transport failure. #### Scenario: transport failure mid-stream - **WHEN** the transport rejects mid-stream - **THEN** the protocol throws `MigrateError(STATE_TRANSFER_FAILED)` with `context.bytesSent` populated **Verified by:** `src/state-transfer/state-transfer.spec-conformance.test.ts::"throws STATE_TRANSFER_FAILED on transport failure"` --- ### Requirement: ForwardingTunnel drains messages after cutover The package SHALL export `ForwardingTunnel`, `ForwardingTunnelConfig`, and a `TunnelForwarder` function type. The tunnel SHALL forward messages addressed to the migrated identity to the new location until the drain deadline elapses, after which `TUNNEL_DRAINED` is raised on further forward attempts. #### Scenario: forward after drain - **WHEN** a message is submitted to the tunnel after the drain deadline - **THEN** the call throws `MigrateError(TUNNEL_DRAINED)` **Verified by:** `src/tunnel/forwarding-tunnel.spec-conformance.test.ts::"throws TUNNEL_DRAINED after drain deadline"` --- ### Requirement: Error-code registry is frozen and namespaced NET_MIGRATE `MIGRATE_CODES` SHALL be frozen under the `NET_MIGRATE` namespace and SHALL include exactly: `MIGRATION_REJECTED`, `STATE_TRANSFER_FAILED`, `TUNNEL_DRAINED`, `MIGRATION_TIMEOUT`. Every code SHALL be reachable from a production throw site. #### Scenario: registry membership - **WHEN** `MIGRATE_CODES` is inspected - **THEN** every key maps to a value of the form `"NET_MIGRATE."` **Verified by:** `src/error-codes.spec-conformance.test.ts::"MIGRATE_CODES is frozen and prefixed NET_MIGRATE"` --- ### Requirement: No bare-Error throws in production code `src/` SHALL contain zero bare `throw new (Error|TypeError|RangeError|SyntaxError)\(` sites outside test files. #### Scenario: source grep returns zero hits - **WHEN** the grep is run - **THEN** the output is empty **Verified by:** `tests/no-bare-throws.test.ts::"network-plugin-migration src/ has no bare Error throws"` --- ### Requirement: README is auto-docs idempotent The package `README.md` SHALL contain exactly one balanced auto-docs block; the generator SHALL produce a byte-identical file on a second run. #### Scenario: marker count is exactly one - **WHEN** `grep -c "begin:auto-docs" packages/network/network-plugin-migration/README.md` - **THEN** output is `1` **Verified by:** `scripts/generate-package-module-tree.test.ts::"README regen is idempotent for network-plugin-migration"`