package config import ( "strings" "testing" ) // DM-06: config.go used to default JWT_SECRET_KEY, the NATS URL and its // credentials, and the AI/optimiser hosts to the REAL production values. Two // consequences: anyone holding the repository could mint a valid token for any // account against a deployment that had not overridden the secret, and any // local run silently joined the live NATS stream. // The literals that must never come back. Written out so a revert is a test // failure rather than something noticed in review. func TestProductionValuesAreNotDefaults(t *testing.T) { for _, key := range []string{ "JWT_SECRET_KEY", "NATS_URL", "NATS_USER", "NATS_PASSWORD", "AI_LAYER_BASE_URL", "ROUTE_OPTIMIZER_URL", "DB_PASSWORD", } { setEnv(t, key, "") } setEnv(t, "ENV", "development") cfg := Load() banned := map[string]string{ "NatsURL": cfg.NatsURL, "NatsUser": cfg.NatsUser, "NatsPassword": cfg.NatsPassword, "AILayerBaseURL": cfg.AILayerBaseURL, "RouteOptimizerURL": cfg.RouteOptimizerURL, "DBPassword": cfg.DBPassword, } for field, got := range banned { if got != "" { t.Errorf("%s defaulted to %q — production values must not be defaults", field, got) } } // The old hardcoded secret must not be what we sign with. if cfg.JWTSecret == "DoormileSuperSecretJWTKey2026!" { t.Error("JWTSecret fell back to the literal that used to be in config.go") } } // With no secret configured outside production the service still runs, but on // a key that exists only for this process. func TestUnsetSecretOutsideProductionIsEphemeralNotShared(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "") setEnv(t, "ENV", "development") first := Load().JWTSecret second := Load().JWTSecret if first == "" || second == "" { t.Fatal("an unset secret produced an empty signing key; tokens would be forgeable") } if first == second { t.Error("two loads produced the same generated key — it is not ephemeral") } if len(first) < 32 { t.Errorf("generated key is %d chars, too short to be a signing key", len(first)) } } // In production an absent secret is NOT quietly replaced — it is left absent so // Validate can refuse the boot with a message that says why. Silently // generating one would invalidate every live session on each restart. func TestProductionRefusesToStartWithoutASecret(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "") setEnv(t, "ENV", "production") cfg := Load() if cfg.JWTSecret != "" { t.Errorf("production generated a secret (%q); it must stay empty so Validate fails", cfg.JWTSecret) } err := cfg.Validate() if err == nil { t.Fatal("Validate accepted an empty JWT secret in production") } if !strings.Contains(err.Error(), "JWT_SECRET_KEY") { t.Errorf("Validate error does not name the variable: %v", err) } } // Outside production the ephemeral key is enough to pass validation, so local // development needs no configuration at all. func TestValidatePassesOutsideProductionWithNoSecret(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "") setEnv(t, "ENV", "development") if err := Load().Validate(); err != nil { t.Errorf("development should boot without a configured secret: %v", err) } } // A configured secret always validates, production or not. func TestValidatePassesWithAConfiguredSecret(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "a-real-configured-secret") setEnv(t, "ENV", "production") if err := Load().Validate(); err != nil { t.Errorf("a configured secret must validate: %v", err) } } // An explicitly configured secret is always used verbatim. func TestConfiguredSecretIsUsedVerbatim(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "a-real-configured-secret") setEnv(t, "ENV", "production") if got := Load().JWTSecret; got != "a-real-configured-secret" { t.Errorf("JWTSecret = %q, want the configured value", got) } } func TestIsProductionIsCaseAndSpaceInsensitive(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "x") for _, env := range []string{"production", "Production", "PRODUCTION", " production "} { setEnv(t, "ENV", env) if !Load().IsProduction() { t.Errorf("ENV=%q was not treated as production", env) } } for _, env := range []string{"development", "staging", "test", ""} { setEnv(t, "ENV", env) if Load().IsProduction() { t.Errorf("ENV=%q was treated as production", env) } } } // The geocoder is a PUBLIC service, not a Doormile host, so it keeps its // default — removing it would break place search for no security gain. func TestGeocoderKeepsItsPublicDefault(t *testing.T) { setEnv(t, "JWT_SECRET_KEY", "x") setEnv(t, "GEOCODER_URL", "") if got := Load().GeocoderURL; !strings.Contains(got, "nominatim") { t.Errorf("GeocoderURL = %q, want the public Nominatim default", got) } }