tests fixes and sprints work

This commit is contained in:
master
2026-01-22 19:08:46 +02:00
parent c32fff8f86
commit 726d70dc7f
881 changed files with 134434 additions and 6228 deletions

View File

@@ -1,6 +1,6 @@
# Complete Module Matrix
This document provides a comprehensive inventory of all 46+ modules in the StellaOps solution (`src/StellaOps.sln`), explaining the purpose of each module and how they relate to the documented architecture.
This document provides a comprehensive inventory of all 46+ modules in the StellaOps platform. Module build entry points are the module solutions listed in docs/dev/SOLUTION_BUILD_GUIDE.md.
## Table of Contents

View File

@@ -39,7 +39,7 @@ infrastructure:
- 'src/Directory.Build.props' # Source directory properties
- 'src/Directory.Packages.props'
- 'nuget.config' # NuGet feed configuration
- 'StellaOps.sln' # Solution file
- 'src/**/StellaOps.*.sln' # Module solution files
- '.gitea/workflows/**' # CI/CD workflow changes
```

View File

@@ -0,0 +1,299 @@
# 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<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:
```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): RTS0.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.

View File

@@ -331,7 +331,7 @@ Before running tests offline or during rate-limited periods, warm the NuGet cach
```bash
# Warm cache with throttled requests to avoid 429 errors
export NUGET_MAX_HTTP_REQUESTS=4
dotnet restore src/StellaOps.sln --disable-parallel
dotnet restore src/<Module>/StellaOps.<Module>.sln --disable-parallel
# Verify cache is populated
ls ~/.nuget/packages | wc -l
@@ -340,12 +340,14 @@ ls ~/.nuget/packages | wc -l
```powershell
# PowerShell equivalent
$env:NUGET_MAX_HTTP_REQUESTS = "4"
dotnet restore src\StellaOps.sln --disable-parallel
dotnet restore src\<Module>\StellaOps.<Module>.sln --disable-parallel
# Verify cache
(Get-ChildItem "$env:USERPROFILE\.nuget\packages").Count
```
See docs/dev/SOLUTION_BUILD_GUIDE.md for the module solution list.
### Rate Limiting Mitigation
If encountering NuGet 429 (Too Many Requests) errors from package sources:
@@ -392,7 +394,7 @@ docker compose -f devops/compose/docker-compose.ci.yaml up -d
./devops/scripts/local-ci.sh smoke --no-restore
# 4. Or run specific category offline
dotnet test src/StellaOps.sln \
dotnet test src/<Module>/StellaOps.<Module>.sln \
--filter "Category=Unit" \
--no-restore \
--no-build

View File

@@ -121,8 +121,8 @@ docker compose -f devops/compose/docker-compose.ci.yaml down -v
### Build fails
```bash
dotnet clean src/StellaOps.sln
dotnet build src/StellaOps.sln
dotnet clean src/<Module>/StellaOps.<Module>.sln
dotnet build src/<Module>/StellaOps.<Module>.sln
```
### Tests fail

View File

@@ -68,7 +68,7 @@ unit-tests:
with:
dotnet-version: '10.0.100'
- name: Build
run: dotnet build src/StellaOps.sln --configuration Release
run: dotnet build src/<Module>/StellaOps.<Module>.sln --configuration Release
- name: Run Unit lane
run: ./scripts/test-lane.sh Unit --results-directory ./test-results
- name: Upload results