fix(nip11): advertise auth_required: true to match actual enforcement#556
Merged
tlongwell-block merged 1 commit intoMay 13, 2026
Merged
Conversation
The REQ, EVENT, and COUNT handlers in this relay unconditionally require AuthState::Authenticated. The previous value (config.require_auth_token) reflected the REST API token toggle, not WebSocket protocol auth, so NIP-11 was lying about behaviour. This breaks the desktop pairing flow: probe_relay_requires_auth in desktop/src-tauri/src/commands/pairing.rs reads limitation.auth_required to decide whether to route the phone's QR code URL through the unauthenticated /pair sidecar. With the wrong NIP-11 value, the QR pointed at the bare relay URL and the phone could not pair against a NIP-43 enforcing relay. Tighten the existing e2e nip11 test to pin the invariant: 'is a bool' becomes 'is true', with a comment naming what enforces it. Signed-off-by: Tyler Longwell <109685178+tlongwell-block@users.noreply.github.com>
6dced8b to
3f2ec07
Compare
This was referenced May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The relay's NIP-11 information document was advertising
limitation.auth_required: falseeven though the relay's WebSocket protocol handlers (REQ, EVENT, COUNT) unconditionally requireAuthState::Authenticated. This caused the desktop pairing flow to omit the/pairsidecar path from the QR code URL on NIP-43-enforcing relays, so phones could not pair.The bug, traced end-to-end
Relay (the lie):
crates/sprout-relay/src/nip11.rssetauth_required: config.require_auth_token. Butrequire_auth_tokenis the REST API token toggle — it has no effect on WebSocket protocol auth. The protocol handlers (handlers/req.rs,handlers/event.rs,handlers/count.rs) all unconditionally reject connections that are notAuthState::Authenticated, regardless of that flag. The NIP-11 doc has been inconsistent with the protocol since the initial commit (058c4b92); PR feat: relay membership with NIP-43 compliance #448 ("relay membership with NIP-43 compliance") added43tosupported_nipsand theselffield but did not revisitauth_required.Desktop (the consumer):
desktop/src-tauri/src/commands/pairing.rs::probe_relay_requires_authreadslimitation.auth_requiredto decide whether to append/pairto the relay URL embedded in the pairing QR. The/pairpath is the unauthenticated NIP-AB sidecar that an unpaired phone needs to reach the desktop. With afalseadvertisement, the QR pointed at the bare relay URL and the phone could not connect (NIP-43 membership check fails).Empirical confirmation against
wss://sprout.up.railway.app(production):AUTHchallenge +CLOSED auth-required: not authenticated.OK <id> false "restricted: not a relay member"(fromhandle_authincrates/sprout-relay/src/handlers/auth.rs)."auth_required": false. That's what this PR fixes.The fix
crates/sprout-relay/src/nip11.rs: extractrelay_limitation()(the canonicalRelayLimitation) so the advertised invariant is testable without going throughConfig::from_env(). Setauth_required: true. RenameRelayInfo::from_config(_unused_config, relay_pubkey)toRelayInfo::build(relay_pubkey)—Configwas no longer used. New unit test pins the invariant.crates/sprout-relay/src/router.rs: update two callers toRelayInfo::build(...).crates/sprout-relay/src/config.rs: correct stale doc onrequire_auth_tokenand the startup warning — they previously said "NIP-42 / unauthenticated connections," which is the exact confusion that produced this bug.crates/sprout-test-client/tests/e2e_relay.rs: tighten the existing nip11 assertion from "is a bool" to "== true", with a comment naming the invariant.Propagation to the desktop
No desktop changes are needed. Once a relay redeploys with this fix,
probe_relay_requires_authindesktop/src-tauri/src/commands/pairing.rswill seeauth_required: trueand append/pairto the QR URL automatically. The pairing flow then routes the phone through the existingsprout-pair-relaysidecar, which has been correctly configured and routed at the nginx layer all along.Tests
nip11::tests::auth_required_is_advertised_true(runs incargo test -p sprout-relay).e2e_relay::test_nip11_relay_info(runs against a live relay).sprout-relayunit tests pass. Clippy clean. Pre-commit hooks (rust-fmt, clippy, rust-tests, desktop-check, desktop-tauri-fmt, desktop-tauri-check, mobile-check, mobile-test, web-check) pass.Reviewed with
Iterated with
codex reviewuntil 10/10 on minimalism, elegance, and correctness.