Artifact Links API
Sprint: SPRINT_20260507_002_Scanner_artifact_association_graph
Responsibility
The SBOM service is the durable owner of artifact associations. Scanner, CLI, CI, registry plugins, and Console produce or review link evidence, but graph persistence lives in the SBOM service so SBOM lineage, image evidence, and scan evidence can be resolved through one tenant-scoped API surface.
Authentication And Tenancy
Direct SBOM service calls require a validated Authority bearer token or a Router-generated signed identity envelope:
- reads require
sbom:read; - writes and status changes require
sbom:write; - the canonical
stellaops:tenantclaim owns the source, image, SBOM, scan, and link records.
The request body or query may still carry tenantId/tenant for compatibility and mismatch detection. It cannot select another tenant: omitted uses the authenticated tenant, equal is accepted, and mismatch is rejected before repository access. Caller-supplied createdBy/operatorId and x-user-id values do not override the authenticated actor.
Persistence
Startup migration 003_artifact_associations.sql creates:
sbom.artifact_subjectssbom.artifact_links
The migration is embedded in StellaOps.SbomService.Persistence and is applied by the existing SBOM service startup migration wiring. Local harness mode uses an in-memory artifact association repository only when the explicit local harness is enabled.
Link Confidence
| Confidence | Meaning |
|---|---|
verified | Link is backed by strong evidence or operator confirmation. |
strong-candidate | Link is likely correct but still needs confirmation or stronger evidence. |
weak-candidate | Link was inferred from weak metadata and should not influence release decisions. |
rejected | Link was reviewed and excluded from resolved graphs. |
Strong evidence types include signed provenance, SBOM subject references, OCI referrers, scanner output, CLI explicit input, and UI confirmation. Heuristics and metadata hints create candidates.
Endpoints
Create One Link
POST /api/v1/artifact-links
Creates or updates a single relationship.
{
"tenantId": "tenant-a",
"from": {
"kind": "oci-image",
"digest": "sha256:..."
},
"to": {
"kind": "scan-job",
"scanJobId": "scan-123"
},
"relationship": "SCANNED_BY",
"evidenceType": "scanner-output",
"verified": true,
"createdBy": "scanner-worker"
}
Import A Bundle
POST /api/v1/artifact-links/import
Imports a related source/build/image/SBOM/scan/detector set and creates deterministic links:
- build
DERIVED_FROMsource - image
BUILT_BYbuild, or imageDERIVED_FROMsource when no build is supplied - SBOM
DESCRIBESimage/source - image/SBOM/source
SCANNED_BYscan job - scan job
PRODUCEDdetector reports
Resolve A Graph
GET /api/v1/artifact-links/resolve
Query parameters:
tenant(optional authenticated-tenant assertion)- one of
subjectKey,imageDigest,sbomDigest,scanJobId, orrepoUrlpluscommitSha maxDepth(default4)
Rejected links are excluded from resolved graphs.
Review Queues
GET /api/v1/artifact-links/unlinked?tenant=<tenant>&kind=<kind>&limit=50GET /api/v1/artifact-links/candidates?tenant=<tenant>&limit=50
Status Changes
POST /api/v1/artifact-links/{linkId}/confirmPOST /api/v1/artifact-links/{linkId}/rejectPOST /api/v1/artifact-links/{linkId}/verify
Request body:
{
"tenantId": "tenant-a",
"reason": "matched CI build provenance",
"operatorId": "alice"
}
Identity Rules
- OCI image subjects require immutable
sha256:digests. Mutable tags are not accepted as verified identity. - SBOM subjects require the SBOM document
sha256:digest. - Source snapshots require
repoUrlpluscommitSha. - Build runs require
buildIdorprimaryLocator. - Scan jobs require
scanJobIdorprimaryLocator.
UI And CLI Consumers
Console scan detail resolves by scan job ID and tenant context:
/api/sbomservice/api/v1/artifact-links/resolve?tenant=tenant-a&scanJobId=scan-123&maxDepth=5
CLI commands are under:
stella artifact link export
stella artifact link import
stella artifact link create
stella artifact link resolve
stella artifact link candidates
stella artifact link unlinked
stella artifact link confirm|reject|verify
CLI export is offline and writes the import body exactly; online commands require --server, STELLAOPS_SBOMSERVICE_URL, or STELLAOPS_BACKEND_URL.
