Skip to content

Commit a13960b

Browse files
splintersfuryclaude
andcommitted
Show graceful empty states for Pipeline and Corpus when Redis/manifest unavailable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5dbfe52 commit a13960b

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

services/dashboard/backend/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ async def set_triage_state(analysis_id: str, function: str, body: TriageUpdate,
440440
async def corpus_overview():
441441
"""Get corpus overview with per-CVE status and aggregate metrics."""
442442
if not MANIFEST_PATH.exists():
443-
raise HTTPException(status_code=404, detail="Corpus manifest not found")
443+
return CorpusOverview()
444444
return get_corpus_overview(MANIFEST_PATH, CORPUS_DIR)
445445

446446

services/dashboard/frontend/src/app/corpus/page.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,28 @@ export default function CorpusPage() {
852852

853853
const hasEvaluated = data.evaluated > 0;
854854

855+
// Empty corpus — no manifest loaded
856+
if (data.total_cves === 0) {
857+
return (
858+
<div className="space-y-6">
859+
<div>
860+
<h1 className="text-2xl font-semibold">CVE Validation Corpus</h1>
861+
<p className="mt-1 text-sm text-muted-foreground">
862+
Ground truth for rule engine precision &amp; recall measurement
863+
</p>
864+
</div>
865+
<div className="rounded-lg border bg-muted/50 p-8 text-center">
866+
<p className="text-muted-foreground">No corpus data loaded.</p>
867+
<p className="mt-1 text-sm text-muted-foreground">
868+
The corpus manifest has not been configured. Set{" "}
869+
<code className="rounded bg-muted px-1">AUTOPIFF_MANIFEST_PATH</code>{" "}
870+
or run the full Docker stack to use the validation corpus.
871+
</p>
872+
</div>
873+
</div>
874+
);
875+
}
876+
855877
// Unique categories from CVEs
856878
const allCategories = [
857879
...new Set(data.cves.map((c) => c.expected_category_primary).filter(Boolean)),

services/dashboard/frontend/src/app/pipeline/page.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default function PipelinePage() {
4747

4848
const onlineCount = health.stages.filter((s) => s.status === "online").length;
4949
const totalStages = health.stages.length;
50+
const allUnknown = health.stages.every((s) => s.status === "unknown");
5051

5152
// Group stages by type
5253
const pipelineStages = health.stages.filter((s) =>
@@ -68,33 +69,45 @@ export default function PipelinePage() {
6869
</p>
6970
</div>
7071

72+
{/* No Redis banner */}
73+
{!health.redis_connected && (
74+
<div className="rounded-lg border border-yellow-500/30 bg-yellow-500/5 p-4">
75+
<p className="text-sm font-medium text-yellow-700 dark:text-yellow-400">
76+
Redis not connected
77+
</p>
78+
<p className="mt-1 text-xs text-muted-foreground">
79+
Pipeline monitoring requires a connection to Karton Redis. Set <code className="rounded bg-muted px-1">KARTON_REDIS_HOST</code> or run the full Docker stack to see live consumer status.
80+
</p>
81+
</div>
82+
)}
83+
7184
{/* Summary cards */}
7285
<div className="grid grid-cols-3 gap-4">
7386
<div className="rounded-xl border bg-card p-5">
7487
<p className="text-sm text-muted-foreground">Active Consumers</p>
7588
<p className={cn(
7689
"mt-1 text-2xl font-semibold",
77-
onlineCount === totalStages ? "text-green-600 dark:text-green-400" : onlineCount > 0 ? "text-yellow-600 dark:text-yellow-400" : "text-red-600 dark:text-red-400"
90+
allUnknown ? "text-muted-foreground" : onlineCount === totalStages ? "text-green-600 dark:text-green-400" : onlineCount > 0 ? "text-yellow-600 dark:text-yellow-400" : "text-red-600 dark:text-red-400"
7891
)}>
79-
{onlineCount} / {totalStages}
92+
{allUnknown ? "—" : `${onlineCount} / ${totalStages}`}
8093
</p>
8194
</div>
8295
<div className="rounded-xl border bg-card p-5">
8396
<p className="text-sm text-muted-foreground">Redis</p>
8497
<p className={cn(
8598
"mt-1 text-2xl font-semibold",
86-
health.redis_connected ? "text-green-600 dark:text-green-400" : "text-red-600 dark:text-red-400"
99+
health.redis_connected ? "text-green-600 dark:text-green-400" : "text-muted-foreground"
87100
)}>
88-
{health.redis_connected ? "Connected" : "Disconnected"}
101+
{health.redis_connected ? "Connected" : "Not configured"}
89102
</p>
90103
</div>
91104
<div className="rounded-xl border bg-card p-5">
92105
<p className="text-sm text-muted-foreground">Pipeline Status</p>
93106
<p className={cn(
94107
"mt-1 text-2xl font-semibold",
95-
onlineCount === totalStages ? "text-green-600 dark:text-green-400" : "text-yellow-600 dark:text-yellow-400"
108+
allUnknown ? "text-muted-foreground" : onlineCount === totalStages ? "text-green-600 dark:text-green-400" : "text-yellow-600 dark:text-yellow-400"
96109
)}>
97-
{onlineCount === totalStages ? "Healthy" : onlineCount > 0 ? "Degraded" : "Down"}
110+
{allUnknown ? "No data" : onlineCount === totalStages ? "Healthy" : onlineCount > 0 ? "Degraded" : "Down"}
98111
</p>
99112
</div>
100113
</div>

0 commit comments

Comments
 (0)