Skip to main content

Module streamauth

Module streamauth 

Source
Expand description

Concord v2 stream-key NIP-42 authentication.

Every v2 plane is kind-1059 traffic addressed to a DERIVED per-stream pubkey (control, guestbook, per-channel chat, rekey, dissolved) — never the user’s own identity. Relays that gate kind 1059 behind NIP-42 (ditto-relay’s default AUTH_KINDS=4,1059) require that EVERY authors entry in a kind-1059 REQ be an authenticated pubkey on the connection, and reply CLOSED auth-required: all authors must be authenticated otherwise. The user’s login can’t satisfy that — the stream address isn’t their pubkey — so an unauthenticated client reads back ZERO events and a join’s control-plane verify (or any community fetch) fails closed.

The fix (mirroring Armada’s streamAuth): the client HOLDS the stream secret keys (derived from the community_root / channel keys it already stores), so it can NIP-42-authenticate AS each stream by signing an extra kind-22242 AUTH event per stream against the relay’s challenge. This module is the registry of stream keys the client currently holds plus the challenge responder; the connection ends up authenticated as the user AND every stream it will query.

Signing is local (raw derived keys) — it never touches the account signer / bunker.

Functions§

clear
Forget every registered stream key (on session swap). The responder task exits on its own when its SessionGuard invalidates.
ensure_responder
Ensure the persistent stream-AUTH responder is running for this session (idempotent). It watches the client’s notification stream and, on EVERY relay AUTH challenge, authenticates as all registered stream keys on that relay.
is_empty
Whether we hold any stream keys (skip the whole dance when not).
prime
Prepare gated relays for an imminent fetch: make sure the community’s stream keys are registered and the responder is live, so the fetch’s REQ-triggered challenge is answered. A no-op when no client is connected (offline tests).
prime_auth
Prime the connection AUTH on relays before a live subscription: a subscription (unlike a fetch) isn’t auto-retried after the AUTH gate, so the socket must already be authenticated as EVERY stream the sub’s authors will name — one unauthenticated key fails the whole REQ. Two passes:
register
Register a batch of stream keys (idempotent). Returns how many were NEW.
register_community
Register every plane a community currently exposes: control, guestbook, the dissolved plane, and each readable channel’s Chat Plane (a keyless private channel has no readable plane yet, so it’s skipped — its rekey plane keys up first). Called at join and on every follow so a rotated address is covered.