Skip to content

fix: extract NIP-OA owner on open relays for observer frame auth#513

Merged
tlongwell-block merged 6 commits into
mainfrom
feat/nip-oa-open-relay-observer-registration
May 8, 2026
Merged

fix: extract NIP-OA owner on open relays for observer frame auth#513
tlongwell-block merged 6 commits into
mainfrom
feat/nip-oa-open-relay-observer-registration

Conversation

@tlongwell-block
Copy link
Copy Markdown
Collaborator

Problem

On open Sprout relays (require_relay_membership = false), managed agents cannot publish kind:24200 observer frames because the relay's handle_agent_observer_event() requires an agent→owner mapping in the DB. This mapping is normally written during NIP-OA auth, but on open relays the enforce_relay_membership() function short-circuits with return Ok(None) before extracting the NIP-OA owner — so the mapping never gets written.

Root Cause

In crates/sprout-relay/src/api/mod.rs, enforce_relay_membership() returns Ok(None) immediately when require_relay_membership = false, skipping NIP-OA owner extraction entirely. The auth handler then sees nip_oa_owner = None and skips the DB backfill.

Fix

  1. extract_nip_oa_owner helper — pure function that validates a NIP-OA auth tag and returns the owner pubkey (no side effects, no membership checks)
  2. Auth handler — on open relays, calls extract_nip_oa_owner directly when the membership gate returns None, enabling the existing DB backfill path
  3. enforce_relay_membership unchanged — stays a pure gate function for all other callers (HTTP, media, git, audio)

Design Decisions

  • Semantic separation: extraction ≠ enforcement. The helper is testable in isolation.
  • Gated explicitly: !state.config.require_relay_membership && state.config.allow_nip_oa_auth
  • First-write-wins: existing conflict resolution in the auth handler handles re-registrations
  • 3 unit tests cover the helper directly

Files Changed

  • crates/sprout-relay/src/api/mod.rsextract_nip_oa_owner helper + tests + doc update
  • crates/sprout-relay/src/handlers/auth.rs — open-relay NIP-OA backfill call
  • crates/sprout-relay/src/config.rsallow_nip_oa_auth doc comment update

Testing

  • All 148 relay tests pass
  • All 35 auth tests pass
  • cargo clippy clean
  • cargo fmt clean

NIP-OA signatures are cryptographically self-proving — if verify_auth_tag
passes, the owner relationship is authentic regardless of config flags.
The allow_nip_oa_auth flag now only controls whether NIP-OA can grant
membership access on closed relays, not whether the relay records
agent→owner mappings from valid attestations.
@tlongwell-block tlongwell-block force-pushed the feat/nip-oa-open-relay-observer-registration branch from b454e16 to 810528f Compare May 8, 2026 19:41
@tlongwell-block tlongwell-block merged commit 32c3fd1 into main May 8, 2026
15 checks passed
@tlongwell-block tlongwell-block deleted the feat/nip-oa-open-relay-observer-registration branch May 8, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant