szl-kernels-live / scripts /kernel_portfolio_truth.mjs
betterwithage's picture
Deploy GitHub source e03cdb25aee1
c9917d4 verified
Raw
History Blame Contribute Delete
4.62 kB
const SHA40 = /^[0-9a-f]{40}$/;
const SHA256 = /^[0-9a-f]{64}$/;
const RESULT_STATES = new Set(["PASS", "FAIL"]);
function exactKeys(value, expected, label) {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new Error(`${label} must be an object`);
}
const actual = Object.keys(value).sort();
const wanted = [...expected].sort();
if (JSON.stringify(actual) !== JSON.stringify(wanted)) {
throw new Error(`${label} fields do not match the contract`);
}
}
export function validateSnapshot(index, receipt) {
if (!index || !Array.isArray(index.kernels) || !index.kernels.length) {
throw new Error("contract index has no kernels");
}
if (!receipt || !Array.isArray(receipt.results)) {
throw new Error("receipt has no results");
}
if (
typeof index.recorded_at !== "string" ||
index.recorded_at.length === 0 ||
receipt.recorded_at !== index.recorded_at
) {
throw new Error("receipt recorded_at does not match the contract index");
}
const resultById = new Map();
for (const result of receipt.results) {
if (!result || typeof result.id !== "string" || resultById.has(result.id)) {
throw new Error("receipt result IDs must be unique non-empty strings");
}
if (!RESULT_STATES.has(result.status)) {
throw new Error(`receipt result ${result.id} has an unsupported status`);
}
if (!SHA40.test(result.revision || "")) {
throw new Error(`receipt result ${result.id} has an invalid revision`);
}
if (!SHA256.test(result.tree_digest_sha256 || "")) {
throw new Error(`receipt result ${result.id} has an invalid tree digest`);
}
resultById.set(result.id, result);
}
const indexIds = new Set();
const statuses = new Map();
for (const row of index.kernels) {
if (!row || typeof row.id !== "string" || indexIds.has(row.id)) {
throw new Error("contract index IDs must be unique non-empty strings");
}
indexIds.add(row.id);
const result = resultById.get(row.id);
if (!result) {
throw new Error(`receipt is missing ${row.id}`);
}
if (result.revision !== row.revision) {
throw new Error(`receipt revision does not match ${row.id}`);
}
if (result.tree_digest_sha256 !== row.tree_digest_sha256) {
throw new Error(`receipt tree digest does not match ${row.id}`);
}
statuses.set(row.id, result.status);
}
if (resultById.size !== indexIds.size) {
throw new Error("receipt and contract index ID sets do not match");
}
const summary = {
kernels: receipt.results.length,
passed: receipt.results.filter((result) => result.status === "PASS").length,
failed: receipt.results.filter((result) => result.status === "FAIL").length,
};
exactKeys(receipt.summary, ["failed", "kernels", "passed"], "receipt summary");
if (
receipt.summary.kernels !== summary.kernels ||
receipt.summary.passed !== summary.passed ||
receipt.summary.failed !== summary.failed ||
summary.kernels !== index.kernels.length
) {
throw new Error("receipt summary does not recompute from exact results");
}
return statuses;
}
export function classifyLiveHead(data, expectedRevision) {
if (!SHA40.test(expectedRevision || "")) {
return { state: "UNAVAILABLE", reason: "Recorded revision is malformed" };
}
if (!data || typeof data !== "object" || !SHA40.test(data.sha || "")) {
return { state: "UNAVAILABLE", reason: "Live-head response is malformed" };
}
if (data.sha === expectedRevision) {
return { state: "MATCH", sha: data.sha };
}
return { state: "DRIFT", sha: data.sha };
}
export async function fetchLiveHead(
url,
expectedRevision,
{ fetchImpl = globalThis.fetch, timeoutMs = 8000 } = {},
) {
if (typeof fetchImpl !== "function") {
return { state: "UNAVAILABLE", reason: "Fetch is unavailable" };
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetchImpl(url, {
cache: "no-store",
headers: { Accept: "application/json" },
signal: controller.signal,
});
if (!response.ok) {
return { state: "UNAVAILABLE", reason: `HTTP ${response.status}` };
}
return classifyLiveHead(await response.json(), expectedRevision);
} catch (error) {
const reason = controller.signal.aborted
? `Live-head request timed out after ${timeoutMs}ms`
: error instanceof Error
? error.message
: "Live-head request failed";
return { state: "UNAVAILABLE", reason };
} finally {
clearTimeout(timeout);
}
}