9.6 KiB
Witness Visualization Components
Sprint: SPRINT_20260118_020_FE_witness_visualization
The witness visualization component suite provides UI for displaying runtime witness data, comparing static analysis paths with runtime observations, and managing witness gate results in release promotion flows.
Overview
Runtime witnesses confirm that static analysis reachability paths are actually exercised during application execution. These components visualize:
- Witness Status: Whether a path has been witnessed at runtime
- Static vs Runtime Comparison: Side-by-side or overlay views comparing predicted and observed paths
- Gate Results: Witness gate outcomes for release promotion decisions
- Unwitnessed Advisories: Paths requiring runtime exercise before promotion
Components
Core Components
| Component | Purpose | Location |
|---|---|---|
WitnessStatusChipComponent |
Status badge showing witness state | shared/domain/witness-status-chip/ |
WitnessComparisonComponent |
Static vs runtime path comparison | shared/components/witness-comparison/ |
UnwitnessedAdvisoryComponent |
Advisory panel for unwitnessed paths | shared/components/unwitnessed-advisory/ |
GateSummaryPanelComponent |
Gate results with witness metrics | shared/domain/gate-summary-panel/ |
Witness Status Chip
Displays the witness status of a reachability path with color-coded badges.
import { WitnessStatusChipComponent, WitnessStatus } from '@app/shared/domain/witness-status-chip';
States
| State | Color | Icon | Description |
|---|---|---|---|
witnessed |
Green | ✓ | Path confirmed by runtime observation |
unwitnessed |
Yellow | ○ | Path not yet observed at runtime |
stale |
Orange | ⏱ | Witness data is outdated |
failed |
Red | ✗ | Witness verification failed |
Usage
<!-- Basic usage -->
<app-witness-status-chip [status]="'witnessed'" />
<!-- With details for tooltip -->
<app-witness-status-chip
[status]="'witnessed'"
[details]="{
status: 'witnessed',
lastObserved: '2026-01-15T10:30:00Z',
observationCount: 42,
rekorLogIndex: 12345
}"
[showCount]="true"
(chipClick)="onChipClick()"
/>
Input Properties
| Property | Type | Default | Description |
|---|---|---|---|
status |
WitnessStatus |
required | Witness status to display |
details |
WitnessStatusDetails |
null |
Optional metadata for tooltip |
showCount |
boolean |
true |
Whether to show observation count |
Witness Comparison Component
Side-by-side or overlay view comparing static analysis paths with runtime observations. The main visualization for understanding witness coverage.
import {
WitnessComparisonComponent,
WitnessComparisonData,
ComparisonPathStep,
ComparisonMetrics,
} from '@app/shared/components/witness-comparison';
Features
- View Modes: List view (vertical) or overlay view (side-by-side columns)
- Color Coding: Green (confirmed), yellow (static only), orange (runtime only/unexpected)
- Filtering: Filter by confirmation status
- Metrics Summary: Totals and confirmation rate display
- Step Drill-down: Click steps for detailed information
Usage
<app-witness-comparison
[data]="comparisonData"
(stepClick)="onStepClick($event)"
(refresh)="onRefresh()"
/>
Input Properties
| Property | Type | Description |
|---|---|---|
data |
WitnessComparisonData |
Comparison data with paths and metrics |
Output Events
| Event | Type | Description |
|---|---|---|
stepClick |
ComparisonPathStep |
Emitted when user clicks a step |
refresh |
void |
Emitted when user requests data refresh |
Data Models
interface ComparisonPathStep {
nodeId: string;
symbol: string;
file?: string;
line?: number;
package?: string;
inStatic: boolean; // Found in static analysis
inRuntime: boolean; // Observed at runtime
runtimeInvocations?: number;
lastObserved?: string;
}
interface ComparisonMetrics {
totalSteps: number;
confirmedSteps: number; // Both static and runtime
staticOnlySteps: number; // Static only (unwitnessed)
runtimeOnlySteps: number; // Runtime only (unexpected)
confirmationRate: number; // Percentage confirmed
}
interface WitnessComparisonData {
claimId: string;
cveId?: string;
packageName: string;
packageVersion?: string;
pathSteps: ComparisonPathStep[];
metrics: ComparisonMetrics;
generatedAt: string;
}
Unwitnessed Advisory Component
Advisory panel displayed when release promotion encounters paths without runtime witnesses. Used in the gate flow to inform operators about witness coverage gaps.
import {
UnwitnessedAdvisoryComponent,
UnwitnessedAdvisoryData,
UnwitnessedPath,
} from '@app/shared/components/unwitnessed-advisory';
Features
- Severity Summary: Visual breakdown by vulnerability severity
- Path List: Sortable list of unwitnessed paths
- Blocking/Advisory Mode: Different styling based on gate configuration
- Action Buttons: Create test tasks for individual paths or all at once
Usage
<app-unwitnessed-advisory
[data]="advisoryData"
(createTestTask)="onCreateTestTask($event)"
(createAllTestTasks)="onCreateAllTestTasks()"
(viewComparison)="onViewComparison()"
/>
Input Properties
| Property | Type | Description |
|---|---|---|
data |
UnwitnessedAdvisoryData |
Advisory data with paths and configuration |
Output Events
| Event | Type | Description |
|---|---|---|
createTestTask |
UnwitnessedPath |
Create test task for specific path |
createAllTestTasks |
void |
Create test tasks for all paths |
viewComparison |
void |
Open full comparison view |
Data Models
interface UnwitnessedPath {
pathId: string;
cveId?: string;
vulnId: string;
packageName: string;
packageVersion?: string;
entrypoint: string;
sink: string;
severity: 'critical' | 'high' | 'medium' | 'low' | 'unknown';
confidence: number;
lastAnalyzed?: string;
}
interface UnwitnessedAdvisoryData {
totalUnwitnessed: number;
paths: UnwitnessedPath[];
targetEnvironment?: string;
isBlocking: boolean;
}
Gate Summary Panel (Extended)
Extended to support witness gate display with metrics, expandable details, and comparison links.
import {
GateSummaryPanelComponent,
GateResult,
WitnessGateMetrics,
WitnessPathSummary,
} from '@app/shared/domain/gate-summary-panel';
Witness Gate Support
The GateResult interface now supports witness-specific properties:
interface GateResult {
id: string;
name: string;
state: 'PASS' | 'WARN' | 'BLOCK' | 'SKIP';
reason?: string;
ruleHits?: number;
gateType?: 'standard' | 'witness' | 'cve' | 'sbom';
witnessMetrics?: WitnessGateMetrics;
}
interface WitnessGateMetrics {
totalPaths: number;
witnessedPaths: number;
unwitnessedPaths: number;
stalePaths?: number;
unwitnessedPathDetails?: WitnessPathSummary[];
}
interface WitnessPathSummary {
pathId: string;
entrypoint: string;
sink: string;
severity?: 'critical' | 'high' | 'medium' | 'low' | 'unknown';
vulnId?: string;
}
Usage
<app-gate-summary-panel
[gates]="gates"
[policyRef]="policyReference"
[snapshotRef]="snapshotReference"
(openExplain)="onOpenExplain($event)"
(openEvidence)="onOpenEvidence()"
(openComparison)="onOpenComparison($event)"
/>
Witness Gate Features
- Metrics Display: Shows X/Y witnessed paths, unwitnessed count, stale count
- Advisory Styling: Yellow border and background for WARN state witness gates
- Expandable Details: Click "Details" to see unwitnessed path list
- Compare Button: Opens full comparison view
Color Coding Reference
Comparison States
| State | Color | CSS Variable | Meaning |
|---|---|---|---|
| Confirmed | Green | --green-500 |
Path in both static and runtime |
| Static Only | Yellow | --yellow-500 |
Path predicted but not observed |
| Runtime Only | Orange | --orange-500 |
Unexpected path observed |
Severity Colors
| Severity | Color | CSS Variable |
|---|---|---|
| Critical | Red | --red-500 |
| High | Orange | --orange-500 |
| Medium | Yellow | --yellow-500 |
| Low | Blue | --blue-500 |
| Unknown | Gray | --gray-400 |
Integration with Existing Components
The witness visualization components integrate with several existing UI elements:
| Existing Component | Integration |
|---|---|
WitnessDrawerComponent |
Can embed comparison view |
WitnessPageComponent |
Full reachability analysis page |
TimelineListComponent |
Display witness observation timeline |
GateExplainDrawerComponent |
Show witness gate explanation |
Accessibility
All witness visualization components follow WCAG 2.1 AA guidelines:
- ARIA labels for all interactive elements
- Keyboard navigation support
- Focus management for expandable sections
- Color + icon combinations (not color alone)
- Screen reader announcements for status changes
Testing
Unit tests are located alongside components:
witness-status-chip.component.spec.tswitness-comparison.component.spec.tsunwitnessed-advisory.component.spec.tsgate-summary-panel.component.spec.ts
Run tests:
cd src/Web/StellaOps.Web
npm test -- --include="**/*witness*" --include="**/*gate-summary*"