VEX Trust Lattice Specification

Status: Implementation Complete (Sprint 7100) Version: 1.0.0 Last Updated: 2025-12-22 Source Advisory: docs/product/advisories/archived/22-Dec-2026 - Building a Trust Lattice for VEX Sources.md

1. Overview

The VEX Trust Lattice provides a mathematically rigorous framework for converting heterogeneous VEX claims from multiple sources into a single, signed, reproducible verdict with a numeric confidence and a complete audit trail.

Goals

  1. Explainability: Every verdict includes a full breakdown of how it was computed
  2. Reproducibility: Same inputs always produce identical verdicts (deterministic)
  3. Auditability: Signed verdict manifests with pinned inputs for regulatory compliance
  4. Tunability: Per-tenant, per-source trust configuration without code changes

Non-Goals


2. Trust Vector Model

Each VEX source is assigned a 3-component trust vector scored in the range [0…1].

2.1 Provenance (P)

Measures cryptographic and process integrity of the source.

ScoreDescription
1.00DSSE-signed, timestamped, Rekor/Git anchored, key in allow-list, rotation policy OK
0.75DSSE-signed + public key known, but no transparency log
0.40Unsigned but retrieved via authenticated, immutable artifact repo
0.10Opaque/CSV/email/manual import

2.2 Coverage ©

Measures how well the statement’s scope maps to the target asset.

ScoreDescription
1.00Exact package + version/build digest + feature/flag context matched
0.75Exact package + version range matched; partial feature context
0.50Product-level only; maps via CPE/PURL family
0.25Family-level heuristics; no version proof

2.3 Replayability ®

Measures whether the claim can be deterministically re-derived.

ScoreDescription
1.00All inputs pinned (feeds, SBOM hash, ruleset hash, lattice version); replays byte-identical
0.60Inputs mostly pinned; non-deterministic ordering tolerated but stable outcome
0.20Ephemeral APIs; no snapshot

2.4 Weight Configuration

The base trust score is computed as:

BaseTrust(S) = wP * P + wC * C + wR * R

Default weights:

Weights are tunable per policy and sum to 1.0.


3. Claim Scoring

3.1 Base Trust Calculation

double BaseTrust(double P, double C, double R, TrustWeights W)
    => W.wP * P + W.wC * C + W.wR * R;

3.2 Claim Strength Multipliers (M)

Each VEX claim carries a strength multiplier based on evidence quality:

StrengthValueDescription
ExploitabilityWithReachability1.00Exploitability analysis + reachability proof subgraph provided
ConfigWithEvidence0.80Config/feature-flag reason with evidence
VendorBlanket0.60Vendor blanket statement
UnderInvestigation0.40“Under investigation”

3.3 Freshness Decay (F)

Time-decay curve with configurable half-life:

double Freshness(DateTime issuedAt, DateTime cutoff, double halfLifeDays = 90, double floor = 0.35)
{
    var ageDays = (cutoff - issuedAt).TotalDays;
    var decay = Math.Exp(-Math.Log(2) * ageDays / halfLifeDays);
    return Math.Max(decay, floor);
}

Parameters:

3.4 ClaimScore Formula

ClaimScore = BaseTrust(S) * M * F

Example calculation:

Source: Red Hat (Vendor)
  P = 0.90, C = 0.75, R = 0.60
  BaseTrust = 0.45*0.90 + 0.35*0.75 + 0.20*0.60 = 0.405 + 0.2625 + 0.12 = 0.7875

Claim: ConfigWithEvidence (M = 0.80)
Freshness: 30 days old (F = 0.79)

ClaimScore = 0.7875 * 0.80 * 0.79 = 0.498

4. Lattice Merge Algorithm

4.1 Partial Ordering

Claims are ordered by a tuple: (scope_specificity, ClaimScore).

Scope specificity levels:

  1. Exact digest match (highest)
  2. Exact version match
  3. Version range match
  4. Product family match
  5. Platform match (lowest)

4.2 Conflict Detection

Conflicts occur when claims for the same (CVE, Asset) have different statuses:

bool HasConflict(IEnumerable<Claim> claims)
    => claims.Select(c => c.Status).Distinct().Count() > 1;

