# 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` | 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 ```html ``` #### 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 ```typescript 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 ```html ``` --- ### 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` | VeriKey copied to clipboard | | `copyHash` | `EventEmitter` | Any hash copied | | `verify` | `EventEmitter` | Verify button clicked | | `downloadEvidence` | `EventEmitter` | 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 ```html ``` --- ### 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` | VeriKey copied | | `refresh` | `EventEmitter` | Refresh requested | #### InputManifest Interface ```typescript 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 ```typescript interface InputManifestDisplayConfig { showSource: boolean; showSbom: boolean; showVex: boolean; showPolicy: boolean; showSigners: boolean; showTimeWindow: boolean; } ``` #### Usage ```html ``` --- ## 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: ```bash cd src/Web/StellaOps.Web npm run storybook ``` --- ## Integration Examples ### Finding Row Integration ```typescript // finding-row.component.ts @Component({ selector: 'stellaops-finding-row', template: `
` }) export class FindingRowComponent { @Input() finding!: FindingRow; @Output() openProofPanel = new EventEmitter(); } ``` ### Decision Detail Panel ```typescript // decision-detail-panel.component.ts @Component({ template: `
` }) export class DecisionDetailPanelComponent { // ... } ``` --- ## Theming Components use CSS custom properties for theming: ```css /* 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 --- ## Related Documentation - [Provcache Module README](../provcache/README.md) — Core concepts and architecture - [Provcache Architecture](../provcache/architecture.md) — Technical deep-dive - [UI Architecture](./architecture.md) — Angular patterns and state management - [Accessibility Guide](../../accessibility.md) — WCAG compliance guidelines