Files
git.stella-ops.org/docs/modules/ui/provcache-components.md
2025-12-25 23:10:09 +02:00

12 KiB

Provcache UI Components

This document describes the Angular components for visualizing provenance cache data, trust scores, and proof trees in the StellaOps Console.

Overview

The Provcache UI components provide visual feedback for:

  • Cache state awareness — Users see whether decisions come from cache (fast) or are freshly computed
  • Trust transparency — Trust scores with breakdowns by evidence component
  • Proof visualization — Interactive proof trees showing evidence chain
  • Input manifest — Details of all inputs that form a cached decision

Components

ProvenanceBadgeComponent

Selector: stellaops-provenance-badge

Displays a compact badge indicating the provenance state of a decision.

Inputs

Input Type Default Description
state 'cached' | 'computed' | 'stale' | 'unknown' 'unknown' Current provenance state
cacheDetails CacheDetails | null null Optional cache metadata
trustScore number | null null Optional trust score (0-100)
size 'small' | 'medium' | 'large' 'medium' Badge size variant

Outputs

Output Type Description
viewProofTree EventEmitter<void> Emitted when user clicks to view proof

States & Icons

State Icon Tooltip CSS Class
cached "Provenance-cached" badge--cached
computed 🔄 "Freshly computed" badge--computed
stale "Stale - recomputing" badge--stale
unknown "Unknown provenance" badge--unknown

Usage

<!-- Basic usage -->
<stellaops-provenance-badge [state]="'cached'"></stellaops-provenance-badge>

<!-- With cache details -->
<stellaops-provenance-badge
  [state]="'cached'"
  [cacheDetails]="{ source: 'valkey', ageSeconds: 45, veriKey: 'sha256:abc...' }"
  [trustScore]="85"
  (viewProofTree)="openProofTree()">
</stellaops-provenance-badge>

Accessibility

  • Uses role="status" for screen reader announcements
  • Tooltip content exposed via aria-label
  • Color is not the sole indicator — icons and text labels provided

TrustScoreDisplayComponent

Selector: stellaops-trust-score-display

Visualizes a trust score (0-100) with optional breakdown by evidence component.

Inputs

Input Type Default Description
score number 0 Overall trust score (0-100)
breakdown TrustScoreBreakdown | null null Component-level scores
mode 'donut' | 'badge' | 'inline' 'donut' Display mode
showBreakdown boolean false Show breakdown tooltip
compact boolean false Use compact sizing
thresholds { high: number; medium: number } { high: 80, medium: 50 } Color thresholds

TrustScoreBreakdown Interface

interface TrustScoreBreakdown {
  reachability: number;     // 0.0-1.0 (25% weight)
  sbomCompleteness: number; // 0.0-1.0 (20% weight)
  vexCoverage: number;      // 0.0-1.0 (20% weight)
  policyFreshness: number;  // 0.0-1.0 (15% weight)
  signerTrust: number;      // 0.0-1.0 (20% weight)
}

Display Modes

Mode Description
donut Circular SVG chart with score in center
badge Compact pill-shaped badge
inline Text-only display for tight spaces

Color Coding

