Merge Preview

Audience: analysts and integrators who need to understand or render how Stella Ops reconciles conflicting VEX statements. Part of the Snapshot concept.

Overview

Merge Preview shows how VEX statements from different sources combine using lattice logic. It lets an analyst see, for a single CVE against a single artifact, exactly how the final status was derived. The preview helps you understand:

  1. What each source contributes
  2. How conflicts are resolved
  3. What evidence is missing
  4. The final merged status

Merge Semantics

Stella Ops uses a three-layer merge model:

vendor ⊕ distro ⊕ internal = final

Where ⊕ represents the lattice join operation.

Layer Hierarchy

LayerDescriptionTypical Trust
VendorSoftware vendor’s VEX statements0.95-1.0
DistroDistribution maintainer’s assessments0.85-0.95
InternalOrganization’s own assessments0.70-0.90

Lattice Operations

Using K4 (Kleene’s 4-valued logic):

StatusLattice Position
AffectedTop (Both)
UnderInvestigationUnknown (Neither)
FixedTrue
NotAffectedFalse

Join table (⊕):

         | Affected | Under... | Fixed | NotAffected
---------+----------+----------+-------+------------
Affected |    A     |    A     |   A   |     A
Under... |    A     |    U     |   U   |     U
Fixed    |    A     |    U     |   F   |     F
NotAff   |    A     |    U     |   F   |     N

API Endpoint

GET /policy/merge-preview/{cveId}

Parameters:

Response:

{
  "cveId": "CVE-2024-1234",
  "artifactDigest": "sha256:abc...",
  "contributions": [
    {
      "layer": "vendor",
      "sources": ["lodash-security"],
      "status": "NotAffected",
      "trustScore": 0.95,
      "statements": [...],
      "mergeTrace": {
        "explanation": "Vendor states not affected due to version"
      }
    },
    {
      "layer": "distro",
      "sources": ["redhat-csaf"],
      "status": "Affected",
      "trustScore": 0.90,
      "statements": [...],
      "mergeTrace": {
        "explanation": "Distro states affected without context"
      }
    },
    {
      "layer": "internal",
      "sources": [],
      "status": null,
      "trustScore": 0,
      "statements": [],
      "mergeTrace": null
    }
  ],
  "finalStatus": "NotAffected",
  "finalConfidence": 0.925,
  "missingEvidence": [
    {
      "type": "internal-assessment",
      "description": "Add internal security assessment",
      "priority": "medium"
    }
  ],
  "latticeType": "K4",
  "generatedAt": "2024-12-22T12:00:00Z"
}

Conflict Resolution

When sources disagree, resolution follows:

  1. Trust Weight: Higher trust wins
  2. Lattice Position: If trust equal, higher lattice position wins
  3. Freshness: If still tied, more recent statement wins
  4. Tie: First statement wins

Resolution Trace

Each merge includes explanation:

{
  "leftSource": "vendor:lodash",
  "rightSource": "distro:redhat",
  "leftStatus": "NotAffected",
  "rightStatus": "Affected",
  "leftTrust": 0.95,
  "rightTrust": 0.90,
  "resultStatus": "NotAffected",
  "explanation": "'vendor:lodash' has higher trust weight than 'distro:redhat'"
}

UI Components

Layer Cards

Each layer shows:

Merge Flow Diagram

Visual representation:

┌─────────┐     ┌─────────┐     ┌──────────┐     ┌─────────┐
│ Vendor  │ ──⊕─│ Distro  │ ──⊕─│ Internal │ ──=─│ Final   │
│ NotAff. │     │ Affected│     │    —     │     │ NotAff. │
│ (0.95)  │     │ (0.90)  │     │          │     │ (0.925) │
└─────────┘     └─────────┘     └──────────┘     └─────────┘

Missing Evidence CTA

Prominent call-to-action for missing evidence:

┌─────────────────────────────────────────┐
│ ⚠ Improve Confidence                    │
│                                         │
│ [+] Add internal security assessment    │
│     Increases confidence by ~5%         │
│                                         │
│ [+] Add reachability analysis           │
│     Determines if code is called        │
└─────────────────────────────────────────┘

Merge Traces (Expandable)

Detailed explanation of each merge:

▼ Merge Details

Vendor layer:
  Sources: lodash-security
  Status: NotAffected (trust: 95%)

Distro layer:
  Sources: redhat-csaf
  Status: Affected (trust: 90%)
  Merge: 'lodash-security' has higher trust weight

Internal layer:
  No statements

Final: NotAffected (confidence: 92.5%)

Configuration

Trust Weights

Configure in trust.yaml:

sources:
  vendor: 1.0
  distro: 0.9
  nvd: 0.8
  internal: 0.85
  community: 0.5
  unknown: 0.3

Lattice Type

Configure lattice in policy.yaml:

lattice:
  type: K4  # or Boolean, 8-state
  joinStrategy: trust-weighted

Use Cases

1. Understanding Disagreement

When vendor says “not affected” but NVD says “affected”:

2. Adding Internal Context

When external sources lack context:

3. Audit Documentation

For compliance:

Best Practices

  1. Review Conflicts: When layers disagree, investigate why
  2. Add Internal Context: Your reachability data often resolves conflicts
  3. Trust Calibration: Adjust trust weights based on source accuracy
  4. Document Decisions: Use merge preview in exception justifications