4.3 Conflict Penalty

When conflicts exist, apply a penalty to weaker/older claims:

const double ConflictPenalty = 0.25;

if (contradictory)
{
    var strongest = claims.OrderByDescending(c => c.Score).First();
    foreach (var claim in claims.Where(c => c.Status != strongest.Status))
    {
        claim.AdjustedScore = claim.Score * (1 - ConflictPenalty);
    }
}

4.4 Winner Selection

Final verdict is selected by:

var winner = scored
    .OrderByDescending(x => (x.Claim.ScopeSpecificity, x.AdjustedScore))
    .First();

4.5 Audit Trail Generation

Every merge produces:

public sealed record MergeResult
{
    public VexStatus Status { get; init; }
    public double Confidence { get; init; }
    public ImmutableArray<VerdictExplanation> Explanations { get; init; }
    public ImmutableArray<string> EvidenceRefs { get; init; }
    public string PolicyHash { get; init; }
    public string LatticeVersion { get; init; }
}

5. Policy Gates

Gates are evaluated after merge to enforce policy requirements.

5.1 MinimumConfidenceGate

Requires minimum confidence by environment for certain statuses.

gates:
  minimumConfidence:
    enabled: true
    thresholds:
      production: 0.75
      staging: 0.60
      development: 0.40
    applyToStatuses:
      - not_affected
      - fixed

Behavior: Fails if confidence < threshold for specified statuses.

5.2 UnknownsBudgetGate

Limits exposure to unknown/unscored dependencies.

gates:
  unknownsBudget:
    enabled: true
    maxUnknownCount: 5
    maxCumulativeUncertainty: 2.0

Behavior: Fails if:

5.3 SourceQuotaGate

Prevents single-source dominance without corroboration.

gates:
  sourceQuota:
    enabled: true
    maxInfluencePercent: 60
    corroborationDelta: 0.10

Behavior: Fails if single source influence > 60% AND no second source within delta=0.10.

5.4 ReachabilityRequirementGate

Requires reachability proof for critical vulnerabilities.

gates:
  reachabilityRequirement:
    enabled: true
    severityThreshold: CRITICAL
    requiredForStatuses:
      - not_affected
    bypassReasons:
      - component_not_present

Behavior: Fails if not_affected on CRITICAL CVE without reachability proof (unless bypass reason applies).


6. Deterministic Replay

6.1 Input Pinning

To guarantee “same inputs → same verdict”, pin:

6.2 Verdict Manifest

{
  "manifestId": "verd:tenant:asset:cve:1234567890",
  "tenant": "acme-corp",
  "assetDigest": "sha256:abc123...",
  "vulnerabilityId": "CVE-2025-12345",
  "inputs": {
    "sbomDigests": ["sha256:..."],
    "vulnFeedSnapshotIds": ["nvd:2025-12-22"],
    "vexDocumentDigests": ["sha256:..."],
    "reachabilityGraphIds": ["graph:..."],
    "clockCutoff": "2025-12-22T12:00:00Z"
  },
  "result": {
    "status": "not_affected",
    "confidence": 0.82,
    "explanations": [...]
  },
  "policyHash": "sha256:...",
  "latticeVersion": "1.2.0",
  "evaluatedAt": "2025-12-22T12:00:01Z",
  "manifestDigest": "sha256:..."
}

6.3 Signing

Verdict manifests are signed using DSSE with predicate type:

https://stella-ops.org/attestations/vex-verdict/1

6.4 Replay Verification

POST /api/v1/authority/verdicts/{manifestId}/replay

Response:
{
  "success": true,
  "originalManifest": {...},
  "replayedManifest": {...},
  "differences": [],
  "signatureValid": true
}

7. Configuration Reference

Full Configuration Example

# etc/trust-lattice.yaml
version: "1.0"

trustLattice:
  weights:
    provenance: 0.45
    coverage: 0.35
    replayability: 0.20

  freshness:
    halfLifeDays: 90
    floor: 0.35

  conflictPenalty: 0.25

  defaults:
    vendor:
      provenance: 0.90
      coverage: 0.70
      replayability: 0.60
    distro:
      provenance: 0.80
      coverage: 0.85
      replayability: 0.60
    internal:
      provenance: 0.85
      coverage: 0.95
      replayability: 0.90