Score Range Class Color
≥ high (80) score--high Green (#4caf50)
≥ medium (50) score--medium Yellow (#ff9800)
< medium score--low Red (#f44336)

Usage

<!-- Donut chart with breakdown -->
<stellaops-trust-score-display
  [score]="85"
  [breakdown]="breakdown"
  [mode]="'donut'"
  [showBreakdown]="true">
</stellaops-trust-score-display>

<!-- Compact badge -->
<stellaops-trust-score-display
  [score]="72"
  [mode]="'badge'"
  [compact]="true">
</stellaops-trust-score-display>

ProofTreeComponent

Selector: stellaops-proof-tree

Renders a decision's proof chain as a collapsible tree with verification capabilities.

Inputs

Input Type Default Description
digest DecisionDigest | null null The decision digest to display
merkleTree MerkleTree | null null Optional Merkle tree structure
verdicts VerdictEntry[] [] Vulnerability verdicts
evidenceChunks EvidenceChunk[] [] Evidence artifacts
isVerifying boolean false Show verification spinner

Outputs

Output Type Description
copyVeriKey EventEmitter<string> VeriKey copied to clipboard
copyHash EventEmitter<string> Any hash copied
verify EventEmitter<void> Verify button clicked
downloadEvidence EventEmitter<EvidenceChunk> Evidence download requested

Tree Structure

DecisionDigest
├── VeriKey: sha256:abc123...
├── Trust Score: 85
│   ├── Reachability: 95%
│   ├── SBOM Completeness: 85%
│   ├── VEX Coverage: 90%
│   ├── Policy Freshness: 88%
│   └── Signer Trust: 92%
├── Verdicts (12)
│   ├── CVE-2025-1234 → not_affected
│   ├── CVE-2025-5678 → fixed
│   └── ...
├── Merkle Tree
│   ├── Root: sha256:root...
│   ├── Left
│   │   ├── sha256:sbom... (sbom-hash)
│   │   └── sha256:vex... (vex-set-hash)
│   └── Right
│       ├── sha256:policy... (policy-hash)
│       └── sha256:signers... (signers-hash)
└── Evidence Chunks (5)
    ├── [sbom] SPDX 2.3 SBOM document
    ├── [vex] VEX statement bundle
    └── ...

Verdict Statuses

Status Color Meaning
not_affected Green Vulnerability not applicable
fixed Blue Patched/remediated
affected Red Vulnerable
under_investigation Yellow Pending analysis
mitigated Cyan Mitigating controls in place

Usage

<stellaops-proof-tree
  [digest]="decisionDigest"
  [merkleTree]="merkleTree"
  [verdicts]="verdicts"
  [evidenceChunks]="chunks"
  [isVerifying]="verifying"
  (verify)="verifyProof()"
  (copyVeriKey)="copyToClipboard($event)"
  (downloadEvidence)="downloadChunk($event)">
</stellaops-proof-tree>

InputManifestComponent

Selector: stellaops-input-manifest

Displays the exact inputs that formed a VeriKey and cached decision.

Inputs

Input Type Default Description
manifest InputManifest | null null The manifest to display
mode 'full' | 'compact' | 'summary' 'full' Display mode
displayConfig InputManifestDisplayConfig (all true) Section visibility

Outputs

Output Type Description
copyVeriKey EventEmitter<string> VeriKey copied
refresh EventEmitter<void> Refresh requested

InputManifest Interface

interface InputManifest {
  veriKey: string;
  sourceArtifact: SourceArtifactInfo;
  sbom: SbomInfo;
  vex: VexInfo;
  policy: PolicyInfoManifest;
  signers: SignerInfo;
  timeWindow: TimeWindowInfo;
  generatedAt: string;
}

interface SourceArtifactInfo {
  digest: string;
  artifactType: string;
  ociReference?: string;
  sizeBytes?: number;
}

interface SbomInfo {
  hash: string;
  format: string;         // 'spdx-2.3', 'cyclonedx-1.6'
  packageCount: number;
  completenessScore: number;
  createdAt: string;
}

interface VexInfo {
  hashSetHash: string;
  statementCount: number;
  sources: string[];
  latestStatementAt: string;
}

interface PolicyInfoManifest {
  hash: string;
  packId: string;
  version: number;
  lastUpdatedAt: string;
  name?: string;
}

interface SignerInfo {
  setHash: string;
  signerCount: number;
  certificates?: CertificateInfo[];
}

interface CertificateInfo {
  subject: string;
  issuer: string;
  fingerprint: string;
  expiresAt: string;
  trustLevel: 'fulcio' | 'enterprise-ca' | 'self-signed';
}

interface TimeWindowInfo {
  bucket: string;
  startsAt: string;
  endsAt: string;
}

Display Modes

Mode Description
full All sections with full details
compact Reduced spacing, abbreviated values
summary Grid layout for quick overview

Section Visibility

interface InputManifestDisplayConfig {
  showSource: boolean;
  showSbom: boolean;
  showVex: boolean;
  showPolicy: boolean;
  showSigners: boolean;
  showTimeWindow: boolean;
}

Usage

<!-- Full manifest display -->
<stellaops-input-manifest
  [manifest]="inputManifest"
  [mode]="'full'"
  (copyVeriKey)="copyToClipboard($event)">
</stellaops-input-manifest>

<!-- Security-focused view -->
<stellaops-input-manifest
  [manifest]="inputManifest"
  [mode]="'compact'"
  [displayConfig]="{ showSource: false, showSbom: false, showVex: true, showPolicy: true, showSigners: true, showTimeWindow: false }">
</stellaops-input-manifest>

Storybook Documentation

All components have Storybook stories in src/Web/StellaOps.Web/src/stories/provcache/:

File Description
provenance-badge.stories.ts All badge states, trust scores, sizes
trust-score-display.stories.ts Score ranges, modes, breakdowns
input-manifest.stories.ts Modes, SBOM formats, certificates
proof-tree.stories.ts Tree depths, verdicts, verification

Run Storybook to explore:

cd src/Web/StellaOps.Web
npm run storybook

Integration Examples

Finding Row Integration

// finding-row.component.ts
@Component({
  selector: 'stellaops-finding-row',
  template: `
    <div class="finding-row">
      <stellaops-provenance-badge
        [state]="finding.provenanceState"
        [cacheDetails]="finding.cacheDetails"
        [trustScore]="finding.trustScore"
        (viewProofTree)="openProofPanel.emit(finding)">
      </stellaops-provenance-badge>
      <!-- ... rest of finding row -->
    </div>
  `
})
export class FindingRowComponent {
  @Input() finding!: FindingRow;
  @Output() openProofPanel = new EventEmitter<FindingRow>();
}

Decision Detail Panel

// decision-detail-panel.component.ts
@Component({
  template: `
    <div class="decision-detail-panel">
      <stellaops-trust-score-display
        [score]="digest.trustScore"
        [breakdown]="digest.trustScoreBreakdown"
        [mode]="'donut'"
        [showBreakdown]="true">
      </stellaops-trust-score-display>

      <stellaops-proof-tree
        [digest]="digest"
        [merkleTree]="merkleTree"
        [verdicts]="verdicts"
        [evidenceChunks]="chunks"
        [isVerifying]="verifying$ | async"
        (verify)="verifyProof()"
        (downloadEvidence)="downloadChunk($event)">
      </stellaops-proof-tree>

      <stellaops-input-manifest
        [manifest]="manifest"
        [mode]="'full'">
      </stellaops-input-manifest>
    </div>
  `
})
export class DecisionDetailPanelComponent {
  // ...
}

Theming

Components use CSS custom properties for theming:

/* Dark mode overrides */
@media (prefers-color-scheme: dark) {
  --trust-score-high: #81c784;
  --trust-score-medium: #ffb74d;
  --trust-score-low: #e57373;
  --badge-cached-bg: #1b5e20;
  --badge-computed-bg: #0d47a1;
}

Accessibility

All components follow WCAG 2.1 AA guidelines:

  • Keyboard navigation — All interactive elements focusable and operable
  • Screen reader support — ARIA labels, roles, and live regions
  • Color independence — Icons and text supplement color coding
  • Focus indicators — Visible focus outlines on interactive elements
  • Motion preferences — Reduced motion respected where applicable