Separate observation from evaluation in blacklist sources

Each source's Query() method previously set r.Listed and r.Severity,
embedding verdict logic inside the prober. Evaluation now lives in a
dedicated Evaluate(SourceResult) (bool, string) method per source,
keeping Query() as pure observation.

A package-level EvaluateResult() helper looks up the source by ID and
delegates to its Evaluate method; rules.go, report.go, types.go, and
provider.go all call this instead of reading pre-set r.Listed/r.Severity
values. An unknownSource sentinel handles results whose source is no
longer registered.
This commit is contained in:
nemunaire 2026-05-15 18:04:10 +08:00
commit c437339bda
13 changed files with 123 additions and 44 deletions

View file

@ -24,8 +24,9 @@ func TestURLhausSource_NoResults(t *testing.T) {
t.Fatalf("expected 1 result, got %d", len(results))
}
r := results[0]
if !r.Enabled || r.Listed || r.Error != "" {
t.Fatalf("expected enabled+clean, got %+v", r)
listed, _ := s.Evaluate(r)
if !r.Enabled || listed || r.Error != "" {
t.Fatalf("expected enabled+clean, got %+v, Evaluate listed=%v", r, listed)
}
}
@ -48,8 +49,11 @@ func TestURLhausSource_Listed(t *testing.T) {
s := &urlhausSource{endpoint: srv.URL}
r := s.Query(context.Background(), "example.com", "example.com", sdk.CheckerOptions{"enable_urlhaus": true, "urlhaus_auth_key": "k"})[0]
if !r.Listed || len(r.Evidence) != 1 {
t.Fatalf("expected 1 listed evidence, got %+v", r)
if len(r.Evidence) != 1 {
t.Fatalf("expected 1 evidence item, got %+v", r)
}
if listed, severity := s.Evaluate(r); !listed || severity != SeverityCrit {
t.Errorf("expected Evaluate()=(true, crit), got (%v, %q)", listed, severity)
}
if r.Evidence[0].Status != "online" {
t.Errorf("evidence status = %q", r.Evidence[0].Status)