diff --git a/server/env_scrub_test.go b/server/env_scrub_test.go index a60b6b0..0fca0fc 100644 --- a/server/env_scrub_test.go +++ b/server/env_scrub_test.go @@ -1,6 +1,8 @@ package server import ( + "context" + "os" "os/exec" "strings" "testing" @@ -34,3 +36,30 @@ func TestScrubSecretEnvHidesSecretsFromChildren(t *testing.T) { t.Errorf("non-secret variable did not reach the child process") } } + +// New must apply the options it receives. An earlier version accepted +// ...Option and never called them, so the binary kept the secrets in the +// environment while the unit test above still passed. +func TestNewAppliesSecretScrubOption(t *testing.T) { + // t.Setenv restores both after the test: the scrub unsets them for the rest + // of this process, and later tests still need the DSN. + if dsn := os.Getenv("ARTEX_PG_DSN"); dsn != "" { + t.Setenv("ARTEX_PG_DSN", dsn) + } + t.Setenv("ANTHROPIC_API_KEY", "scrub-probe") + t.Setenv("OPENAI_API_KEY", "scrub-probe") + + m, err := NewManager(t.TempDir(), "") + if err != nil { + t.Skipf("no manager: %v", err) + } + t.Cleanup(func() { m.Close() }) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _ = New(ctx, m, t.TempDir(), t.TempDir(), t.TempDir(), WithSecretScrub()) + + if os.Getenv("ANTHROPIC_API_KEY") != "" || os.Getenv("OPENAI_API_KEY") != "" { + t.Fatal("New did not apply WithSecretScrub: the secrets are still in the environment") + } +} diff --git a/server/server.go b/server/server.go index 8a76124..eddea90 100644 --- a/server/server.go +++ b/server/server.go @@ -156,6 +156,9 @@ func New(ctx context.Context, m *Manager, skillDir string, dataDir string, keyDi profChatAgents: map[int64]*agent.ChatAgent{}, provByProfile: map[int64]*provEntry{}, llmHealth: newLLMHealthRegistry(m.pg), taskAgents: map[string]*taskAgentBundle{}, archiveWake: make(chan struct{}, 1)} + for _, o := range opts { + o(s) + } s.initSetupToken() s.initSideQuestions() // Circuit-breaker thresholds/cooldowns are hot parameters on the failure path; push the global retry policy to the Registry once at startup,