sbom

package
v1.801.307 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Pure core of the SBOM lens: the wire types, the CycloneDX parser, the row builder, and the datastore value coercers. Everything here is I/O-free so the tests drive it with inline documents — no datastore needed — exactly as the analytics lens proves out its assemblers. The handlers (sbom.go) are the thin orchestration that persists these rows and reads them back.

Registry pull — the CONSUMER half of the SBOM lane. The registry is the source of truth: CI produces the CycloneDX SBOM and `cosign attach`es it to the image DIGEST. This file reads that attached artifact back with go-containerregistry (pure-Go, no binary deps) and hands the raw CycloneDX document to the SAME server-side parser the POST /v1/sbom path uses (parseComponents), so ingest and pull share one component-flattening code path.

Two attachment conventions are honored, in order:

  1. cosign SBOM tag — `cosign attach sbom` writes an image tagged `sha256-<hex>.sbom` in the SAME repo as the subject. Deterministic, no referrers API needed. Tried first.
  2. OCI 1.1 referrers — the registry's /referrers response for the digest lists manifests that declare the subject; we pick the CycloneDX one by its artifactType/mediaType. Fallback for registries/producers that use referrers.

A pull failure is NON-FATAL to the caller: pull-on-miss simply falls back to the honest 404. Nothing here fabricates components — a document must parse as CycloneDX or it is ignored.

Package sbom mounts the Hanzo Cloud /v1/sbom/* surface: the backend half of "SBOM visible in console on deployments + tracked in the datastore globally". CI POSTs a CycloneDX SBOM keyed by image digest; the console GETs it back by digest or image ref.

GLOBAL BY DESIGN. Unlike the analytics lens (which is strictly per-org), an SBOM belongs to an image DIGEST, not a tenant — the digest is content-addressed, so any tenant deploying that image resolves the SAME component set. The store is therefore cross-tenant on purpose: ingest is gated to super-admin/CI (the build fleet), and resolve exposes only the immutable bill-of-materials of an image, no tenant data. This is why there is no org predicate here.

ONE datastore client. Like clients/analytics, this package rides the SAME datastore-go client the ai subsystem opens in the shared Bootstrap (ai/object.DatastoreExec/DatastoreQuery). It never opens a second connection.

Surface (/v1 only):

POST /v1/sbom          ingest a CycloneDX SBOM (super-admin / CI only)
GET  /v1/sbom/{ref}    resolve by image digest OR image ref (for the console)
GET  /v1/sbom/health   liveness + datastore connectivity (not JWT-gated)

Registered as id "sbom" with cloud.HealthOwner + order 137: it serves its own /v1/sbom/health, so serve.go skips the generic liveness route. Order 137 binds /v1/sbom/* before the ai subsystem's /v1/* catch-all (150).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount wires the SBOM surface onto app and bootstraps the global table.

func Prefetch

func Prefetch(ctx context.Context, log luxlog.Logger, ref string)

Prefetch materializes the SBOM for a deployed image ref if it is not already in the datastore, on a deploy-digest signal from the platform. It is the deploy-time trigger: idempotent (a hit is a no-op), best-effort (a miss/pull-failure logs and returns, never blocks a deploy), and safe to call from a goroutine. Exported so clients/platform can fire it after a deployment goes live WITHOUT this package importing platform (dependency points platform → sbom, one direction).

Types

type SbomComponent

type SbomComponent struct {
	Name    string `json:"name"`
	Version string `json:"version"`
	Type    string `json:"type"`
	Purl    string `json:"purl"`
	License string `json:"license"`
}

SbomComponent is one flattened dependency: name/version/type/purl + a single license string (first id | name | expression found, else "").

type SbomIngest

type SbomIngest struct {
	ImageDigest string          `json:"imageDigest"`
	ImageRef    string          `json:"imageRef"`
	SourceRepo  string          `json:"sourceRepo"`
	GitSha      string          `json:"gitSha"`
	Format      string          `json:"format"`
	Document    json.RawMessage `json:"document"`
}

SbomIngest is the POST /v1/sbom body from CI: the image identity + a raw CycloneDX document whose components[] we flatten and persist.

type SbomView

type SbomView struct {
	ImageDigest    string          `json:"imageDigest"`
	ImageRef       string          `json:"imageRef"`
	SourceRepo     string          `json:"sourceRepo"`
	GitSha         string          `json:"gitSha"`
	IngestedAt     string          `json:"ingestedAt"`
	ComponentCount int             `json:"componentCount"`
	Truncated      bool            `json:"truncated,omitempty"`
	Components     []SbomComponent `json:"components"`
}

SbomView is the GET /v1/sbom/{ref} response the console renders.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL