save progress
This commit is contained in:
287
docs/modules/triage/evidence-panel.md
Normal file
287
docs/modules/triage/evidence-panel.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user