52 lines
3.8 KiB
JavaScript
52 lines
3.8 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import { fileURLToPath } from "node:url";
|
|
import { aggregateReceipts } from "../lib/aggregate.mjs";
|
|
import { digestJson } from "../lib/canonical.mjs";
|
|
import { finalizeReceipt, JOB_IDS, loadReceiptValidator, SUITE_IDS } from "../lib/receipt.mjs";
|
|
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const validator = loadReceiptValidator(path.resolve(here, "..", "..", "schemas", "product-verifier-receipt.schema.json"));
|
|
const d = `sha256-${"a".repeat(64)}`;
|
|
const sri = `sha512-${Buffer.alloc(64).toString("base64")}`;
|
|
|
|
function receipt(job, index) {
|
|
const totals = { property: index < 4 ? 16667 : 16666, fuzz: index < 2 ? 8334 : 8333 };
|
|
const suites = SUITE_IDS.map((id) => {
|
|
const evidence = id === "property" ? { total: totals.property, hardPolicyViolations: 0 }
|
|
: id === "fuzz" ? { total: totals.fuzz }
|
|
: id === "hostile" ? { executions: 64 }
|
|
: id === "legacy" ? { executions: 41 }
|
|
: id === "transaction" ? { faultBoundaryClasses: ["lock", "journal", "backup", "write", "fsync", "rename", "commit"], raceClasses: ["concurrency", "drift", "symlink-swap", "target-swap", "corrupt-journal", "recovery-race"] }
|
|
: {};
|
|
return { id, status: "passed", executions: evidence.total || evidence.executions || 1, failures: 0, evidenceSha256: digestJson(evidence), evidence };
|
|
});
|
|
return finalizeReceipt({ schemaVersion: 1, receiptVersion: "1.0.0", status: "passed",
|
|
job: { id: job, workflowRunId: "1", workflowRunAttempt: "1" },
|
|
candidate: { commit: "1".repeat(40), package: "agentic-awesome-skills", version: "14.6.0", tarballBytes: 1, tarballSha256: d, tarballSha512: sri, packManifestSha256: d, installTreeSha256: d },
|
|
verifier: { version: "1.0.0", commit: "2".repeat(40), rootDigest: d, contractDigest: d, owner: "aas-v1-independent-verifier" },
|
|
environment: { platform: job.startsWith("linux") ? "linux" : job.startsWith("macos") ? "darwin" : "win32", osVersion: "test", kernelVersion: "test", architecture: "x64", nodeVersion: job.endsWith("22") ? "v22.23.1" : "v24.18.0", nodeExecutableSha256: d, runnerImageLabel: "test", runnerImageVersion: "test", filesystemType: job.startsWith("linux") ? "ext4" : job.startsWith("macos") ? "apfs" : "ntfs", filesystemCaseSensitivity: job.startsWith("linux") ? "sensitive" : "insensitive-preserving" },
|
|
observer: { contractVersion: "1.0.0", backend: job.startsWith("linux") ? "linux-strace-process-tree" : job.startsWith("macos") ? "macos-fs_usage-process" : "windows-etw-kernel-process-tree", selfTestDigest: d, networkSentinels: 1, writeSentinels: 1, overflow: false, ambiguousLineage: false },
|
|
zones: Object.fromEntries(["home", "project", "cache", "tmp"].map((name) => [name, { beforeSha256: d, afterSha256: d, persistentWriteCount: 0 }])),
|
|
suites, canonicalPayload: { sha256: d, excludedFields: ["timestamp", "correlationId", "localizedMessage", "diagnostics"], sampleCount: 60 }, failures: [] });
|
|
}
|
|
|
|
test("aggregator accepts only the exact complete matrix", () => {
|
|
const receipts = JOB_IDS.map(receipt);
|
|
assert.equal(aggregateReceipts(receipts, validator).status, "passed");
|
|
const missing = aggregateReceipts(receipts.slice(1), validator);
|
|
assert.equal(missing.status, "failed");
|
|
assert.ok(missing.failures.some((entry) => entry.code === "AAS_VERIFIER_MATRIX_MISSING_JOB"));
|
|
});
|
|
|
|
test("aggregator catches receipt tampering and duplicates", () => {
|
|
const receipts = JOB_IDS.map(receipt);
|
|
receipts[0].candidate.tarballBytes = 2;
|
|
const result = aggregateReceipts([...receipts.slice(0, 5), receipts[0]], validator);
|
|
assert.equal(result.status, "failed");
|
|
assert.ok(result.failures.some((entry) => entry.code === "AAS_VERIFIER_RECEIPT_DIGEST"));
|
|
assert.ok(result.failures.some((entry) => entry.code === "AAS_VERIFIER_MATRIX_DUPLICATE_JOB"));
|
|
});
|