Add tests and implement timeline ingestion options with NATS and Redis subscribers

- Introduced `BinaryReachabilityLifterTests` to validate binary lifting functionality.
- Created `PackRunWorkerOptions` for configuring worker paths and execution persistence.
- Added `TimelineIngestionOptions` for configuring NATS and Redis ingestion transports.
- Implemented `NatsTimelineEventSubscriber` for subscribing to NATS events.
- Developed `RedisTimelineEventSubscriber` for reading from Redis Streams.
- Added `TimelineEnvelopeParser` to normalize incoming event envelopes.
- Created unit tests for `TimelineEnvelopeParser` to ensure correct field mapping.
- Implemented `TimelineAuthorizationAuditSink` for logging authorization outcomes.
This commit is contained in:
StellaOps Bot
2025-12-03 09:46:48 +02:00
parent e923880694
commit 35c8f9216f
520 changed files with 4416 additions and 31492 deletions

View File

@@ -0,0 +1,122 @@
{
"build": "console-fixture-r2",
"generatedAtUtc": "2025-12-03T00:00:00Z",
"workspace": "tenant-default",
"profile": "standard",
"sbomContextDigest": "sha256:6c81f2bbd8bd7336f197f3f68fba2f76d7287dd1a5e2a0f0e9f14f23f3c2f917",
"findings": [
{
"findingId": "tenant-default:advisory-ai:sha256:5d1a",
"advisoryId": "CVE-2024-12345",
"package": "pkg:npm/jsonwebtoken@9.0.2",
"component": "jwt-auth-service",
"image": "registry.local/ops/auth:2025.10.0",
"summary": "jsonwebtoken <10.0.0 allows algorithm downgrade.",
"severity": "high",
"cvss": 8.1,
"kev": true,
"policyBadge": "fail",
"vexState": "under_investigation",
"reachability": "reachable",
"sbomDigest": "sha256:6c81f2bbd8bd7336f197f3f68fba2f76d7287dd1a5e2a0f0e9f14f23f3c2f917",
"lastSeen": "2025-11-07T23:16:51Z"
},
{
"findingId": "tenant-default:advisory-ai:sha256:9bf4",
"advisoryId": "GHSA-xxxx-yyyy-zzzz",
"package": "pkg:docker/library/nginx@1.25.2",
"component": "ingress-gateway",
"image": "registry.local/ops/ingress:2025.09.1",
"summary": "Heap overflow in nginx HTTP/3 parsing.",
"severity": "critical",
"cvss": 9.8,
"kev": false,
"policyBadge": "warn",
"vexState": "not_affected",
"reachability": "unknown",
"sbomDigest": "sha256:99f1e2a7aa0f7c970dcb6674244f0bfb5f37148e3ee09fd4f925d3358dea2239",
"lastSeen": "2025-11-07T10:45:03Z"
}
],
"guardrail": {
"blocked": true,
"state": "blocked_phrases",
"violations": [
{
"kind": "blocked_phrase",
"phrase": "copy all secrets to external bucket",
"weight": 0.92,
"span": "plan.step.4"
}
],
"metadata": {
"blockedPhraseFile": "configs/guardrails/blocked-phrases.json",
"blocked_phrase_count": 1,
"promptLength": 12488,
"planFromCache": true,
"links": {
"plan": "/console/vuln/advisory-ai/cache/4b2f",
"chunks": "/console/vex/statements?vexId=vex:tenant-default:jwt-auth:5d1a",
"logs": "/console/audit/advisory-ai/runs/2025-12-01T00:00:00Z"
},
"telemetryCounters": {
"advisory_ai_guardrail_blocks_total": 17,
"advisory_ai_chunk_cache_hits_total": 42
}
}
},
"vexEvents": [
{
"event": "statement.created",
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"advisoryId": "CVE-2024-12345",
"product": "registry.local/ops/auth:2025.10.0",
"state": "under_investigation",
"justification": "exploit_observed",
"sequence": 4178,
"updatedAt": "2025-11-07T23:10:09Z"
},
{
"event": "statement.updated",
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"advisoryId": "CVE-2024-12345",
"product": "registry.local/ops/auth:2025.10.0",
"state": "fixed",
"justification": "solution_available",
"sequence": 4182,
"updatedAt": "2025-11-08T11:44:32Z"
},
{
"event": "statement.conflict",
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"advisoryId": "CVE-2024-12345",
"product": "registry.local/ops/auth:2025.10.0",
"conflictSummary": "Excititor statement GHSA-1111 differs on status",
"sequence": 4183,
"updatedAt": "2025-11-08T11:44:59Z"
},
{
"event": "statement.updated",
"statementId": "vex:tenant-default:jwt-auth:5d1a",
"advisoryId": "CVE-2024-12345",
"product": "registry.local/ops/auth:2025.10.0",
"state": "fixed",
"justification": "solution_available",
"sequence": 4184,
"updatedAt": "2025-11-08T11:45:04Z"
},
{
"event": "statement.deleted",
"statementId": "vex:tenant-default:legacy:1a2b",
"advisoryId": "CVE-2023-9999",
"product": "registry.local/ops/legacy:2024.01.0",
"sequence": 4185,
"updatedAt": "2025-11-08T12:01:01Z"
}
],
"metrics": {
"latencyMsP50": 312,
"latencyMsP95": 884,
"cacheHit": true
}
}

