finish off sprint advisories and sprints

This commit is contained in:
master
2026-01-24 00:12:43 +02:00
parent 726d70dc7f
commit c70e83719e
266 changed files with 46699 additions and 1328 deletions

View File

@@ -0,0 +1,253 @@
# Unified Trust Score
> **Ownership:** Signals Guild / Platform Guild
> **Services:** `StellaOps.Signals.UnifiedScore`
> **API:** `POST /api/v1/score/evaluate`, `GET /api/v1/score/{id}/replay`
> **CLI:** `stella score compute|explain|replay|verify`, `stella gate score evaluate`
## 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 calculation**`IUncertaintyScoreCalculator` computes the unknowns fraction (U) from signal presence/absence
4. **Conflict detection**`IConflictDetector` 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 Range | Band | Meaning | Recommended Action |
|---------|------|---------|-------------------|
| 0.0 0.2 | **Complete** | All signals present | Automated decisions safe |
| 0.2 0.4 | **Adequate** | Sufficient signal coverage | Automated decisions safe |
| 0.4 0.6 | **Sparse** | Signal gaps exist | Manual review recommended |
| 0.6 1.0 | **Insufficient** | Critical data missing | Block until more signals arrive |
Band thresholds align with Determinization configuration:
- `RefreshEntropyThreshold: 0.40` — triggers signal refresh attempt
- `ManualReviewEntropyThreshold: 0.60` — requires human review
---
## Delta-If-Present
When signals are absent, the facade calculates how the score would change if each missing signal were provided:
```json
{
"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:
- **Immutable** once published
- **Content-addressed** via SHA-256 hash
- **Pinnable** by policy rules via `weights_ref`
- **Auditable** — the manifest version and hash are included in every score result
See [Scoring Algebra §4](../../technical/scoring-algebra.md) for the manifest schema.
---
## API Endpoints
| Method | Path | Purpose |
|--------|------|---------|
| `POST` | `/api/v1/score/evaluate` | Compute unified score |
| `GET` | `/api/v1/score/{scoreId}` | Retrieve previously computed score |
| `GET` | `/api/v1/score/weights` | List weight manifest versions |
| `GET` | `/api/v1/score/weights/{version}` | Get specific manifest |
| `GET` | `/api/v1/score/weights/effective` | Get effective manifest for a date |
| `GET` | `/api/v1/score/{scoreId}/replay` | Fetch signed replay proof |
| `POST` | `/api/v1/score/verify` | Verify a replay log |
### Evaluate Request
```json
{
"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)
```json
{
"score_id": "score_a1b2c3d4e5f67890",
"score_value": 72,
"bucket": "ScheduleNext",
"unknowns_fraction": 0.15,
"unknowns_band": "Complete",
"weight_manifest": {
"version": "v2026-01-22",
"content_hash": "sha256:..."
},
"ews_digest": "sha256:...",
"determinization_fingerprint": "sha256:...",
"computed_at": "2026-01-23T10:00:00Z"
}
```
---
## CLI Commands
### `stella score compute`
Compute a unified score from signal values:
```bash
stella score compute \
--finding-id CVE-2024-1234@pkg:npm/lodash@4.17.0 \
--cvss 7.5 --epss 0.15 \
--reachability 0.9 --runtime 0.7 \
--format table
```
### `stella score explain`
Show a detailed breakdown of a score:
```bash
stella score explain CVE-2024-1234@pkg:npm/lodash@4.17.0
```
### `stella score replay`
Fetch the signed replay proof for a previously computed score:
```bash
stella score replay score_a1b2c3d4e5f67890
```
### `stella score verify`
Re-execute the computation and verify it matches the original:
```bash
stella score verify score_a1b2c3d4e5f67890
```
### `stella gate score evaluate` (enhanced)
Existing gate command with new flags:
```bash
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:
```bash
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 computed score can produce a **replay proof** — a DSSE-signed attestation (payload type `application/vnd.stella.score+json`) 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 proofs enable:
- **Independent verification** — auditors re-execute the computation
- **Transparency logging** — optional anchoring to Rekor for non-repudiation
- **OCI storage** — proofs stored as OCI referrers ("StellaBundle" pattern)
---
## Troubleshooting
### High Unknowns Fraction (U > 0.6)
**Symptom:** Score shows "Insufficient" band, decisions are blocked.
**Causes:**
- Missing reachability analysis (run `stella scan` with `--reachability`)
- No VEX data available (check VEX feed configuration)
- Runtime observations not collected (configure runtime agent)
**Resolution:**
1. Run `stella score explain <finding-id>` to see which signals are missing
2. Use `--show-deltas` to understand which signals would have the most impact
3. Prioritize gathering signals with the highest weight × delta
### 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` to see the per-dimension breakdown and understand which signals are reducing the score.
### Replay Verification Fails
**Symptom:** `stella score verify` reports `score_matches: false`.
**Causes:**
- Weight manifest version changed between compute and verify
- Signal inputs were modified after scoring
- Non-determinism in signal providers (check for time-dependent signals)
**Resolution:**
1. Pin the weight manifest version in the verify request
2. Ensure canonical inputs match (compare SHA-256 hashes)
3. Check the `differences` field in the verify response for specific mismatches