API/UI Surfacing for New Metadata (SC7)

Status: Draft · Date: 2025-12-04 Scope: Define API endpoints and UI components for surfacing CVSS v4, CycloneDX 1.7/CBOM, SLSA 1.2, and evidence metadata with deterministic pagination and sorting.

Objectives

API Endpoints

Vulnerability Ratings (CVSS v4 + v3.1)

GET /api/v1/scans/{scanId}/vulnerabilities

Response includes dual CVSS ratings:

{
  "vulnerabilities": [
    {
      "id": "CVE-2025-0001",
      "ratings": [
        {
          "method": "CVSSv4",
          "score": 8.5,
          "severity": "high",
          "vector": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N"
        },
        {
          "method": "CVSSv31",
          "score": 7.5,
          "severity": "high",
          "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
        }
      ],
      "evidence": {
        "source": "concelier:nvd:2025-12-03",
        "hash": "b3:eeee1111...",
        "proofId": "proof-12345"
      }
    }
  ],
  "meta": {
    "page": {
      "cursor": "eyJpZCI6IkNWRS0yMDI1LTAwMDEiLCJzY29yZSI6OC41fQ==",
      "size": 100,
      "hasMore": true
    },
    "sort": {
      "field": "ratings.CVSSv4.score",
      "direction": "desc"
    }
  }
}

CBOM Services

GET /api/v1/scans/{scanId}/services

Response includes CBOM properties:

{
  "services": [
    {
      "name": "api-gateway",
      "version": "1.0.0",
      "cbom": {
        "ingress": "0.0.0.0:8080",
        "egress": "https://external-api.example.invalid:443",
        "dataClassification": "pii",
        "provider": null,
        "region": null
      }
    }
  ],
  "meta": {
    "page": {
      "cursor": "eyJuYW1lIjoiYXBpLWdhdGV3YXkifQ==",
      "size": 100
    }
  }
}

Source Provenance (SLSA)

GET /api/v1/scans/{scanId}/provenance

Response includes SLSA Source Track:

{
  "provenance": {
    "source": {
      "repo": "https://example.invalid/demo",
      "ref": "refs/tags/v1.0.0",
      "commit": "aaaa...",
      "treeHash": "b3:1111..."
    },
    "build": {
      "id": "build-12345",
      "invocationHash": "b3:2222...",
      "builderId": "https://builder.stellaops.local/scanner"
    },
    "dsse": {
      "hash": "sha256:4444...",
      "cas": "cas://provenance/demo/v1.0.0.dsse"
    }
  }
}

Evidence Lookup

GET /api/v1/evidence/{evidenceHash}

Returns evidence details:

{
  "evidence": {
    "hash": "b3:eeee1111...",
    "source": "scanner:binary-analyzer:v1.0.0",
    "type": "binary",
    "metadata": {
      "buildId": "abc123...",
      "symbolsHash": "b3:...",
      "confidence": 0.95
    },
    "cas": "cas://evidence/openssl/3.0.0/binary-analysis.json"
  }
}

Pagination & Sorting

Deterministic Cursors

Cursors are base64-encoded tuples of sort keys:

{
  "cursor": "base64({\"id\":\"CVE-2025-0001\",\"score\":8.5})",
  "decode": {
    "primaryKey": "id",
    "secondaryKey": "score",
    "lastValue": {"id": "CVE-2025-0001", "score": 8.5}
  }
}

Sort Fields

EndpointDefault SortAllowed Fields
/vulnerabilitiesratings.CVSSv4.score desc, id ascid, ratings.CVSSv4.score, ratings.CVSSv31.score, severity
/componentspurl asc, name ascpurl, name, version, type
/servicesname ascname, version, cbom.dataClassification

Page Size

ParameterDefaultMinMax
pageSize1001500

UI Components

Vulnerability Table Columns

ColumnSourceSortableFilterable
CVE IDidYesYes (search)
CVSS v4 Scoreratings[method=CVSSv4].scoreYesYes (range)
CVSS v4 Severityratings[method=CVSSv4].severityYesYes (multi-select)
CVSS v3.1 Scoreratings[method=CVSSv31].scoreYesYes (range)
Affected Componentaffects[].refNoYes (search)
Evidence Sourceevidence.sourceNoYes (multi-select)

CBOM Service View

ColumnSourceSortableFilterable
Service NamenameYesYes
Ingresscbom.ingressNoYes
Egresscbom.egressNoYes
Data Classificationcbom.dataClassificationYesYes (multi-select)
Providercbom.providerYesYes
Regioncbom.regionYesYes

Filters

interface VulnerabilityFilters {
  severity?: ('critical' | 'high' | 'medium' | 'low')[];
  cvssV4ScoreMin?: number;
  cvssV4ScoreMax?: number;
  cvssV31ScoreMin?: number;
  cvssV31ScoreMax?: number;
  hasEvidence?: boolean;
  evidenceSource?: string[];
  affectedComponent?: string;
}

interface ServiceFilters {
  dataClassification?: ('pii' | 'internal' | 'public' | 'confidential')[];
  hasEgress?: boolean;
  provider?: string[];
  region?: string[];
}

Download Formats

Export Endpoints

GET /api/v1/scans/{scanId}/export?format={format}
FormatContent-TypeDeterministic
cdx-1.7application/vnd.cyclonedx+jsonYes
cdx-1.6application/vnd.cyclonedx+jsonYes
spdx-3.0application/spdx+jsonYes
csvtext/csvYes
pdfapplication/pdfPartial*

*PDF includes timestamp in footer

CSV Export Columns

cve_id,cvss_v4_score,cvss_v4_vector,cvss_v31_score,cvss_v31_vector,severity,affected_purl,evidence_hash,evidence_source
CVE-2025-0001,8.5,"CVSS:4.0/...",7.5,"CVSS:3.1/...",high,pkg:npm/example-lib@2.0.0,b3:eeee...,concelier:nvd:2025-12-03

Determinism Requirements

  1. Sort stability: All sorts use secondary key (usually id) for tie-breaking
  2. Cursor encoding: Deterministic JSON serialization before base64
  3. Timestamps: UTC ISO-8601, no sub-millisecond precision unless non-zero
  4. Export ordering: Same ordering rules as API responses
  5. Filter normalization: Sort filter arrays before query execution

Offline Support

Prefetch Manifest

{
  "prefetch": {
    "vulnerabilities": "/api/v1/scans/{scanId}/vulnerabilities?pageSize=500",
    "components": "/api/v1/scans/{scanId}/components?pageSize=500",
    "services": "/api/v1/scans/{scanId}/services",
    "provenance": "/api/v1/scans/{scanId}/provenance"
  },
  "cache": {
    "ttl": 86400,
    "storage": "indexeddb"
  }
}

Static Export

For air-gapped environments, export complete dataset:

GET /api/v1/scans/{scanId}/offline-bundle

Returns zip containing: