import { validateIOFormatBoundReceiptSet, type IOFormatBoundRuntimeReceiptSetIR, } from "./io-format-receipt-binding"; import { type IOFormatRuntimeIdentityIR, type IOFormatRuntimeRouteQuery, } from "./io-format-runtime-receipt"; export const IO_FORMAT_RECEIPT_FRESHNESS_SCHEMA = 1 as const; export const IO_FORMAT_RECEIPT_FRESHNESS_TASK = "M12-05F" as const; export interface IOFormatReceiptFreshnessEnvelopeIR { schemaVersion: typeof IO_FORMAT_RECEIPT_FRESHNESS_SCHEMA; task: typeof IO_FORMAT_RECEIPT_FRESHNESS_TASK; parentBindingSha256: string; boundReceiptSetSha256: string; runtimeSha256: string; bound: IOFormatBoundRuntimeReceiptSetIR; } export interface IOFormatReceiptFreshnessExpectedIR { parentBindingSha256: string; parentReceiptSetSha256: string; inventorySha256: string; boundReceiptSetSha256: string; runtimeSha256: string; runtime: IOFormatRuntimeIdentityIR; receiptIdentities: Array>; } export type IOFormatReceiptFreshnessFailure = | "RECEIPT_INVALID" | "RECEIPT_FORGED" | "RECEIPT_STALE" | "RECEIPT_CROSS_VERSION"; export class IOFormatReceiptFreshnessError extends Error { readonly code = "IO_FORMAT_UNSUPPORTED" as const; readonly reason: IOFormatReceiptFreshnessFailure; constructor(reason: IOFormatReceiptFreshnessFailure, message: string) { super(`IO_FORMAT_UNSUPPORTED: ${reason}: ${message}`); this.name = "IOFormatReceiptFreshnessError"; this.reason = reason; } } const SHA256 = /^[a-f0-9]{64}$/; function record(value: unknown, path: string): Record { if (typeof value !== "object" || value === null || Array.isArray(value)) { throw new IOFormatReceiptFreshnessError("RECEIPT_INVALID", `${path} must be an object`); } return value as Record; } function exactKeys(value: Record, expected: readonly string[], path: string): void { const actual = Object.keys(value).sort(); const allowed = [...expected].sort(); if (actual.length !== allowed.length || actual.some((key, index) => key !== allowed[index])) { throw new IOFormatReceiptFreshnessError("RECEIPT_FORGED", `${path} contains undeclared fields`); } } function sha(value: unknown, path: string): string { if (typeof value !== "string" || !SHA256.test(value)) { throw new IOFormatReceiptFreshnessError("RECEIPT_INVALID", `${path} is not SHA-256`); } return value; } function stableValue(value: unknown): unknown { if (Array.isArray(value)) return value.map(stableValue); if (typeof value === "object" && value !== null) { return Object.fromEntries(Object.keys(value as Record).sort().map((key) => [key, stableValue((value as Record)[key])])); } return value; } function stableJSON(value: unknown): string { return JSON.stringify(stableValue(value)); } function sameRuntime(left: IOFormatRuntimeIdentityIR, right: IOFormatRuntimeIdentityIR): boolean { return stableJSON(left) === stableJSON(right); } export function parseIOFormatReceiptFreshness(value: unknown): IOFormatReceiptFreshnessEnvelopeIR { const input = record(value, "input"); exactKeys(input, ["schemaVersion", "task", "parentBindingSha256", "boundReceiptSetSha256", "runtimeSha256", "bound"], "input"); if (input.schemaVersion !== IO_FORMAT_RECEIPT_FRESHNESS_SCHEMA || input.task !== IO_FORMAT_RECEIPT_FRESHNESS_TASK) { throw new IOFormatReceiptFreshnessError("RECEIPT_INVALID", "freshness envelope header is invalid"); } const boundInput = record(input.bound, "bound"); const parentReceiptSetSha256 = sha(boundInput.parentReceiptSetSha256, "bound.parentReceiptSetSha256"); const inventorySha256 = sha(boundInput.inventorySha256, "bound.inventorySha256"); let bound: IOFormatBoundRuntimeReceiptSetIR; try { bound = validateIOFormatBoundReceiptSet(input.bound, parentReceiptSetSha256, inventorySha256); } catch (error) { if (error instanceof IOFormatReceiptFreshnessError) throw error; throw new IOFormatReceiptFreshnessError("RECEIPT_FORGED", error instanceof Error ? error.message : "bound receipt set is invalid"); } return { schemaVersion: IO_FORMAT_RECEIPT_FRESHNESS_SCHEMA, task: IO_FORMAT_RECEIPT_FRESHNESS_TASK, parentBindingSha256: sha(input.parentBindingSha256, "input.parentBindingSha256"), boundReceiptSetSha256: sha(input.boundReceiptSetSha256, "input.boundReceiptSetSha256"), runtimeSha256: sha(input.runtimeSha256, "input.runtimeSha256"), bound, }; } function expectedHashes(expected: IOFormatReceiptFreshnessExpectedIR): void { sha(expected.parentBindingSha256, "expected.parentBindingSha256"); sha(expected.parentReceiptSetSha256, "expected.parentReceiptSetSha256"); sha(expected.inventorySha256, "expected.inventorySha256"); sha(expected.boundReceiptSetSha256, "expected.boundReceiptSetSha256"); sha(expected.runtimeSha256, "expected.runtimeSha256"); if (!Array.isArray(expected.receiptIdentities) || expected.receiptIdentities.length !== 14) { throw new IOFormatReceiptFreshnessError("RECEIPT_INVALID", "expected receipt identity set is incomplete"); } } export function validateIOFormatReceiptFreshness(value: unknown, expected: IOFormatReceiptFreshnessExpectedIR): IOFormatReceiptFreshnessEnvelopeIR { expectedHashes(expected); const parsed = parseIOFormatReceiptFreshness(value); if (parsed.parentBindingSha256 !== expected.parentBindingSha256 || parsed.bound.parentReceiptSetSha256 !== expected.parentReceiptSetSha256 || parsed.bound.inventorySha256 !== expected.inventorySha256) { throw new IOFormatReceiptFreshnessError("RECEIPT_STALE", "receipt parent or inventory identity is stale"); } if (parsed.boundReceiptSetSha256 !== expected.boundReceiptSetSha256) { throw new IOFormatReceiptFreshnessError("RECEIPT_FORGED", "receipt-set content identity does not match the trusted build"); } if (parsed.runtimeSha256 !== expected.runtimeSha256 || !sameRuntime(parsed.bound.runtime, expected.runtime)) { throw new IOFormatReceiptFreshnessError("RECEIPT_CROSS_VERSION", "runtime identity does not match the trusted build"); } for (const receipt of parsed.bound.receipts) { if (receipt.runtimeSha256 !== expected.runtimeSha256) { throw new IOFormatReceiptFreshnessError("RECEIPT_CROSS_VERSION", `${receipt.format}:${receipt.operation} runtime identity is stale`); } const expectedReceipt = expected.receiptIdentities.find((candidate) => candidate.format === receipt.format && candidate.operation === receipt.operation); if (!expectedReceipt || stableJSON(receipt) !== stableJSON(expectedReceipt)) { throw new IOFormatReceiptFreshnessError("RECEIPT_FORGED", `${receipt.format}:${receipt.operation} receipt content is not trusted`); } } return parsed; } async function sha256Text(value: string): Promise { const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(value)); return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join(""); } /** Recomputes the canonical receipt-set and runtime digests for an independent checker. */ export async function verifyIOFormatReceiptFreshness(value: unknown, expected: IOFormatReceiptFreshnessExpectedIR): Promise { const parsed = validateIOFormatReceiptFreshness(value, expected); if (await sha256Text(stableJSON(parsed.bound)) !== parsed.boundReceiptSetSha256) { throw new IOFormatReceiptFreshnessError("RECEIPT_FORGED", "receipt-set canonical digest does not match its contents"); } if (await sha256Text(stableJSON(parsed.bound.runtime)) !== parsed.runtimeSha256) { throw new IOFormatReceiptFreshnessError("RECEIPT_FORGED", "runtime canonical digest does not match its contents"); } return parsed; } export type IOFormatFreshRuntimeRouteResult = | { status: "READY"; format: IOFormatRuntimeRouteQuery["format"]; operation: IOFormatRuntimeRouteQuery["operation"]; operator: string; receipt: IOFormatReceiptFreshnessEnvelopeIR["bound"]["receipts"][number]; freshness: "VERIFIED" } | { status: "BLOCKED"; code: "IO_FORMAT_UNSUPPORTED"; reason: IOFormatReceiptFreshnessFailure | "UNAVAILABLE"; format: IOFormatRuntimeRouteQuery["format"]; operation: IOFormatRuntimeRouteQuery["operation"] }; export function resolveFreshIOFormatRuntimeRoute(value: unknown, expected: IOFormatReceiptFreshnessExpectedIR, query: IOFormatRuntimeRouteQuery): IOFormatFreshRuntimeRouteResult { try { const parsed = validateIOFormatReceiptFreshness(value, expected); const receipt = parsed.bound.receipts.find((candidate) => candidate.format === query.format && candidate.operation === query.operation); if (!receipt || receipt.runtimeStatus !== "AVAILABLE" || receipt.registered !== true || receipt.rnaIdentifier === null || receipt.buildOptionEnabled === false) { return { status: "BLOCKED", code: "IO_FORMAT_UNSUPPORTED", reason: "UNAVAILABLE", format: query.format, operation: query.operation }; } return { status: "READY", format: query.format, operation: query.operation, operator: receipt.operator, receipt, freshness: "VERIFIED" }; } catch (error) { const reason = error instanceof IOFormatReceiptFreshnessError ? error.reason : "RECEIPT_INVALID"; return { status: "BLOCKED", code: "IO_FORMAT_UNSUPPORTED", reason, format: query.format, operation: query.operation }; } }