Files
playbook/antigravity-awesome-skills/verification/aas-v1/verifier/lib/receipt.mjs
T
2026-07-18 00:02:59 +00:00

57 lines
2.0 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
import Ajv2020 from "ajv/dist/2020.js";
import addFormats from "ajv-formats";
import { canonicalJson, digestJson, sha256 } from "./canonical.mjs";
export const JOB_IDS = Object.freeze([
"linux-node-22", "linux-node-24", "macos-node-22", "macos-node-24",
"windows-node-22", "windows-node-24",
]);
export const SUITE_IDS = Object.freeze([
"package", "entrypoints", "mcp", "property", "fuzz", "hostile",
"legacy", "transaction", "adapters",
]);
export function receiptDigest(receipt) {
const { receiptDigest: _omitted, ...payload } = receipt;
return digestJson(payload);
}
export function finalizeReceipt(receipt) {
return { ...receipt, receiptDigest: receiptDigest(receipt) };
}
export function writeCanonicalReceipt(file, receipt) {
const finalized = finalizeReceipt(receipt);
fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
fs.writeFileSync(file, `${canonicalJson(finalized)}\n`, { mode: 0o600, flag: "wx" });
return finalized;
}
export function loadReceiptValidator(schemaFile) {
const ajv = new Ajv2020({ allErrors: true, strict: true, strictRequired: false });
addFormats(ajv);
return ajv.compile(JSON.parse(fs.readFileSync(schemaFile, "utf8")));
}
export function validateReceipt(receipt, validator) {
const failures = [];
if (!validator(receipt)) failures.push({ code: "AAS_VERIFIER_RECEIPT_SCHEMA", errors: validator.errors });
if (receipt.receiptDigest !== receiptDigest(receipt)) failures.push({ code: "AAS_VERIFIER_RECEIPT_DIGEST" });
const ids = (receipt.suites || []).map((entry) => entry.id);
if (new Set(ids).size !== SUITE_IDS.length || SUITE_IDS.some((id) => !ids.includes(id))) {
failures.push({ code: "AAS_VERIFIER_RECEIPT_SUITE_SET", ids });
}
for (const suite of receipt.suites || []) {
if (suite.evidenceSha256 !== digestJson(suite.evidence)) failures.push({ code: "AAS_VERIFIER_SUITE_EVIDENCE_DIGEST", suite: suite.id });
}
return failures;
}
export function executableDigest() {
return sha256(fs.readFileSync(process.execPath));
}