@suaveplan/network-gundb-server - Server-tier GunDB relay daemon for @suaveplan/network-discovery-gundb clients — Node-only HTTP/WebSocket relay with structural Zod wire-payload validation, AbortSignal lifecycle, health/ready/live endpoints, OTel observability, and injectable Gun factory for real-fake integration tests.
Summary
Server-tier GunDB relay daemon. Hosts a Gun relay peer plus standard
/health / /ready / /live probes on a single Node http.Server.
Browser-tier clients running @suaveplan/network-discovery-gundb pass
http(s)://<host>:<port>/gun in their peers[] list and gossip
signed peer-announces through the relay.
Documentation tree
- errors — (no submodules)
- errors — (no submodules)
- health — (no submodules)
- health — (no submodules)
- otel — (no submodules)
- otel — (no submodules)
- server — (no submodules)
- listen-http — Free function that binds a
node:httpserver to(port, host)and translates the resulting Node EventEmitter signals… - server — (no submodules)
- listen-http — Free function that binds a
- types — (no submodules)
- types — (no submodules)
- validation — (no submodules)
- validation — (no submodules)
Why this package
- Single daemon, no orchestrator coupling. Boot the relay, publish the endpoint, watch the health probes.
- Defensive by default. Every inbound announce is structurally
validated against the shared Zod schema; malformed records are
dropped silently and counted on
gundb_server.invalid_messages_total{reason}. - Injection-friendly. The Gun runtime is a peer dep — production
wires real
Gun, tests bind a deterministic in-memory fake. - Lifecycle-correct.
start({ signal? })resolves with the bound{ address, port }.stop()is idempotent.
Run the daemon
import { GunDBServer } from "@suaveplan/network-gundb-server";
import Gun from "gun";
const server = new GunDBServer({
port: 8765,
host: "0.0.0.0",
storagePath: "./data/gun",
radisk: true,
maxConnections: 256,
gunFactory: (cfg) => Gun(cfg),
});
const { address, port } = await server.start();
console.log(`relay listening on ${address}:${port}/gun`);
process.on("SIGTERM", async () => {
await server.stop();
process.exit(0);
});
Configuration reference
See src/types/types.md for the full strict
GunDBServerConfig. All fields except port and gunFactory are
optional and have spec-documented defaults.
Health endpoints
| Verb | 200 OK when | 503 when |
|---|---|---|
/live |
process alive (always, until stop) | after stop() |
/ready |
started AND below maxConnections |
starting, at-cap, or stopped |
/health |
started AND below maxConnections |
starting, at-cap, or stopped |
See src/health/health.md.
Observability
OpenTelemetry instrument names emitted by the daemon:
gundb_server.start/gundb_server.stop— spans.gundb_server.connections_total{outcome}— counter.gundb_server.messages_relayed_total{outcome}— counter.gundb_server.invalid_messages_total{reason}— security counter.gundb_server.active_connections— up-down gauge.gundb_server.start_duration_ms— histogram.
See src/otel/otel.md.
Security model
The relay does not verify Ed25519 signatures on inbound announces — signature verification is the client's responsibility per the gossip security model. The relay structurally validates the presence and shape of every signature field so a malformed announce cannot poison the namespace, then forwards the signed payload unchanged.
See src/validation/validation.md.
Companion package
@suaveplan/network-discovery-gundb is
the browser-tier client this daemon serves.