carlos / platform Public

registry: wildcard_domains table — pass-owned delegated wildcard parents

Paul Campbell dfdb1390e692826a98ddd34e7a6171b3515cc44e parent 9e7ecf9
2 files changed, +89 −0
  • internal/registry/registry.go +60 −0
  • internal/registry/registry_test.go +29 −0
diff --git a/internal/registry/registry.go b/internal/registry/registry.go
index 124ce77a6..df32d490c 100644
--- a/internal/registry/registry.go
+++ b/internal/registry/registry.go
@@ -346,6 +346,19 @@ CREATE TABLE IF NOT EXISTS route_aliases (
dns_checked_at INTEGER NOT NULL DEFAULT 0,
cert_expires_at INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0
+);`); err != nil {
+ return err
+ }
+ // wildcard_domains is a derived table (a later reconcile pass owns every
+ // row, materializing domains.Claim records whose Wildcard capability is
+ // set into it) — a plain CREATE TABLE IF NOT EXISTS, same shape as
+ // route_aliases above: additive, so existing DBs migrate on open.
+ if _, err := r.sql.Exec(`
+CREATE TABLE IF NOT EXISTS wildcard_domains (
+ host TEXT PRIMARY KEY,
+ account TEXT NOT NULL DEFAULT '',
+ app TEXT NOT NULL DEFAULT '',
+ created_at INTEGER NOT NULL DEFAULT 0
);`); err != nil {
return err
}
@@ -1261,6 +1274,53 @@ func (r *Registry) SetAliasCertExpiresAt(alias string, at int64) error {
return err
}
+// WildcardDomain is one derived row of the wildcard_domains table: a
+// customer domain whose claim carries wildcard:true and whose primary
+// route lives on this box — i.e. a delegated wildcard-cert parent the
+// edge should obtain *.host for. Wholly pass-owned, like route_aliases:
+// every row traces to a claim, so removal needs no ownership flag.
+type WildcardDomain struct {
+ Host string
+ Account string
+ App string
+ CreatedAt int64
+}
+
+// ListWildcardDomains returns every wildcard domain, ordered by host.
+func (r *Registry) ListWildcardDomains() ([]WildcardDomain, error) {
+ rows, err := r.sql.Query(`SELECT host, account, app, created_at FROM wildcard_domains ORDER BY host`)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var out []WildcardDomain
+ for rows.Next() {
+ var w WildcardDomain
+ if err := rows.Scan(&w.Host, &w.Account, &w.App, &w.CreatedAt); err != nil {
+ return nil, err
+ }
+ out = append(out, w)
+ }
+ return out, rows.Err()
+}
+
+// UpsertWildcardDomain inserts or updates a row by host.
+func (r *Registry) UpsertWildcardDomain(w WildcardDomain) error {
+ _, err := r.sql.Exec(`
+INSERT INTO wildcard_domains (host, account, app, created_at)
+VALUES (?, ?, ?, ?)
+ON CONFLICT(host) DO UPDATE SET account=excluded.account, app=excluded.app, created_at=excluded.created_at`,
+ w.Host, w.Account, w.App, w.CreatedAt)
+ return err
+}
+
+// DeleteWildcardDomain removes host's row. Idempotent: a host already gone
+// is a success, same contract as DeleteAlias.
+func (r *Registry) DeleteWildcardDomain(host string) error {
+ _, err := r.sql.Exec(`DELETE FROM wildcard_domains WHERE host = ?`, host)
+ return err
+}
+
// Fingerprint summarizes the routes, fleets, fleet_boxes and route_aliases
// tables over a fresh connection, for the edge's cheap change poll. It is
// content-accurate: it hashes the actual VALUES of the reload-relevant
diff --git a/internal/registry/registry_test.go b/internal/registry/registry_test.go
index 0f8717b7b..b06d0734d 100644
--- a/internal/registry/registry_test.go
+++ b/internal/registry/registry_test.go
@@ -2020,3 +2020,32 @@ func TestMigrateIdempotentWithAliases(t *testing.T) {
t.Fatalf("route_aliases row lost across a second Open: %+v", got)
}
}
+
+func TestWildcardDomains(t *testing.T) {
+ r := openTestRegistry(t)
+
+ if err := r.UpsertWildcardDomain(WildcardDomain{Host: "woodstar.app", Account: "bab", App: "woodstar-relay", CreatedAt: 100}); err != nil {
+ t.Fatal(err)
+ }
+ if err := r.UpsertWildcardDomain(WildcardDomain{Host: "example.org", Account: "bad", App: "other", CreatedAt: 200}); err != nil {
+ t.Fatal(err)
+ }
+ // Upsert by host: same host, new owner fields win.
+ if err := r.UpsertWildcardDomain(WildcardDomain{Host: "woodstar.app", Account: "bab", App: "woodstar-relay2", CreatedAt: 300}); err != nil {
+ t.Fatal(err)
+ }
+ got, err := r.ListWildcardDomains()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(got) != 2 || got[0].Host != "example.org" || got[1].Host != "woodstar.app" || got[1].App != "woodstar-relay2" {
+ t.Fatalf("list = %+v", got)
+ }
+ if err := r.DeleteWildcardDomain("example.org"); err != nil {
+ t.Fatal(err)
+ }
+ got, _ = r.ListWildcardDomains()
+ if len(got) != 1 || got[0].Host != "woodstar.app" {
+ t.Fatalf("after delete: %+v", got)
+ }
+}