import { graphExecutionRepresentation } from "./graph-execution.js"; import { lstat } from "node:fs/promises"; import { join } from "node:path"; import { hexDigest, ExecutionPlanError, type ExecutionPlan } from "./plan.js"; import { loadExecutionInstallation, type PackageInstallationSelection } from "./installation.js"; import { candidateMetadataBudget, readCandidateMetadata, type CandidateMetadataBudget, type CandidateMetadataScope, } from "./metadata.js"; const rootPattern = /^\/nix\/store\/[a-z0-9]{32}-[^/\s]+$/; async function readJson(root: string, file: string, scope: CandidateMetadataScope) { const input = await readCandidateMetadata(join(root, file), scope, 32 * 1024 * 1024); try { return { value: JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(input.bytes)), releaseTree: input.releaseTree, }; } catch (error) { input.releaseTree(); throw error; } finally { input.releaseInput(); } } /** Load the checked Nix output, preserving its original compilation and provenance. * The selected toolchain validates generated code during the build. This loader * checks stored identities and artifact/runtime contracts, never recompiles the * historical candidate with whichever compiler happens to run the host. */ export async function loadCheckedInstallationCandidate( root: string, selections: Readonly> = {}, resources: { budget?: CandidateMetadataBudget; owner?: string } = {}, ) { if (!rootPattern.test(root) || !(await lstat(root)).isDirectory()) throw Error("Candidate must be an immutable Nix output directory"); const scope = (resources.budget ?? candidateMetadataBudget).acquire(resources.owner ?? root); try { // Validate the duplicated source contract by digest, then discard its tree // before allocating the substantially larger checked execution plan. const workspaceDigest = await (async () => { const input = await readJson(root, "candidate.json", scope); try { const { executionContracts: _legacyContracts, ...workspace } = input.value; return hexDigest(workspace); } finally { input.releaseTree(); } })(); // Sequential reads avoid partially rejected Promise.all() work allocating // after the failed candidate's reservation has been released. const values = []; for (const file of [ "execution-plan.json", "execution-artifacts.json", "source.json", "entry.json", "kernel.json", "queries.json", ]) { const parsed = await readJson(root, file, scope); values.push(parsed.value); } const [plan, artifacts, source, entryRequest, kernel, queries] = values; if ( plan?.definition?.codec !== "camino-execution-plan-v1" || hexDigest(plan.definition) !== plan.digest || workspaceDigest !== hexDigest(plan.definition.workspace) ) throw new ExecutionPlanError( "CANDIDATE_PLAN_MISMATCH", root, "Stored plan must match its digest and exact workspace source contract", ); if ( source.kind !== "workspace" || source.commit !== plan.definition.workspace.sourceRootCommit || typeof source.repository !== "string" ) throw new ExecutionPlanError("CANDIDATE_SOURCE_MISMATCH", root, "Expected exact workspace source provenance"); const repository = new URL(source.repository); if ( !["https:", "ssh:"].includes(repository.protocol) || repository.username || repository.password || repository.hash || repository.search ) throw new ExecutionPlanError("CANDIDATE_SOURCE_INVALID", root, "Expected a source URL without credentials"); if ( artifacts.codec !== "camino-checked-execution-v2" || typeof artifacts.generator !== "string" || !/^[0-9a-f]{64}$/.test(artifacts.generator) || !artifacts.roots || typeof artifacts.roots !== "object" || Array.isArray(artifacts.roots) ) throw new ExecutionPlanError("CANDIDATE_ARTIFACTS_INVALID", root, "Expected checked package roots"); for (const entry of Object.values(artifacts.roots)) if (typeof entry !== "string" || !rootPattern.test(entry)) throw new ExecutionPlanError( "CANDIDATE_ARTIFACTS_INVALID", root, "Package artifacts must be immutable Nix roots", ); const installation = await loadExecutionInstallation(plan, artifacts.roots, selections, scope); const entry = compileWorkspaceEntry(plan, entryRequest); for (const [name, program, codec] of [ ["kernel", kernel, "camino-kernel-program-v1"], ["queries", queries, "camino-query-program-v1"], ] as const) if (program?.codec !== codec || program.plan !== kernel.plan || hexDigest(program) !== artifacts.programs?.[name]) throw new ExecutionPlanError( "CANDIDATE_PROGRAM_MISMATCH", name, "Stored interpreter input must match the checked build and plan", ); const expectedGraph = graphExecutionRepresentation(plan, installation, kernel, queries); // The stored graph embeds the same kernel/query programs. Validate it in a // short-lived scope and retain the representation that shares those trees. await (async () => { const input = await readJson(root, "graph-execution.json", scope); try { const digest = hexDigest(input.value); if (digest !== hexDigest(expectedGraph) || artifacts.execution !== digest) throw new ExecutionPlanError( "CANDIDATE_EXECUTION_MISMATCH", root, "Stored graph execution differs from checked inputs", ); } finally { input.releaseTree(); } })(); const provenance = { workspaceRevision: plan.definition.workspace.id as string, source: { repository: source.repository as string, commit: source.commit as string }, generator: artifacts.generator as string, packages: (plan as ExecutionPlan).definition.packages.map((pkg) => ({ revision: pkg.revision, source: pkg.source, })), }; const reference = { root, digest: hexDigest({ plan: plan.digest, world: installation.world, provenance, roots: artifacts.roots, entry, programs: artifacts.programs, }), }; return { reference, workspace: plan.definition.workspace.workspaceId, world: hexDigest(expectedGraph), plan: kernel.plan as string, graphExecution: expectedGraph, provenance, entry, kernel, queries, installation, executionPlan: plan as ExecutionPlan, metadata: { get bytes() { return scope.bytes; }, release: scope.release, }, }; } catch (error) { scope.release(); throw error; } } export function compileWorkspaceEntry(plan: ExecutionPlan, entryRequest: unknown): { operation: string } | null { let entry: { operation: string } | null = null; if (entryRequest !== null) { if ( typeof entryRequest !== "object" || Array.isArray(entryRequest) || Object.keys(entryRequest).sort().join(",") !== "atom,interface,operation" ) throw new ExecutionPlanError( "INVALID_ENTRY_FACTORY", "entry", "Entry declaration must name atom, interface and operation identities", ); const operation = plan.definition.operations.find( (op) => op.atomId === (entryRequest as Record).atom && op.interfaceRevisionId === (entryRequest as Record).interface && op.operationId === (entryRequest as Record).operation, ); if ( !operation || operation.scope !== "class" || operation.execution.kind !== "transaction" || operation.input.kind !== "builtin" || operation.input.name !== "unit" || operation.output.kind !== "object-ref" ) throw new ExecutionPlanError( "INVALID_ENTRY_FACTORY", "entry", "Entry must be a checked unit-input class transaction returning one object reference", ); entry = { operation: operation.key }; } return entry; }