Unified Trust Score

Ownership: Signals Guild Services: StellaOps.Signals.UnifiedScore API: POST /api/v1/score/evaluate, GET /api/v1/score/{id}, GET /api/v1/score/history, replay, weights, verify, and explain routes CLI: shipped score reads are stella score explain and stella gate score weights; Scanner owns public stella score replay|bundle|verify

Overview

The Unified Trust Score is a facade over existing EWS (Evidence-Weighted Score) and Determinization systems. It provides a single API for computing risk scores, uncertainty metrics, and score replay proofs without replacing any underlying scoring logic.


How It Works

  1. Input — Caller provides signal values (reachability, runtime, exploit, etc.) and optional context (CVE ID, PURL, SBOM ref)
  2. EWS computation — The facade delegates to IEvidenceWeightedScoreCalculator using weights from a versioned manifest
  3. Entropy calculationIUncertaintyScoreCalculator computes the unknowns fraction (U) from signal presence/absence
  4. Conflict detectionIConflictDetector identifies contradictory signals
  5. Delta calculation — For missing signals, computes potential score impact ranges
  6. Result assembly — Returns UnifiedScoreResult combining all outputs

The Unknowns Fraction (U)

The UnknownsFraction exposes how much of the score depends on absent data:

U = 1 - (weighted_present_signals / total_weight)

Unknowns Bands

U RangeBandMeaningRecommended Action
0.0 – 0.2CompleteAll signals presentAutomated decisions safe
0.2 – 0.4AdequateSufficient signal coverageAutomated decisions safe
0.4 – 0.6SparseSignal gaps existManual review recommended
0.6 – 1.0InsufficientCritical data missingBlock until more signals arrive

Band thresholds align with Determinization configuration:


Delta-If-Present

When signals are absent, the facade calculates how the score would change if each missing signal were provided:

{
  "signal": "reachability",
  "min_impact": -15,
  "max_impact": 8,
  "weight": 0.30,
  "description": "If reachability confirmed as not-reachable, score decreases by up to 15"
}

This helps operators prioritize which signals to gather first.


Weight Manifests

EWS weights are stored in versioned JSON files under etc/weights/:

etc/weights/v2026-01-22.weights.json

Manifests are:

See Scoring Algebra §4 for the manifest schema.


API Endpoints

MethodPathPurpose
POST/api/v1/score/evaluateCompute unified score
GET/api/v1/score/{scoreId}Retrieve previously computed score
GET/api/v1/score/historyQuery tenant-scoped score history by CVE/PURL
GET/api/v1/score/weightsList weight manifest versions
GET/api/v1/score/weights/{version}Get specific manifest
GET/api/v1/score/weights/effectiveGet effective manifest for a date
GET/api/v1/score/{scoreId}/replayFetch the DSSE-shaped replay envelope (currently unsigned)
POST/api/v1/score/verifyVerify a replay log
GET/api/v1/score/explain/{digest}Fetch canonical explanation contract (score.explain.v1)

The route group requires the signals.score.read policy (canonical claim score.read) and authenticated tenant context. Evaluation additionally requires signals.score.evaluate (score.evaluate), so it needs both claims. Verification is read-scoped. Both claim values are issued by Authority from the canonical StellaOpsScopes catalog.

Explain Error Taxonomy

GET /api/v1/score/explain/{digest} uses deterministic error bodies:

Evaluate Request

{
  "cve_id": "CVE-2024-1234",
  "purl": "pkg:npm/lodash@4.17.0",
  "signals": {
    "reachability": 0.9,
    "runtime": 0.7,
    "exploit": 0.3,
    "backport": 0.0,
    "source": 0.5,
    "mitigation": 0.0
  },
  "options": {
    "include_breakdown": true,
    "include_delta": true,
    "weight_set_id": "v2026-01-22"
  }
}

Evaluate Response (key fields)

{
  "score_id": "score_a1b2c3d4e5f67890",
  "score_value": 72,
  "bucket": "ScheduleNext",
  "unknowns_fraction": 0.15,
  "unknowns_band": "Complete",
  "unknowns": ["runtime", "backport"],
  "proof_ref": "proof://score/sha256%3A...",
  "weight_manifest": {
    "version": "v2026-01-22",
    "content_hash": "sha256:..."
  },
  "ews_digest": "sha256:...",
  "determinization_fingerprint": "sha256:...",
  "computed_at": "2026-01-23T10:00:00Z"
}

CLI Commands

Current shipped behavior differs from the older direct-command design below:

Shipped score explanation

stella score explain accepts a score digest, not a finding id:

stella score explain sha256:<score-digest>

Dormant direct-command design (not shipped)

The source-only ScoreCommandGroup sketches compute, history, score-ID replay, and score-ID verify commands. CommandFactory does not register that group. In the public command tree, stella score replay|bundle|verify belongs to Scanner proof bundles; do not use those verbs as clients for the Signals score-ID API.

stella gate score evaluate (enhanced)

Existing gate command with new flags:

stella gate score evaluate \
  --finding-id CVE-2024-1234@pkg:npm/lodash \
  --cvss 7.5 --epss 0.15 \
  --show-unknowns --show-deltas \
  --weights-version v2026-01-22

stella gate score weights

Manage weight manifests:

stella gate score weights list
stella gate score weights show v2026-01-22
stella gate score weights diff v2026-01-22 v2026-02-01

Score Replay and Verification

Every persisted score can produce a DSSE-shaped replay envelope that records:

  1. Canonical input hashes (SBOM, VEX, etc.)
  2. Transform versions applied (canonicalization, normalization, decay)
  3. Step-by-step algebra decisions (signal × weight = contribution)
  4. Final score and metadata

Replay envelopes enable:

Current limitation: the envelope has an empty signatures array, Rekor inclusion is null, and the envelope is reconstructed from signals.score_history; it is not stored as an OCI referrer. These fields must not be presented as signed or transparency-anchored proof until real verification is implemented.


Troubleshooting

High Unknowns Fraction (U > 0.6)

Symptom: Score shows “Insufficient” band, decisions are blocked.

Causes:

Resolution:

  1. Obtain the replay digest from the score response or history record.
  2. Run stella score explain sha256:<score-digest> to inspect the recorded breakdown.
  3. Prioritize gathering missing signals with the highest configured weight.

Score Disagrees with CVSS

Symptom: EWS score is much lower than expected from CVSS alone.

Explanation: EWS incorporates reachability, runtime, backport, and mitigation signals that CVSS does not. A high-CVSS vulnerability that is not reachable or already mitigated will have a lower EWS score.

Resolution: Run stella score explain sha256:<score-digest> to see the per-dimension breakdown and understand which signals are reducing the score.

Replay Verification Fails

Symptom: POST /api/v1/score/verify returns score_matches: false.

Causes:

Resolution:

  1. Pin the weight manifest version in the API verify request.
  2. Ensure canonical inputs match (compare SHA-256 hashes).
  3. Check the differences field in the verify response for specific mismatches.

The shipped stella score verify command verifies Scanner proof bundles and does not call this Signals endpoint.