fix: insight generation auth failure and test isolation#21
Conversation
Insight generation fails silently when ANTHROPIC_API_KEY is set because agent CLIs use the env var key instead of subscription auth. Add cleanEnv() that strips ANTHROPIC_API_KEY and CLAUDECODE from the environment and sets CLAUDE_NO_SOUND=1, applied to all three generator functions (claude, codex, gemini). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The in-progress task items in the insights list were missing the agent badge that completed entries display. Add a task-agent span between the task body and dismiss button, styled consistently with row-agent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TestGenerateInsight_DefaultAgent was calling insight.Generate directly, which invokes `claude -p` if the CLI is on PATH. The spawned claude process creates a session file that the file watcher syncs into the production database. Add insight.GenerateFunc type and Server.generateFunc field (defaulting to insight.Generate) so tests can inject a stub. The test now uses a stub that returns an error, matching the existing assertion without spawning any subprocess. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- TestCleanEnv: use exact key/value map lookups instead of prefix matching to avoid false positives (e.g. CLAUDE_NO_SOUND=10) - WithGenerateFunc: guard against nil to prevent runtime panics - TestGenerateInsight_DefaultAgent: assert agent == "claude" to verify default-agent assignment is not silently regressed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
handleContextError was writing a 504 response on DeadlineExceeded, racing with http.TimeoutHandler's buffered 503 response. On Windows CI, Go's select randomly picked the handler's 504 over the middleware's 503, causing TestMiddleware_Timeout/GetMinimap to fail. Change handleContextError to return true without writing — same as it already does for Canceled — letting the withTimeout middleware handle the response consistently. Also consolidate search.go's inline context error handling to use handleContextError. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The denylist approach leaked the entire host environment (cloud credentials, database passwords, other API keys) to agent CLI subprocesses. Switch to an allowlist of system vars the CLIs need (PATH, HOME, LANG, proxy settings, etc.) so only safe variables are passed through. This also eliminates the case-sensitivity bypass on Windows since the allowlist matches by known prefixes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Windows emits env keys with mixed casing (Path, ComSpec) that didn't match the uppercase allowlist prefixes. Parse the key separately and compare case-insensitively via strings.ToUpper. Prefix entries ending with _ (LC_, XDG_, SSL_CERT_) match any key starting with that prefix; all others require exact match. Add TestEnvKeyAllowed with table-driven cases covering Windows-style casing and unknown var exclusion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
review_guidelines was wrapped in a [review_guidelines] section header, making it a TOML table instead of a top-level string. The threat_model key inside it was also wrong — the field is review_guidelines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
The previous approach of suppressing writes in handleContextError could produce implicit 200s if a handler were ever called without withTimeout. Restore the 504 write for DeadlineExceeded so handlers always produce a concrete error response. The middleware test race (503 vs 504) was caused by using an already-expired context, making Go's select pick randomly between the handler and middleware channels. Fix by accepting either 503 or 504 in middleware tests, since both are valid timeout responses. The internal test (no middleware) deterministically expects 504. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Windows CLIs resolve auth/config/cache paths via these vars. Without them, insight generation can fail on Windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add assertTimeoutRace helper that checks status code, Content-Type, and error body based on which path won: 503 expects "request timed out", 504 expects "gateway timeout" with application/json. Replaces bare status-code-only checks in TestMiddleware_Timeout and TestSearch_DeadlineExceeded. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
…est keys - Add PATHEXT, WINDIR, HOMEDRIVE, HOMEPATH to env allowlist so agent CLIs can resolve executables and config paths on Windows - assertTimeoutRace now checks Content-Type for both 503 and 504 - TestCleanEnv normalizes env map keys to uppercase for cross-platform correctness (Windows returns Path not PATH) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Remove cmd.Env = cleanEnv() from all three generator functions. The cleanEnv helper and its tests are retained for potential future use but no longer applied to agent CLI subprocesses. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Summary
ANTHROPIC_API_KEYandCLAUDECODEfrom the environment when invoking agent CLIs (claude,codex,gemini) for insight generation, forcing subscription-based auth. Also setsCLAUDE_NO_SOUND=1.TestGenerateInsight_DefaultAgentwas spawning a realclaudeprocess, which created session files that the file watcher synced into the production database. Introduceinsight.GenerateFuncandServer.generateFunc(injectable viaWithGenerateFuncoption) so tests use a stub.Test plan
CGO_ENABLED=1 go test -tags fts5 ./internal/insight/passesCGO_ENABLED=1 go test -tags fts5 ./internal/server/passesgo vet ./...cleanANTHROPIC_API_KEYset in shell, verify Claude uses subscription auth🤖 Generated with Claude Code