Files
git.stella-ops.org/docs/modules/concelier/api/conflicts.md

8.4 KiB

Linkset Conflicts API Reference (v1)

Status: stable; aligns with LNM v1 (frozen 2025-11-17).

Intent

  • Document conflict detection and representation in the Link-Not-Merge system.
  • Conflicts are surfaced but never automatically resolved; consumers implement their own resolution strategy.
  • This reference describes conflict types, detection logic, and how conflicts appear in API responses.

The Concelier LNM (Link-Not-Merge) approach differs from traditional advisory aggregation:

  • Link: Observations from multiple sources are linked together via shared identifiers (CVE, GHSA, PURL, CPE).
  • Not Merge: Conflicting data is preserved with full provenance rather than collapsed into a single "truth".
  • Surface, Don't Resolve: Conflicts are clearly marked for downstream consumers to handle according to their own policies.

Conflict Types

severity-mismatch

Sources disagree on severity rating.

{
  "field": "severity",
  "reason": "severity-mismatch",
  "observedValue": "critical",
  "observedAt": "2025-11-18T08:00:00Z",
  "evidenceHash": "sha256:f6e5d4c3b2a1098765432109876543210fedcba0987654321fedcba098765432"
}

Detection: Triggered when severity labels (critical, high, medium, low) or CVSS scores differ by more than 1.0 points between observations.

Common causes:

  • Different CVSS versions (v2 vs v3 vs v3.1)
  • Vendor-specific severity assessments
  • Time lag between source updates

version-range-conflict

Sources disagree on affected version ranges.

{
  "field": "affected.ranges",
  "reason": "version-range-conflict",
  "observedValue": "{\"fixed\": \"2.0.0\"}",
  "observedAt": "2025-11-19T12:00:00Z",
  "evidenceHash": "sha256:a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"
}

Detection: Triggered when version range events differ between observations for the same package.

Common causes:

  • Backports creating different fix points per distribution
  • Vendor patches not reflected in upstream
  • Different ecosystem-specific versioning

status-conflict

Sources disagree on vulnerability status.

{
  "field": "status",
  "reason": "status-conflict",
  "observedValue": "not_affected",
  "observedAt": "2025-11-20T09:00:00Z",
  "evidenceHash": "sha256:b2c3d4e5f6a789012345678901234567890abcdef1234567890abcdef1234567b"
}

Detection: Triggered when status values (affected, not_affected, under_investigation, fixed) differ.

Common causes:

  • VEX statements from vendors
  • Incomplete upstream analysis
  • Context-specific applicability (e.g., platform-dependent)

cpe-mismatch

Sources disagree on CPE identifiers.

{
  "field": "cpe",
  "reason": "cpe-mismatch",
  "observedValue": "cpe:2.3:a:example:lib:*:*:*:*:*:*:*:*",
  "observedAt": "2025-11-18T16:00:00Z",
  "evidenceHash": "sha256:c3d4e5f6a789012345678901234567890abcdef1234567890abcdef123456789c"
}

Detection: Triggered when CPE identifiers for the same advisory don't match.

Common causes:

  • Different CPE dictionary versions
  • Vendor vs product naming variations
  • Platform-specific CPE assignments

reference-conflict

Sources provide conflicting reference information.

{
  "field": "references",
  "reason": "reference-conflict",
  "observedValue": "https://example.com/advisory/different",
  "observedAt": "2025-11-21T10:00:00Z",
  "evidenceHash": "sha256:d4e5f6a789012345678901234567890abcdef1234567890abcdef123456789def"
}

Conflict in Linkset Response

Full linkset with multiple conflicts:

