# OpenSpec Change: enterprise-browser-network-discovery-gundb - **Change ID**: enterprise-browser-network-discovery-gundb - **Package**: `@suaveplan/network-discovery-gundb` - **Category**: browser - **Target path**: `browser/network/network-discovery-gundb` - **Status**: SUPERSEDED-BY-GENESIS-WAVE - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/network-discovery-gundb.md` --- ## Summary Deliver `@suaveplan/network-discovery-gundb` on the genesis branch at enterprise quality. The package implements `DiscoveryStrategy` from `@suaveplan/network` using GunDB for gossip-based peer metadata. Ships `GunDBDiscovery`, `GunNodeManager`, and `GunDBInitializer` with strict-mode that refuses to start without explicit peer relay lists, signed metadata via `@suaveplan/crypto`, Zod validation on every inbound message, rate limiting, and full test coverage of all three modules. --- ## Current-state audit (genesis) Fresh build — does not exist on genesis yet. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/network` (`workspace:^`) | `DiscoveryStrategy` interface | | `@suaveplan/error` (`workspace:^`) | Typed GunDB errors | | `@suaveplan/types` (`workspace:^`) | `LoggerLike` | | `@suaveplan/crypto` (`workspace:^`) | ed25519 metadata signing + verification | | `@suaveplan/schema-registry` (`workspace:^`) | Register `GunDBMessage` Zod schemas | | `zod` (`catalog:forms`) | Message schemas | | `@opentelemetry/api` (`catalog:observability`) | Peer/message metrics | | `tslib` (`catalog:build`) | Runtime helpers | External: `gun` (Bun catalog). Dev: `vitest`, `@vitest/coverage-istanbul`, `@suaveplan/testing`, `react` + `@types/react` for stories. --- ## Preserved public API surface (from main branch) ```ts class GunDBDiscovery implements DiscoveryStrategy { constructor(config: GunDBDiscoveryConfig) start(): Promise stop(): Promise getPeers(): PeerInfo[] on(event: 'peer:discovered' | 'peer:left' | 'error', handler: Function): void } interface GunDBDiscoveryConfig { peers: string[] // Required; strict mode refuses empty list roomId: string sign?: boolean // Default true; sign metadata with @suaveplan/crypto strict?: boolean // Default true } // + GunDBConnectionStatus, GunDBMessage, GunDBMessageType, GunDBPeerMetadata ``` --- ## New additions for genesis ### 1. Strict-mode relay gate `GunDBDiscoveryConfig.peers` must be non-empty when `strict: true` (default). Throws `GUN_RELAY_UNREACHABLE` at init if empty. ### 2. Signed metadata On write: sign `GunDBPeerMetadata` using `@suaveplan/crypto` ed25519. On read: verify signature; drop unverified entries with `GUN_SIGNATURE_INVALID`. ### 3. Zod validation `GunDBMessageSchema` + `GunDBPeerMetadataSchema` validated at boundary; malformed messages emit `GUN_MESSAGE_REJECTED`. ### 4. Rate limiting Configurable max inbound metadata updates per second per peer; excess dropped with counter metric. ### 5. `sideEffects` audit Gun has import-time effects; `sideEffects` in `package.json` accurately reflects Gun's behaviour. ### 6. Error codes `GUN_RELAY_UNREACHABLE`, `GUN_MESSAGE_REJECTED`, `GUN_SIGNATURE_INVALID`. ### 7. OTel metrics Counter `discovery.gundb.peers_seen_total`, counter `discovery.gundb.messages_rejected_total{reason}`, histogram `discovery.gundb.sync_latency_ms`. --- ## File layout ```text browser/network/network-discovery-gundb/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts gundb-discovery/ gundb-discovery.ts gundb-discovery.md gundb-discovery.types.ts gundb-discovery.test.ts index.ts gun-node-manager/ gun-node-manager.ts gun-node-manager.md gun-node-manager.test.ts index.ts gundb-initializer/ gundb-initializer.ts gundb-initializer.md gundb-initializer.test.ts index.ts schema/ gundb-schema/ gundb-schema.ts gundb-schema.md index.ts tests/ integration.test.ts ``` React in devDeps for `gundb-discovery.stories.tsx`. --- ## Impact **Downstream**: `@suaveplan/network-discovery-hybrid` (optional peer dep). **Prerequisites**: `@suaveplan/network`, `@suaveplan/error`, `@suaveplan/crypto` on Verdaccio.