288 lines
8.8 KiB
Markdown
288 lines
8.8 KiB
Markdown
# Evidence Panel Component
|
|
|
|
> **Sprint:** SPRINT_20260107_006_001_FE
|
|
> **Module:** Triage UI
|
|
> **Version:** 1.0.0
|
|
|
|
## Overview
|
|
|
|
The Evidence Panel provides a unified tabbed interface for viewing all evidence related to a security finding. It consolidates five categories of evidence:
|
|
|
|
1. **Provenance** - DSSE attestation chain, signer identity, Rekor transparency
|
|
2. **Reachability** - Code path analysis showing if vulnerability is reachable
|
|
3. **Diff** - Source code changes introducing the vulnerability
|
|
4. **Runtime** - Runtime telemetry and execution evidence
|
|
5. **Policy** - OPA/Rego policy decisions and lattice trace
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────────────┐
|
|
│ TabbedEvidencePanelComponent │
|
|
├──────────────────────────────────────────────────────────────────────┤
|
|
│ [Provenance] [Reachability] [Diff] [Runtime] [Policy] │
|
|
├──────────────────────────────────────────────────────────────────────┤
|
|
│ ┌──────────────────────────────────────────────────────────────────┐ │
|
|
│ │ Tab Content (lazy-loaded) │ │
|
|
│ │ │ │
|
|
│ │ ProvenanceTabComponent / ReachabilityTabComponent / etc. │ │
|
|
│ └──────────────────────────────────────────────────────────────────┘ │
|
|
└──────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Components
|
|
|
|
### TabbedEvidencePanelComponent
|
|
|
|
**Selector:** `app-tabbed-evidence-panel`
|
|
|
|
**Inputs:**
|
|
- `findingId: string` - The finding ID to load evidence for
|
|
|
|
**Outputs:**
|
|
- `tabChange: EventEmitter<EvidenceTabType>` - Emitted when tab changes
|
|
|
|
**Usage:**
|
|
```html
|
|
<app-tabbed-evidence-panel
|
|
[findingId]="selectedFindingId"
|
|
(tabChange)="onTabChange($event)"
|
|
/>
|
|
```
|
|
|
|
### ProvenanceTabComponent
|
|
|
|
Displays DSSE attestation information including:
|
|
- DSSE verification badge (verified/partial/missing)
|
|
- Attestation chain visualization (build → scan → triage → policy)
|
|
- Signer identity and key information
|
|
- Rekor log index with verification link
|
|
- Collapsible in-toto statement JSON
|
|
|
|
### DsseBadgeComponent
|
|
|
|
**Selector:** `app-dsse-badge`
|
|
|
|
Displays the DSSE verification status as a badge.
|
|
|
|
**Inputs:**
|
|
- `status: DsseBadgeStatus` - 'verified' | 'partial' | 'missing'
|
|
- `details?: DsseVerificationDetails` - Additional verification details
|
|
- `showTooltip?: boolean` - Show tooltip on hover (default: true)
|
|
- `animate?: boolean` - Enable hover animations (default: true)
|
|
|
|
**States:**
|
|
| State | Color | Icon | Meaning |
|
|
|-------|-------|------|---------|
|
|
| verified | Green | ✓ | Full DSSE chain verified |
|
|
| partial | Amber | ⚠ | Some attestations missing |
|
|
| missing | Red | ✗ | No valid attestation |
|
|
|
|
### AttestationChainComponent
|
|
|
|
**Selector:** `app-attestation-chain`
|
|
|
|
Visualizes the attestation chain as connected nodes.
|
|
|
|
**Inputs:**
|
|
- `nodes: AttestationChainNode[]` - Chain nodes to display
|
|
|
|
**Outputs:**
|
|
- `nodeClick: EventEmitter<AttestationChainNode>` - Emitted on node click
|
|
|
|
### PolicyTabComponent
|
|
|
|
Displays policy evaluation details including:
|
|
- Verdict badge (ALLOW/DENY/QUARANTINE/REVIEW)
|
|
- OPA/Rego rule path that matched
|
|
- K4 lattice merge trace visualization
|
|
- Counterfactual analysis ("What would change verdict?")
|
|
- Policy version and editor link
|
|
|
|
### ReachabilityTabComponent
|
|
|
|
Integrates the existing `ReachabilityContextComponent` with:
|
|
- Summary header with status badge
|
|
- Confidence percentage display
|
|
- Entry points list
|
|
- Link to full graph view
|
|
|
|
## Services
|
|
|
|
### EvidenceTabService
|
|
|
|
**Path:** `services/evidence-tab.service.ts`
|
|
|
|
Fetches evidence data for each tab with caching.
|
|
|
|
```typescript
|
|
interface EvidenceTabService {
|
|
getProvenanceEvidence(findingId: string, forceRefresh?: boolean): Observable<LoadState<ProvenanceEvidence>>;
|
|
getReachabilityEvidence(findingId: string, forceRefresh?: boolean): Observable<LoadState<ReachabilityData>>;
|
|
getDiffEvidence(findingId: string, forceRefresh?: boolean): Observable<LoadState<DiffEvidence>>;
|
|
getRuntimeEvidence(findingId: string, forceRefresh?: boolean): Observable<LoadState<RuntimeEvidence>>;
|
|
getPolicyEvidence(findingId: string, forceRefresh?: boolean): Observable<LoadState<PolicyEvidence>>;
|
|
clearCache(findingId?: string): void;
|
|
}
|
|
```
|
|
|
|
### TabUrlPersistenceService
|
|
|
|
**Path:** `services/tab-url-persistence.service.ts`
|
|
|
|
Manages URL query param persistence for selected tab.
|
|
|
|
```typescript
|
|
interface TabUrlPersistenceService {
|
|
readonly selectedTab$: Observable<EvidenceTabType>;
|
|
getCurrentTab(): EvidenceTabType;
|
|
setTab(tab: EvidenceTabType): void;
|
|
navigateToTab(tab: EvidenceTabType): void;
|
|
}
|
|
```
|
|
|
|
## Keyboard Shortcuts
|
|
|
|
| Key | Action |
|
|
|-----|--------|
|
|
| `1` | Go to Provenance tab |
|
|
| `2` | Go to Reachability tab |
|
|
| `3` | Go to Diff tab |
|
|
| `4` | Go to Runtime tab |
|
|
| `5` | Go to Policy tab |
|
|
| `→` | Next tab |
|
|
| `←` | Previous tab |
|
|
| `Home` | First tab |
|
|
| `End` | Last tab |
|
|
|
|
## URL Persistence
|
|
|
|
The selected tab is persisted in the URL query string:
|
|
|
|
```
|
|
/triage/findings/CVE-2024-1234?tab=provenance
|
|
/triage/findings/CVE-2024-1234?tab=reachability
|
|
/triage/findings/CVE-2024-1234?tab=diff
|
|
/triage/findings/CVE-2024-1234?tab=runtime
|
|
/triage/findings/CVE-2024-1234?tab=policy
|
|
```
|
|
|
|
This enables:
|
|
- Deep linking to specific evidence
|
|
- Browser history navigation
|
|
- Sharing links with colleagues
|
|
|
|
## Data Models
|
|
|
|
### ProvenanceEvidence
|
|
|
|
```typescript
|
|
interface ProvenanceEvidence {
|
|
dsseStatus: DsseBadgeStatus;
|
|
dsseDetails?: DsseVerificationDetails;
|
|
attestationChain: AttestationChainNode[];
|
|
signer?: SignerInfo;
|
|
rekorLogIndex?: number;
|
|
rekorVerifyUrl?: string;
|
|
inTotoStatement?: object;
|
|
}
|
|
```
|
|
|
|
### AttestationChainNode
|
|
|
|
```typescript
|
|
interface AttestationChainNode {
|
|
id: string;
|
|
type: 'build' | 'scan' | 'triage' | 'policy' | 'custom';
|
|
label: string;
|
|
status: 'verified' | 'pending' | 'missing' | 'failed';
|
|
predicateType?: string;
|
|
digest?: string;
|
|
timestamp?: string;
|
|
signer?: string;
|
|
details?: AttestationDetails;
|
|
}
|
|
```
|
|
|
|
### PolicyEvidence
|
|
|
|
```typescript
|
|
interface PolicyEvidence {
|
|
verdict: PolicyVerdict;
|
|
rulePath?: string;
|
|
latticeTrace?: LatticeTraceStep[];
|
|
counterfactuals?: PolicyCounterfactual[];
|
|
policyVersion?: string;
|
|
policyDigest?: string;
|
|
policyEditorUrl?: string;
|
|
evaluatedAt?: string;
|
|
}
|
|
```
|
|
|
|
## Accessibility
|
|
|
|
The Evidence Panel follows WAI-ARIA tabs pattern:
|
|
|
|
- `role="tablist"` on tab navigation
|
|
- `role="tab"` on each tab button
|
|
- `role="tabpanel"` on each panel
|
|
- `aria-selected` indicates active tab
|
|
- `aria-controls` links tabs to panels
|
|
- `aria-labelledby` links panels to tabs
|
|
- `tabindex` management for keyboard navigation
|
|
- Screen reader announcements on tab change
|
|
|
|
## Testing
|
|
|
|
### Unit Tests
|
|
|
|
Located in `evidence-panel/*.spec.ts`:
|
|
|
|
- Tab navigation behavior
|
|
- DSSE badge states and styling
|
|
- Attestation chain rendering
|
|
- Keyboard navigation
|
|
- URL persistence
|
|
- Loading/error states
|
|
|
|
### E2E Tests
|
|
|
|
Located in `e2e/evidence-panel.e2e.spec.ts`:
|
|
|
|
- Full tab switching workflow
|
|
- Evidence loading and display
|
|
- Copy JSON functionality
|
|
- URL persistence across reloads
|
|
- Accessibility compliance
|
|
|
|
## API Dependencies
|
|
|
|
The Evidence Panel depends on these API endpoints:
|
|
|
|
| Endpoint | Method | Description |
|
|
|----------|--------|-------------|
|
|
| `/api/evidence/provenance/{findingId}` | GET | Fetch provenance data |
|
|
| `/api/evidence/reachability/{findingId}` | GET | Fetch reachability data |
|
|
| `/api/evidence/diff/{findingId}` | GET | Fetch diff data |
|
|
| `/api/evidence/runtime/{findingId}` | GET | Fetch runtime data |
|
|
| `/api/evidence/policy/{findingId}` | GET | Fetch policy data |
|
|
|
|
See [Evidence API Reference](../../../api/evidence-api.md) for details.
|
|
|
|
## Screenshots
|
|
|
|
### Provenance Tab
|
|

|
|
|
|
### Policy Tab with Lattice Trace
|
|

|
|
|
|
### Attestation Chain Expanded
|
|

|
|
|
|
## Changelog
|
|
|
|
| Version | Date | Changes |
|
|
|---------|------|---------|
|
|
| 1.0.0 | 2026-01-09 | Initial implementation |
|