{
  "advisoryId": "CVE-2024-9999",
  "source": "aggregated",
  "purl": ["pkg:maven/org.example/library@1.5.0"],
  "cpe": [
    "cpe:2.3:a:example:library:1.5.0:*:*:*:*:*:*:*",
    "cpe:2.3:a:example_inc:lib:1.5.0:*:*:*:*:java:*:*"
  ],
  "summary": "Deserialization vulnerability in example library",
  "publishedAt": "2024-09-01T00:00:00Z",
  "modifiedAt": "2024-09-15T00:00:00Z",
  "severity": "high",
  "status": "affected",
  "provenance": {
    "ingestedAt": "2025-11-20T10:30:00Z",
    "connectorId": "multi-source-aggregator",
    "evidenceHash": "sha256:aggregated-evidence-hash"
  },
  "conflicts": [
    {
      "field": "severity",
      "reason": "severity-mismatch",
      "observedValue": "critical",
      "observedAt": "2025-11-15T10:00:00Z",
      "evidenceHash": "sha256:nvd-observation-hash"
    },
    {
      "field": "severity",
      "reason": "severity-mismatch",
      "observedValue": "medium",
      "observedAt": "2025-11-18T14:00:00Z",
      "evidenceHash": "sha256:vendor-observation-hash"
    },
    {
      "field": "cpe",
      "reason": "cpe-mismatch",
      "observedValue": "cpe:2.3:a:example_inc:lib:1.5.0:*:*:*:*:java:*:*",
      "observedAt": "2025-11-17T08:00:00Z",
      "evidenceHash": "sha256:github-observation-hash"
    },
    {
      "field": "affected.ranges",
      "reason": "version-range-conflict",
      "observedValue": "{\"type\": \"SEMVER\", \"events\": [{\"introduced\": \"1.0.0\"}, {\"fixed\": \"1.5.1\"}]}",
      "observedAt": "2025-11-19T12:00:00Z",
      "evidenceHash": "sha256:distro-observation-hash"
    }
  ],
  "timeline": [
    {"event": "first-observed", "at": "2025-11-15T10:00:00Z", "evidenceHash": "sha256:nvd-observation-hash"},
    {"event": "conflict-detected", "at": "2025-11-17T08:00:00Z", "evidenceHash": "sha256:github-observation-hash"},
    {"event": "conflict-detected", "at": "2025-11-18T14:00:00Z", "evidenceHash": "sha256:vendor-observation-hash"},
    {"event": "conflict-detected", "at": "2025-11-19T12:00:00Z", "evidenceHash": "sha256:distro-observation-hash"}
  ],
  "normalized": {
    "aliases": ["CVE-2024-9999", "GHSA-xxxx-yyyy-zzzz"],
    "severities": [
      {"source": "nvd", "type": "CVSS_V3", "score": 9.8, "label": "critical"},
      {"source": "github", "type": "CVSS_V3", "score": 7.5, "label": "high"},
      {"source": "vendor", "type": "CVSS_V3", "score": 5.3, "label": "medium"}
    ],
    "ranges": [
      {"source": "nvd", "type": "SEMVER", "introduced": "0", "fixed": "1.6.0"},
      {"source": "distro", "type": "SEMVER", "introduced": "1.0.0", "fixed": "1.5.1"}
    ]
  },
  "cached": false,
  "observations": [
    "obs:nvd:CVE-2024-9999:2025-11-15",
    "obs:github:GHSA-xxxx-yyyy-zzzz:2025-11-17",
    "obs:vendor:CVE-2024-9999:2025-11-18",
    "obs:distro:CVE-2024-9999:2025-11-19"
  ]
}

Querying for Conflicts

List Only Linksets with Conflicts

GET /v1/lnm/linksets?includeConflicts=true&hasConflicts=true
X-Stella-Tenant: acme

Filter by Conflict Type

POST /v1/lnm/linksets/search
X-Stella-Tenant: acme
Content-Type: application/json

{
  "conflictTypes": ["severity-mismatch", "version-range-conflict"],
  "includeConflicts": true,
  "pageSize": 50
}

Advisory Summary with Conflicts

GET /advisories/summary?conflicts_only=true
X-Stella-Tenant: acme

Response:

{
  "meta": {
    "tenant": "acme",
    "count": 3,
    "sort": "advisory"
  },
  "items": [
    {
      "advisoryKey": "CVE-2024-9999",
      "aliases": ["CVE-2024-9999", "GHSA-xxxx-yyyy-zzzz"],
      "source": "aggregated",
      "confidence": 0.65,
      "conflicts": [
        {"field": "severity", "reason": "severity-mismatch", "sourceIds": ["nvd", "vendor", "github"]}
      ],
      "counts": {
        "observations": 4,
        "conflictFields": 2
      }
    }
  ]
}

Conflict Resolution Strategies

Concelier does not resolve conflicts, but here are common strategies consumers implement:

Source Priority

Prioritize sources by trust level:

nvd > vendor > github > community

Most Recent

Use the most recently observed value:

Sort by observedAt desc, take first

Most Conservative

For severity, use the highest rating:

critical > high > medium > low

Voting/Consensus

Use the value with most agreement:

Count occurrences, take majority

Conflict Confidence Impact

The confidence field in linksets reflects conflict presence:

  • No conflicts: confidence ≥ 0.9
  • Minor conflicts (1-2 fields): confidence 0.7-0.9
  • Major conflicts (3+ fields or severity): confidence < 0.7

Notes

  • Conflicts are preserved indefinitely; they are only removed if all observations align.
  • Evidence hashes allow consumers to trace conflicts back to specific observations.
  • The timeline array shows when conflicts were first detected.
  • Multiple conflicts on the same field from different sources create multiple entries.

Changelog

  • 2025-12-06: Initial conflict reference documentation (CONCELIER-WEB-OAS-62-001).
  • 2025-11-17: LNM v1 conflict model frozen.