# Unified Trust Score Architecture > **Ownership:** Policy Guild • Signals Guild > **Services:** `StellaOps.Signals.UnifiedScore` (facade), `StellaOps.Signals.EvidenceWeightedScore` (core), `StellaOps.Policy.Determinization` (entropy) > **Related docs:** [Policy architecture](../modules/policy/architecture.md), [EWS migration](../modules/policy/design/confidence-to-ews-migration.md), [Score Proofs API](../api/scanner-score-proofs-api.md) This document describes the **unified trust score facade** that provides a single API for accessing risk scores, uncertainty metrics, and evidence from the underlying EWS and Determinization systems. --- ## 1 · Design Principle: Facade Over Rewrite Stella Ops has mature, battle-tested scoring systems: | System | Purpose | Maturity | |--------|---------|----------| | **EWS** | 6-dimension risk scoring with guardrails | Production (1000+ determinism tests) | | **Determinization** | Entropy, confidence decay, conflict detection | Production | | **RiskEngine** | Signal-specific providers (CVSS/KEV/EPSS) | Production | The unified score facade **does not replace these systems**. Instead, it: 1. **Combines** EWS scores with Determinization entropy in a single result 2. **Externalizes** EWS weights to versioned manifest files for auditing 3. **Exposes** the unknowns fraction (U) as a first-class metric --- ## 2 · Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ IUnifiedScoreService │ │ (Facade) │ ├─────────────────────────────────────────────────────────────┤ │ • ComputeAsync(request) → UnifiedScoreResult │ │ • Combines EWS + Determinization + ConflictDetector │ │ • Loads weights from versioned manifests │ └─────────────┬───────────────────────┬───────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────┐ │ EvidenceWeightedScore │ │ Determinization │ │ Calculator │ │ │ ├─────────────────────────┤ ├─────────────────────────┤ │ • 6-dimension scoring │ │ • Entropy calculation │ │ • Guardrails (caps/ │ │ • Confidence decay │ │ floors) │ │ • Signal gap tracking │ │ • Anchor metadata │ │ • Fingerprinting │ │ • Policy digest │ │ • Conflict detection │ └─────────────────────────┘ └─────────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────┐ │ etc/weights/*.json │ │ (Versioned Weight Manifests) │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 3 · What the Facade Provides ### 3.1 · Unified Score Result ```csharp public sealed record UnifiedScoreResult { // From EWS public int Score { get; } // 0-100 public string Bucket { get; } // ActNow, ScheduleNext, Investigate, Watchlist public IReadOnlyList Breakdown { get; } public AppliedGuardrails Guardrails { get; } public string EwsDigest { get; } // SHA-256 of EWS result // From Determinization public double UnknownsFraction { get; } // U metric (0.0 = complete, 1.0 = no data) public UnknownsBand UnknownsBand { get; } // Complete, Adequate, Sparse, Insufficient public IReadOnlyList Gaps { get; } public IReadOnlyList Conflicts { get; } public string DeterminizationFingerprint { get; } // Combined public IReadOnlyList DeltaIfPresent { get; } // Impact if missing signals arrive public string WeightManifestRef { get; } // version + hash public DateTimeOffset ComputedAt { get; } } ``` ### 3.2 · Unknowns Fraction (U) The `UnknownsFraction` directly exposes Determinization's entropy calculation: ``` U = 1 - (weighted_present_signals / total_weight) ``` | U Range | Band | Meaning | Action | |---------|------|---------|--------| | 0.0 – 0.2 | Complete | All signals present | Automated decisions | | 0.2 – 0.4 | Adequate | Sufficient for evaluation | Automated decisions | | 0.4 – 0.6 | Sparse | Signal gaps exist | Manual review recommended | | 0.6 – 1.0 | Insufficient | Critical data missing | Block pending more signals | Thresholds align with existing Determinization config: - `RefreshEntropyThreshold: 0.40` → triggers signal refresh - `ManualReviewEntropyThreshold: 0.60` → requires human review ### 3.3 · Delta-If-Present When signals are missing, the facade calculates potential score impact: ```json { "delta_if_present": [ { "signal": "reachability", "min_impact": -15, "max_impact": +8, "description": "If reachability confirmed as not-reachable, score decreases by up to 15" }, { "signal": "runtime", "min_impact": 0, "max_impact": +25, "description": "If runtime execution observed, score increases by up to 25" } ] } ``` --- ## 4 · Weight Manifests ### 4.1 · Location Weight manifests are stored in `etc/weights/` with versioned filenames: ``` etc/weights/ ├── v2026-01-22.weights.json ├── v2026-02-01.weights.json └── ... ``` ### 4.2 · Schema ```json { "version": "v2026-01-22", "effective_from": "2026-01-22T00:00:00Z", "description": "EWS default weights", "weights": { "rch": 0.30, "rts": 0.25, "bkp": 0.15, "xpl": 0.15, "src": 0.10, "mit": 0.10 }, "hash": "sha256:..." } ``` ### 4.3 · Versioning Rules 1. **Immutable once published** – Manifest content never changes after creation 2. **Hash verification** – SHA-256 of canonical JSON ensures integrity 3. **Policy pinning** – Policies can specify `weights_ref` to lock a version 4. **Fallback** – If manifest missing, EWS uses compiled defaults --- ## 5 · Existing Systems (Unchanged) ### 5.1 · EWS Formula (Preserved) The EWS formula remains unchanged: ``` rawScore = (RCH × w_rch) + (RTS × w_rts) + (BKP × w_bkp) + (XPL × w_xpl) + (SRC × w_src) - (MIT × w_mit) finalScore = clamp(rawScore, 0, 1) × 100 ``` With guardrails: - **Speculative cap** (45): RCH=0 and RTS=0 - **Not-affected cap** (15): BKP≥1.0, VEX=not_affected, RTS<0.6 - **Runtime floor** (60): RTS≥0.8 ### 5.2 · Determinization (Preserved) Entropy and decay calculations remain unchanged: ``` entropy = 1 - (present_weight / total_weight) decay = max(floor, exp(-ln(2) × age_days / half_life_days)) ``` With conflict detection: - VEX vs Reachability contradiction - Static vs Runtime contradiction - Multiple VEX status conflict - Backport vs Status conflict --- ## 6 · Integration Points ### 6.1 · CLI Commands ```bash # Existing (enhanced) stella gate score evaluate --finding-id CVE-2024-1234@pkg:npm/lodash \ --cvss 7.5 --epss 0.15 --reachability function \ --show-unknowns --show-deltas # New stella score compute --finding-id CVE-2024-1234@pkg:npm/lodash \ --cvss 7.5 --epss 0.15 stella score explain CVE-2024-1234@pkg:npm/lodash stella gate score weights list stella gate score weights show v2026-01-22 stella gate score weights diff v2026-01-22 v2026-02-01 ``` ### 6.2 · API Endpoints ``` POST /api/v1/score/evaluate # Compute unified score GET /api/v1/score/{id}/replay # Fetch signed replay proof GET /api/v1/score/weights # List weight manifests GET /api/v1/score/weights/{v} # Get specific manifest ``` #### Replay Endpoint Response The `/score/{id}/replay` endpoint returns a DSSE-signed attestation with payload type `application/vnd.stella.score+json`: ```json { "signed_replay_log_dsse": "BASE64", "rekor_inclusion": {"logIndex": 12345, "rootHash": "…"}, "canonical_inputs": [ {"name": "sbom.json", "sha256": "…"}, {"name": "vex.json", "sha256": "…"} ], "transforms": [ {"name": "canonicalize_spdx", "version": "1.1"}, {"name": "age_decay", "params": {"lambda": 0.02}} ], "algebra_steps": [ {"signal": "rch", "w": 0.30, "value": 0.78, "term": 0.234} ], "final_score": 85 } ``` Replay proofs are stored as OCI referrers ("StellaBundle" pattern) attached to the scored artifact. ### 6.3 · Console UI Finding detail views show: - Score with bucket (existing) - Unknowns fraction (U) with color-coded band - Delta-if-present for missing signals - Weight manifest version --- ## 7 · Determinism Guarantees The facade inherits determinism from underlying systems: | Aspect | Guarantee | |--------|-----------| | EWS score | Identical inputs → identical score (1000+ iteration tests) | | Entropy | Identical signal presence → identical U | | Fingerprint | Content-addressed SHA-256 | | Weight manifest | Immutable after creation | The facade adds no additional sources of non-determinism. --- ## 8 · What We're NOT Doing - ❌ Replacing EWS formula - ❌ Replacing Determinization entropy calculation - ❌ Changing guardrail logic - ❌ Changing conflict detection - ❌ Breaking existing CLI commands - ❌ Breaking existing API contracts The facade is **additive** – existing functionality continues to work unchanged.