445fbf8cda
Two simplifications: 1. Derive admin URL from RelayEngine.url. NIP-86 spec mandates that the admin endpoint is "the same URI as ws(s)://, called via http(s)://" — so KtorRelay derives the NIP-98 binding URL by calling relay.url.toHttp() instead of accepting publicUrl as a separate config. Single source of truth (info.relay_url), accidental misconfiguration impossible, no Host-header fallback. StaticConfig.AdminSection.public_url is gone. 2. Uniform code path for admin-enabled vs disabled. Empty allow-list isn't a special case anywhere: Nip86Server.isAuthorized returns false for everyone, dispatch rejects, Nip86HttpHandler returns NotAdmin → 403. KtorRelay always assembles the Nip86HttpRoute and registers the POST endpoint; Nip86Server.isEnabled() and the "is admin on?" branches in the handler and route are deleted. Nip86EndToEndTest's admin-disabled case is now a behavioral test: sign a valid token, expect 403 NotAdmin (was 405 with the no-route variant, was 403 with the fake-disabled-route variant). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>