package config import ( "encoding/base64" "strings" "testing" "time" ) func TestLoadAcceptsExactly32ByteKeys(t *testing.T) { values := map[string]string{ "DATABASE_URL": "postgres://localhost/test", "DATA_ENCRYPTION_KEY_BASE64": base64.StdEncoding.EncodeToString([]byte(strings.Repeat("a", 32))), "PHONE_HMAC_KEY_BASE64": base64.StdEncoding.EncodeToString([]byte(strings.Repeat("b", 32))), "SESSION_COOKIE_SECURE": "false", } cfg, err := load(func(key string) (string, bool) { value, ok := values[key]; return value, ok }) if err != nil { t.Fatalf("load returned error: %v", err) } if len(cfg.EncryptionKey) != 32 || len(cfg.PhoneHMACKey) != 32 { t.Fatalf("unexpected key lengths: %d, %d", len(cfg.EncryptionKey), len(cfg.PhoneHMACKey)) } } func TestLoadRejectsWrongKeyLength(t *testing.T) { values := map[string]string{ "DATABASE_URL": "postgres://localhost/test", "DATA_ENCRYPTION_KEY_BASE64": base64.StdEncoding.EncodeToString([]byte(strings.Repeat("a", 31))), "PHONE_HMAC_KEY_BASE64": base64.StdEncoding.EncodeToString([]byte(strings.Repeat("b", 32))), } _, err := load(func(key string) (string, bool) { value, ok := values[key]; return value, ok }) if err == nil || !strings.Contains(err.Error(), "exactly 32 bytes") { t.Fatalf("expected exact length error, got %v", err) } } func TestLoadRequiresSecureCookieInProduction(t *testing.T) { key := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("x", 32))) values := map[string]string{ "APP_ENV": "production", "DATABASE_URL": "postgres://localhost/test", "DATA_ENCRYPTION_KEY_BASE64": key, "PHONE_HMAC_KEY_BASE64": key, "SESSION_COOKIE_SECURE": "false", } _, err := load(func(key string) (string, bool) { value, ok := values[key]; return value, ok }) if err == nil || !strings.Contains(err.Error(), "must be true") { t.Fatalf("expected production cookie error, got %v", err) } } func TestLoadRequiresTLSAndReleaseMigrationsInProduction(t *testing.T) { key := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("x", 32))) values := map[string]string{ "APP_ENV": "production", "DATABASE_URL": "postgres://queue:secret@pg.internal/queue?sslmode=verify-full", "DATA_ENCRYPTION_KEY_BASE64": key, "PHONE_HMAC_KEY_BASE64": key, "SESSION_COOKIE_SECURE": "true", "MIGRATE_ON_START": "false", } if _, err := load(func(key string) (string, bool) { value, ok := values[key]; return value, ok }); err != nil { t.Fatalf("secure production configuration rejected: %v", err) } values["DATABASE_URL"] = "postgres://queue:secret@pg.internal/queue?sslmode=disable" if _, err := load(func(key string) (string, bool) { value, ok := values[key]; return value, ok }); err == nil || !strings.Contains(err.Error(), "TLS") { t.Fatalf("expected production database TLS error, got %v", err) } values["DATABASE_URL"] = "postgres://queue:secret@pg.internal/queue?sslmode=verify-full" values["MIGRATE_ON_START"] = "true" if _, err := load(func(key string) (string, bool) { value, ok := values[key]; return value, ok }); err == nil || !strings.Contains(err.Error(), "MIGRATE_ON_START") { t.Fatalf("expected production migration mode error, got %v", err) } } func TestLoadConfiguresPublicTicketRateLimits(t *testing.T) { key := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("x", 32))) values := map[string]string{ "DATABASE_URL": "postgres://localhost/test", "DATA_ENCRYPTION_KEY_BASE64": key, "PHONE_HMAC_KEY_BASE64": key, "SESSION_COOKIE_SECURE": "false", } lookup := func(name string) (string, bool) { value, ok := values[name]; return value, ok } cfg, err := load(lookup) if err != nil { t.Fatal(err) } if cfg.PublicTicketProjectLimit != 1000 || cfg.PublicTicketPhoneLimit != 5 || cfg.PublicTicketRateWindow != time.Minute { t.Fatalf("unexpected public ticket limits: project=%d phone=%d window=%s", cfg.PublicTicketProjectLimit, cfg.PublicTicketPhoneLimit, cfg.PublicTicketRateWindow) } values["PUBLIC_TICKET_PROJECT_LIMIT"] = "1200" values["PUBLIC_TICKET_PHONE_LIMIT"] = "8" values["PUBLIC_TICKET_RATE_WINDOW"] = "2m" cfg, err = load(lookup) if err != nil { t.Fatal(err) } if cfg.PublicTicketProjectLimit != 1200 || cfg.PublicTicketPhoneLimit != 8 || cfg.PublicTicketRateWindow != 2*time.Minute { t.Fatalf("configured public ticket limits not applied: project=%d phone=%d window=%s", cfg.PublicTicketProjectLimit, cfg.PublicTicketPhoneLimit, cfg.PublicTicketRateWindow) } } func TestLoadRejectsInvalidPublicTicketRateLimits(t *testing.T) { key := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("x", 32))) base := map[string]string{ "DATABASE_URL": "postgres://localhost/test", "DATA_ENCRYPTION_KEY_BASE64": key, "PHONE_HMAC_KEY_BASE64": key, "SESSION_COOKIE_SECURE": "false", } tests := []struct { name string key string value string }{ {name: "project limit", key: "PUBLIC_TICKET_PROJECT_LIMIT", value: "0"}, {name: "phone limit", key: "PUBLIC_TICKET_PHONE_LIMIT", value: "0"}, {name: "window", key: "PUBLIC_TICKET_RATE_WINDOW", value: "0s"}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { values := make(map[string]string, len(base)+1) for name, value := range base { values[name] = value } values[test.key] = test.value if _, err := load(func(name string) (string, bool) { value, ok := values[name]; return value, ok }); err == nil { t.Fatalf("%s=%q should be rejected", test.key, test.value) } }) } }