Files
projectbrain-Public/scripts/verify-release-metadata.mjs
T

22 lines
1.5 KiB
JavaScript

#!/usr/bin/env node
import { createHash } from "node:crypto";
import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import process from "node:process";
const root = resolve(import.meta.dirname, "..");
const outputFlag = process.argv.indexOf("--output");
const output = resolve(root, outputFlag >= 0 ? process.argv[outputFlag + 1] : "release-artifacts");
const sbomText = await readFile(resolve(output, "projectbrain.cdx.json"), "utf8");
const provenance = JSON.parse(await readFile(resolve(output, "projectbrain.provenance.json"), "utf8"));
const sbom = JSON.parse(sbomText);
const canonicalSbom = `${JSON.stringify(sbom, null, 2)}\n`;
const digest = createHash("sha256").update(JSON.stringify(sbom)).digest("hex");
const failures = [];
if (sbom.bomFormat !== "CycloneDX" || sbom.specVersion !== "1.6" || !Array.isArray(sbom.components) || sbom.components.length === 0) failures.push("SBOM is not a populated CycloneDX 1.6 document");
if (sbomText !== canonicalSbom) failures.push("SBOM is not canonical pretty-printed JSON");
if (provenance.predicateType !== "https://slsa.dev/provenance/v1" || !provenance.subject?.length) failures.push("Provenance has no SLSA v1 subjects");
if (provenance.sbom?.sha256 !== digest) failures.push("Provenance SBOM digest does not match");
if (failures.length) { console.error(failures.join("\n")); process.exit(1); }
console.log(`Release metadata verified: ${sbom.components.length} components and ${provenance.subject.length} subjects.`);