Scanner SBOM readiness API

GET /api/v1/sbom-readiness?tenant=<tenant>&digest=<sha256> is the Scanner-owned read model for an image’s latest scan attempt and latest durable successful SBOM. It requires an authenticated principal with scanner:read/scans:read authorization and a legitimate tenant context.

Version 2 additive fields

contractVersion is scanner.sbom-readiness.v2. The endpoint preserves the v1 fields and adds:

FieldMeaning
readinessabsent, ready, or stale, derived only from a durable scanner.artifact_boms row.
scanStatusLatest persisted attempt: pending, running, succeeded, failed, cancelled, or null when no attempt exists.
lastAttemptAtLatest scanner.scan_runtime_state.updated_at, regardless of outcome.
lastSuccessfulScanAtLatest scanner.artifact_boms.inserted_at; failed, cancelled, and reaped attempts never set or refresh it.
lastAttemptFailureReasonBounded safe reason for a failed/cancelled latest attempt. Unknown legacy text maps to a generic log-correlation message.

readiness=stale when lastSuccessfulScanAt is older than Scanner:SbomReadiness:SuccessfulScanMaxAge. The option must be positive and defaults to 14 days, matching the Console image-coverage freshness rule.

Compatibility fields

The existing fields retain their v1 semantics:

Truth table

Durable BOMLatest persisted attemptreadinessscanStatus
nonenoneabsentnull
nonePending (queued)absentpending
noneRunningabsentrunning
noneSucceededabsentsucceeded
noneFailedabsentfailed
noneCancelledabsentcancelled
freshany/latest absentreadynormalized latest status or null
older than the configured maximum ageany/latest absentstalenormalized latest status or null

The stale-Pending reaper durably writes Failed plus its bounded timeout reason. The API therefore reports scanStatus=failed; it does not invent a stored reaped lifecycle value.

Consumer boundary

Release Orchestrator can continue reading the additive response through its v1 fields. Integrations’ registry-image projection and the Images UI adopt the v2 fields under STI-4; until then their legacy/direct runtime timestamp is not evidence that a scan succeeded.