353 lines
9.6 KiB
Markdown
353 lines
9.6 KiB
Markdown
# 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.
|
|
|
|
```typescript
|
|
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
|
|
|
|
```html
|
|
<!-- 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.
|
|
|
|
```typescript
|
|
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
|
|
|
|
```html
|
|
<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
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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
|
|
|
|
```html
|
|
<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
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
import {
|
|
GateSummaryPanelComponent,
|
|
GateResult,
|
|
WitnessGateMetrics,
|
|
WitnessPathSummary,
|
|
} from '@app/shared/domain/gate-summary-panel';
|
|
```
|
|
|
|
#### Witness Gate Support
|
|
|
|
The `GateResult` interface now supports witness-specific properties:
|
|
|
|
```typescript
|
|
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
|
|
|
|
```html
|
|
<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.ts`
|
|
- `witness-comparison.component.spec.ts`
|
|
- `unwitnessed-advisory.component.spec.ts`
|
|
- `gate-summary-panel.component.spec.ts`
|
|
|
|
Run tests:
|
|
|
|
```bash
|
|
cd src/Web/StellaOps.Web
|
|
npm test -- --include="**/*witness*" --include="**/*gate-summary*"
|
|
```
|