diff --git a/internal/catalogue/declaration.go b/internal/catalogue/declaration.go index 3e812b7..ab5ab85 100644 --- a/internal/catalogue/declaration.go +++ b/internal/catalogue/declaration.go @@ -596,6 +596,13 @@ func composeName(values map[string]any, publicDomain string) { if !ok || strings.TrimSpace(label) == "" { return } + if strings.TrimSpace(label) == "@" { + // The apex: a module served at the bare public domain, no subdomain — the zone-file + // convention `@`. Composes to the domain itself, so a node's own site is a label like any + // other rather than the one route that must still carry a full name. + values["name"] = publicDomain + return + } values["name"] = strings.TrimSpace(label) + "." + publicDomain } diff --git a/internal/catalogue/routing_test.go b/internal/catalogue/routing_test.go index 08e57a1..f2a4fe4 100644 --- a/internal/catalogue/routing_test.go +++ b/internal/catalogue/routing_test.go @@ -48,6 +48,22 @@ func TestALabelComposesWithTheNodesPublicDomain(t *testing.T) { } } +func TestTheApexLabelComposesToTheBareDomain(t *testing.T) { + got, err := Resolve(shelf(proxy(), labelled("board", "@", 4000)), + []string{"board"}, withDomain("example.tld"), World{}) + if err != nil { + t.Fatal(err) + } + given := received(t, mustDeclare(t, got)) + if len(given) != 1 { + t.Fatalf("the proxy was told about %d of 1: %v", len(given), given) + } + // `@` is the zone-file apex: served at the bare public domain, no subdomain, no leading dot. + if given[0].Values["name"] != "example.tld" { + t.Fatalf("the apex label did not compose to the bare domain: %v", given[0].Values) + } +} + func TestOneNodeSettingMovesTheCatalogueBetweenDomains(t *testing.T) { // The ADR's name-agnostic check: the same catalogue resolves against two different public // domains by changing one node setting and nothing else.