import React from 'react'; import { useNavigate } from 'react-router-dom'; import type { HealthScore, PostureSummary, BacklogStats, ConfidenceDistribution, ScannerQuality, HotSink, OwaspBucket, LanguageHealth, SuppressionHygiene, BaselineInfo, WeightedFile, OverviewCount, } from '../../api/types'; import { truncPath } from '../../utils/truncPath'; // ── HealthScoreCard ───────────────────────────────────────────────────────── export function HealthScoreCard({ health, posture, }: { health: HealthScore; posture?: PostureSummary; }) { const gradeClass = `grade-${health.grade.toLowerCase()}`; const gradeAccent = health.grade === 'A' || health.grade === 'B' ? 'var(--green)' : health.grade === 'C' ? 'var(--amber)' : 'var(--red)'; return (
Health Score
{health.grade}
{health.score} / 100
{posture && (
{posture.message}
)}
{health.components.map((c) => { const barColor = c.score >= 70 ? 'var(--green)' : c.score >= 40 ? 'var(--amber)' : 'var(--red)'; return (
{c.label}
{c.score}
); })}
); } // ── PostureBanner ────────────────────────────────────────────────────────── export function PostureBanner({ posture }: { posture: PostureSummary }) { return (
{posture.message}
); } // ── BacklogCard ──────────────────────────────────────────────────────────── export function BacklogCard({ backlog }: { backlog: BacklogStats }) { const total = backlog.age_buckets.reduce((s, b) => s + b.count, 0); const noHistory = backlog.oldest_open_days == null && backlog.age_buckets.length === 0; if (noHistory) { return null; } return (
Backlog Age
{backlog.oldest_open_days != null ? `${backlog.oldest_open_days}d` : '–'}
Oldest open
{backlog.median_age_days != null ? `${backlog.median_age_days}d` : '–'}
Median age
{backlog.stale_count}
Older than 30 days
{total > 0 && (
)}
); } function BucketBar({ buckets }: { buckets: OverviewCount[] }) { const total = buckets.reduce((s, b) => s + b.count, 0); if (total === 0) return null; const colors = [ 'var(--accent)', 'var(--green)', 'var(--amber)', 'var(--red)', 'var(--muted)', ]; return (
`${b.name}: ${b.count}`).join(' · ')} > {buckets.map((b, i) => (
))}
); } // ── ConfidenceDistributionChart ──────────────────────────────────────────── export function ConfidenceDistributionChart({ dist, }: { dist: ConfidenceDistribution; }) { const total = dist.high + dist.medium + dist.low + dist.none; if (total === 0) { return (

No data

); } const segments = [ { label: 'High', value: dist.high, color: 'var(--green)' }, { label: 'Medium', value: dist.medium, color: 'var(--amber)' }, { label: 'Low', value: dist.low, color: 'var(--muted)' }, { label: 'None', value: dist.none, color: 'var(--subtle)' }, ]; return (
{segments.map((s) => s.value > 0 ? (
) : null, )}
{segments.map((s) => (
{s.label} {s.value}
))}
); } // ── ScannerQualityPanel ──────────────────────────────────────────────────── export function ScannerQualityPanel({ quality, crossFileRatio, }: { quality: ScannerQuality; crossFileRatio?: number; }) { const symexAttempted = Object.entries(quality.symex_breakdown || {}) .filter(([k]) => k !== 'not_attempted') .reduce((s, [, v]) => s + v, 0); const symexTotal = Object.values(quality.symex_breakdown || {}).reduce( (s, v) => s + v, 0, ); const totalFiles = quality.files_scanned + quality.files_skipped; const filesValue = totalFiles.toLocaleString(); const filesDetail = quality.files_skipped > 0 ? `${quality.files_scanned.toLocaleString()} fresh · ${quality.files_skipped.toLocaleString()} from cache` : quality.files_scanned > 0 ? `${quality.files_scanned.toLocaleString()} freshly indexed` : undefined; const dynamic = quality.dynamic_verification ?? { total: 0, confirmed: 0, partially_confirmed: 0, not_confirmed: 0, inconclusive: 0, unsupported: 0, }; const dynamicDetail = dynamic.total > 0 ? `${dynamic.total.toLocaleString()} verdicts · ${dynamic.partially_confirmed.toLocaleString()} partially confirmed · ${dynamic.not_confirmed.toLocaleString()} not confirmed · ${dynamic.inconclusive.toLocaleString()} inconclusive · ${dynamic.unsupported.toLocaleString()} unsupported` : 'no dynamic verdicts in latest scan'; const rows: Array<{ label: string; hint: string; value: string; detail?: string; }> = [ { label: 'Files', hint: 'Files the scanner saw on this run.', value: filesValue, detail: filesDetail, }, { label: 'Functions analyzed', hint: 'Function bodies the call graph saw.', value: quality.functions_analyzed.toLocaleString(), }, { label: 'Call edges resolved', hint: 'Share of call sites that the scanner resolved to a known callee. The remainder are typically external/library calls.', value: `${(quality.call_resolution_rate * 100).toFixed(1)}%`, detail: quality.unresolved_calls > 0 ? `${quality.unresolved_calls.toLocaleString()} unresolved` : undefined, }, { label: 'Cross-file flows', hint: 'Findings whose taint path crosses a file boundary.', value: crossFileRatio != null ? `${(crossFileRatio * 100).toFixed(1)}%` : '0%', detail: 'of findings', }, { label: 'Symbolic verification', hint: 'Taint findings the symbolic engine attempted to verify (confirmed, infeasible, or inconclusive).', value: symexTotal > 0 ? `${(quality.symex_verified_rate * 100).toFixed(1)}%` : 'n/a', detail: symexTotal > 0 ? `${symexAttempted} of ${symexTotal} taint findings` : 'no taint findings', }, { label: 'Dynamic verification', hint: 'Findings re-run in generated harnesses against the dynamic payload corpus.', value: dynamic.total > 0 ? `${dynamic.confirmed.toLocaleString()} confirmed` : 'not run', detail: dynamicDetail, }, ]; return (
{rows.map((r) => (
{r.label}
{r.value}
{r.detail &&
{r.detail}
}
))}
); } // ── HotSinksList ─────────────────────────────────────────────────────────── export function HotSinksList({ sinks }: { sinks: HotSink[] }) { if (!sinks.length) { return (

