fix(core): fold loopback hosts to 127.0.0.1 in tenant host normalization - #4784
Open
tonbistudio wants to merge 1 commit into
Open
fix(core): fold loopback hosts to 127.0.0.1 in tenant host normalization#4784tonbistudio wants to merge 1 commit into
tonbistudio wants to merge 1 commit into
Conversation
Clients canonicalize loopback relay URLs to 127.0.0.1 before connecting: buzz-core's normalize_relay_url rewrites localhost/[::1] for the managed agent runtime key, the desktop passes that canonicalized URL to spawned agent harnesses, and buzz-auth's NIP-42 check applies the same equivalence. Host-based community resolution compared the literal Host header, so a deployment with BUZZ_DOMAIN=localhost was half-reachable: the desktop app connected fine while every agent harness got 404 on the WebSocket upgrade and exited with code 1. Fold localhost, [::1], and any 127.0.0.0/8 address to 127.0.0.1 in normalize_host - the single normalization rule shared by storage and lookup - preserving explicit non-default ports. Non-loopback hosts are unchanged, including near-misses like localhost.example. Note for existing loopback deployments: a community stored under a localhost host key will be ensured under 127.0.0.1 on next startup; operators should set BUZZ_DOMAIN/RELAY_URL to 127.0.0.1, or stored loopback host rows can be rewritten by migration. Co-Authored-By: Claude Fable 5 <[email protected]> Signed-off-by: ntombisol <[email protected]>
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.
Problem
On any deployment with a loopback
BUZZ_DOMAIN(e.g. the compose stack withBUZZ_DOMAIN=localhost), the desktop app connects fine but every managed-agent harness gets404 Not Foundon the WebSocket upgrade and exits with code 1.The two sides disagree about loopback equivalence:
buzz-core::relay::normalize_relay_urlrewrites every loopback host (localhost,[::1],127.0.0.0/8) to127.0.0.1. The desktop runs the workspace relay URL through it for the managed-agent runtime key (ManagedAgentRuntimeKey::new) and passes the canonicalized URL to the spawned harness asBUZZ_RELAY_URL(managed_agents/runtime.rs).buzz-auth's NIP-42 verification applies the same equivalence (nip42.rsnormalize_relay_url).buzz-core::tenant::normalize_host) does no loopback folding, so a community stored underlocalhost:3000never matches a connection whose Host is127.0.0.1:3000.The repo already half-knows about this footgun —
desktop/tests/helpers/seed.tswarns: "localhost!=127.0.0.1to normalize_host — … or every /query 404s."Reproduction: deploy
deploy/composewithBUZZ_DOMAIN=localhost, add the community in the desktop app asws://localhost:3000, start any managed agent. The app works; the agent harness logsinitial relay connect failed with terminal error: WebSocket error: HTTP error: 404 Not Foundand dies.Fix
Fold loopback hosts (
localhost,[::1], any127.0.0.0/8address) to the canonical127.0.0.1innormalize_host— the single normalization rule shared by storage (communities.host) and lookup — preserving explicit non-default ports. This mirrors the equivalence clients already apply, and it lands at the one choke point, sorelay_url_authority(startup seeding,bind_deployment_community,buzz-admin) inherits it automatically.Non-loopback hosts are unchanged; near-misses (
localhost.example,128.0.0.1) stay distinct tenants (covered by tests).Tests
buzz-core: newnormalize_host_folds_loopback_variantsandnormalize_host_does_not_fold_non_loopback; existing tests that pinned the unfolded behavior updated ([::1]cases now use non-loopback IPv6 literals to keep testing bracket preservation).buzz-relay: newdeployment_loopback_spellings_bind_to_one_communityregression test — a community seeded from any loopbackRELAY_URLspelling binds for all loopback connection hosts.cargo test -p buzz-coreandcargo test -p buzz-relay --lib tenantpass.Compatibility note
An existing deployment whose community row is stored under a
localhosthost key will, after this change, be ensured/looked up under127.0.0.1. That is the intended convergence, but operators of existing loopback deployments will see a fresh deployment community unless stored loopback host rows are rewritten. If preferred, I can add a migration that folds existing stored loopback hosts — happy to take guidance from maintainers on which shape you want.An alternative fix (passing the un-normalized URL to spawned harnesses) was considered and rejected: it only fixes the desktop's own agents, while this fixes all clients that canonicalize, and keeps the NIP-42 equivalence consistent end to end.
🤖 Generated with Claude Code