Back to Freedom.Tech Back
All nostream releasesAll versions
Release Mon, Sep 28, 2026 6 min read

nostream 3.1.0

Original release notes

Minor Changes

Adds limits.event.pow settings that scale the required proof-of-work difficulty between a configured floor and ceiling based on the observed event rate, in place of the existing static eventId.minLeadingZeroBits value (the static pubkey.minLeadingZeroBits check is unaffected and still enforced independently). The event rate is tracked per worker process with the same EWMA shape already used by the relay's rate limiter. Disabled by default (limits.event.pow.enabled: false), so existing static PoW configuration is unaffected unless explicitly opted in.

  • #641 837540b Thanks @Ferryx349! - feat: add disabled-by-default admin API with password auth, session, and health endpoints
  • #666 44f3bb4 Thanks @Ferryx349! - feat: add admin observability dashboard with Grafana embed and provisioned metrics panels
  • #653 8ab4825 Thanks @Ferryx349! - feat: add OpenTelemetry metrics bootstrap with OTLP export for Prometheus
  • #661 237b1a4 Thanks @Ferryx349! - feat: instrument event and websocket handlers with OpenTelemetry metrics

Adds a dashboard section that renders the latest NIP-66 probe snapshot with per-target DNS, TLS, WebSocket RTT, and NIP-11 status.

  • #784 c6c4c4f Thanks @Ferryx349! - feat(admin): add GET/PATCH /admin/notifications API for operator alert config

Closes #760.

Adds a Notifications view to the admin dashboard for configuring targets and event toggles, testing delivery, and browsing the delivery log via the admin API.

Closes #761

Accepts and stores kind-1984 report events, weighting each report by the reporter's WoT distance from wot.seedPubkey (full weight for a direct follow, halving each additional hop, zero for a pubkey outside the trust graph). Reports from a nip56.trustedModerators pubkey always get maximum weight and are flagged actionable, ready for a future management-API surface to act on; every other report is stored for manual review only. Disabled by default (nip56.enabled: false).

Clients can now include a search field in REQ filter objects to perform full-text queries against event content. Results are ranked by relevance (ts_rank) instead of the usual created_at ordering, per the NIP-50 specification.

Features:

  • New search filter field accepted in REQ messages
  • PostgreSQL GIN index on to_tsvector('simple', event_content) for fast full-text lookups
  • Configurable text-search language (defaults to simple, supports english, spanish, etc.)
  • Configurable max search query length for abuse prevention
  • NIP-50 listed in NIP-11 relay information document
  • Search can be combined with all existing filter fields (kinds, authors, tags, etc.)
  • #702 e172cce Thanks @Anshumancanrock! - feat(nip42): enforce authentication on reads for restricted event kinds (encrypted DMs, gift wraps) across REQ, live broadcasts and COUNT
  • #716 2f5a1c0 Thanks @Anshumancanrock! - feat(nip42): add session tracking with optional TTL and publish-time authRequired (NIP-11 restricted_writes)
  • #732 d413bd6 Thanks @Anshumancanrock! - Add a CLI to mint NIP-43 invite codes (nostream invite create) so operators can issue a claim without SQL. New codes honor nip43.defaultMaxUses and nip43.inviteCodeExpirySeconds.
  • #650 3461dfe Thanks @Anshumancanrock! - Add NIP-43 invite code foundation: InviteCodeRepository with atomic claimCode, invite_codes migration, and event kind/tag constants.

NIP-43 kind 28935 is not an event clients publish - it is a REQ the relay answers by minting an invite code on the fly and returning a relay-signed ephemeral event. Nostream now serves those subscriptions, completing the membership flow: request a claim, join with kind 28934, publish.

Off by default. It requires nip43.enabled and the new nip43.allowInviteRequests, a NIP-42 authenticated requester, an info.self consistent with the relay signing key, and a per-pubkey budget under the new limits.invite.rateLimits (5/hour by default). This also makes the previously inert nip43.inviteRequestWhitelist setting take effect. The minted event is never persisted and never broadcast: the claim tag is a bearer secret and is sent only to the socket that asked for it.

Two fixes the flow depended on. The relay signs its own events with a key derived from SECRET, but info.self was a hand-edited string that nothing validated - by default it was a placeholder that is not a pubkey at all, so any NIP-43 client verifying a relay-signed event against self would reject it. info.self is now optional: when unset or unparseable, NIP-11 advertises the derived signing pubkey instead, and nostream info prints that pubkey so operators can pin it.

Kind 28935 also sits in the ephemeral range, so a client-published one fell through to EphemeralEventStrategy and was broadcast to every subscriber - including everyone subscribed to kind 28935 waiting for a real invite. Anyone could inject a forged claim tag into that subscription. It is now rejected with an OK false and never broadcast, and bypasses the NIP-43 admission gate so that rejection actually reaches non-members, who are the ones most likely to publish it by mistake while trying to obtain a code.

CLI.md and README.md now describe the request flow. CLI.md previously claimed the relay "does not yet generate kind 28935 on REQ", and never mentioned that nostream info prints the signing pubkey that CONFIGURATION.md tells operators to pin.

  • #676 0bfa0b5 Thanks @Anshumancanrock! - Add NIP-43 join/leave request event strategies (kinds 28934/28936) with NIP-42 auth enforcement, created_at freshness validation, invite code claiming, and admission management. When nip43.enabled is set, publishing is restricted to admitted members even without payments enabled, and NIP-43 is advertised in the NIP-11 document (hidden when disabled). Join/leave update the admission cache so membership changes take effect immediately.
  • #675 5a70839 Thanks @Ferryx349! - feat(nip66): add shared relay probe engine for DNS, TLS, WebSocket RTT, and NIP-11 checks
  • #741 afa8999 Thanks @Ferryx349! - feat(nip66): publish kind 30166 and 10166 relay health events after probe runs

After each relay monitor probe run, sign and store NIP-66 relay discovery and monitor announcement events using the configured monitor identity, bootstrap kind 0/10002 on first run, and persist via the existing parameterized replaceable event path.

Fixes #696

  • #724 d14b1e9 Thanks @Ferryx349! - feat(nip66): add RelayMonitorWorker cluster worker and probe scheduler
  • #689 e294a71 Thanks @Ferryx349! - Add NIP-66 relay monitor settings foundation with defaults for probe interval, timeouts, targets, monitor identity, and DNS cache TTL.