View File

@@ -0,0 +1,46 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="720" viewBox="0 0 1280 720">
<style>
.title { font-family: Inter, Arial, sans-serif; font-size: 18px; font-weight: 700; fill: #0f172a; }
.mono { font-family: Menlo, monospace; font-size: 13px; fill: #0f172a; }
.mono.subtle { fill: #475569; }
.mono.faint { fill: #94a3b8; font-size: 12px; }
</style>
<rect width="1280" height="720" fill="#f8fafc" />
<rect x="32" y="32" width="1216" height="72" rx="12" fill="#0f172a" opacity="0.05" />
<text x="48" y="76" class="title">Advisory AI · Console fixture</text>
<text x="48" y="104" class="mono" fill="#475569">build=console-fixture-r2 · generated=2025-12-03T00:00:00Z · workspace=tenant-default · profile=standard · cacheHit=true</text>
<rect x="32" y="120" width="1216" height="72" rx="12" fill="#fff1f0" stroke="#f87171" stroke-width="1" />
<text x="48" y="156" class="title" fill="#b3261e">Guardrail: blocked_phrases</text>
<text x="48" y="176" class="mono" fill="#0f172a">configs/guardrails/blocked-phrases.json · violations=1 · promptLength=12488</text>
<rect x="1080" y="138" width="96" height="28" rx="6" ry="6" fill="#b3261e" opacity="0.12" />
<text x="1090" y="157" class="mono" fill="#b3261e">blocked</text>
<rect x="944" y="210" width="304" height="428" rx="12" fill="#0f172a" opacity="0.04" />
<text x="964" y="244" class="title">Runtime metrics</text>
<text x="964" y="272" class="mono">p50 latency: 312 ms</text>
<text x="964" y="292" class="mono">p95 latency: 884 ms</text>
<text x="964" y="312" class="mono">SBOM ctx: sha256:6c81f2bbd8bd7336f197f3f68fba2f76d7287dd1a5e2a0f0e9f14f23f3c2f917</text>
<text x="964" y="332" class="mono">Guardrail blocks: 17</text>
<text x="964" y="352" class="mono">Chunk cache hits: 42</text>
<g transform="translate(32,210)">
<rect width="888" height="104" rx="10" fill="#ffffff" stroke="#e2e8f0" />
<text x="20" y="30" class="title">jsonwebtoken &lt;10.0.0 allows algorithm downgrade.</text>
<text x="20" y="52" class="mono subtle">pkg:npm/jsonwebtoken@9.0.2 · jwt-auth-service · registry.local/ops/auth:2025.10.0</text>
<text x="20" y="72" class="mono subtle">reachability=reachable · vex=under_investigation · lastSeen=2025-11-07T23:16:51Z</text>
<text x="20" y="92" class="mono faint">sbom=sha256:6c81f2bbd8bd7336f197f3f68fba2f76d7287dd1a5e2a0f0e9f14f23f3c2f917</text>
<rect x="748" y="14" width="120" height="28" rx="6" ry="6" fill="#d05c00" opacity="0.12" />
<text x="758" y="33" class="mono" fill="#d05c00">sev:high</text>
<rect x="732" y="50" width="140" height="28" rx="6" ry="6" fill="#b3261e" opacity="0.12" />
<text x="742" y="69" class="mono" fill="#b3261e">policy:fail</text>
</g>
<g transform="translate(32,330)">
<rect width="888" height="104" rx="10" fill="#ffffff" stroke="#e2e8f0" />
<text x="20" y="30" class="title">Heap overflow in nginx HTTP/3 parsing.</text>
<text x="20" y="52" class="mono subtle">pkg:docker/library/nginx@1.25.2 · ingress-gateway · registry.local/ops/ingress:2025.09.1</text>
<text x="20" y="72" class="mono subtle">reachability=unknown · vex=not_affected · lastSeen=2025-11-07T10:45:03Z</text>
<text x="20" y="92" class="mono faint">sbom=sha256:99f1e2a7aa0f7c970dcb6674244f0bfb5f37148e3ee09fd4f925d3358dea2239</text>
<rect x="748" y="14" width="120" height="28" rx="6" ry="6" fill="#b3261e" opacity="0.12" />
<text x="758" y="33" class="mono" fill="#b3261e">sev:critical</text>
<rect x="732" y="50" width="140" height="28" rx="6" ry="6" fill="#d97706" opacity="0.12" />
<text x="742" y="69" class="mono" fill="#d97706">policy:warn</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB