save progress

This commit is contained in:
master
2026-01-09 18:27:36 +02:00
parent e608752924
commit a21d3dbc1f
361 changed files with 63068 additions and 1192 deletions

View 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
![Provenance Tab](../../assets/screenshots/evidence-provenance.png)
### Policy Tab with Lattice Trace
![Policy Tab](../../assets/screenshots/evidence-policy.png)
### Attestation Chain Expanded
![Attestation Chain](../../assets/screenshots/attestation-chain.png)
## Changelog
| Version | Date | Changes |
|---------|------|---------|
| 1.0.0 | 2026-01-09 | Initial implementation |