Skip to content

[CI verification only] fix(relay): report verified NIP-OA owner after any admission - #2

Closed
rclod wants to merge 1 commit into
mainfrom
fix/nip-oa-owner-for-direct-members
Closed

[CI verification only] fix(relay): report verified NIP-OA owner after any admission#2
rclod wants to merge 1 commit into
mainfrom
fix/nip-oa-owner-for-direct-members

Conversation

@rclod

@rclod rclod commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Fork-internal PR to run CI on the reworked commit before block#6078 is approved for upstream CI. Not for merge.

…ission

The agent→owner backfill ran only when `require_relay_membership` was false.
On a closed relay it never ran, and `enforce_relay_membership` did not fill the
gap: it reported an owner only when it had USED the delegation to admit the
agent (`MembershipDecision::ViaOwner`). An agent that is also a direct relay
member took the `::Member` branch, which returned `Ok(None)` and discarded a
valid, cryptographically self-proving attestation.

So on a closed relay, any agent enrolled directly in `relay_members` had
`users.agent_owner_pubkey` left NULL however valid its attestation. That column
is not cosmetic — `is_agent` in the admission path derives from it (so such
agents are limited at `human_messages_per_min` rather than
`agent_standard_messages_per_min`), owner-managed agent lists have no
relationship to display, and `channel_add_policy = "owner_only"` has no owner to
compare against, refusing `add-member` for every actor including the real owner.

Fixed in the shared helper rather than per call site. The attestation is now
verified once, before the admission branches, and `MembershipDecision::OpenRelay`
and `::Member` carry it; `enforce_relay_membership` reports it from every
admitted variant. Both WebSocket AUTH and `POST /events` consume that shared
result, so the open-relay-only workaround each carried is deleted rather than
duplicated — the HTTP path had the same gap and would otherwise have kept it.

Membership answers "may this caller connect"; the attestation answers "who owns
this agent". Deriving the second from the first was the bug. The security
boundary is unchanged: the tag's own verification in `extract_nip_oa_owner`.

The decision→owner mapping is split into `owner_from_decision` so the behaviour
that regressed is testable without a database, with three tests over it —
notably that a direct member reports its owner, which is what previously
returned None.

Co-authored-by: themiguelamador <themiguelamador@users.noreply.github.com>
Signed-off-by: rclod <3385524+rclod@users.noreply.github.com>
@rclod
rclod force-pushed the fix/nip-oa-owner-for-direct-members branch from a24e243 to f0fbbfc Compare August 16, 2026 21:25
@rclod

rclod commented Aug 16, 2026

Copy link
Copy Markdown
Owner Author

Verified green: run 31973435216, 21 passed / 2 skipped / 0 failed.

@rclod rclod closed this Aug 16, 2026
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