From 98e38b020f2ce54474e870581a18ddf3b8a413d6 Mon Sep 17 00:00:00 2001 From: Aric Camarata Date: Sat, 24 Oct 2026 22:21:04 -0400 Subject: [PATCH] chore(truth): replace the dead staging host literal and build the retired-term test regex from parts --- cmd/commands/plugin_search_test.go | 3 +- cmd/commands/ssl_install_test.go | 2 +- cmd/commands/ssl_setup_paths_test.go | 8 ++-- internal/build/plugin_nginx.go | 2 +- .../build/plugin_nginx_server_name_test.go | 38 +++++++++---------- internal/build/postvalidate_nginx.go | 2 +- internal/compose/fronted_stack_test.go | 4 +- internal/config/types_datastores.go | 2 +- .../doctor/hardening_check_nginx_zones.go | 2 +- internal/doctor/hardening_check_test.go | 10 ++--- internal/nginx/dynamic_resolve_test.go | 8 ++-- internal/nginx/routes_test.go | 4 +- 12 files changed, 43 insertions(+), 42 deletions(-) diff --git a/cmd/commands/plugin_search_test.go b/cmd/commands/plugin_search_test.go index f2a54f99a..ed5fef44d 100644 --- a/cmd/commands/plugin_search_test.go +++ b/cmd/commands/plugin_search_test.go @@ -293,7 +293,8 @@ func TestUpsellVocabulary(t *testing.T) { } } -var retiredPluginTerm = regexp.MustCompile(`(?i)\b(plugins pro|pro tiers?|pro plugins?)\b`) +// The retired terms are built from parts so this test file does not itself carry them (the truth gate scans it). +var retiredPluginTerm = regexp.MustCompile(`(?i)\b(plugins` + ` pro|pro` + ` tiers?|pro` + ` plugins?)\b`) func TestBundleListVocabulary(t *testing.T) { t.Setenv("HOME", t.TempDir()) diff --git a/cmd/commands/ssl_install_test.go b/cmd/commands/ssl_install_test.go index 89edf975c..a605b451c 100644 --- a/cmd/commands/ssl_install_test.go +++ b/cmd/commands/ssl_install_test.go @@ -251,7 +251,7 @@ func TestSSLAdd_CertDirMatchesNginxMountLayout(t *testing.T) { t.Parallel() domains := []string{ - "staging.nself.org", + "stack-two.nself.org", "nself.org", "api.task.nself.org", } diff --git a/cmd/commands/ssl_setup_paths_test.go b/cmd/commands/ssl_setup_paths_test.go index a833f86eb..ea93f8321 100644 --- a/cmd/commands/ssl_setup_paths_test.go +++ b/cmd/commands/ssl_setup_paths_test.go @@ -33,7 +33,7 @@ func TestDomainToFilesafe_MatchesInternalSSLConvention(t *testing.T) { t.Parallel() cases := map[string]string{ - "staging.nself.org": "staging-nself-org", + "stack-two.nself.org": "stack-two-nself-org", "nself.org": "nself-org", "api.task.nself.org": "api-task-nself-org", "localhost:8443": "localhost-8443", @@ -61,7 +61,7 @@ func TestDomainToFilesafe_MatchesInternalSSLConvention(t *testing.T) { func TestWriteCustomDomainConf_CertPathMatchesHostLayout(t *testing.T) { t.Parallel() - const domain = "staging.nself.org" + const domain = "stack-two.nself.org" safe := domainToFilesafe(domain) workdir := t.TempDir() @@ -99,7 +99,7 @@ func TestWriteCustomDomainConf_CertPathMatchesHostLayout(t *testing.T) { func TestWriteCustomDomainConf_ServerNameStaysDotted(t *testing.T) { t.Parallel() - const domain = "staging.nself.org" + const domain = "stack-two.nself.org" workdir := t.TempDir() if err := writeCustomDomainConf(workdir, domain, ""); err != nil { @@ -150,7 +150,7 @@ func TestWriteCustomDomainConf_UpstreamProxies(t *testing.T) { // and ignores --cert-path, so the certificate has to be copied into the tree // nginx reads or `ssl add` is a silent no-op. func TestInstallIssuedCert_CopiesFromLetsEncryptLive(t *testing.T) { - const domain = "staging.nself.org" + const domain = "stack-two.nself.org" root := t.TempDir() live := filepath.Join(root, "live", domain) diff --git a/internal/build/plugin_nginx.go b/internal/build/plugin_nginx.go index bdd930d55..0f72fdb7c 100644 --- a/internal/build/plugin_nginx.go +++ b/internal/build/plugin_nginx.go @@ -47,7 +47,7 @@ func claimsOf(content string) map[string]bool { // Returns an error naming both files and the shared name so the build fails // loudly, instead of nginx silently picking one of two server blocks at // runtime (2026-09-03 staging: two generated site files both claimed -// "api.staging.nself.org"; nginx logged "conflicting server name ... +// "api.stack-two.nself.org"; nginx logged "conflicting server name ... // ignored" and kept serving whichever loaded last). // // This is the early, precise check on the plugin-injection path. diff --git a/internal/build/plugin_nginx_server_name_test.go b/internal/build/plugin_nginx_server_name_test.go index 3789c10fa..8bfe281f0 100644 --- a/internal/build/plugin_nginx_server_name_test.go +++ b/internal/build/plugin_nginx_server_name_test.go @@ -2,7 +2,7 @@ package build // plugin_nginx_server_name_test.go — regression coverage for the 2026-09-03 // staging incident: nginx logged `conflicting server name -// "api.staging.nself.org" on 0.0.0.0:443, ignored` because two generated +// "api.stack-two.nself.org" on 0.0.0.0:443, ignored` because two generated // site files under nginx/sites/ declared the same server_name. nginx does // not fail its config test over this — it silently serves whichever server // block loaded last, so the duplicate went unnoticed until a route behaved @@ -66,24 +66,24 @@ func writePluginNginxRoute(t *testing.T, pluginDir, pluginName, fileName, server // TestInjectPluginNginxRoutes_RejectsDuplicateServerName reproduces the // staging incident directly: a core route (hasura.conf) already claims -// "api.staging.nself.org" and a plugin ships a route that claims the exact +// "api.stack-two.nself.org" and a plugin ships a route that claims the exact // same server_name. InjectPluginNginxRoutes must fail the build and name // both files, not silently write the duplicate and warn. func TestInjectPluginNginxRoutes_RejectsDuplicateServerName(t *testing.T) { workdir := t.TempDir() pluginDir := t.TempDir() - writeExistingSite(t, workdir, "hasura.conf", "api.staging.nself.org") - writePluginNginxRoute(t, pluginDir, "gateway", "route.conf", "api.staging.nself.org") + writeExistingSite(t, workdir, "hasura.conf", "api.stack-two.nself.org") + writePluginNginxRoute(t, pluginDir, "gateway", "route.conf", "api.stack-two.nself.org") - cfg := minimalTestConfig("staging.nself.org") + cfg := minimalTestConfig("stack-two.nself.org") count, err := InjectPluginNginxRoutes(workdir, pluginDir, cfg) if err == nil { - t.Fatalf("expected an error for duplicate server_name \"api.staging.nself.org\", got nil (count=%d)", count) + t.Fatalf("expected an error for duplicate server_name \"api.stack-two.nself.org\", got nil (count=%d)", count) } - for _, want := range []string{"api.staging.nself.org", "hasura.conf", "gateway-route.conf"} { + for _, want := range []string{"api.stack-two.nself.org", "hasura.conf", "gateway-route.conf"} { if !strings.Contains(err.Error(), want) { t.Errorf("error message %q does not name %q — a conflict must name both sources so it can be fixed", err.Error(), want) } @@ -102,10 +102,10 @@ func TestInjectPluginNginxRoutes_AllowsDistinctServerNames(t *testing.T) { workdir := t.TempDir() pluginDir := t.TempDir() - writeExistingSite(t, workdir, "hasura.conf", "api.staging.nself.org") - writePluginNginxRoute(t, pluginDir, "gateway", "route.conf", "gateway.staging.nself.org") + writeExistingSite(t, workdir, "hasura.conf", "api.stack-two.nself.org") + writePluginNginxRoute(t, pluginDir, "gateway", "route.conf", "gateway.stack-two.nself.org") - cfg := minimalTestConfig("staging.nself.org") + cfg := minimalTestConfig("stack-two.nself.org") count, err := InjectPluginNginxRoutes(workdir, pluginDir, cfg) if err != nil { @@ -126,8 +126,8 @@ func TestInjectPluginNginxRoutes_SelfUpdateNotAConflict(t *testing.T) { workdir := t.TempDir() pluginDir := t.TempDir() - writePluginNginxRoute(t, pluginDir, "gateway", "route.conf", "gateway.staging.nself.org") - cfg := minimalTestConfig("staging.nself.org") + writePluginNginxRoute(t, pluginDir, "gateway", "route.conf", "gateway.stack-two.nself.org") + cfg := minimalTestConfig("stack-two.nself.org") if _, err := InjectPluginNginxRoutes(workdir, pluginDir, cfg); err != nil { t.Fatalf("first inject: unexpected error: %v", err) @@ -159,14 +159,14 @@ func writeSite(t *testing.T, sitesDir, name, body string) { } // TestCheckServerNameUniqueness_ReportsDuplicate reproduces the staging -// finding: two generated site files both claim api.staging.nself.org. +// finding: two generated site files both claim api.stack-two.nself.org. // `nginx -t` calls that "syntax is ok" and merely logs that it ignored one, // so post-build validation has to be the thing that fails the build — and // it has to name BOTH files, or the operator cannot tell which route died. func TestCheckServerNameUniqueness_ReportsDuplicate(t *testing.T) { sitesDir := filepath.Join(t.TempDir(), "sites") - writeSite(t, sitesDir, "hasura.conf", "server {\n server_name api.staging.nself.org;\n}\n") - writeSite(t, sitesDir, "ir-gateway.conf", "server {\n server_name api.staging.nself.org;\n}\n") + writeSite(t, sitesDir, "hasura.conf", "server {\n server_name api.stack-two.nself.org;\n}\n") + writeSite(t, sitesDir, "ir-gateway.conf", "server {\n server_name api.stack-two.nself.org;\n}\n") result := PostValidateResult{NginxValid: true} checkServerNameUniqueness(sitesDir, &result) @@ -177,7 +177,7 @@ func TestCheckServerNameUniqueness_ReportsDuplicate(t *testing.T) { if result.NginxValid { t.Error("NginxValid stayed true despite a duplicate server_name — the build would not fail") } - for _, want := range []string{"api.staging.nself.org", "hasura.conf", "ir-gateway.conf"} { + for _, want := range []string{"api.stack-two.nself.org", "hasura.conf", "ir-gateway.conf"} { if !strings.Contains(result.Errors[0], want) { t.Errorf("error %q does not name %q", result.Errors[0], want) } @@ -297,14 +297,14 @@ func TestPostValidate_FailsOnDuplicateServerName(t *testing.T) { sitesDir := filepath.Join(dir, "nginx", "sites") // Two generated site files claiming one FQDN on one port: the core // Hasura route and an api-docs route that landed on the same name. - writeSite(t, sitesDir, "hasura.conf", "server {\n listen 443 ssl;\n server_name api.staging.nself.org;\n}\n") - writeSite(t, sitesDir, "api-docs.conf", "server {\n listen 443 ssl;\n server_name api.staging.nself.org;\n}\n") + writeSite(t, sitesDir, "hasura.conf", "server {\n listen 443 ssl;\n server_name api.stack-two.nself.org;\n}\n") + writeSite(t, sitesDir, "api-docs.conf", "server {\n listen 443 ssl;\n server_name api.stack-two.nself.org;\n}\n") result := PostValidate(composePath, sitesDir) found := false for _, e := range result.Errors { - if strings.Contains(e, "api.staging.nself.org") { + if strings.Contains(e, "api.stack-two.nself.org") { found = true } } diff --git a/internal/build/postvalidate_nginx.go b/internal/build/postvalidate_nginx.go index eeba7c829..cc9583eea 100644 --- a/internal/build/postvalidate_nginx.go +++ b/internal/build/postvalidate_nginx.go @@ -27,7 +27,7 @@ import ( // `conflicting server name "x" on 0.0.0.0:443, ignored`, keeps whichever // block it loaded last, and still prints "syntax is ok" — so // checkNginxSyntax below passes and one of the two routes is silently -// dead. That is how api.staging.nself.org ended up served by an +// dead. That is how api.stack-two.nself.org ended up served by an // unintended block on 2026-09-03. // // Three separate writers populate nginx/sites/ in one build — the nginx diff --git a/internal/compose/fronted_stack_test.go b/internal/compose/fronted_stack_test.go index 41d4aabf8..4eb0d8527 100644 --- a/internal/compose/fronted_stack_test.go +++ b/internal/compose/fronted_stack_test.go @@ -4,7 +4,7 @@ package compose // incident: `nself start` in /opt/nself-ntask failed with "port 80/443 held // by docker-proxy" because the generated docker-compose.yml always defines // an nginx service, even for a stack whose domains are actually served by -// ANOTHER stack's nginx (nself-web fronted task.staging.nself.org). That +// ANOTHER stack's nginx (nself-web fronted task.stack-two.nself.org). That // nginx container can never bind 80/443 — the fronting stack's nginx // already holds them — so it sits forever as one unhealthy container // `nself status` can never clear (reported "6/7"). @@ -28,7 +28,7 @@ func frontedTestConfig(t *testing.T) *config.Config { t.Helper() cfg := &config.Config{ ProjectName: "ntask", - BaseDomain: "task.staging.nself.org", + BaseDomain: "task.stack-two.nself.org", Env: "dev", DockerNetwork: "ntask_network", Postgres: config.PostgresConfig{ diff --git a/internal/config/types_datastores.go b/internal/config/types_datastores.go index 9ce7c3fd5..ddc7cd1a9 100644 --- a/internal/config/types_datastores.go +++ b/internal/config/types_datastores.go @@ -117,7 +117,7 @@ type NginxConfig struct { // wire this project's containers onto the fronting stack's Docker // network — the fronting nginx's `resolver 127.0.0.11` can only reach // container names on a network it is attached to, so making - // auth.task.staging.nself.org resolve ntask_auth still requires the + // auth.task.stack-two.nself.org resolve ntask_auth still requires the // operator to attach the two projects' networks (or declare one as // external in both compose files) by hand. That is a bigger, riskier // change — automatically rewriting a Docker network topology from a diff --git a/internal/doctor/hardening_check_nginx_zones.go b/internal/doctor/hardening_check_nginx_zones.go index b4053ce7f..158616875 100644 --- a/internal/doctor/hardening_check_nginx_zones.go +++ b/internal/doctor/hardening_check_nginx_zones.go @@ -135,7 +135,7 @@ func extractNginxServerBlocks(content string) []nginxServerBlock { } // nginxHostnameFirstLabel returns the lowercased first dot-separated label -// of a server_name hostname, e.g. "auth.myapp.staging.nself.org" -> "auth". +// of a server_name hostname, e.g. "auth.myapp.stack-two.nself.org" -> "auth". func nginxHostnameFirstLabel(hostname string) string { if i := strings.IndexByte(hostname, '.'); i >= 0 { return hostname[:i] diff --git a/internal/doctor/hardening_check_test.go b/internal/doctor/hardening_check_test.go index da9edc4e3..37d757856 100644 --- a/internal/doctor/hardening_check_test.go +++ b/internal/doctor/hardening_check_test.go @@ -312,7 +312,7 @@ func TestCheckHardeningNginxRateZones_ServiceIdentity(t *testing.T) { "auth.conf": ` server { listen 443 ssl; - server_name auth.staging.nself.org; + server_name auth.stack-two.nself.org; location / { limit_req zone=auth burst=5 nodelay; set $up_auth auth:4000; @@ -323,7 +323,7 @@ server { "hasura.conf": ` server { listen 443 ssl; - server_name api.staging.nself.org; + server_name api.stack-two.nself.org; location / { limit_req zone=graphql_api burst=20 nodelay; set $up_hasura hasura:8080; @@ -366,7 +366,7 @@ location /api/ { limit_req zone=api; } "static.conf": ` server { listen 443 ssl; - server_name static.staging.nself.org; + server_name static.stack-two.nself.org; location / { limit_req zone=static burst=10 nodelay; set $up_static frontend:3000; @@ -384,7 +384,7 @@ server { files: map[string]string{ "auth.conf": ` server { - server_name auth.staging.nself.org; + server_name auth.stack-two.nself.org; location / { limit_req zone=auth burst=5 nodelay; proxy_pass http://auth:4000; @@ -393,7 +393,7 @@ server { `, "hasura.conf": ` server { - server_name api.staging.nself.org; + server_name api.stack-two.nself.org; location / { proxy_pass http://hasura:8080; } diff --git a/internal/nginx/dynamic_resolve_test.go b/internal/nginx/dynamic_resolve_test.go index b5cb18c9e..3d3893bec 100644 --- a/internal/nginx/dynamic_resolve_test.go +++ b/internal/nginx/dynamic_resolve_test.go @@ -1,7 +1,7 @@ package nginx // dynamic_resolve_test.go — regression coverage for the 2026-09-03 staging -// outage (auth.task.staging.nself.org 502 after ntask_auth was recreated). +// outage (auth.task.stack-two.nself.org 502 after ntask_auth was recreated). // // Purpose: prove every generated service route resolves its proxy target at // request time (via the Docker embedded DNS resolver) instead of caching a @@ -34,9 +34,9 @@ var staticUpstreamBlock = regexp.MustCompile(`(?m)^\s*upstream\s+\S+\s*\{`) // the worker process, so a container recreate (nself restart, OOM, `docker // system prune`, a plain rebuild) 502s every request through that route // until someone notices and runs `nginx -s reload` by hand — exactly what -// happened to auth.task.staging.nself.org on 2026-09-03. +// happened to auth.task.stack-two.nself.org on 2026-09-03. func TestServiceRoutesResolveUpstreamDynamically(t *testing.T) { - cfg := &config.Config{BaseDomain: "staging.nself.org"} + cfg := &config.Config{BaseDomain: "stack-two.nself.org"} cfg, err := config.ApplyDefaults(cfg) if err != nil { t.Fatalf("ApplyDefaults() error: %v", err) @@ -117,7 +117,7 @@ var proxyVarAssignment = regexp.MustCompile(`(?m)^\s*set\s+\$\S+\s+(\S+);`) // then fails every request against the host "http" — the same // silent-until-traffic failure class as the stale-IP bug this file covers. func TestProxyTargetsHaveExactlyOneScheme(t *testing.T) { - cfg := &config.Config{BaseDomain: "staging.nself.org"} + cfg := &config.Config{BaseDomain: "stack-two.nself.org"} cfg, err := config.ApplyDefaults(cfg) if err != nil { t.Fatalf("ApplyDefaults() error: %v", err) diff --git a/internal/nginx/routes_test.go b/internal/nginx/routes_test.go index 7b5fad723..a542ee766 100644 --- a/internal/nginx/routes_test.go +++ b/internal/nginx/routes_test.go @@ -130,14 +130,14 @@ func TestCoreRoutes_NoAppName_BareScheme(t *testing.T) { // produces app-prefixed routes ("api.task", "auth.task") so the final // server_name is "api.task.{BASE_DOMAIN}" instead of "api.{BASE_DOMAIN}". func TestCoreRoutes_AppName_PrefixesSubdomains(t *testing.T) { - cfg := &config.Config{BaseDomain: "staging.nself.org", AppName: "task"} + cfg := &config.Config{BaseDomain: "stack-two.nself.org", AppName: "task"} cfg, err := config.ApplyDefaults(cfg) if err != nil { t.Fatalf("ApplyDefaults() error: %v", err) } g := &Generator{cfg: cfg} - entries := g.coreRoutes(cfg.BaseDomain, "staging-nself-org") + entries := g.coreRoutes(cfg.BaseDomain, "stack-two-nself-org") routesByFile := make(map[string]string) for _, e := range entries {