// An independent package check witnesses its contract and bytes, without // inventing a workspace or granting installation/activation authority. import { readFile, writeFile } from "node:fs/promises"; import { createHash } from "node:crypto"; import { pathToFileURL } from "node:url"; import { join } from "node:path"; const [compilerPath, schemaPath, checksPath, output] = process.argv.slice(2); const compiler = await import(pathToFileURL(compilerPath)); const schema = JSON.parse(await readFile(schemaPath, "utf8")); const checks = JSON.parse(await readFile(checksPath, "utf8")); const generator = createHash("sha256") .update(await readFile(compilerPath)) .digest("hex"); const evidence = []; for (const check of checks) { const pkg = schema.packages.find((pkg) => pkg.revisionId === check.packageRevisionId); if (!pkg) throw Error("Unknown checked package"); const contract = compiler.packageBuildContract(schema, pkg.revisionId); const sourceDigest = compiler.hexDigest({ revision: pkg.revisionId, source: pkg.source }); const manifest = compiler.parsePackageArtifacts( JSON.parse(await readFile(join(check.artifactPath, "share/quixos/package-artifacts.json"), "utf8")), ); compiler.checkPackageCoverage( { ...contract.definition.package, bindingDigest: contract.digest, sourceDigest }, manifest, ); const receipt = JSON.parse(await readFile(join(check.artifactPath, "share/quixos/build-receipt.json"), "utf8")); const expected = compiler.expectedPackageReceipt(contract, manifest, sourceDigest, generator); if (compiler.hexDigest(receipt) !== compiler.hexDigest(expected.receipt)) throw Error("Invalid package build receipt"); const read = await compiler.artifactFileReader({ [pkg.revisionId]: check.artifactPath }); await compiler.checkArtifactFiles(manifest, read); for (const [file, bytes] of expected.sources) if (!Buffer.from(bytes).equals(await read(pkg.revisionId, file, bytes.length))) throw Error("Modified generated binding " + file); evidence.push({ ...check, contract: contract.digest, sourceDigest, receipt }); } await writeFile( join(output, "package-checks.json"), JSON.stringify({ codec: "camino-package-checks-v1", generator, packages: evidence }), );