Skip to content

Release provenance (SBOM, dependency scan)

tools/generate-sbom.ts, tools/dependency-scan.ts, and tools/release-provenance.ts (WU-3517, INIT-091 phase 2) generate release provenance mechanically for every published @lumenflow/* package and pack: an SBOM, a dependency vulnerability scan, a checksum, a signature reference, and a compatibility declaration.

pnpm lumenflow:release --release-version 5.20.0 --verify-provenance

When passed, the gate runs after packed-artifact validation and before npm publish (Phase 3.5 of the release pipeline) for every package in the publish set.

generate-sbom.ts emits a CycloneDX 1.5 JSON document (sbom.cdx.json) per package, built from pnpm list --json --depth Infinity --prod — no new generator dependency (@cyclonedx/cyclonedx-npm or similar) was added, since CycloneDX is a JSON schema, not a runtime library requirement.

import { generateSbomForPackage } from './tools/generate-sbom.ts';

const { sbomPath, sbom } = generateSbomForPackage('packages/@lumenflow/agent/package.json');

dependency-scan.ts runs pnpm audit --json per artifact and fails the release on any critical or high finding (dossier launch gate 12) — no new scanner dependency, since pnpm audit is already part of the toolchain.

import { runDependencyScan } from './tools/dependency-scan.ts';

const { report } = runDependencyScan('@lumenflow/agent', { cwd: 'packages/@lumenflow/agent' });
report.ok; // false if any critical/high finding was found

release-provenance.ts assembles the full record — SBOM, dependency scan, a recursive sha256 checksum over the built dist/, a signature reference, and a compatibility declaration — then runs assertProvenanceGateFailsClosed, which throws (never returns a silent ok: false) when any of the following is missing or stale:

  • SBOM missing, or its component version doesn’t match the artifact version
  • Dependency scan missing, or it found a blocking (critical/high) finding
  • Checksum missing
  • Signature missing
  • Compatibility declaration missing
import { assertProvenanceGateFailsClosed } from './tools/release-provenance.ts';

assertProvenanceGateFailsClosed(record); // throws a descriptive Error on any gap

Signature reference: consumed, not generated

Section titled “Signature reference: consumed, not generated”

resolveSignatureReference looks for an existing signature sidecar (.sig, .sigstore.json, .intoto.jsonl) next to the SBOM. This module is intentionally a consumer, not a producer, of signatures — real cryptographic signing is WU-3371/WU-3372’s job (pack signing and OCI distribution, INIT-087). Until a sidecar exists for a given artifact, the gate above fails closed rather than fabricating a signature — which is exactly why --verify-provenance stays opt-in today.

When an artifact’s version crosses a compatibility-manifest MAJOR boundary, writeMigrationGuideIfNeeded writes a MIGRATION.md alongside the provenance record, naming the previous and new versions and the required migration steps. Below a MAJOR boundary, no migration guide is written.

This module replaces the manual “verify provenance and SBOM” step previously required for the Reliability Operations pack (WU-3383) with a mechanical, per-artifact gate. It does not re-implement pack signing or OCI distribution — that remains WU-3371/WU-3372’s scope under INIT-087.

  • Contract spine — the compatibility manifest this module’s compatibility declaration complements.