gates:
  minimumConfidence:
    enabled: true
    thresholds:
      production: 0.75
      staging: 0.60
      development: 0.40

  unknownsBudget:
    enabled: true
    maxUnknownCount: 5
    maxCumulativeUncertainty: 2.0

  sourceQuota:
    enabled: true
    maxInfluencePercent: 60
    corroborationDelta: 0.10

  reachabilityRequirement:
    enabled: true
    severityThreshold: CRITICAL

8. API Reference

Endpoints

MethodPathDescription
GET/api/v1/excititor/verdicts/{manifestId}Get verdict manifest
GET/api/v1/excititor/verdictsList verdicts (paginated)
POST/api/v1/authority/verdicts/{manifestId}/replayVerify replay
GET/api/v1/authority/verdicts/{manifestId}/downloadDownload signed manifest

See docs/API_CLI_REFERENCE.md for complete API documentation.


9. Examples

Example 1: High-Confidence Verdict

Input:

Calculation:

Red Hat: BaseTrust=0.78, M=0.80, F=0.95 → ClaimScore=0.59
Ubuntu:  BaseTrust=0.72, M=0.80, F=0.90 → ClaimScore=0.52

No conflict (both agree)
Winner: Red Hat (higher score)
Confidence: 0.59
Gates: All pass (> 0.40 threshold)

Example 2: Conflict Resolution

Input:

Calculation:

Vendor:   ClaimScore=0.65
Internal: ClaimScore=0.55

Conflict detected → penalty applied
Internal adjusted: 0.55 * 0.75 = 0.41

Winner: Vendor
Confidence: 0.65
Note: Conflict recorded in audit trail


10. Implementation Reference

10.1 Source Files

ComponentLocation
TrustVectorsrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/TrustVector.cs
TrustWeightssrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/TrustWeights.cs
ClaimStrengthsrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/ClaimStrength.cs
FreshnessCalculatorsrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/FreshnessCalculator.cs
DefaultTrustVectorssrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/DefaultTrustVectors.cs
ProvenanceScorersrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/ProvenanceScorer.cs
CoverageScorersrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/CoverageScorer.cs
ReplayabilityScorersrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/ReplayabilityScorer.cs
SourceClassificationServicesrc/Excititor/__Libraries/StellaOps.Excititor.Core/TrustVector/SourceClassificationService.cs
ClaimScoreMergersrc/Policy/__Libraries/StellaOps.Policy/TrustLattice/ClaimScoreMerger.cs
MinimumConfidenceGatesrc/Policy/__Libraries/StellaOps.Policy/Gates/MinimumConfidenceGate.cs
UnknownsBudgetGatesrc/Policy/__Libraries/StellaOps.Policy/Gates/UnknownsBudgetGate.cs
SourceQuotaGatesrc/Policy/__Libraries/StellaOps.Policy/Gates/SourceQuotaGate.cs
ReachabilityRequirementGatesrc/Policy/__Libraries/StellaOps.Policy/Gates/ReachabilityRequirementGate.cs
TrustVectorCalibratorsrc/Excititor/__Libraries/StellaOps.Excititor.Core/Calibration/TrustVectorCalibrator.cs

10.2 Configuration Files

FilePurpose
etc/trust-lattice.yaml.sampleTrust vector weights, freshness parameters, default vectors
etc/policy-gates.yaml.sampleGate thresholds and enable/disable flags
etc/excititor-calibration.yaml.sampleCalibration learning parameters

10.3 Database Schema

10.4 Test Coverage

Test SuiteLocation
TrustVector testssrc/Excititor/__Tests/StellaOps.Excititor.Core.Tests/TrustVector/
ClaimScoreMerger testssrc/Policy/__Tests/StellaOps.Policy.Tests/TrustLattice/
Gate testssrc/Policy/__Tests/StellaOps.Policy.Tests/Gates/
Calibration testssrc/Excititor/__Tests/StellaOps.Excititor.Core.Tests/Calibration/


Document Version: 1.0.0 Sprint: 7100.0003.0002 Created: 2025-12-22