carlos / platform Public

edges file: wildcard entries merge on collision, dial half only with a served catch-all, delegated set capped fleet-wide (#305 review)

Two boxes publishing the same *.<parent> key used to have the fold keep
one entry wholesale, dropping the other's class by sort order — the
parent's PEM would then load nowhere, or the dial target move to the
wrong box. The fold now merges classes and picks one dial target (route
beats alias, any beats none). The dial half is published only when this
box serves the catch-all (role home); a Wildcard claim without Catchall
publishes the cert half alone (role wildcard) so region edges do not
terminate and backhaul invented names to a 503. The manager's delegated
union is capped at 32 fleet-wide with local rows first, logs when remote
parents exist but this box has no delegation zone, and copies before
appending. Remote parents get the shape check local rows had. The #287
withheld-line test resets its once-per-process map.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 16a2e495e86a440ffb2a1bce667ff229c5de4fd1 parent f7d2cab
6 files changed, +192 −26
  • docs/superpowers/specs/2026-08-20-multi-region-ingress-design.md +14 −7
  • internal/edge/homemap.go +37 −13
  • internal/edge/wildcard.go +29 −2
  • internal/edge/wildcard_parents_test.go +62 −0
  • internal/host/edgesfile.go +26 −4
  • internal/host/edgesfile_test.go +24 −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 349212346..3924eed02 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
@@ -258,13 +258,20 @@ 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.
+homed here) publish as `"*.<parent>": {wildcard: true}` with role `home`
+when this box serves the catch-all (a Catchall claim, alias row at a
+served primary) and role `wildcard` — the cert half alone, no dial
+target — otherwise; never `platform`. Every edge folds them: the fold
+MERGES classes on a cross-box collision and picks one dial target
+(route beats alias, any beats none), `Home` dials only entries with a
+dial half, and the wildcard manager unions `WildcardParents()` into its
+delegated set, capped at the per-box table's 32 fleet-wide (local rows
+first, overflow logged) — 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. `CARLOS_ACME_DELEGATION_ZONE`
+is therefore fleet-wide env: a box without it logs when remote parents
+exist, since it could win the issuer lease.
*Amendment 2026-08-26 (#287).* The publisher writes each exact alias
whose primary is a served row AND whose DNS the sweep has stamped
diff --git a/internal/edge/homemap.go b/internal/edge/homemap.go
index 6da38a2e9..a8ed1c4ca 100644
--- a/internal/edge/homemap.go
+++ b/internal/edge/homemap.go
@@ -105,6 +105,11 @@ const (
// not take its whole file — or the poll — down with it.
const edgeRoleHome = "home"
+// edgeRoleWildcard is the cert-only half of a delegated wildcard parent
+// (#305): the parent's PEM should be loaded everywhere, but this box does
+// not serve the catch-all, so the entry is no dial target.
+const edgeRoleWildcard = "wildcard"
+
// homeMapInterval / homeMapTimeout / homeMapBootTimeout mirror the cert
// mirror's cadence and budgets exactly (certsync.go), for the same reasons: a
// home move is a placement event that converge heals, the poll runs on its own
@@ -156,6 +161,9 @@ type homeEntry struct {
alias bool
// wildcard marks a delegated wildcard parent's catch-all entry.
wildcard bool
+ // dial reports whether the entry is a backhaul target (role home). A
+ // cert-only wildcard entry folds with dial false and Home skips it.
+ dial bool
}
// homeSnapshot is one poll's result, swapped in whole and immutable once
@@ -356,7 +364,14 @@ func parentInput(host string, e homeEntry) bool {
}
func wildcardInput(host string, e homeEntry) bool {
- return e.wildcard && strings.HasPrefix(host, "*.") && len(host) > 2
+ if !e.wildcard || !strings.HasPrefix(host, "*.") {
+ return false
+ }
+ parent := host[2:]
+ // The shape a local wildcard_domains row passed (validHostShape at
+ // reconcile), applied to a remote one: a real dotted name, no further
+ // wildcard label, nothing a challenge FQDN could not be built from.
+ return parent != "" && strings.Contains(parent, ".") && !strings.ContainsAny(parent, "*/ \t")
}
// WildcardParents is every delegated customer wildcard parent another box
@@ -492,19 +507,28 @@ func foldHomes(files map[string]edgesFileView, self string) map[string]homeEntry
continue
}
for host, h := range f.Hosts {
- if host == "" || h.Role != edgeRoleHome {
+ if host == "" || (h.Role != edgeRoleHome && h.Role != edgeRoleWildcard) {
+ continue
+ }
+ in := homeEntry{eip: f.EIP, box: f.Box, platform: h.Platform && !h.Alias && !h.Wildcard, alias: h.Alias, wildcard: h.Wildcard, dial: h.Role == edgeRoleHome}
+ prev, dup := hosts[host]
+ if !dup {
+ hosts[host] = in
continue
}
- if prev, dup := hosts[host]; dup {
- // First box in sorted order wins, everywhere — except that a
- // ROUTE beats an ALIAS whatever the order: a tenant attaching
- // an operator's hostname on one box must not capture it on
- // every other (#287).
- if !(prev.alias && !h.Alias) {
- continue
- }
+ // A collision merges CLASSES and picks ONE dial target: the
+ // classes are facts about the name (a delegated parent's PEM
+ // must load everywhere even if some other box also routes the
+ // key), the dial target is a choice. First box in sorted order
+ // wins the dial — except that a ROUTE beats an ALIAS whatever
+ // the order (#287), and any dial target beats none.
+ merged := prev
+ merged.platform = prev.platform || in.platform
+ merged.wildcard = prev.wildcard || in.wildcard
+ if in.dial && (!prev.dial || (prev.alias && !in.alias)) {
+ merged.eip, merged.box, merged.alias, merged.dial = in.eip, in.box, in.alias, true
}
- hosts[host] = homeEntry{eip: f.EIP, box: f.Box, platform: h.Platform && !h.Alias && !h.Wildcard, alias: h.Alias, wildcard: h.Wildcard}
+ hosts[host] = merged
}
}
return hosts
@@ -536,11 +560,11 @@ func (m *homeMap) Home(host string) (eip, box string, ok bool) {
return "", "", false
}
hosts := m.snapshot().hosts
- if h, ok := hosts[host]; ok {
+ if h, ok := hosts[host]; ok && h.dial {
return h.eip, h.box, true
}
if i := strings.IndexByte(host, '.'); i > 0 {
- if h, ok := hosts["*"+host[i:]]; ok {
+ if h, ok := hosts["*"+host[i:]]; ok && h.dial {
return h.eip, h.box, true
}
}
diff --git a/internal/edge/wildcard.go b/internal/edge/wildcard.go
index c46635e17..8e0743bf7 100644
--- a/internal/edge/wildcard.go
+++ b/internal/edge/wildcard.go
@@ -130,6 +130,33 @@ func newWildcardManager(staticDomains []string, appsDomain string, hosts func()
}
}
+// maxDelegatedParents bounds the delegated set this box will carry —
+// local rows plus every parent other boxes publish (#305). The per-box
+// cap on wildcard_domains (internal/domains, 32) exists because every
+// delegated parent shares one ACME account's new-order budget; a fleet's
+// union must not multiply that by the box count, or one broken delegation
+// zone would have the issuer retrying 32×N orders an hour. Local rows come
+// first; the overflow is logged, once per pass, never silently dropped.
+const maxDelegatedParents = 32
+
+// unionDelegated is the delegated source's merge: local rows, then remote
+// parents, capped. A remote parent on a box with NO delegation zone is a
+// rollout mistake worth a line — this box could win the issuer lease and
+// would then fail every order for it against the customer's own zone.
+func unionDelegated(local, remote []string, zone string) []string {
+ out := make([]string, 0, len(local)+len(remote))
+ out = append(out, local...)
+ if len(remote) > 0 && zone == "" {
+ log.Printf("edge: %d delegated wildcard parent(s) published by other boxes but CARLOS_ACME_DELEGATION_ZONE is unset here — set it fleet-wide, or this box cannot issue for them if it becomes the issuer", len(remote))
+ }
+ out = append(out, remote...)
+ if len(out) > maxDelegatedParents {
+ log.Printf("edge: delegated wildcard parents capped at %d (%d present: %d local, %d remote) — the overflow gets no wildcard", maxDelegatedParents, len(out), len(local), len(remote))
+ out = out[:maxDelegatedParents]
+ }
+ return out
+}
+
// parentsFor computes the wildcard parent set: staticAndDelegated (the
// static CARLOS_WILDCARD_DOMAINS plus any delegated parents refresh() has
// already vetted — both arrive pre-merged through this one parameter) union
@@ -804,7 +831,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 append(out, e.homes.Load().WildcardParents()...)
+ return unionDelegated(out, e.homes.Load().WildcardParents(), zone)
}
out := make([]string, 0, len(wds))
for _, w := range wds {
@@ -818,7 +845,7 @@ func newWildcardFromEnv(e *Edge, cache autocert.Cache) *wildcardManager {
// 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()...)
+ return unionDelegated(out, e.homes.Load().WildcardParents(), zone)
}
// 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 7f18f330c..c5cecd5da 100644
--- a/internal/edge/wildcard_parents_test.go
+++ b/internal/edge/wildcard_parents_test.go
@@ -3,6 +3,8 @@ package edge
import (
"context"
"fmt"
+ "log"
+ "os"
"path/filepath"
"reflect"
"sort"
@@ -373,3 +375,63 @@ func TestWildcardManagerUnionsRemoteDelegatedParents(t *testing.T) {
t.Fatal("remote or local delegated parent not marked delegated")
}
}
+
+// Two boxes publishing the same "*.<parent>" key merge CLASSES and pick one
+// dial target (route beats alias, any beats none), whatever the sort order
+// — a delegated parent's PEM must load everywhere even when another box
+// routes the key too. A cert-only entry is a parent but never a dial target.
+func TestHomeMapWildcardCollisionMergesClasses(t *testing.T) {
+ for _, order := range [][2]string{{"aaa", "zzz"}, {"zzz", "aaa"}} {
+ routeBox, wildBox := order[0], order[1]
+ s := meshTestStore(t)
+ putJSON(t, s, "control/edges/"+routeBox+".json", `{"v":1,"box":"`+routeBox+`","eip":"1.1.1.1","hosts":{"*.customer.example":{"role":"home","platform":true}}}`)
+ putJSON(t, s, "control/edges/"+wildBox+".json", `{"v":1,"box":"`+wildBox+`","eip":"2.2.2.2","hosts":{"*.customer.example":{"role":"wildcard","wildcard":true},"*.certonly.example":{"role":"wildcard","wildcard":true}}}`)
+ m := newHomeMap(s, "self")
+ refreshHomeMap(t, m)
+ if _, box, ok := m.Home("x.customer.example"); !ok || box != routeBox {
+ t.Fatalf("order %v: dial = %s/%v; want the route's box %s", order, box, ok, routeBox)
+ }
+ if got := m.WildcardParents(); !reflect.DeepEqual(got, []string{"certonly.example", "customer.example"}) {
+ t.Fatalf("order %v: WildcardParents = %v", order, got)
+ }
+ if _, _, ok := m.Home("x.certonly.example"); ok {
+ t.Fatalf("order %v: a cert-only wildcard entry was a dial target", order)
+ }
+ }
+ // A remote parent of bad shape is not a parent.
+ s := meshTestStore(t)
+ putJSON(t, s, "control/edges/betty.json", `{"v":1,"box":"betty","eip":"2.2.2.2","hosts":{"*.nodot":{"role":"wildcard","wildcard":true},"*.*.double.example":{"role":"wildcard","wildcard":true},"*.ok.example":{"role":"wildcard","wildcard":true}}}`)
+ m := newHomeMap(s, "self")
+ refreshHomeMap(t, m)
+ if got := m.WildcardParents(); !reflect.DeepEqual(got, []string{"ok.example"}) {
+ t.Fatalf("WildcardParents = %v", got)
+ }
+}
+
+// The fleet's delegated set is capped where the per-box table is: local
+// rows first, the overflow logged and dropped.
+func TestUnionDelegatedCapsAndWarns(t *testing.T) {
+ var buf strings.Builder
+ log.SetOutput(&buf)
+ t.Cleanup(func() { log.SetOutput(os.Stderr) })
+ local := []string{"l1.example", "l2.example"}
+ remote := make([]string, 0, 40)
+ for i := 0; i < 40; i++ {
+ remote = append(remote, fmt.Sprintf("r%02d.example", i))
+ }
+ got := unionDelegated(local, remote, "acme.apps.test")
+ if len(got) != maxDelegatedParents || got[0] != "l1.example" || got[1] != "l2.example" || got[2] != "r00.example" {
+ t.Fatalf("union = %d entries, head %v", len(got), got[:3])
+ }
+ if !strings.Contains(buf.String(), "capped at 32") {
+ t.Fatalf("overflow not logged:\n%s", buf.String())
+ }
+ buf.Reset()
+ if got := unionDelegated(local, []string{"r.example"}, ""); len(got) != 3 || !strings.Contains(buf.String(), "CARLOS_ACME_DELEGATION_ZONE is unset") {
+ t.Fatalf("no-zone case: %v / %s", got, buf.String())
+ }
+ buf.Reset()
+ if got := unionDelegated(local, nil, ""); len(got) != 2 || buf.Len() != 0 {
+ t.Fatalf("local-only case logged or changed: %v / %s", got, buf.String())
+ }
+}
diff --git a/internal/host/edgesfile.go b/internal/host/edgesfile.go
index a45012265..850847120 100644
--- a/internal/host/edgesfile.go
+++ b/internal/host/edgesfile.go
@@ -50,9 +50,10 @@ type edgeHost struct {
// 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.
+ // #305): the key is "*.<parent>" and every edge should load the parent's
+ // mirrored wildcard PEM. With role "home" the box also serves the
+ // catch-all (dial target); with role "wildcard" it is the cert half
+ // alone. Additive (omitempty); never platform.
Wildcard bool `json:"wildcard,omitempty"`
}
@@ -201,6 +202,23 @@ func edgesFilePass(ctx context.Context, s release.Store, reg *registry.Registry,
if err != nil {
return fmt.Errorf("edges: list wildcard domains: %w", err)
}
+ // Two halves, published separately: the CERT half (every edge loads the
+ // parent's PEM) always; the DIAL half (role home — remote edges backhaul
+ // one-label hosts under the parent) only when this box actually serves
+ // the catch-all, i.e. the claim has Catchall and its "*.<parent>" alias
+ // row points at a served primary. A Wildcard claim without Catchall
+ // serves only its exact aliases (published above, each on its own
+ // terms); advertising a dial target for it would have region edges
+ // terminate and backhaul any invented name under the parent to a box
+ // that answers 503.
+ catchallServed := map[string]bool{}
+ for _, a := range aliases {
+ if parent, ok := strings.CutPrefix(a.Alias, "*."); ok {
+ if _, served := hosts[a.Host]; served {
+ catchallServed[parent] = true
+ }
+ }
+ }
for _, wd := range wds {
if wd.Host == "" || strings.HasPrefix(wd.Host, "*.") {
continue
@@ -209,7 +227,11 @@ func edgesFilePass(ctx context.Context, s release.Store, reg *registry.Registry,
if _, taken := hosts[key]; taken {
continue
}
- hosts[key] = edgeHost{Role: "home", Wildcard: true}
+ role := "wildcard"
+ if catchallServed[wd.Host] {
+ role = "home"
+ }
+ hosts[key] = edgeHost{Role: role, Wildcard: true}
}
if eip == "" && *last != nil {
diff --git a/internal/host/edgesfile_test.go b/internal/host/edgesfile_test.go
index 5dbd7447c..e477e740e 100644
--- a/internal/host/edgesfile_test.go
+++ b/internal/host/edgesfile_test.go
@@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"strings"
+ "sync"
"testing"
"time"
@@ -620,6 +621,7 @@ func TestEdgesFileMarksPlatformRows(t *testing.T) {
// aliases, never platform-class, catch-alls never, and never over a real
// route. Detaching one republishes without it.
func TestEdgesFilePublishesPointingAliasesOfServedPrimaries(t *testing.T) {
+ withheldAliasSaid = sync.Map{} // once per PROCESS: isolate from -count>1
s, reg := release.NewDirStore(t.TempDir()), edgesTestRegistry(t)
if err := reg.Upsert(registry.Route{Host: "app.acct.apps.test", Kind: "service", Addr: "10.0.0.1:3000", Status: "ready", Platform: true}); err != nil {
t.Fatal(err)
@@ -704,8 +706,24 @@ func TestEdgesFilePublishesDelegatedWildcardParents(t *testing.T) {
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)
}
+ // customer.example has a served catch-all (Catchall claim) → dial half
+ // too; certonly.example is a Wildcard claim without Catchall → cert
+ // half only; pending.example's catch-all points at an unserved primary.
+ if err := reg.Upsert(registry.Route{Host: "pend.acct.apps.test", Kind: "service", Addr: "10.0.0.1:3002", Status: "pending"}); err != nil {
+ t.Fatal(err)
+ }
+ for _, a := range []registry.RouteAlias{
+ {Alias: "*.customer.example", Host: "app.acct.apps.test", Account: "acct", App: "app"},
+ {Alias: "*.pending.example", Host: "pend.acct.apps.test", Account: "acct", App: "pend"},
+ } {
+ if err := reg.UpsertAlias(a); err != nil {
+ t.Fatal(err)
+ }
+ }
for _, w := range []registry.WildcardDomain{
{Host: "customer.example", Account: "acct", App: "app"},
+ {Host: "certonly.example", Account: "acct", App: "app"},
+ {Host: "pending.example", Account: "acct", App: "pend"},
{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
} {
@@ -735,6 +753,12 @@ func TestEdgesFilePublishesDelegatedWildcardParents(t *testing.T) {
if !ok || h.Role != "home" || !h.Wildcard || h.Platform {
t.Fatalf("*.customer.example = %+v, %v; want home, wildcard, not platform", h, ok)
}
+ for _, name := range []string{"*.certonly.example", "*.pending.example"} {
+ h, ok := f.Hosts[name]
+ if !ok || h.Role != "wildcard" || !h.Wildcard || h.Platform {
+ t.Errorf("%s = %+v, %v; want the cert half only (role wildcard)", name, h, ok)
+ }
+ }
if _, ok := f.Hosts["*.*.odd.example"]; ok {
t.Error("a malformed wildcard_domains row was published")
}