Files
git.stella-ops.org/docs/modules/triage/evidence-panel.md
2026-01-09 18:27:46 +02:00

8.8 KiB

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:

<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.

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.

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

interface ProvenanceEvidence {
  dsseStatus: DsseBadgeStatus;
  dsseDetails?: DsseVerificationDetails;
  attestationChain: AttestationChainNode[];
  signer?: SignerInfo;
  rekorLogIndex?: number;
  rekorVerifyUrl?: string;
  inTotoStatement?: object;
}

AttestationChainNode

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

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 for details.

Screenshots

Provenance Tab

Provenance Tab

Policy Tab with Lattice Trace

Policy Tab

Attestation Chain Expanded

Attestation Chain

Changelog

Version Date Changes
1.0.0 2026-01-09 Initial implementation