Files
2026-05-27 23:47:53 +01:00
..
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00
2026-05-27 23:47:53 +01:00

@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)
  • health — (no submodules)
  • otel — (no submodules)
    • otel — (no submodules)
  • server — (no submodules)
    • listen-http — Free function that binds a node:http server to (port, host) and translates the resulting Node EventEmitter signals…
    • server — (no submodules)
  • types — (no submodules)
    • types — (no submodules)
  • validation — (no submodules)
- [errors](./src/errors/errors.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [health](./src/health/health.md) — _(no submodules)_ - [health](./src/health/health.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_- [server](./src/server/server.md) — _(no submodules)_ - [server](./src/server/server.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_- [validation](./src/validation/validation.md) — _(no submodules)_ - [validation](./src/validation/validation.md) — _(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.