carlos / platform Public

edges file: publish attached custom domains under their own names (#287)

An attached custom domain on an app that already had a ready route lands
in route_aliases, never routes, so it appeared in no edges file: a
non-home edge neither backhauled it (Home missed) nor answered its
validation or let the issuer order for it (KnownHost missed). Custom
domains on a multi-edge deployment therefore worked only through the
home edge.

The publisher now writes each alias whose primary is a served row under
the alias's own name — role home, never platform-class (a customer's
name derives no wildcard parent). Every reader already does the right
thing with an exact name: Home dials the home box with the alias as
SNI, the home box's own upstream map serves it, KnownHost admits it on
every edge, the issuer orders its per-host cert wherever the validation
lands. A *.parent catch-all alias goes verbatim, as the routes' catch-all
rows do: Home's one-label rule dials it, KnownHost still refuses it
(#180). An alias shadowed by a real route is the route's, as Reload
rules.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 5621c58350fee1cc8a8460096264ce9516b85d18 parent da9a7ee
4 files changed, +122 −0
  • docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md +11 −0
  • internal/edge/wildcard_parents_test.go +26 −0
  • internal/host/edgesfile.go +29 −0
  • internal/host/edgesfile_test.go +56 −0
diff --git a/docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md b/docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md
index 8bf68d77c..89d2f2366 100644
--- a/docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md
+++ b/docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md
@@ -256,6 +256,17 @@ follow-up issue, with one constraint stated in advance: an alias whose
host is a `*.<parent>` catch-all must stay wildcard-cert-only if it is
ever published — the same #180 bound this amendment refuses to widen.
+*Amendment 2026-08-26 (#287): done.* The publisher writes each alias
+whose primary is a served row under the alias's own name (`role:
+"home"`, never `platform`), so `Home` backhauls it and `KnownHost`
+admits it on every edge — the issuer orders its per-host cert whichever
+edge the validation lands on. A `*.<parent>` catch-all alias goes
+verbatim, exactly as the routes' catch-all rows do: `Home`'s one-label
+rule dials it, `KnownHost` still refuses it. Custom domains on a
+multi-edge deployment therefore work through any edge — `CNAME` to
+`edge.<apps-domain>` inherits steering and failover; an apex needs the
+current edge-IP set (#299).
+
**Order amplification, accepted.** The set of names a stranger can induce
a fresh ACME order for at the issuer grows from one box's routes to every
box's routes. Each such order for a name whose DNS is dead burns that
diff --git a/internal/edge/wildcard_parents_test.go b/internal/edge/wildcard_parents_test.go
index a97052123..6b234ee3c 100644
--- a/internal/edge/wildcard_parents_test.go
+++ b/internal/edge/wildcard_parents_test.go
@@ -250,3 +250,29 @@ func TestWildcardRefreshIsSerialized(t *testing.T) {
t.Fatalf("parents = %v after generation %d", got, final)
}
}
+
+// #287, reader side: an attached custom domain published under its own
+// name (never platform-class) backhauls, passes the cert gates' exact
+// admission, and derives no wildcard parent; its catch-all form dials but
+// is never an exact admission (#180).
+func TestAliasEntriesBackhaulAndAdmitButDeriveNoParent(t *testing.T) {
+ e, _, base := remoteHomedEdge(t, nil)
+ putJSON(t, base, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","hosts":{"www.customer.com":{"role":"home","platform":false},"*.customer.com":{"role":"home","platform":false},"app.acct.apps.test":{"role":"home","platform":true}}}`)
+ hm := e.homes.Load()
+ refreshHomeMap(t, hm)
+ if _, box, ok := hm.Home("www.customer.com"); !ok || box != "betty" {
+ t.Fatal("alias entry does not backhaul")
+ }
+ if _, _, ok := hm.Home("shop.customer.com"); !ok {
+ t.Fatal("catch-all alias does not dial one label under it")
+ }
+ if !e.deploymentHost("www.customer.com") {
+ t.Fatal("alias entry not admitted by the cert gates")
+ }
+ if e.deploymentHost("*.customer.com") || e.deploymentHost("shop.customer.com") {
+ t.Fatal("a catch-all alias must never be an exact cert admission (#180)")
+ }
+ if got := hm.Hosts(); !reflect.DeepEqual(got, []string{"app.acct.apps.test"}) {
+ t.Fatalf("customer names leaked into the parent input: %v", got)
+ }
+}
diff --git a/internal/host/edgesfile.go b/internal/host/edgesfile.go
index e40f4bea8..27834115c 100644
--- a/internal/host/edgesfile.go
+++ b/internal/host/edgesfile.go
@@ -125,6 +125,35 @@ func edgesFilePass(ctx context.Context, s release.Store, reg *registry.Registry,
// (the leading dot of the first label only) is tried next.
hosts[r.Host] = edgeHost{Role: "home", Platform: r.Platform || r.Provisioned}
}
+ // Attached custom domains (#151) live in route_aliases, not routes, and
+ // were absent from this file (#287): a non-home edge neither backhauled
+ // them (Home missed) nor answered their validations or let the issuer
+ // order for them (KnownHost missed). Publish each alias whose primary is
+ // a served row above, under the alias's own name — the reader wants
+ // exact names, and every reader already does the right thing with one:
+ // Home dials the home box with the alias as SNI, and the home box's own
+ // upstream map serves it. Never platform-class: a customer's name
+ // derives no wildcard parent. A "*.parent" catch-all alias goes verbatim,
+ // as the routes' catch-all rows do — Home's one-label rule dials it,
+ // KnownHost refuses it (PR #180's bound: a wildcard label is never an
+ // exact cert admission). An alias shadowed by a real route is the
+ // route's, as edge.Reload rules.
+ aliases, err := reg.ListAliases()
+ if err != nil {
+ return fmt.Errorf("edges: list aliases: %w", err)
+ }
+ for _, a := range aliases {
+ if a.Alias == "" {
+ continue
+ }
+ if _, served := hosts[a.Host]; !served {
+ continue
+ }
+ if _, taken := hosts[a.Alias]; taken {
+ continue
+ }
+ hosts[a.Alias] = edgeHost{Role: "home"}
+ }
if eip == "" && *last != nil {
var prior edgesFile
diff --git a/internal/host/edgesfile_test.go b/internal/host/edgesfile_test.go
index 79966559a..d167216d3 100644
--- a/internal/host/edgesfile_test.go
+++ b/internal/host/edgesfile_test.go
@@ -612,3 +612,59 @@ func TestEdgesFileMarksPlatformRows(t *testing.T) {
t.Errorf("mark not emitted for an unclassed row: %s", body)
}
}
+
+// #287: attached custom domains are published under their own names —
+// only when their primary is served, never platform-class, catch-alls
+// verbatim, and never over a real route.
+func TestEdgesFilePublishesAliasesOfServedPrimaries(t *testing.T) {
+ s, reg := release.NewDirStore(t.TempDir()), edgesTestRegistry(t)
+ seedRoute(t, reg, "app.acct.apps.test")
+ if err := reg.Upsert(registry.Route{Host: "pending.acct.apps.test", Kind: "service", Addr: "10.0.0.1:3001", Status: "pending"}); err != nil {
+ t.Fatal(err)
+ }
+ if err := reg.Upsert(registry.Route{Host: "real.example.net", Kind: "service", Addr: "10.0.0.1:3002", Status: "ready", Platform: true}); err != nil {
+ t.Fatal(err)
+ }
+ for _, a := range []registry.RouteAlias{
+ {Alias: "www.customer.com", Host: "app.acct.apps.test", Account: "acct", App: "app"},
+ {Alias: "*.customer.com", Host: "app.acct.apps.test", Account: "acct", App: "app"},
+ {Alias: "orphan.example.org", Host: "pending.acct.apps.test", Account: "acct", App: "pending"},
+ {Alias: "real.example.net", Host: "app.acct.apps.test", Account: "acct", App: "app"}, // shadowed
+ } {
+ if err := reg.UpsertAlias(a); err != nil {
+ t.Fatal(err)
+ }
+ }
+ var lastBody []byte
+ if err := edgesFilePass(context.Background(), s, reg, "annie", "1.2.3.4", "", &lastBody); err != nil {
+ t.Fatal(err)
+ }
+ body, _, err := s.Get(context.Background(), "control/edges/annie.json")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var f struct {
+ Hosts map[string]struct {
+ Role string `json:"role"`
+ Platform bool `json:"platform"`
+ } `json:"hosts"`
+ }
+ if err := json.Unmarshal(body, &f); err != nil {
+ t.Fatal(err)
+ }
+ for _, alias := range []string{"www.customer.com", "*.customer.com"} {
+ h, ok := f.Hosts[alias]
+ if !ok || h.Role != "home" {
+ t.Errorf("%s: not published as home (%+v, %v)", alias, h, ok)
+ }
+ if h.Platform {
+ t.Errorf("%s: a customer alias must never be platform-class", alias)
+ }
+ }
+ if _, ok := f.Hosts["orphan.example.org"]; ok {
+ t.Error("an alias of an unserved primary was published")
+ }
+ if h := f.Hosts["real.example.net"]; !h.Platform {
+ t.Error("an alias colliding with a real route displaced the route's entry")
+ }
+}