package domains // Internal-package tests for reconcile.go's unexported helpers // (hostCertExpiry, mintedRoute, materializeAccounts): reconcile_test.go // is package domains_test and cannot reach these, so this file follows // slugname_test.go's existing convention of a same-package test file living // alongside it. import ( "bytes" "context" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "errors" "io" "log" "math/big" "net" "os" "path/filepath" "testing" "time" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/release" ) // writeWildcardPEM writes a self-signed cert for name valid until notAfter, // in the acme-cache bundle layout certExpiry parses: key block first, then // the certificate. func writeWildcardPEM(t *testing.T, path, name string, notAfter time.Time) { t.Helper() key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatal(err) } tmpl := &x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: name}, DNSNames: []string{name}, NotBefore: time.Now().Add(-time.Hour), NotAfter: notAfter, } der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) if err != nil { t.Fatal(err) } keyDER, err := x509.MarshalECPrivateKey(key) if err != nil { t.Fatal(err) } var buf bytes.Buffer if err := pem.Encode(&buf, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER}); err != nil { t.Fatal(err) } if err := pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: der}); err != nil { t.Fatal(err) } if err := os.WriteFile(path, buf.Bytes(), 0o600); err != nil { t.Fatal(err) } } // A wildcard-covered host has no per-host acme cache entry — its expiry must // come from the covering wildcard-.pem instead of reporting 0 // (certless) forever. func TestCertExpiryWildcardFallback(t *testing.T) { dir := t.TempDir() // certExpiry parses "key PEM block(s) first, then CERTIFICATE" — build a // minimal self-signed cert the same way the edge's wildcard PEM is laid // out. Reuse/adapt the cert-building helper if reconcile_test.go already // has one; otherwise inline ecdsa+x509 self-sign exactly as in // internal/edge/wildcard_test.go's selfSignedWildcard. notAfter := time.Now().Add(45 * 24 * time.Hour).Truncate(time.Second) writeWildcardPEM(t, filepath.Join(dir, "wildcard-abs.oncarlos.com.pem"), "*.abs.oncarlos.com", notAfter) host := "kass.abs.oncarlos.com" if got := hostCertExpiry(dir, host, "oncarlos.com"); got != notAfter.Unix() { t.Fatalf("hostCertExpiry = %d, want %d (wildcard fallback)", got, notAfter.Unix()) } // A grandfathered per-host file that expires SOONER than the wildcard // (autocert stopped renewing it once the wildcard took over serving the // host): the wildcard's later expiry must win, not the stale file — the // edge serves the wildcard, so status must not shadow that with a cert // nothing serves anymore. stalePerHost := time.Now().Add(20 * 24 * time.Hour).Truncate(time.Second) writeWildcardPEM(t, filepath.Join(dir, host), host, stalePerHost) if got := hostCertExpiry(dir, host, "oncarlos.com"); got != notAfter.Unix() { t.Fatalf("hostCertExpiry with stale per-host file = %d, want %d (wildcard's later expiry wins)", got, notAfter.Unix()) } // A per-host entry that is LATER than the wildcard still wins. perHost := time.Now().Add(80 * 24 * time.Hour).Truncate(time.Second) writeWildcardPEM(t, filepath.Join(dir, host), host, perHost) if got := hostCertExpiry(dir, host, "oncarlos.com"); got != perHost.Unix() { t.Fatalf("hostCertExpiry with per-host file = %d, want %d", got, perHost.Unix()) } // Nothing at all → 0, unknown, never a guess. if got := hostCertExpiry(dir, "kass.zzz.oncarlos.com", "oncarlos.com"); got != 0 { t.Fatalf("hostCertExpiry with no files = %d, want 0", got) } // A host under a NON-apps-domain wildcard parent (static go.tito.io / // delegated woodstar.app): the fallback must strip one label and try // the parent's wildcard PEM, not require the apps-domain shape. delegatedNotAfter := time.Now().Add(60 * 24 * time.Hour).Truncate(time.Second) writeWildcardPEM(t, filepath.Join(dir, "wildcard-woodstar.app.pem"), "*.woodstar.app", delegatedNotAfter) if got := hostCertExpiry(dir, "paul.woodstar.app", "oncarlos.com"); got != delegatedNotAfter.Unix() { t.Fatalf("delegated-parent fallback = %d, want %d", got, delegatedNotAfter.Unix()) } // The apex itself must NOT match its own wildcard. if got := hostCertExpiry(dir, "woodstar.app", "oncarlos.com"); got != 0 { t.Fatalf("apex must not claim the wildcard: got %d, want 0", got) } } // A host whose only cert is the RSA variant (autocert writes +rsa // alongside when a client can't do ECDSA) has a cert. Reading it as // certless would hold it at "issuing cert" forever. func TestHostCertExpiryFindsTheRSAVariant(t *testing.T) { dir := t.TempDir() notAfter := time.Now().Add(45 * 24 * time.Hour).Truncate(time.Second) writeWildcardPEM(t, filepath.Join(dir, "shop.customer.com+rsa"), "shop.customer.com", notAfter) if got := hostCertExpiry(dir, "shop.customer.com", "oncarlos.com"); got != notAfter.Unix() { t.Fatalf("hostCertExpiry = %d, want %d (rsa variant)", got, notAfter.Unix()) } // The ECDSA per-host file, when it also exists and is LATER, still wins. later := time.Now().Add(80 * 24 * time.Hour).Truncate(time.Second) writeWildcardPEM(t, filepath.Join(dir, "shop.customer.com"), "shop.customer.com", later) if got := hostCertExpiry(dir, "shop.customer.com", "oncarlos.com"); got != later.Unix() { t.Fatalf("hostCertExpiry with later ecdsa file = %d, want %d", got, later.Unix()) } } // An authoritative "no such name" is the customer's record not existing yet. // A resolver FAILURE is ours. Collapsing both to "" makes the status machine // blame the customer for our outage. func TestDNSStatusSeparatesNoRecordFromLookupFailure(t *testing.T) { edge := map[string]bool{"1.1.1.1": true} notFound := func(string) ([]string, error) { return nil, &net.DNSError{Err: "no such host", IsNotFound: true} } if got := dnsStatus(notFound, "absent.customer.com", edge); got != "" { t.Fatalf("NXDOMAIN = %q, want \"\" (no record yet)", got) } servfail := func(string) ([]string, error) { return nil, &net.DNSError{Err: "server misbehaving", IsTemporary: true} } if got := dnsStatus(servfail, "unknown.customer.com", edge); got != "unresolved" { t.Fatalf("resolver failure = %q, want \"unresolved\" — our fault, not the customer's", got) } plain := func(string) ([]string, error) { return nil, errors.New("boom") } if got := dnsStatus(plain, "other.customer.com", edge); got != "unresolved" { t.Fatalf("non-DNSError failure = %q, want \"unresolved\"", got) } } // TestMintedRouteCarriesRegionAndDropsSocketWhenFleetPlaced: a minted // platform apex must carry its source's Region so the edge dispatches it // through the same fleet channel — but when that Region is a fleet // placement, the source's Socket is a path on the FLEET BOX, not this // platform process, so it must NOT be copied onto the mint (I1, final // customer-fleets review). func TestMintedRouteCarriesRegionAndDropsSocketWhenFleetPlaced(t *testing.T) { src := registry.Route{ Kind: "instance", Socket: "/run/carlos/acme.sock", Region: registry.PlacementTarget("pi"), Status: "ready", App: "acme", Account: "abs", } rt := mintedRoute("acme.abs.oncarlos.com", "acme", "abs", src) if rt.Region != src.Region { t.Fatalf("mintedRoute Region = %q, want %q (fleet-placed source)", rt.Region, src.Region) } if rt.Socket != "" { t.Fatalf("mintedRoute Socket = %q, want empty — a fleet-placed source's socket lives on the fleet box, not here", rt.Socket) } // A plain (non-fleet) Region is still copied, and Socket is still copied // too, unchanged from today's behavior — only the fleet-placed case // clears it. src2 := registry.Route{ Kind: "instance", Socket: "/run/carlos/acme.sock", Region: "ie", Status: "ready", App: "acme", Account: "abs", } rt2 := mintedRoute("acme.abs.oncarlos.com", "acme", "abs", src2) if rt2.Region != "ie" { t.Fatalf("mintedRoute Region = %q, want %q (plain region)", rt2.Region, "ie") } if rt2.Socket != src2.Socket { t.Fatalf("mintedRoute Socket = %q, want %q — a non-fleet source's socket is still copied", rt2.Socket, src2.Socket) } } // A failed LOCAL row write does not unmake an account. The manifest is the // authority on which accounts exist; the registry row is only this box's copy // of that fact. known is what makes an apps///… key path // unambiguous, so dropping the sqid on a write failure would make this box // read every one of that account's keys as legacy for the rest of the pass — // silently skipping its trash markers, route linkage and canary pointers // until some later pass happened to get the row written. func TestMaterializeAccountsKeepsAnAccountKnownWhenTheRowWriteFails(t *testing.T) { log.SetOutput(io.Discard) t.Cleanup(func() { log.SetOutput(os.Stderr) }) ctx := context.Background() s := release.NewDirStore(t.TempDir()) const id = 793481920157 sqid := Sqid(id) body := []byte(`{"id":793481920157,"sqid":"` + sqid + `","name":"Kass","created_at":"2026-08-02T09:00:00Z"}`) if _, err := s.Put(ctx, "accounts/"+sqid+"/account.json", body, ""); err != nil { t.Fatal(err) } acctKeys, err := s.List(ctx, "accounts/") if err != nil { t.Fatal(err) } reg, err := registry.Open(filepath.Join(t.TempDir(), "registry.db")) if err != nil { t.Fatal(err) } if err := reg.Close(); err != nil { // every write from here on fails t.Fatal(err) } if err := reg.PutAccount(id, sqid, "Kass"); err == nil { t.Fatal("a closed registry accepted PutAccount — this test injects nothing") } known := materializeAccounts(ctx, s, acctKeys, reg) if !known[sqid] { t.Fatalf("account %s missing from the set: %v — a failed local row write does not unmake an account whose identity already checked out", sqid, known) } // And the consequence that actually matters: the account's app keys still // read as qualified, so the rest of the pass still sees its objects. acct, app, _, ok := appKeyOwner("apps/"+sqid+"/kass/deleted.json", known) if !ok || acct != sqid || app != "kass" { t.Fatalf("appKeyOwner = (%q, %q, %v); want the key read as qualified under %s", acct, app, ok, sqid) } }