Files
git.stella-ops.org/docs/technical/scoring-algebra.md
2026-01-22 19:08:46 +02:00

10 KiB
Raw Permalink Blame History

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, EWS migration, Score Proofs API

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

public sealed record UnifiedScoreResult
{
    // From EWS
    public int Score { get; }                    // 0-100
    public string Bucket { get; }               // ActNow, ScheduleNext, Investigate, Watchlist
    public IReadOnlyList<DimensionContribution> 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<SignalGap> Gaps { get; }
    public IReadOnlyList<SignalConflict> Conflicts { get; }
    public string DeterminizationFingerprint { get; }

    // Combined
    public IReadOnlyList<SignalDelta> 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:

{
  "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

{
  "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

# 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:

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