Add tiered LOTL mining onion and fleet recon so agents can fallback across execution tiers while operators see spread and vuln posture in Crucible. Includes triple-onion chain, spread cred graph, and full Go/TS/E2E test validation.

This commit is contained in:
AetherForge
2026-06-06 23:53:21 -07:00
parent 6372b07e6c
commit 3938bcd1c5
268 changed files with 21347 additions and 1130 deletions

View File

@@ -2,6 +2,7 @@ package api
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
@@ -57,6 +58,71 @@ func TestListAgentsEmptyArray(t *testing.T) {
}
}
func TestListAgentsPaginated(t *testing.T) {
h := newTestHandler(t)
for i := 0; i < 5; i++ {
if err := h.db.UpsertAgent(&models.Agent{
ID: fmt.Sprintf("agent-%d", i), Name: "n", Status: "online",
}); err != nil {
t.Fatal(err)
}
}
req := httptest.NewRequest(http.MethodGet, "/api/v1/agents?limit=2&offset=1", nil)
rec := httptest.NewRecorder()
h.ListAgents(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status %d body %s", rec.Code, rec.Body.String())
}
var body struct {
Agents []json.RawMessage `json:"agents"`
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatal(err)
}
if len(body.Agents) != 2 || body.Total != 5 || body.Limit != 2 || body.Offset != 1 {
t.Fatalf("unexpected paginated body: %+v", body)
}
}
func TestListAgentsSubnetFilter(t *testing.T) {
h := newTestHandler(t)
agents := []struct {
id, ip string
}{
{"subnet-a", "10.0.1.10"},
{"subnet-b", "10.0.2.20"},
{"subnet-c", "192.168.1.5"},
}
for _, a := range agents {
if err := h.db.UpsertAgent(&models.Agent{
ID: a.id, Name: a.id, IP: a.ip, Status: "online",
}); err != nil {
t.Fatal(err)
}
}
req := httptest.NewRequest(http.MethodGet, "/api/v1/agents?limit=50&subnet=10.0.1.x", nil)
rec := httptest.NewRecorder()
h.ListAgents(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status %d body %s", rec.Code, rec.Body.String())
}
var body struct {
Agents []struct {
ID string `json:"id"`
} `json:"agents"`
Total int `json:"total"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatal(err)
}
if body.Total != 1 || len(body.Agents) != 1 || body.Agents[0].ID != "subnet-a" {
t.Fatalf("unexpected subnet filter body: %+v", body)
}
}
func TestGetAgentStatsLimitCap(t *testing.T) {
h := newTestHandler(t)
req := httptest.NewRequest(http.MethodGet, "/agents/missing-agent/stats?limit=5000", nil)