No data

); } return ( {sinks.map((s) => ( ))}
Sink Findings
{s.callee} {s.count}
); } // ── OwaspChart ───────────────────────────────────────────────────────────── export function OwaspChart({ buckets }: { buckets: OwaspBucket[] }) { if (!buckets.length) { return (

No data

); } const max = Math.max(...buckets.map((b) => b.count), 1); return (
    {buckets.map((b) => (
  • {b.code} {b.label}
    {b.count}
  • ))}
); } // ── WeightedTopFiles ─────────────────────────────────────────────────────── export function WeightedTopFiles({ files, onRowClick, }: { files: WeightedFile[]; onRowClick?: (name: string) => void; }) { if (!files.length) { return (

No data

); } return ( {files.map((f) => ( onRowClick(f.name) : undefined} > ))}
File Severity Score
{truncPath(f.name, 45)} {f.score}
); } function SeverityStack({ high, medium, low, }: { high: number; medium: number; low: number; }) { const total = high + medium + low; if (total === 0) return null; return (
{high > 0 && (
{high}
)} {medium > 0 && (
{medium}
)} {low > 0 && (
{low}
)}
); } // ── LanguageHealthTable ──────────────────────────────────────────────────── export function LanguageHealthTable({ rows }: { rows: LanguageHealth[] }) { if (!rows.length) { return (

No data

); } return ( {rows.map((r) => ( ))}
Language Findings Severity
{r.language} {r.findings}
); } // ── SuppressionHygieneCard ───────────────────────────────────────────────── export function SuppressionHygieneCard({ hygiene, }: { hygiene: SuppressionHygiene; }) { const total = hygiene.fingerprint_level + hygiene.rule_level + hygiene.file_level + hygiene.rule_in_file_level; const blanket = hygiene.rule_level + hygiene.file_level + hygiene.rule_in_file_level; const blanketDisplay = total > 0 ? `${(hygiene.blanket_rate * 100).toFixed(0)}%` : 'n/a'; const blanketDetail = total > 0 ? `${blanket} of ${total} suppressions are not pinned to a specific finding` : 'No suppressions yet'; return (
Blanket rate Lower is better
{blanketDisplay}
{blanketDetail}
By fingerprint Most specific
{hygiene.fingerprint_level}
By rule in a file
{hygiene.rule_in_file_level}
By rule
{hygiene.rule_level}
By file Least specific
{hygiene.file_level}
); } // ── BaselinePinControl ───────────────────────────────────────────────────── interface BaselinePinControlProps { baseline?: BaselineInfo; latestScanId?: string; onPin: (scanId: string) => void; onUnpin: () => void; isPending: boolean; } export function BaselinePinControl({ baseline, latestScanId, onPin, onUnpin, isPending, }: BaselinePinControlProps) { const navigate = useNavigate(); if (baseline) { const net = baseline.drift_new - baseline.drift_fixed; const driftClass = net > 0 ? 'baseline-drift-bad' : net < 0 ? 'baseline-drift-good' : 'baseline-drift-flat'; return (
Baseline: drift: +{baseline.drift_new} new / -{baseline.drift_fixed} fixed ( {net >= 0 ? '+' : ''} {net})
); } if (!latestScanId) return null; return (
No baseline pinned.
); }