fix(ingestion): address code review issues in api and watcher packages

- Strip internal error detail from 500 responses (leak prevention)
- Add path containment assertion in /write handler
- Use Go 1.22 method-prefixed mux routes for automatic 405 responses
- Clarify watch_interval log when watcher not yet wired
- Consolidate validation tests into table-driven TestIngest_Validation
- Watcher: return nil after successful quarantine to avoid double-logging
- Watcher: append timestamp suffix to processed dest if file already exists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mathias Bergqvist
2026-04-22 22:59:39 +02:00
parent a25bb18c54
commit 2f4b577131
4 changed files with 45 additions and 26 deletions

View File

@@ -110,7 +110,9 @@ func processFile(ctx context.Context, cfg Config, path, date string) error {
if logErr := appendWatcherLog(cfg.BrainDir, filename, runErr, date); logErr != nil {
slog.Error("watcher: failed to write log entry", "error", logErr)
}
return runErr
// Return nil: the file was quarantined successfully; the error was already
// logged. Returning runErr would cause processDir to log it again at Error level.
return nil
}
// Move to processed/YYYY-MM-DD/.
@@ -119,6 +121,12 @@ func processFile(ctx context.Context, cfg Config, path, date string) error {
return fmt.Errorf("mkdir processed dir: %w", err)
}
dest := filepath.Join(processedDir, filename)
if _, err := os.Stat(dest); err == nil {
// File already exists in processed; append timestamp to avoid overwriting the archive.
ext := filepath.Ext(filename)
base := strings.TrimSuffix(filename, ext)
dest = filepath.Join(processedDir, base+"-"+time.Now().UTC().Format("150405")+ext)
}
if err := os.Rename(path, dest); err != nil {
return fmt.Errorf("move to processed: %w", err)
}