Reuse verified immutable plans and streamline cooperative hashing

Continue final hosted development reliability qualification.
This commit is contained in:
Timothy J. Aveni
2026-10-12 20:16:56 -07:00
parent 47b316180d
commit 62a09605cf
15 changed files with 214 additions and 57 deletions
+68 -31
View File
@@ -26,43 +26,80 @@ export const contentDigest = (value: unknown) =>
* event loop while verifying large immutable metadata. No validation is skipped.
* This is for asynchronous loading, not a different build/wire identity. */
export async function contentDigestAsync(value: unknown): Promise<string> {
function* parts(value: unknown): Generator<string> {
if (Array.isArray(value)) {
yield "[";
for (let index = 0; index < value.length; index++) {
if (index) yield ",";
// Match canonicalJson's Array.map behavior for sparse arrays too.
if (index in value) yield* parts(value[index]);
}
yield "]";
} else if (value !== null && typeof value === "object") {
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
throw new Error("Expected a plain JSON object");
yield "{";
let first = true;
for (const key of Object.keys(value).sort(compareText)) {
const entry = (value as Record<string, unknown>)[key];
if (entry === undefined) continue;
if (!first) yield ",";
first = false;
yield JSON.stringify(key) + ":";
yield* parts(entry);
}
yield "}";
} else yield canonicalJson(value);
}
const hash = createHash("sha256");
// An explicit stack visits each node once; recursive generator delegation
// otherwise forwards every token through every ancestor of a deep plan.
type Frame = { kind: "value" | "array" | "object"; value: unknown; index?: number; keys?: string[]; wrote?: boolean };
const hash = createHash("sha256"),
stack: Frame[] = [{ kind: "value", value }],
active = new WeakSet<object>();
let buffer = "",
sliceStarted = performance.now();
for (const part of parts(value)) {
sliceStarted = performance.now(),
steps = 0;
const append = (part: string) => {
buffer += part;
if (buffer.length >= 65536) {
hash.update(buffer);
buffer = "";
if (performance.now() - sliceStarted >= 8) {
await setImmediate();
sliceStarted = performance.now();
}
};
while (stack.length) {
const frame = stack[stack.length - 1]!;
if (frame.kind === "value") {
const value = frame.value;
if (value !== null && typeof value === "object") {
if (active.has(value)) throw new Error("Cannot hash cyclic JSON values");
active.add(value);
frame.index = 0;
if (Array.isArray(value)) {
frame.kind = "array";
append("[");
} else {
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
throw new Error("Expected a plain JSON object");
frame.kind = "object";
frame.keys = Object.keys(value).sort(compareText);
frame.wrote = false;
append("{");
}
} else {
append(canonicalJson(value));
stack.pop();
}
} else if (frame.kind === "array") {
const array = frame.value as unknown[];
if (frame.index === array.length) {
append("]");
active.delete(array);
stack.pop();
} else {
const index = frame.index!;
frame.index = index + 1;
if (index) append(",");
// Match canonicalJson's Array.map behavior for sparse arrays too.
if (index in array) stack.push({ kind: "value", value: array[index] });
}
} else {
const object = frame.value as Record<string, unknown>;
if (frame.index === frame.keys!.length) {
append("}");
active.delete(object);
stack.pop();
} else {
const index = frame.index!;
frame.index = index + 1;
const key = frame.keys![index]!,
entry = object[key];
if (entry !== undefined) {
if (frame.wrote) append(",");
frame.wrote = true;
append(JSON.stringify(key) + ":");
stack.push({ kind: "value", value: entry });
}
}
}
if (++steps % 512 === 0 && performance.now() - sliceStarted >= 8) {
await setImmediate();
sliceStarted = performance.now();
}
}
hash.update(buffer);
+4 -4
View File
@@ -1,13 +1,13 @@
import { createHash } from "node:crypto";
import { canonicalJson } from "../capability-model/evolution.js";
import {
executionPlanDigestAsync,
type ExecutionPlan,
type PlanPackage,
ExecutionPlanError,
hexDigest,
hexDigestAsync,
executionVersions,
} from "./plan.js";
import { createHash } from "node:crypto";
import { canonicalJson } from "../capability-model/evolution.js";
export interface ArtifactFile {
path: string;
@@ -366,7 +366,7 @@ export async function checkExecutionWorld(
): Promise<CheckedWorld> {
if (canonicalJson(plan.definition.versions) !== canonicalJson(executionVersions))
fail("world", "Unsupported plan codec versions");
if ((await hexDigestAsync(plan.definition)) !== plan.digest) fail("plan", "Plan digest mismatch");
if ((await executionPlanDigestAsync(plan)) !== plan.digest) fail("plan", "Plan digest mismatch");
const manifests = inputs.map(parsePackageArtifacts);
unique(
manifests.map((m) => m.packageRevisionId),
+2 -2
View File
@@ -1,7 +1,7 @@
import { graphExecutionRepresentation } from "./graph-execution.js";
import { lstat } from "node:fs/promises";
import { join } from "node:path";
import { hexDigest, hexDigestAsync, ExecutionPlanError, type ExecutionPlan } from "./plan.js";
import { hexDigest, hexDigestAsync, sealExecutionPlan, ExecutionPlanError, type ExecutionPlan } from "./plan.js";
import {
loadExecutionInstallation,
createClientContractCatalog,
@@ -72,7 +72,7 @@ export async function loadCheckedInstallationCandidate(
const [plan, artifacts, source, entryRequest, kernel, queries] = values;
if (
plan?.definition?.codec !== "camino-execution-plan-v1" ||
(await hexDigestAsync(plan.definition)) !== plan.digest ||
!(await sealExecutionPlan(plan)) ||
workspaceDigest !== (await hexDigestAsync(plan.definition.workspace))
)
throw new ExecutionPlanError(
+4 -3
View File
@@ -1,3 +1,4 @@
import { executionPlanDigest, type ExecutionPlan, resolvePlannedOperation, ExecutionPlanError } from "./plan.js";
import type {
InterfaceRevision,
InterfaceOperation,
@@ -6,7 +7,7 @@ import type {
} from "../capability-model/types.js";
import { canonicalJson } from "../capability-model/evolution.js";
import { portableValueSchema, tsType } from "../bindings/portable.js";
import { type ExecutionPlan, resolvePlannedOperation, hexDigest, ExecutionPlanError } from "./plan.js";
import type { BindingSchema } from "../bindings/index.js";
import type { PackageBuildContract } from "./build-contract.js";
import { preparationArtifact, type ReactPreparationArtifact } from "../react-build/declarations.js";
@@ -55,7 +56,7 @@ export function publicOperationContract(
}
/** Resolve a public contract to internal dispatch. This does not authorize the receiver. */
export function linkInterfaceOperation(plan: ExecutionPlan, atom: string, contract: PublicOperationContract) {
if (hexDigest(plan.definition) !== plan.digest)
if (executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError("INVALID_PLAN", atom, "Invalid execution plan digest");
const iface = plan.definition.workspace.interfaceImports.find((i) => i.revisionId === contract.interface);
const operation = iface?.members.flatMap((m) => m.operations).find((o) => o.id === contract.operation);
@@ -97,7 +98,7 @@ export function publicQueryContract(pkg: PackageRevision, queryId: string): Publ
};
}
export function linkPackageQuery(plan: ExecutionPlan, contract: PublicQueryContract) {
if (hexDigest(plan.definition) !== plan.digest)
if (executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError("INVALID_PLAN", contract.query, "Invalid execution plan digest");
const pkg = plan.definition.workspace.packageImports.find((p) => p.revisionId === contract.package);
if (!pkg || canonicalJson(publicQueryContract(pkg, contract.query)) !== canonicalJson(contract))
+2 -2
View File
@@ -1,3 +1,4 @@
import { executionPlanDigestAsync, type ExecutionPlan, hexDigest, hexDigestAsync, ExecutionPlanError } from "./plan.js";
import { portableReflectionValue } from "./reflection.js";
import type {
BoundDependency,
@@ -6,7 +7,6 @@ import type {
PersistentAttachment,
} from "../capability-model/types.js";
import { type ExecutionInstallation, type ExecutionGroupIdentity } from "./installation.js";
import { type ExecutionPlan, hexDigest, hexDigestAsync, ExecutionPlanError } from "./plan.js";
export interface ExecutionEnvironment {
/** Explicit host placement. Merely including an optional module does not select it. */
@@ -28,7 +28,7 @@ export async function compileExecutionGroups(
installation: ExecutionInstallation,
environments: Readonly<Record<string, ExecutionEnvironment>>,
): Promise<InstalledExecutionGroup[]> {
if (installation.plan !== plan.digest || (await hexDigestAsync(plan.definition)) !== plan.digest)
if (installation.plan !== plan.digest || (await executionPlanDigestAsync(plan)) !== plan.digest)
throw new ExecutionPlanError("GROUP_PLAN_MISMATCH", plan.digest, "Expected one checked installation");
const workspace = plan.definition.workspace;
const packages = new Map(workspace.packageImports.map((p) => [p.revisionId as string, p]));
+3 -2
View File
@@ -1,4 +1,5 @@
import { ExecutionPlanError, hexDigest, type ExecutionPlan } from "./plan.js";
import { executionPlanDigest, ExecutionPlanError, hexDigest, type ExecutionPlan } from "./plan.js";
import type { ExecutionInstallation } from "./installation.js";
/** Execution inputs, not build evidence. Nominal revision IDs remain dispatch
@@ -10,7 +11,7 @@ export function graphExecutionRepresentation(
kernel: unknown,
queries: unknown,
) {
if (installation.plan !== plan.digest || hexDigest(plan.definition) !== plan.digest)
if (installation.plan !== plan.digest || executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError("GRAPH_PLAN_MISMATCH", "graph", "Expected one checked installation");
if (
!kernel ||
+3 -2
View File
@@ -1,9 +1,10 @@
import { executionPlanDigestAsync, ExecutionPlanError, type ExecutionPlan } from "./plan.js";
import { compileInspectionTemplates, type InspectionTemplate, type InspectionKernel } from "./inspection.js";
import path from "node:path";
import { loadCheckedArtifactWorld } from "./receipts.js";
import { contentArtifactUrl, loadArtifactWorld, type LoadedArtifactWorld } from "./files.js";
import { selectArtifactImplementation, type ArtifactImplementation, type ComponentArtifact } from "./artifacts.js";
import { ExecutionPlanError, hexDigestAsync, type ExecutionPlan } from "./plan.js";
import {
publicOperationContract,
publicQueryContract,
@@ -47,7 +48,7 @@ export async function clientContractCatalog(
requestedPackages: readonly string[],
checkedKernel?: InspectionKernel,
): Promise<ClientContractCatalog> {
if (installation.plan !== plan.digest || (await hexDigestAsync(plan.definition)) !== plan.digest)
if (installation.plan !== plan.digest || (await executionPlanDigestAsync(plan)) !== plan.digest)
throw new ExecutionPlanError(
"CATALOG_PLAN_MISMATCH",
plan.digest,
+3 -2
View File
@@ -1,3 +1,4 @@
import { executionPlanDigest, type ExecutionPlan, ExecutionPlanError, hexDigest } from "./plan.js";
import { portableReflectionType, portableReflectionValue } from "./reflection.js";
import type {
ValueType,
@@ -7,7 +8,7 @@ import type {
BoundDependency,
PackageExport,
} from "../capability-model/types.js";
import { type ExecutionPlan, ExecutionPlanError, hexDigest } from "./plan.js";
import { portableValueSchema } from "../bindings/portable.js";
import { subscriptionContract } from "../capability-model/journals.js";
type PreparedStep = string | null | { case: string; id: string };
@@ -25,7 +26,7 @@ function preparedInputPaths(type: ValueType, path: PreparedStep[] = []): Prepare
}
/** Small data-only interpreter input; no compiler, parser, Node module or SQL dependency reaches the browser. */
export function compileKernelProgram(plan: ExecutionPlan): unknown {
if (hexDigest(plan.definition) !== plan.digest)
if (executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError("INVALID_PLAN", "kernel", "Plan digest mismatch");
const workspace = plan.definition.workspace;
if (workspace.sharedAttachments.some((attachment) => attachment.kind !== "edge"))
+3 -2
View File
@@ -1,6 +1,7 @@
import { executionPlanDigest, ExecutionPlanError, hexDigest, type ExecutionPlan } from "./plan.js";
import { parse } from "@babel/parser";
import { builtinModules } from "node:module";
import { ExecutionPlanError, hexDigest, type ExecutionPlan } from "./plan.js";
import type { ExecutionInstallation } from "./installation.js";
import type { ArtifactImplementation, ArtifactReader } from "./artifacts.js";
@@ -212,7 +213,7 @@ export async function reportExecutionPlacement(
installation: ExecutionInstallation,
read: ArtifactReader,
) {
if (installation.plan !== plan.digest || hexDigest(plan.definition) !== plan.digest)
if (installation.plan !== plan.digest || executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError(
"PLACEMENT_PLAN_MISMATCH",
plan.digest,
+49
View File
@@ -17,6 +17,7 @@ import { linkQueries, type LinkedQuery } from "../query/link.js";
import { type BindingSchema } from "../bindings/index.js";
import { unsupportedQueryOperator } from "./query-operators.js";
import { packageBuildContexts } from "./build-contract.js";
import { setImmediate } from "node:timers/promises";
export class ExecutionPlanError extends Error {
constructor(
@@ -31,6 +32,54 @@ export class ExecutionPlanError extends Error {
export const hexDigest = (value: unknown): string => contentDigest(value).slice("sha256:".length);
export const hexDigestAsync = async (value: unknown): Promise<string> =>
(await contentDigestAsync(value)).slice("sha256:".length);
// Checked runtime metadata is owned JSON, not live Graph data. Reuse its proof
// only after every reachable record is immutable. Weak keys retain neither old
// Candidates nor an application cache; unsealed compiler inputs are rehashed.
const sealedPlanDigests = new WeakMap<ExecutionPlan, string>();
export const executionPlanDigest = (plan: ExecutionPlan): string =>
sealedPlanDigests.get(plan) ?? hexDigest(plan.definition);
export const executionPlanDigestAsync = async (plan: ExecutionPlan): Promise<string> =>
sealedPlanDigests.get(plan) ?? (await hexDigestAsync(plan.definition));
/** Transfers owned parsed JSON into immutable runtime metadata. Freeze before
* yielding to hashing so concurrent mutation cannot invalidate the proof. */
export async function sealExecutionPlan(plan: ExecutionPlan): Promise<boolean> {
if (sealedPlanDigests.has(plan)) return true;
if (!Object.hasOwn(plan, "definition") || !Object.hasOwn(plan, "digest")) return false;
const pending: object[] = [plan],
seen = new WeakSet<object>();
let sliceStarted = performance.now(),
count = 0;
while (pending.length) {
const value = pending.pop()!;
if (seen.has(value)) continue;
if (
!Array.isArray(value) &&
Object.getPrototypeOf(value) !== Object.prototype &&
Object.getPrototypeOf(value) !== null
)
throw new ExecutionPlanError("INVALID_PLAN_JSON", "plan", "Expected owned JSON records");
for (const key of Reflect.ownKeys(value)) {
const descriptor = Object.getOwnPropertyDescriptor(value, key)!;
if (typeof key !== "string" || !Object.hasOwn(descriptor, "value"))
throw new ExecutionPlanError(
"INVALID_PLAN_JSON",
"plan",
"Runtime metadata cannot contain accessors or symbols",
);
if (descriptor.value !== null && typeof descriptor.value === "object") pending.push(descriptor.value);
}
Object.freeze(value);
seen.add(value);
if (++count % 1024 === 0 && performance.now() - sliceStarted >= 8) {
await setImmediate();
sliceStarted = performance.now();
}
}
const digest = await hexDigestAsync(plan.definition);
if (digest !== plan.digest) return false;
sealedPlanDigests.set(plan, digest);
return true;
}
const sorted = <T>(values: readonly T[], key: (value: T) => string): T[] =>
[...values].sort((a, b) => (key(a) < key(b) ? -1 : key(a) > key(b) ? 1 : 0));
export const publicOperationKey = (atom: string, iface: string, operation: string): string =>
+3 -2
View File
@@ -1,4 +1,5 @@
import { ExecutionPlanError, hexDigest, type ExecutionPlan, type PlannedQuery } from "./plan.js";
import { executionPlanDigest, ExecutionPlanError, type ExecutionPlan, type PlannedQuery } from "./plan.js";
/** Contracts promised by a direct result. Interface dependencies are explicit; accidental
* overlap among today's implementations does not silently widen an exported interface contract. */
export function resultInterfaces(plan: ExecutionPlan, operationKey: string): string[] {
@@ -23,7 +24,7 @@ export function resultInterfaces(plan: ExecutionPlan, operationKey: string): str
}
/** Compile-time observeResult compatibility. Observation does not grant read or mutation authority. */
export function checkResultProjection(plan: ExecutionPlan, operationKey: string, queryId: string): PlannedQuery {
if (hexDigest(plan.definition) !== plan.digest)
if (executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError("INVALID_PLAN", "projection", "Plan digest mismatch");
const query = plan.definition.queries.find((q) => q.id === queryId);
if (!query) throw new ExecutionPlanError("UNKNOWN_PROJECTION", queryId, "No installed query");
+3 -2
View File
@@ -1,7 +1,8 @@
import { executionPlanDigest, ExecutionPlanError, type ExecutionPlan } from "./plan.js";
import { compileKernelProgram } from "./kernel.js";
import { compileInspectionTemplates } from "./inspection.js";
import { portableValueSchema } from "../bindings/portable.js";
import { ExecutionPlanError, hexDigest, type ExecutionPlan } from "./plan.js";
import type { ValueType } from "../capability-model/types.js";
import { compileQueryComposition } from "../query/composition.js";
import { queryTreeBlueprint } from "./query-trees.js";
@@ -24,7 +25,7 @@ const lowerTypes = (value: unknown): unknown =>
/** Checked query IR and installed getter identities, without GraphQL schemas/parsers or SQL adapters.
* Keep authored selection names only for output paths; field access uses resolved interface/member IDs. */
export function compileQueryProgram(plan: ExecutionPlan): unknown {
if (hexDigest(plan.definition) !== plan.digest)
if (executionPlanDigest(plan) !== plan.digest)
throw new ExecutionPlanError("INVALID_PLAN", "queries", "Plan digest mismatch");
const allQueries = new Map(plan.definition.queries.map(({ id, query }) => [id, query.checked]));
const compositions = plan.definition.workspace.packageImports.flatMap((pkg) =>
+3 -2
View File
@@ -1,8 +1,9 @@
import { executionPlanDigest, hexDigest, type ExecutionPlan, type PlannedQuery } from "./plan.js";
import { compileQuery } from "../query/compile.js";
import { linkQueries } from "../query/link.js";
import { capabilityId } from "../capability-model/types.js";
import { portableValueSchema } from "../bindings/portable.js";
import { hexDigest, type ExecutionPlan, type PlannedQuery } from "./plan.js";
import { compileKernelProgram } from "./kernel.js";
import { queryProgramEntry } from "./queries.js";
import { unsupportedQueryOperator } from "./query-operators.js";
@@ -17,7 +18,7 @@ export interface QueryDocument {
/** Runtime query documents use the same language, nominal contracts, linking
* and interpreter as packaged queries. They introduce no resources or code. */
export async function compilePublicQuery(plan: ExecutionPlan, request: QueryDocument) {
if (hexDigest(plan.definition) !== plan.digest) throw Error("INVALID_PLAN");
if (executionPlanDigest(plan) !== plan.digest) throw Error("INVALID_PLAN");
if (
typeof request.document !== "string" ||
Buffer.byteLength(request.document) > 32768 ||
+13 -1
View File
@@ -55,10 +55,22 @@ test("hashing is canonical and rejects values outside the persisted JSON contrac
test("cooperative hashing preserves canonical identities and services the event loop", async () => {
const sparse = [1, 2, 3];
delete sparse[1];
const values = [null, false, -0, "中\\n\ud800", sparse, { z: 1, a: { omitted: undefined, b: [false, 1e100] } }];
const values: unknown[] = [
null,
false,
-0,
"中\\n\ud800",
sparse,
{ z: 1, a: { omitted: undefined, b: [false, 1e100] } },
];
const shared = { text: "中😀".repeat(22000) };
values.push({ first: shared, second: shared });
for (const value of values) assert.equal(await contentDigestAsync(value), contentDigest(value));
for (const value of [undefined, NaN, Infinity, new Date(), [undefined]])
await assert.rejects(contentDigestAsync(value));
const cyclic: { next?: unknown } = {};
cyclic.next = cyclic;
await assert.rejects(contentDigestAsync(cyclic), /cyclic JSON/);
const large = Array.from({ length: 50000 }, (_, index) => ({ z: "definition".repeat(8), a: index }));
const expected = contentDigest(large);
let serviced = false;
+51
View File
@@ -9,6 +9,9 @@ import {
implementationDigest,
clientContractCatalog,
hexDigest,
executionPlanDigest,
executionPlanDigestAsync,
sealExecutionPlan,
parsePackageArtifacts,
artifactPath,
type PackageArtifacts,
@@ -21,6 +24,54 @@ import { compileKernelProgram } from "../src/execution-world/kernel.js";
import { loadCompositeWorkspace } from "./composite-fixture.js";
import { standardNativeBackends } from "../src/execution-world/native-backends.js";
test("sealed runtime plans reuse verified integrity while mutable copies are rechecked", async () => {
const workspace = await loadReaderWorkspace();
const compiled = compileExecutionPlan(workspace);
const plan: ExecutionPlan = JSON.parse(JSON.stringify(compiled));
assert.equal(await sealExecutionPlan(plan), true);
assert.equal(executionPlanDigest(plan), compiled.digest);
assert.equal(await executionPlanDigestAsync(plan), compiled.digest);
assert.throws(() => {
plan.definition.workspace.sourceRootCommit = "f".repeat(40);
}, TypeError);
assert.throws(() => {
plan.digest = "0".repeat(64);
}, TypeError);
const stringify = JSON.stringify;
JSON.stringify = () => {
throw Error("Repeated serialization of sealed metadata");
};
try {
assert.equal(executionPlanDigest(plan), compiled.digest);
assert.equal(await executionPlanDigestAsync(plan), compiled.digest);
} finally {
JSON.stringify = stringify;
}
const changed: ExecutionPlan = structuredClone(plan);
changed.definition.workspace.sourceRootCommit = "f".repeat(40);
Object.freeze(changed);
assert.notEqual(executionPlanDigest(changed), plan.digest);
assert.notEqual(await executionPlanDigestAsync(changed), plan.digest);
assert.equal(await sealExecutionPlan(changed), false, "shallow freezing is not an integrity proof");
const resigned: ExecutionPlan = structuredClone(plan);
resigned.definition.workspace.sourceRootCommit = "e".repeat(40);
resigned.digest = executionPlanDigest(resigned);
assert.equal(await sealExecutionPlan(resigned), true);
assert.notEqual(executionPlanDigest(resigned), plan.digest);
workspace.sourceRootCommit = "d".repeat(40);
assert.equal(workspace.sourceRootCommit, "d".repeat(40), "sealing owned JSON leaves compiler inputs editable");
});
test("runtime plan sealing rejects accessor-backed metadata", async () => {
const plan: ExecutionPlan = compileExecutionPlan(await loadReaderWorkspace());
assert.equal(await sealExecutionPlan(Object.create(plan)), false, "inherited integrity fields cannot be sealed");
Object.defineProperty(plan.definition, "codec", { get: () => "camino-execution-plan-v1", enumerable: true });
await assert.rejects(sealExecutionPlan(plan), /INVALID_PLAN_JSON/);
});
test("optional targets close over calls into another package", async () => {
const workspace = await loadCompositeWorkspace();
const before = compileExecutionPlan(workspace).definition.operations.find(