carlos / platform Public

edges file: delegated customer wildcards are published and loaded on every edge (#305)

A delegated parent (wildcard_domains) lived only in the registry of the
box homing its primary, so a region edge never loaded the parent's
wildcard PEM the mirror had already put on its disk: pds.woodstar.app
terminated on IE and failed TLS through AU/UK/US while woodstar.app
itself, an exact alias, worked everywhere after #287.

The publisher writes each parent as "*.<parent>" in its own class
(wildcard: true, never platform); the fold keeps it; WildcardParents()
hands the bare parents to the wildcard manager's delegated source, which
unions them with its local rows on every pass — a non-issuer loadCached()s
the mirrored PEM, the issuer already minted it — and a delegated entry
appearing or leaving wakes the manager. Home's one-label rule dials hosts
under the parent as it already did for a catch-all row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev f7d2cabdbdae4194f4e09631b844caf109dbf58c parent 845a850
6 files changed, +206 −11
  • docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md +12 −2
  • internal/edge/homemap.go +38 −7
  • internal/edge/wildcard.go +7 −2
  • internal/edge/wildcard_parents_test.go +76 −0
  • internal/host/edgesfile.go +26 −0
  • internal/host/edgesfile_test.go +47 −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 70efa2bd9..349212346 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,16 @@ 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 (#305).* Delegated customer wildcard parents
+(`wildcard_domains` rows — a claim with the Wildcard capability, primary
+homed here) publish as `"*.<parent>": {role: home, wildcard: true}`,
+never `platform`. Every edge folds them: `Home`'s one-label rule dials
+hosts under the parent, and the wildcard manager unions
+`WildcardParents()` into its delegated set — a non-issuer loads the
+parent's mirrored PEM, the issuer minted it — so `pds.customer.example`
+terminates on a region edge exactly as on the home box. Precedence is
+unchanged: a static or apps-domain parent still beats a delegated one.
+
*Amendment 2026-08-26 (#287).* The publisher writes each exact alias
whose primary is a served row AND whose DNS the sweep has stamped
`pointing` under the alias's own name (`role: "home"`, `alias: true`,
@@ -265,8 +275,8 @@ gate keeps the issuer's orderable set to names that actually resolve
here (attach needs no DNS proof, so the raw alias set is tenant-chosen
and unbounded); the fold lets a route beat an alias on a cross-box name
collision, whatever the boxes' sort order; a `*.<parent>` catch-all
-alias is NOT published — its delegated wildcard parent is box-local, so
-a remote edge could dial it but never terminate it. Two residuals stay
+alias is NOT published from the alias table — its dial target comes from
+the wildcard entry below. Two residuals stay
as they were: an ORDER still only starts from a hello reaching the
issuer (#286), so a steered custom domain whose hellos never land there
stays certless; and nothing purges `control/certs/` on detach. Net for
diff --git a/internal/edge/homemap.go b/internal/edge/homemap.go
index 3ef5cf39a..6da38a2e9 100644
--- a/internal/edge/homemap.go
+++ b/internal/edge/homemap.go
@@ -141,6 +141,9 @@ type edgesHostView struct {
// Alias marks an attached custom domain (#287). On a name collision
// across boxes a route entry beats an alias entry (foldHomes).
Alias bool `json:"alias,omitempty"`
+ // Wildcard marks a delegated customer wildcard parent's catch-all entry
+ // (#305): WildcardParents feeds it to the wildcard manager.
+ Wildcard bool `json:"wildcard,omitempty"`
}
// homeEntry is one folded answer: where to dial, and which box that is.
@@ -151,6 +154,8 @@ type homeEntry struct {
platform bool
// alias marks an attached custom domain's entry (never platform).
alias bool
+ // wildcard marks a delegated wildcard parent's catch-all entry.
+ wildcard bool
}
// homeSnapshot is one poll's result, swapped in whole and immutable once
@@ -326,29 +331,55 @@ func (m *homeMap) refreshHosts(ctx context.Context) error {
func samePlatformSet(a, b map[string]homeEntry) bool {
na, nb := 0, 0
for h, e := range a {
- if !parentInput(h, e) {
+ if !parentInput(h, e) && !wildcardInput(h, e) {
continue
}
na++
- if eb, ok := b[h]; !ok || !parentInput(h, eb) {
+ if eb, ok := b[h]; !ok || (parentInput(h, e) != parentInput(h, eb)) || (wildcardInput(h, e) != wildcardInput(h, eb)) {
return false
}
}
for h, e := range b {
- if parentInput(h, e) {
+ if parentInput(h, e) || wildcardInput(h, e) {
nb++
}
}
return na == nb
}
-// parentInput is the one filter Hosts and samePlatformSet share: a marked,
-// exact (non catch-all) name. A catch-all coming or going cannot move a
-// parent, so it must not wake the manager either.
+// parentInput is the filter Hosts and samePlatformSet share for ACCOUNT
+// parents: a marked, exact (non catch-all) name. wildcardInput is its twin
+// for delegated parents (WildcardParents). Anything else coming or going
+// cannot move a parent, so it must not wake the manager either.
func parentInput(host string, e homeEntry) bool {
return e.platform && !strings.HasPrefix(host, "*.")
}
+func wildcardInput(host string, e homeEntry) bool {
+ return e.wildcard && strings.HasPrefix(host, "*.") && len(host) > 2
+}
+
+// WildcardParents is every delegated customer wildcard parent another box
+// publishes ("*.<parent>" entries marked wildcard, #305), as bare parents.
+// The wildcard manager unions these with its own wildcard_domains rows so
+// a region edge loads the parent's mirrored PEM and terminates the
+// one-label hosts Home already dials for it. Sorted, nil-safe, nothing for
+// an unlabelled box (as Hosts).
+func (m *homeMap) WildcardParents() []string {
+ if m == nil || m.self == "" {
+ return nil
+ }
+ snap := m.snapshot()
+ out := make([]string, 0)
+ for h, e := range snap.hosts {
+ if wildcardInput(h, e) {
+ out = append(out, strings.TrimPrefix(h, "*."))
+ }
+ }
+ sort.Strings(out)
+ return out
+}
+
// Hosts is every exact PLATFORM-class name the deployment's OTHER boxes
// home. Sorted, nil-safe. The wildcard manager unions these with this box's
// own routes so its parent set is the deployment's, not the box's (#300):
@@ -473,7 +504,7 @@ func foldHomes(files map[string]edgesFileView, self string) map[string]homeEntry
continue
}
}
- hosts[host] = homeEntry{eip: f.EIP, box: f.Box, platform: h.Platform && !h.Alias, alias: h.Alias}
+ hosts[host] = homeEntry{eip: f.EIP, box: f.Box, platform: h.Platform && !h.Alias && !h.Wildcard, alias: h.Alias, wildcard: h.Wildcard}
}
}
return hosts
diff --git a/internal/edge/wildcard.go b/internal/edge/wildcard.go
index 681c3bfa1..c46635e17 100644
--- a/internal/edge/wildcard.go
+++ b/internal/edge/wildcard.go
@@ -804,7 +804,7 @@ func newWildcardFromEnv(e *Edge, cache autocert.Cache) *wildcardManager {
out := append([]string(nil), lastGood...)
mu.Unlock()
log.Printf("edge: wildcard domains read failed: %v — delegated set unchanged this pass", err)
- return out
+ return append(out, e.homes.Load().WildcardParents()...)
}
out := make([]string, 0, len(wds))
for _, w := range wds {
@@ -813,7 +813,12 @@ func newWildcardFromEnv(e *Edge, cache autocert.Cache) *wildcardManager {
mu.Lock()
lastGood = out
mu.Unlock()
- return out
+ // Plus every delegated parent another box publishes (#305): the
+ // issuer minted its wildcard, the mirror put the PEM on this disk,
+ // and refresh's static/apps-domain precedence applies to these
+ // exactly as to local rows. Read-through, never folded into
+ // lastGood: the home map is its own last-good.
+ return append(out, e.homes.Load().WildcardParents()...)
}
// Hosts are the DEPLOYMENT's (this box's routes plus every name another
// box homes, #300), so a region edge derives the account parents of apps
diff --git a/internal/edge/wildcard_parents_test.go b/internal/edge/wildcard_parents_test.go
index 3a233d6bb..7f18f330c 100644
--- a/internal/edge/wildcard_parents_test.go
+++ b/internal/edge/wildcard_parents_test.go
@@ -297,3 +297,79 @@ func TestHomeMapRouteBeatsAliasOnCollision(t *testing.T) {
}
}
}
+
+// #305, reader side: a marked "*.<parent>" entry is a delegated parent for
+// the wildcard manager AND a dial target for hosts one label under it; an
+// unmarked catch-all (a pre-#305 file, or a route's own catch-all row) is
+// only the latter. A wildcard entry appearing wakes the manager.
+func TestHomeMapWildcardParents(t *testing.T) {
+ s := meshTestStore(t)
+ putJSON(t, s, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","hosts":{"*.customer.example":{"role":"home","wildcard":true},"*.plain.example":{"role":"home"},"app.acct.apps.test":{"role":"home","platform":true}}}`)
+ m := newHomeMap(s, "annie")
+ var woke atomic.Int32
+ m.setHostsWake(func() { woke.Add(1) })
+ refreshHomeMap(t, m)
+ waitWoke(t, &woke, 1)
+ if got := m.WildcardParents(); !reflect.DeepEqual(got, []string{"customer.example"}) {
+ t.Fatalf("WildcardParents = %v", got)
+ }
+ if got := m.Hosts(); !reflect.DeepEqual(got, []string{"app.acct.apps.test"}) {
+ t.Fatalf("a wildcard entry leaked into Hosts: %v", got)
+ }
+ for _, h := range []string{"pds.customer.example", "x.plain.example"} {
+ if _, box, ok := m.Home(h); !ok || box != "betty" {
+ t.Errorf("%s: not dialed via the catch-all", h)
+ }
+ }
+ // A second delegated parent lands: wake.
+ putJSON(t, s, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","hosts":{"*.customer.example":{"role":"home","wildcard":true},"*.second.example":{"role":"home","wildcard":true},"app.acct.apps.test":{"role":"home","platform":true}}}`)
+ refreshHomeMap(t, m)
+ waitWoke(t, &woke, 2)
+ if got := m.WildcardParents(); !reflect.DeepEqual(got, []string{"customer.example", "second.example"}) {
+ t.Fatalf("WildcardParents = %v", got)
+ }
+ // An unmarked catch-all coming or going still wakes nobody.
+ putJSON(t, s, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","hosts":{"*.customer.example":{"role":"home","wildcard":true},"*.second.example":{"role":"home","wildcard":true},"app.acct.apps.test":{"role":"home","platform":true},"*.plain2.example":{"role":"home"}}}`)
+ refreshHomeMap(t, m)
+ time.Sleep(20 * time.Millisecond)
+ if woke.Load() != 2 {
+ t.Fatalf("an unmarked catch-all woke the manager (%d)", woke.Load())
+ }
+ var unlabelled *homeMap
+ if unlabelled.WildcardParents() != nil {
+ t.Fatal("nil map reported parents")
+ }
+}
+
+// The manager built from env on a region edge unions the remote delegated
+// parent: it is in the parent set AND delegated (challenge via the
+// delegation zone), alongside its own local rows.
+func TestWildcardManagerUnionsRemoteDelegatedParents(t *testing.T) {
+ e, _, base := remoteHomedEdge(t, nil)
+ reg, err := registry.Open(filepath.Join(t.TempDir(), "registry.db"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Cleanup(func() { reg.Close() })
+ e.reg = reg
+ if err := reg.UpsertWildcardDomain(registry.WildcardDomain{Host: "local.example", Account: "acct", App: "app"}); err != nil {
+ t.Fatal(err)
+ }
+ putJSON(t, base, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","hosts":{"*.customer.example":{"role":"home","wildcard":true}}}`)
+ refreshHomeMap(t, e.homes.Load())
+ t.Setenv("CARLOS_WILDCARD_DOMAINS", "")
+ t.Setenv("PLATFORM_APPS_DOMAIN", "apps.test")
+ t.Setenv("CARLOS_DNS_PROVIDER", "route53")
+ t.Setenv("CARLOS_ACME_DELEGATION_ZONE", "acme.apps.test")
+ w := newWildcardFromEnv(e, autocert.DirCache(t.TempDir()))
+ if w == nil {
+ t.Fatal("want a manager")
+ }
+ w.refresh()
+ if got := w.currentParents(); !reflect.DeepEqual(got, []string{"customer.example", "local.example"}) {
+ t.Fatalf("parents = %v", got)
+ }
+ if !w.isDelegated("customer.example") || !w.isDelegated("local.example") {
+ t.Fatal("remote or local delegated parent not marked delegated")
+ }
+}
diff --git a/internal/host/edgesfile.go b/internal/host/edgesfile.go
index 715c7467d..a45012265 100644
--- a/internal/host/edgesfile.go
+++ b/internal/host/edgesfile.go
@@ -49,6 +49,11 @@ type edgeHost struct {
// route beat an alias on a name collision across boxes: a tenant
// attaching an operator's hostname must never capture it fleet-wide.
Alias bool `json:"alias,omitempty"`
+ // Wildcard marks a delegated customer wildcard parent (wildcard_domains,
+ // #305): the key is "*.<parent>", the box homes everything one label
+ // under it, and every edge should load the parent's mirrored wildcard
+ // PEM. Additive (omitempty); never platform.
+ Wildcard bool `json:"wildcard,omitempty"`
}
// edgesFile is the wire shape at edgesFileKey(box), schema v1 (spec Part 3):
@@ -186,6 +191,27 @@ func edgesFilePass(ctx context.Context, s release.Store, reg *registry.Registry,
hosts[a.Alias] = edgeHost{Role: "home", Alias: true}
}
+ // Delegated customer wildcards (#305): the wildcard_domains rows are the
+ // parents this box obtains "*.<parent>" for (a claim with the Wildcard
+ // capability, primary homed here). Published as the catch-all key with
+ // its own class so a remote edge both dials one-label hosts under it
+ // (Home's rule) and loads the parent's mirrored wildcard PEM — the two
+ // halves #302 could not deliver from an alias row alone. Never platform.
+ wds, err := reg.ListWildcardDomains()
+ if err != nil {
+ return fmt.Errorf("edges: list wildcard domains: %w", err)
+ }
+ for _, wd := range wds {
+ if wd.Host == "" || strings.HasPrefix(wd.Host, "*.") {
+ continue
+ }
+ key := "*." + wd.Host
+ if _, taken := hosts[key]; taken {
+ continue
+ }
+ hosts[key] = edgeHost{Role: "home", Wildcard: true}
+ }
+
if eip == "" && *last != nil {
var prior edgesFile
if err := json.Unmarshal(*last, &prior); err == nil {
diff --git a/internal/host/edgesfile_test.go b/internal/host/edgesfile_test.go
index b56d0392b..5dbd7447c 100644
--- a/internal/host/edgesfile_test.go
+++ b/internal/host/edgesfile_test.go
@@ -695,3 +695,50 @@ func TestEdgesFilePublishesPointingAliasesOfServedPrimaries(t *testing.T) {
t.Error("a detached alias was still published")
}
}
+
+// #305: delegated customer wildcard parents publish as "*.<parent>" in their
+// own class — never platform, never over an existing key.
+func TestEdgesFilePublishesDelegatedWildcardParents(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: "*.taken.example", Kind: "service", Addr: "10.0.0.1:3001", Status: "ready", Platform: true}); err != nil {
+ t.Fatal(err)
+ }
+ for _, w := range []registry.WildcardDomain{
+ {Host: "customer.example", Account: "acct", App: "app"},
+ {Host: "*.odd.example", Account: "acct", App: "app"}, // never written by the pass; refused here too
+ {Host: "taken.example", Account: "acct", App: "app"}, // a real route owns the key
+ } {
+ if err := reg.UpsertWildcardDomain(w); 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"`
+ Wildcard bool `json:"wildcard"`
+ } `json:"hosts"`
+ }
+ if err := json.Unmarshal(body, &f); err != nil {
+ t.Fatal(err)
+ }
+ h, ok := f.Hosts["*.customer.example"]
+ if !ok || h.Role != "home" || !h.Wildcard || h.Platform {
+ t.Fatalf("*.customer.example = %+v, %v; want home, wildcard, not platform", h, ok)
+ }
+ if _, ok := f.Hosts["*.*.odd.example"]; ok {
+ t.Error("a malformed wildcard_domains row was published")
+ }
+ if h := f.Hosts["*.taken.example"]; !h.Platform || h.Wildcard {
+ t.Errorf("a wildcard entry displaced a real route's key: %+v", h)
+ }
+}