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:
| Field | Meaning |
|---|---|
readiness | absent, ready, or stale, derived only from a durable scanner.artifact_boms row. |
scanStatus | Latest persisted attempt: pending, running, succeeded, failed, cancelled, or null when no attempt exists. |
lastAttemptAt | Latest scanner.scan_runtime_state.updated_at, regardless of outcome. |
lastSuccessfulScanAt | Latest scanner.artifact_boms.inserted_at; failed, cancelled, and reaped attempts never set or refresh it. |
lastAttemptFailureReason | Bounded 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:
- a durable BOM wins:
state=ready,scanId=null,updatedAtis the durable BOM timestamp, andfailureReason=null, even if a newer attempt failed; - without a BOM,
state,scanId,updatedAt, andfailureReasoncontinue to describe the latest runtime attempt; - therefore v2 consumers must not use legacy
updatedAtas an unqualified successful-scan timestamp.
Truth table
| Durable BOM | Latest persisted attempt | readiness | scanStatus |
|---|---|---|---|
| none | none | absent | null |
| none | Pending (queued) | absent | pending |
| none | Running | absent | running |
| none | Succeeded | absent | succeeded |
| none | Failed | absent | failed |
| none | Cancelled | absent | cancelled |
| fresh | any/latest absent | ready | normalized latest status or null |
| older than the configured maximum age | any/latest absent | stale | normalized 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.
