package config import ( "os" "path/filepath" "testing" ) func TestLoadAppliesDefaultsAndResolvesSecrets(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com/v1") t.Setenv("AIGW_SERVER_ADDRESS", "127.0.0.1:9090") path := writeConfig(t, `{ "providers": [{"id":"primary","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models": [{"id":"example/model","routes":[{"provider":"primary","upstream_model":"model"}]}] }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.Server.Address != "127.0.0.1:9090" || cfg.Server.MaxBodyBytes == 0 { t.Fatalf("defaults not applied: %+v", cfg.Server) } if cfg.Providers[0].APIKey != "secret" { t.Fatal("provider secret was not resolved") } if cfg.Providers[0].BaseURL != "https://example.com/v1" { t.Fatal("provider URL was not resolved") } if cfg.Providers[0].WireAPI != "chat_completions" { t.Fatalf("default wire API = %q", cfg.Providers[0].WireAPI) } if cfg.Providers[0].Slug != "primary" { t.Fatalf("default provider slug = %q", cfg.Providers[0].Slug) } if cfg.Models[0].Routes[0].Weight != 1 { t.Fatalf("expected default route weight 1, got %d", cfg.Models[0].Routes[0].Weight) } } func TestLoadResolvesActiveProviderProbeConfiguration(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com/v1") t.Setenv("TEST_ACTIVE_PROBES", "true") path := writeConfig(t, `{ "provider_health":{"active_probes_enabled_env":"TEST_ACTIVE_PROBES","probe_interval_seconds":15,"probe_timeout_seconds":2}, "providers":[{"id":"primary","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models":[{"id":"example/model","routes":[{"provider":"primary","upstream_model":"model"}]}] }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if !cfg.ProviderHealth.ActiveProbesEnabled || cfg.ProviderHealth.ProbeIntervalSeconds != 15 || cfg.ProviderHealth.ProbeTimeoutSeconds != 2 { t.Fatalf("unexpected provider health config: %+v", cfg.ProviderHealth) } } func TestLoadResolvesSharedProviderHealthConfiguration(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_REDIS_URL", "redis://redis:6379/0") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("TEST_SHARED_HEALTH", "true") path := writeConfig(t, `{ "control_plane":{"enabled":true}, "provider_health":{"shared_history_enabled_env":"TEST_SHARED_HEALTH","shared_history_stream":"test:health","shared_history_ttl_seconds":120,"shared_history_max_events":500} }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if !cfg.ProviderHealth.SharedHistoryEnabled || cfg.ProviderHealth.SharedHistoryStream != "test:health" || cfg.ProviderHealth.SharedHistoryTTLSeconds != 120 || cfg.ProviderHealth.SharedHistoryMaxEvents != 500 { t.Fatalf("unexpected shared provider health config: %+v", cfg.ProviderHealth) } } func TestLoadAllowsSharedProviderHealthWithoutRedis(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("TEST_SHARED_HEALTH", "true") path := writeConfig(t, `{ "control_plane":{"enabled":true}, "provider_health":{"shared_history_enabled_env":"TEST_SHARED_HEALTH"} }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if !cfg.ProviderHealth.SharedHistoryEnabled || cfg.ControlPlane.RedisURL != "" { t.Fatalf("unexpected degraded shared provider health config: %+v", cfg.ProviderHealth) } } func TestLoadRejectsInvalidActiveProviderProbeConfiguration(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com/v1") path := writeConfig(t, `{ "provider_health":{"probe_interval_seconds":5,"probe_timeout_seconds":5}, "providers":[{"id":"primary","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models":[{"id":"example/model","routes":[{"provider":"primary","upstream_model":"model"}]}] }`) if _, err := Load(path); err == nil { t.Fatal("expected invalid provider probe timeout to be rejected") } } func TestLoadValidatesPublicProviderSlugs(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com") for _, providers := range []string{ `[{"id":"primary","slug":"Not Valid","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}]`, `[{"id":"one","slug":"shared-provider","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"},{"id":"two","slug":"shared-provider","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}]`, } { path := writeConfig(t, `{"providers":`+providers+`,"models":[{"id":"example/model","routes":[{"provider":"primary","upstream_model":"model"}]}]}`) if _, err := Load(path); err == nil { t.Fatalf("expected invalid provider slugs to be rejected: %s", providers) } } } func TestLoadAcceptsOpenAIResponsesWireAPI(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com") path := writeConfig(t, `{ "providers": [{"id":"responses","protocol":"openai","wire_api":"responses","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models": [{"id":"example/model","routes":[{"provider":"responses","upstream_model":"gpt-example"}]}] }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.Providers[0].WireAPI != "responses" { t.Fatalf("wire API = %q", cfg.Providers[0].WireAPI) } } func TestLoadAcceptsOpenAIEmbeddingsWireAPI(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com/v1") path := writeConfig(t, `{ "providers": [{"id":"embeddings","protocol":"openai","wire_api":"embeddings","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models": [{"id":"example/embedding","capabilities":["embeddings"],"routes":[{"provider":"embeddings","upstream_model":"embedding-model"}]}] }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.Providers[0].WireAPI != "embeddings" || len(cfg.Models[0].Capabilities) != 1 || cfg.Models[0].Capabilities[0] != "embeddings" { t.Fatalf("unexpected embeddings config: provider=%+v model=%+v", cfg.Providers[0], cfg.Models[0]) } } func TestLoadRejectsIncompatibleWireAPI(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "https://example.com") path := writeConfig(t, `{ "providers": [{"id":"bad","protocol":"anthropic","wire_api":"responses","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models": [{"id":"example/model","routes":[{"provider":"bad","upstream_model":"model"}]}] }`) if _, err := Load(path); err == nil { t.Fatal("expected incompatible wire API to be rejected") } } func TestLoadRejectsUnknownFieldsAndTrailingData(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") unknown := writeConfig(t, `{"unknown":true}`) if _, err := Load(unknown); err == nil { t.Fatal("expected unknown field error") } trailing := writeConfig(t, `{} {}`) if _, err := Load(trailing); err == nil { t.Fatal("expected trailing JSON error") } } func TestLoadRejectsLiteralExternalServiceValues(t *testing.T) { for _, content := range []string{ `{"server":{"address":":9090"}}`, `{"providers":[{"id":"primary","protocol":"openai","base_url":"https://example.test","api_key_env":"TEST_KEY"}]}`, `{"billing":{"stripe":{"success_url":"https://console.example.test"}}}`, } { if _, err := Load(writeConfig(t, content)); err == nil { t.Fatalf("expected literal external service value to be rejected: %s", content) } } } func TestLoadControlPlaneModeWithoutStaticRoutes(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_REDIS_URL", "redis://redis:6379/0") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("AIGW_ADMIN_TOKEN", "admin-secret") t.Setenv("AIGW_PUBLIC_URL", "http://localhost:8080/admin/") t.Setenv("AIGW_INFERENCE_PUBLIC_URL", "https://api.example.test") path := writeConfig(t, `{ "control_plane": {"enabled":true}, "admin": {"enabled":true} }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.ControlPlane.DatabaseURL == "" || cfg.ControlPlane.RedisURL == "" || cfg.Admin.Token != "admin-secret" { t.Fatalf("control-plane secrets were not resolved: %+v", cfg) } if len(cfg.Providers) != 0 || len(cfg.Models) != 0 { t.Fatal("control-plane mode unexpectedly requires static providers or models") } if cfg.Admin.InferencePublicURL != "https://api.example.test" { t.Fatalf("inference public URL = %q", cfg.Admin.InferencePublicURL) } } func TestLoadDerivesInferenceURLFromConsoleOrigin(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("AIGW_ADMIN_TOKEN", "admin-secret") t.Setenv("AIGW_PUBLIC_URL", "https://console.example.test/admin/") path := writeConfig(t, `{"control_plane":{"enabled":true},"admin":{"enabled":true}}`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.Admin.InferencePublicURL != "https://console.example.test" { t.Fatalf("derived inference URL = %q", cfg.Admin.InferencePublicURL) } } func TestLoadControlPlaneModeWithoutRedis(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_REDIS_URL", "") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") path := writeConfig(t, `{"control_plane":{"enabled":true}}`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.ControlPlane.RedisURL != "" { t.Fatalf("Redis URL = %q, want empty", cfg.ControlPlane.RedisURL) } } func TestLoadRejectsAdminWithoutControlPlane(t *testing.T) { t.Setenv("AIGW_ADMIN_TOKEN", "admin-secret") path := writeConfig(t, `{"admin":{"enabled":true}}`) if _, err := Load(path); err == nil { t.Fatal("expected admin without control plane to be rejected") } } func TestLoadResolvesStripeSecrets(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("TEST_STRIPE_KEY", "rk_test_example") t.Setenv("TEST_STRIPE_WEBHOOK", "whsec_example") t.Setenv("TEST_STRIPE_SUCCESS", "https://console.example.test/admin/?topup=success") t.Setenv("TEST_STRIPE_CANCEL", "https://console.example.test/admin/?topup=cancel") t.Setenv("AIGW_STRIPE_PORTAL_RETURN_URL", "https://console.example.test/admin/?billing=portal") t.Setenv("AIGW_SETTLEMENT_SPOOL_PATH", filepath.Join(t.TempDir(), "settlements.jsonl")) path := writeConfig(t, `{ "control_plane":{"enabled":true}, "billing":{"enabled":true,"stripe":{"enabled":true,"api_key_env":"TEST_STRIPE_KEY","webhook_secret_env":"TEST_STRIPE_WEBHOOK","success_url_env":"TEST_STRIPE_SUCCESS","cancel_url_env":"TEST_STRIPE_CANCEL"}} }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.Billing.Stripe.APIKey != "rk_test_example" || cfg.Billing.Stripe.WebhookSecret != "whsec_example" { t.Fatal("Stripe secrets were not resolved") } if cfg.Billing.Stripe.SuccessURL != "https://console.example.test/admin/?topup=success" || cfg.Billing.Stripe.CancelURL != "https://console.example.test/admin/?topup=cancel" { t.Fatal("Stripe callback URLs were not resolved") } } func TestLoadCanDisableStripeFromEnvironmentWithoutCredentials(t *testing.T) { t.Setenv("AIGW_DATABASE_URL", "postgres://aigw:aigw@postgres/aigw") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("AIGW_SETTLEMENT_SPOOL_PATH", filepath.Join(t.TempDir(), "settlements.jsonl")) t.Setenv("TEST_STRIPE_ENABLED", "false") path := writeConfig(t, `{ "control_plane":{"enabled":true}, "billing":{"enabled":true,"currency":"usd","default_max_output_tokens":1024,"min_top_up_minor":500,"max_top_up_minor":1000000, "stripe":{"enabled_env":"TEST_STRIPE_ENABLED"}} }`) cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.Billing.Stripe.Enabled || cfg.Billing.Stripe.APIKey != "" { t.Fatalf("Stripe should be disabled without credentials: %+v", cfg.Billing.Stripe) } } func TestLoadRejectsEmptyExternalServiceEnvironment(t *testing.T) { t.Setenv("TEST_UPSTREAM_KEY", "secret") t.Setenv("TEST_UPSTREAM_URL", "") path := writeConfig(t, `{ "providers": [{"id":"primary","protocol":"openai","base_url_env":"TEST_UPSTREAM_URL","api_key_env":"TEST_UPSTREAM_KEY"}], "models": [{"id":"example/model","routes":[{"provider":"primary","upstream_model":"model"}]}] }`) if _, err := Load(path); err == nil { t.Fatal("expected empty provider URL environment variable to be rejected") } } func TestLoadRejectsBillingWithoutControlPlane(t *testing.T) { path := writeConfig(t, `{"billing":{"enabled":true}}`) if _, err := Load(path); err == nil { t.Fatal("expected billing without control plane to be rejected") } } func TestVersionedExamplesResolveExternalServicesFromEnvironment(t *testing.T) { t.Setenv("AIGW_SERVER_ADDRESS", "127.0.0.1:18081") t.Setenv("AIGW_PUBLIC_ADDRESS", "127.0.0.1:18081") t.Setenv("AIGW_ADMIN_ADDRESS", "127.0.0.1:18082") t.Setenv("AIGW_WEBHOOK_ADDRESS", "127.0.0.1:18083") t.Setenv("AIGW_OPERATIONS_ADDRESS", "127.0.0.1:19090") t.Setenv("AIGW_API_KEYS", `[{"key":"test","key_id":"key","tenant_id":"tenant","project_id":"project","scopes":["inference"]}]`) t.Setenv("OPENAI_BASE_URL", "https://openai.example.test/v1") t.Setenv("OPENAI_API_KEY", "openai-secret") t.Setenv("ANTHROPIC_BASE_URL", "https://anthropic.example.test/v1") t.Setenv("ANTHROPIC_API_KEY", "anthropic-secret") staticConfig, err := Load(filepath.Join("..", "..", "config.example.json")) if err != nil { t.Fatalf("load static example: %v", err) } if staticConfig.Providers[0].BaseURL != "https://openai.example.test/v1" { t.Fatalf("static provider URL = %q", staticConfig.Providers[0].BaseURL) } responsesConfig, err := Load(filepath.Join("..", "..", "config.responses.example.json")) if err != nil { t.Fatalf("load Responses example: %v", err) } if len(responsesConfig.Providers) != 1 || responsesConfig.Providers[0].WireAPI != "responses" { t.Fatalf("Responses example provider = %+v", responsesConfig.Providers) } t.Setenv("AIGW_DATABASE_URL", "postgres://example:secret@postgres.example.test/aigw") t.Setenv("AIGW_REDIS_URL", "redis://redis.example.test:6379/0") t.Setenv("AIGW_CREDENTIAL_KEY", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") t.Setenv("AIGW_ADMIN_TOKEN", "bootstrap-secret") t.Setenv("AIGW_PUBLIC_URL", "https://console.example.test/admin/") t.Setenv("AIGW_SMTP_FROM_ADDRESS", "no-reply@example.test") t.Setenv("AIGW_SMTP_ADDRESS", "smtp.example.test:587") t.Setenv("AIGW_SMTP_USERNAME", "") t.Setenv("AIGW_SMTP_PASSWORD", "") t.Setenv("AIGW_WEBAUTHN_RP_ID", "console.example.test") t.Setenv("AIGW_WEBAUTHN_ORIGINS", "https://console.example.test") t.Setenv("AIGW_STRIPE_API_KEY", "rk_test_example") t.Setenv("AIGW_STRIPE_ENABLED", "true") t.Setenv("AIGW_STRIPE_WEBHOOK_SECRET", "whsec_example") t.Setenv("AIGW_STRIPE_SUCCESS_URL", "https://console.example.test/admin/?topup=success") t.Setenv("AIGW_STRIPE_CANCEL_URL", "https://console.example.test/admin/?topup=cancel") t.Setenv("AIGW_STRIPE_PORTAL_RETURN_URL", "https://console.example.test/admin/?billing=portal") t.Setenv("AIGW_SETTLEMENT_SPOOL_PATH", filepath.Join(t.TempDir(), "settlements.jsonl")) controlConfig, err := Load(filepath.Join("..", "..", "config.control.example.json")) if err != nil { t.Fatalf("load control-plane example: %v", err) } if controlConfig.Billing.Stripe.SuccessURL != "https://console.example.test/admin/?topup=success" { t.Fatalf("Stripe success URL = %q", controlConfig.Billing.Stripe.SuccessURL) } } func writeConfig(t *testing.T, content string) string { t.Helper() path := filepath.Join(t.TempDir(), "config.json") if err := os.WriteFile(path, []byte(content), 0o600); err != nil { t.Fatal(err) } return path }