This commit is contained in:
2026-08-07 23:59:34 +02:00
parent 2253041756
commit 7735c9a51d
122 changed files with 880 additions and 5863 deletions
+46
View File
@@ -176,3 +176,49 @@ func TestEnsureInboxClassifierVersionRequeuesArchivedOnce(t *testing.T) {
t.Fatalf("classifier migration must be one-shot, n=%d err=%v", n, err)
}
}
func TestProactiveSecurityInboxLifecycle(t *testing.T) {
ctx := context.Background()
store, err := OpenStore(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer store.Close()
agent, _, err := store.CreateAgent(ctx, "agent-security", "Security Agent")
if err != nil {
t.Fatal(err)
}
task, err := store.UpsertTask(ctx, Task{ID: "task-security", AgentID: agent.ID, Name: "Security Alerts", Type: "rss", URL: "https://example.org/feed", Enabled: true, PollInterval: "1h", MaxItems: 10})
if err != nil {
t.Fatal(err)
}
_, err = store.Ingest(ctx, agent.ID, task.ID, []Document{{URL: "https://example.org/advisory", CanonicalURL: "https://example.org/advisory", Title: "Critical security advisory", Text: "A concrete security advisory with enough source text to be classified and later materialized into a proactive security node.", Metadata: map[string]any{"security_proactive": "true"}}})
if err != nil {
t.Fatal(err)
}
claimed, err := store.ClaimInbox(ctx, 1)
if err != nil || len(claimed) != 1 {
t.Fatalf("claim classification: %#v %v", claimed, err)
}
if err := store.CompleteClassification(ctx, claimed[0].ID, "candidate", .71, "kb-security", map[string]any{"priority_score": .71, "security_candidate": true}); err != nil {
t.Fatal(err)
}
if err := store.QueueProactiveSecurity(ctx, claimed[0].ID); err != nil {
t.Fatal(err)
}
securityItems, err := store.ClaimProactiveSecurity(ctx, 1)
if err != nil || len(securityItems) != 1 || securityItems[0].ProactiveState != "processing" {
t.Fatalf("claim proactive: %#v %v", securityItems, err)
}
if err := store.CompleteProactiveSecurity(ctx, claimed[0].ID, "external-node-1", map[string]any{"security_event_type": "vulnerability"}); err != nil {
t.Fatal(err)
}
materialized, err := store.ListInbox(ctx, "materialized", 10)
if err != nil || len(materialized) != 1 || materialized[0].MaterializedNodeID != "external-node-1" || materialized[0].ProactiveState != "done" {
t.Fatalf("materialized lifecycle mismatch: %#v %v", materialized, err)
}
results, err := store.SearchCandidates(ctx, "critical security advisory", 5, 0)
if err != nil || len(results) != 1 {
t.Fatalf("materialized document must remain searchable before SearXNG: %#v %v", results, err)
}
}