4.7 KiB
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 07-research-agent-search | 01 | research-agent |
|
|
|
|
|
|
Phase 07 Plan 01: SearXNG Client + ResearchAgent Summary
One-liner: SearXNG HTTP client + background ResearchAgent that polls NetBox for needs_research items, enriches via SearXNG search + Tier 2 LLM text completion, patches NetBox custom fields, and transitions status to researched every 10 minutes or on-demand via POST /api/research/trigger.
Tasks Completed
| Task | Name | Commit | Key Files |
|---|---|---|---|
| 1 | SearXNG client + netbox.ListDevicesWithStatus | 30cd279 |
internal/research/searxng.go, internal/netbox/client.go, internal/config/config.go |
| 2 | ResearchAgent worker + main.go wiring + trigger endpoint | 0072aa4 |
internal/research/agent.go, internal/api/handlers/research.go, internal/api/router.go, cmd/hwlab/main.go |
Decisions Made
-
Interface injection for Agent dependencies —
NetBoxer,TextCompleter, andCatalogTransitionerinterfaces ininternal/research/agent.goallow stub injection in tests without a live NetBox or LLM. The concrete*netbox.Clientand*ai.TierClientsatisfy these interfaces automatically. -
TierClient.TextComplete as distinct method — Rather than forcing research prompts through
AnalyzePhotos(which builds a vision multipart message), added a cleanTextComplete(ctx, prompt) (string, error)method onTierClientthat posts a simple single-user-message ChatCompletion. This keeps the vision and text paths separate and makes intent clear. -
SanitizeQuery exported — The T-07-01 threat mitigation (strip
[^a-zA-Z0-9 .\-_]+before SearXNG dispatch) is tested from the_testpackage, which requires the function to be exported. Consistent with the plan's explicit mention of adversarial input testing. -
Product URL fallback — If the LLM does not return a
product_urlin its JSON response, the agent falls back to the first SearXNG result URL. This ensuresproduct_urlis populated even when the LLM provides incomplete JSON.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Test expectation for sanitizeQuery with / character
- Found during: Task 2 GREEN phase
- Issue: Test case
"Dell<script>alert(1)</script>"expected"Dell script alert 1 /script "but/is correctly stripped by the[^a-zA-Z0-9 .\-_]+regex - Fix: Updated test expectation to
"Dell script alert 1 script"(correct behavior) - Files modified: internal/research/agent_test.go
- Commit:
0072aa4
None otherwise — plan executed as written.
Known Stubs
None. All interfaces are fully implemented. The NoOpResearchClient in internal/ai/research.go is still present but is no longer used — it has been superseded by research.SearXNGClient wired in main.go.
Threat Surface Scan
No new trust boundaries introduced beyond those documented in the plan's threat model. T-07-01 (query sanitization) is mitigated and tested. T-07-03 (trigger DoS) is mitigated — RunOnce is bounded per-item with no queuing amplification.