# Signals Module Architecture ## Overview The **Signals** module provides a unified evidence-weighted scoring system for vulnerability findings. It aggregates evidence from multiple sources (reachability analysis, runtime observations, backport detection, exploit intelligence, source trust, and mitigations) into a single 0-100 score that enables rapid triage. ## Module Purpose - **Unify Scoring:** Combine disparate evidence signals into one actionable score - **Enable Triage:** Support sorting, filtering, and prioritization by evidence strength - **Maintain Determinism:** Same inputs + policy = same score, always - **Provide Transparency:** Decomposable scores with explanations ## Location ``` src/Signals/ ├── StellaOps.Signals/ │ └── EvidenceWeightedScore/ │ ├── EvidenceWeightedScoreCalculator.cs │ ├── EvidenceWeightedScoreInput.cs │ ├── EvidenceWeightedScoreResult.cs │ ├── Normalizers/ │ │ ├── BackportEvidenceNormalizer.cs │ │ ├── ExploitLikelihoodNormalizer.cs │ │ ├── MitigationNormalizer.cs │ │ ├── ReachabilityNormalizer.cs │ │ ├── RuntimeSignalNormalizer.cs │ │ └── SourceTrustNormalizer.cs │ ├── Guardrails/ │ │ └── ScoreGuardrails.cs │ └── Policy/ │ ├── EvidenceWeightPolicy.cs │ └── EvidenceWeightPolicyProvider.cs └── __Tests/ └── StellaOps.Signals.Tests/ └── EvidenceWeightedScore/ ``` ## Core Concepts ### Evidence Dimensions | Dimension | Symbol | Description | Source Module | |-----------|--------|-------------|---------------| | Reachability | RCH | Code path reachability to vulnerable sink | Policy | | Runtime | RTS | Live observation strength (eBPF/dyld/ETW) | Policy | | Backport | BKP | Patch evidence from distro/changelog/binary | Concelier | | Exploit | XPL | Exploit probability (EPSS + KEV) | Scanner, Concelier | | Source Trust | SRC | VEX source trustworthiness | Excititor | | Mitigations | MIT | Active protective controls | Policy | ### Scoring Formula ``` Score = clamp01(W_rch*RCH + W_rts*RTS + W_bkp*BKP + W_xpl*XPL + W_src*SRC - W_mit*MIT) * 100 ``` Note: MIT is **subtractive** — mitigations reduce risk. ### Guardrails Hard caps and floors based on evidence conditions: 1. **Not-Affected Cap:** If vendor says not-affected (BKP=1) and no runtime contradiction (RTS<0.6), cap at 15 2. **Runtime Floor:** If strong live signal (RTS>=0.8), floor at 60 3. **Speculative Cap:** If no reachability and no runtime (RCH=0, RTS=0), cap at 45 ### Score Buckets | Bucket | Range | Meaning | |--------|-------|---------| | ActNow | 90-100 | Strong evidence of exploitable risk; immediate action | | ScheduleNext | 70-89 | Likely real; schedule for next sprint | | Investigate | 40-69 | Moderate evidence; investigate when touching component | | Watchlist | 0-39 | Low/insufficient evidence; monitor | ## Architecture ### Component Diagram ``` ┌─────────────────────────────────────────────────────────────────┐ │ Signals Module │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌──────────────────────────────────┐ │ │ │ NormalizerAggr. │───▶│ EvidenceWeightedScoreCalculator │ │ │ └────────┬────────┘ └──────────────┬───────────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────┐ ┌──────────────────────────────────┐ │ │ │ Normalizers │ │ ScoreGuardrails │ │ │ │ ┌─────┐ ┌─────┐ │ └──────────────────────────────────┘ │ │ │ │ BKP │ │ XPL │ │ │ │ │ └─────┘ └─────┘ │ ┌──────────────────────────────────┐ │ │ │ ┌─────┐ ┌─────┐ │ │ EvidenceWeightPolicyProvider │ │ │ │ │ MIT │ │ RCH │ │ └──────────────────────────────────┘ │ │ │ └─────┘ └─────┘ │ │ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ RTS │ │ SRC │ │ │ │ │ └─────┘ └─────┘ │ │ │ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌───────────────────────────────────────┐ │ External Modules │ │ Consumers │ │ │ │ │ │ • Policy (RCH, RTS) │ │ • Policy Engine (verdict enrichment) │ │ • Concelier (BKP) │ │ • Findings API (score endpoints) │ │ • Scanner (XPL) │ │ • Web UI (score components) │ │ • Excititor (SRC) │ │ │ └─────────────────────┘ └───────────────────────────────────────┘ ``` ### Data Flow 1. **Finding arrives** for scoring 2. **NormalizerAggregator** collects evidence from source modules 3. **Individual normalizers** convert raw evidence to 0-1 values 4. **EvidenceWeightedScoreCalculator** applies formula 5. **ScoreGuardrails** apply caps/floors 6. **Result** returned with score, bucket, breakdown, explanations ### Policy Configuration Weight policies are loaded from YAML and can vary by: - **Tenant:** Different organizations may prioritize differently - **Environment:** Production may weight runtime higher than dev - **Policy version:** Changes are versioned for reproducibility ```yaml version: "ews.v1" profile: production weights: rch: 0.30 rts: 0.25 bkp: 0.15 xpl: 0.15 src: 0.10 mit: 0.10 guardrails: not_affected_cap: enabled: true max_score: 15 runtime_floor: enabled: true min_score: 60 speculative_cap: enabled: true max_score: 45 ``` ## Integration Points ### Inbound (Evidence Sources) | Source | Data | Interface | |--------|------|-----------| | Policy/ConfidenceCalculator | ReachabilityEvidence, RuntimeEvidence | Direct type reference | | Concelier/BackportProofService | ProofBlob | Direct type reference | | Scanner/EpssPriorityCalculator | EPSS score, percentile | Direct type reference | | Concelier/VendorRiskSignalExtractor | KEV status | Direct type reference | | Excititor/TrustVector | Trust vector components | Direct type reference | | Policy/GateMultipliers | Active mitigations | Direct type reference | ### Outbound (Consumers) | Consumer | Usage | |----------|-------| | Policy Engine | Verdict enrichment, score-based rules | | Findings API | Score endpoints (calculate, get, history) | | Web UI | Score display components | | Webhooks | Score change notifications | | Attestor | Scoring proofs in attestations | ## Determinism The Signals module maintains strict determinism: 1. **Same inputs + same policy = same score:** No randomness, no time-dependent factors in formula 2. **Policy versioning:** Every policy has a digest; scores include policy digest 3. **Reproducible proofs:** Scoring proofs can be verified by recalculation 4. **Stable ordering:** Input order doesn't affect result ## Performance | Metric | Target | |--------|--------| | Single score calculation | <10ms | | Batch (100 findings) | <1s | | Policy load | <100ms | | Cache hit ratio | >80% | ## Testing Strategy | Level | Focus | Location | |-------|-------|----------| | L0 Unit | Calculator, normalizers, guardrails | `*.Tests` | | L0 Property | Monotonicity, bounds, determinism | `*.Tests/Properties` | | S1 Integration | Cross-module evidence flow | `*.Tests/Integration` | | S1 Snapshot | Result JSON structure | `*.Tests/Snapshots` | ## Related Documentation - Product Advisory: `docs/product-advisories/24-Dec-2025 - Evidence-Weighted Score Model.md` - Sprint Plans: `docs/implplan/SPRINT_8200_0012_*.md` - Policy Confidence (deprecated): `docs/modules/policy/confidence-scoring.md` - Backport Detection: `docs/modules/concelier/backport-detection.md` - EPSS Enrichment: `docs/modules/scanner/epss-enrichment.md` - Trust Vector: `docs/modules/excititor/trust-vector.md`