Files
2026-05-27 23:29:53 +01:00

4.7 KiB

OpenSpec Change: enterprise-network-assignment

  • Change ID: enterprise-network-assignment
  • Package: @suaveplan/network-assignment
  • Category: universal/network
  • Target path: universal/network/network-assignment
  • Status: SUPERSEDED-BY-GENESIS-WAVE
  • Date: 2026-04-24

Summary

Deliver @suaveplan/network-assignment on the genesis branch from scratch at enterprise quality. The package provides peer assignment algorithms: consistent hashing for deterministic peer selection, rendezvous hashing for load balancing, weighted random assignment, geographic/latency-aware assignment, and re-assignment on peer addition/removal with minimal disruption. Genesis adds structured errors via @suaveplan/error, Zod schemas for all assignment types, OTel instrumentation on assignment operations, injectable Rng for reproducible assignments, and property-based tests for distribution invariants.


Current-state audit (genesis)

The package does not exist on genesis yet — this is a fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) Base class for NetworkAssignmentError; stable error codes
@suaveplan/types (workspace:^) LoggerLike, Clock, Rng
@suaveplan/logger (workspace:^) Structured logging
zod (catalog:forms) Zod schemas
@opentelemetry/api (catalog:observability) Spans + counters on assignment
tslib (catalog:build) Runtime helpers

Dev deps: vitest, @vitest/coverage-istanbul, fast-check (all catalog:testing).


Public API surface

Core

function createAssigner(options?: AssignerOptions): Assigner

interface Assigner {
  addPeer(peer: Peer): void
  removePeer(peerId: string): void
  assign(key: string): Peer | null
  assignN(key: string, n: number): ReadonlyArray<Peer>
  rebalance(): RebalanceResult
  snapshot(): AssignerSnapshot
}

Types

interface Peer {
  id: string
  weight?: number
  region?: string
  latencyMs?: number
  capacity?: number
  tags?: Record<string, string>
}

interface RebalanceResult {
  readonly reassigned: number
  readonly moved: ReadonlyArray<{ key: string; from: string; to: string }>
  readonly durationMs: number
}

interface AssignerSnapshot {
  readonly peers: ReadonlyArray<Peer>
  readonly assignments: number
  readonly algorithm: AssignmentAlgorithm
}

type AssignmentAlgorithm = 'consistent-hash' | 'rendezvous' | 'weighted-random' | 'latency-aware'

interface AssignerOptions {
  algorithm?: AssignmentAlgorithm
  virtualNodes?: number    // for consistent hashing, default 150
  replicationFactor?: number
  rng?: Rng
  logger?: LoggerLike
  clock?: Clock
}

Algorithm utilities

function consistentHash(key: string, peers: Peer[], virtualNodes?: number): Peer | null
function rendezvousHash(key: string, peers: Peer[]): Peer | null
function weightedRandom(peers: Peer[], rng: Rng): Peer | null
function latencyAware(peers: Peer[], maxPeers?: number): Peer | null

Error codes

type NetworkAssignmentErrorCode =
  | 'ASSIGN_NO_PEERS'
  | 'ASSIGN_PEER_NOT_FOUND'
  | 'ASSIGN_INVALID_OPTIONS'

function registerNetworkAssignmentErrorCodes(): void

Genesis additions

  1. Structured NetworkAssignmentError with stable ASSIGN.* codes
  2. Zod schemas for AssignerOptions, Peer
  3. Four assignment algorithms: consistent hash (FNV-1a + virtual nodes), rendezvous hash (HRW), weighted random, latency-aware
  4. Injectable Rng for deterministic weighted-random assignments in tests
  5. OTel instrumentation — counter assignment.assign_total, histogram assignment.rebalance_duration_ms
  6. Property-based tests — consistent hash monotonicity (adding peer reassigns minimum keys), distribution uniformity, weight-proportional assignment

File layout

universal/network/network-assignment/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/
      index.ts
    types/
      common.ts
      common.md
    core/
      assigner/
        assigner.ts
        assigner.md
        assigner.types.ts
        assigner.test.ts
        index.ts
    algorithms/
      consistent-hash.ts
      consistent-hash.md
      consistent-hash.test.ts
      rendezvous-hash.ts
      rendezvous-hash.md
      rendezvous-hash.test.ts
      weighted-random.ts
      weighted-random.md
      weighted-random.test.ts
      latency-aware.ts
      latency-aware.md
      latency-aware.test.ts
    __benchmarks__/
      assignment.bench.ts
  tests/
    integration.test.ts
    property.test.ts

Impact

Workspace dep prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/logger must be published.