From 8fd800e69af8d921134c9c76cc329a28025d190a Mon Sep 17 00:00:00 2001 From: "Timothy J. Aveni" Date: Sun, 20 Sep 2026 01:05:02 -0700 Subject: [PATCH] Execute checked capability bindings through scoped package runners --- src/execution-world/index.ts | 2 + src/execution-world/kernel.ts | 201 ++++++++++++++++++++++++++++++++++ test/emit-portable-reader.ts | 2 + 3 files changed, 205 insertions(+) create mode 100644 src/execution-world/kernel.ts diff --git a/src/execution-world/index.ts b/src/execution-world/index.ts index 335c596..c924f5b 100644 --- a/src/execution-world/index.ts +++ b/src/execution-world/index.ts @@ -6,3 +6,5 @@ export * from "./files.js"; export * from "./receipts.js"; export { generatePortableTypeScriptBindings } from "../bindings/portable.js"; + +export * from "./kernel.js"; diff --git a/src/execution-world/kernel.ts b/src/execution-world/kernel.ts new file mode 100644 index 0000000..00dcdd0 --- /dev/null +++ b/src/execution-world/kernel.ts @@ -0,0 +1,201 @@ +import type { + ValueType, + InitializationField, + PersistentAttachment, + DependencyBinding, +} from "../capability-model/types.js"; +import { type ExecutionPlan, ExecutionPlanError, hexDigest } from "./plan.js"; +import { portableValueSchema } from "../bindings/portable.js"; +/** 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) + throw new ExecutionPlanError("INVALID_PLAN", "kernel", "Plan digest mismatch"); + const workspace = plan.definition.workspace; + if (workspace.sharedAttachments.length) + throw new ExecutionPlanError( + "UNSUPPORTED_SHARED_STORAGE", + "kernel", + "Stage 0 requires explicit conformance-owned storage", + ); + const schema = (type: ValueType): unknown | null => { + try { + return portableValueSchema(type); + } catch { + return null; + } + }; + const ownerBySlot = new Map(); + const edges: unknown[] = []; + const owners = plan.definition.owners.map((owner) => { + const slots: unknown[] = []; + for (const storage of owner.storage as PersistentAttachment[]) { + if (storage.kind === "state") { + const shape = schema(storage.valueType); + if (!shape) + throw new ExecutionPlanError("UNSUPPORTED_STORAGE_CODEC", storage.id, "Unsupported canonical value type"); + ownerBySlot.set(storage.id, owner.id); + slots.push({ + id: storage.id, + schema: shape, + policy: storage.storagePolicy.kind === "register" ? "register" : "crdt", + ...(Object.hasOwn(storage, "defaultValue") ? { defaultLiteral: storage.defaultValue } : {}), + }); + } else { + const endpoints = storage.endpoints.map((endpoint) => { + if ( + endpoint.ordered || + endpoint.keyType || + endpoint.retainOther || + (endpoint.onDelete && endpoint.onDelete !== "restrict") + ) + throw new ExecutionPlanError( + "UNSUPPORTED_GRAPH_FEATURE", + storage.id, + "Ordered/keyed/deletion policies require LF-18", + ); + return { + projection: endpoint.projectionId, + constraint: { + kind: endpoint.constraint.kind, + id: + endpoint.constraint.kind === "atom" + ? endpoint.constraint.atomId + : endpoint.constraint.interfaceRevisionId, + }, + cardinality: endpoint.cardinality, + }; + }); + edges.push({ id: storage.id, owner: owner.id, a: endpoints[0], b: endpoints[1] }); + } + } + return { + id: owner.id, + atom: owner.atom, + interface: owner.interface, + slots, + initialize: (owner.initialization as InitializationField[]).map((field) => ({ + input: field.input, + binding: + field.binding.kind === "state" + ? { kind: "state", slot: field.binding.slotId } + : { kind: "edge", edge: field.binding.edgeTypeId, projection: field.binding.projectionId }, + })), + }; + }); + const slotOwner = (slot: string) => { + const owner = ownerBySlot.get(slot); + if (!owner) throw new ExecutionPlanError("MISSING_STORAGE_OWNER", slot, "No checked owner"); + return owner; + }; + const via = (binding: DependencyBinding) => + "via" in binding && binding.via + ? { via: { edge: binding.via.edgeTypeId, projection: binding.via.projectionId } } + : {}; + const operations = plan.definition.operations.map((operation) => { + const binding = operation.binding; + let target: unknown; + let unsupported: string | null = null; + if (binding.kind === "state") + target = { kind: "state", owner: slotOwner(binding.slotId), slot: binding.slotId, primitive: binding.primitive }; + else if (binding.kind === "edge") + target = { + kind: "edge", + edge: binding.edgeTypeId, + projection: binding.projectionId, + primitive: binding.primitive, + }; + else { + const pkg = workspace.packageImports.find((p) => p.revisionId === binding.packageRevisionId)!; + const entry = pkg.exports.find((e) => e.id === binding.exportId)!; + const ports = binding.dependencies.map((dependency) => { + const requirement = entry.dependencyPorts.find((p) => p.id === dependency.portId)!.requirement; + const bound = dependency.binding; + const common = { id: dependency.portId, ...via(bound) }; + if (bound.kind === "state" && requirement.kind === "state") + return { + ...common, + kind: "state", + owner: slotOwner(bound.slotId), + slot: bound.slotId, + primitives: requirement.primitives, + }; + if (bound.kind === "edge" && requirement.kind === "edge") + return { + ...common, + kind: "edge", + edge: bound.edgeTypeId, + projection: bound.projectionId, + primitives: requirement.primitives, + }; + if (bound.kind === "interface" && requirement.kind === "interface") { + const iface = workspace.interfaceImports.find((i) => i.revisionId === bound.interfaceRevisionId)!; + return { + ...common, + kind: "interface", + interface: bound.interfaceRevisionId, + operations: requirement.operations ?? iface.members.flatMap((m) => m.operations.map((o) => o.id)), + }; + } + if (bound.kind === "creation" && requirement.kind === "creation") + return { + ...common, + kind: "creation", + atom: bound.atomId, + schema: portableValueSchema(requirement.inputType), + recipe: hexDigest({ plan: plan.digest, operation: operation.key, port: dependency.portId }), + owners: bound.owners.map((seed) => { + const owner = owners.find((o) => o.atom === bound.atomId && o.interface === seed.interfaceRevisionId); + if (!owner) + throw new ExecutionPlanError( + "MISSING_STORAGE_OWNER", + dependency.portId, + "Creation has no initialization owner", + ); + return { owner: owner.id, inputPath: seed.inputPath }; + }), + }; + unsupported = `UNSUPPORTED_EXECUTION_PORT:${bound.kind}`; + return { ...common, kind: "unavailable" }; + }); + target = { kind: "package", package: binding.packageRevisionId, export: binding.exportId, ports }; + } + const input = schema(operation.input), + output = schema(operation.output); + return { + key: operation.key, + atom: operation.atomId, + interface: operation.interfaceRevisionId, + operation: operation.operationId, + scope: operation.scope, + effect: operation.execution.kind, + targets: operation.execution.kind === "remote" ? [] : operation.execution.targets, + input, + output, + unsupported: unsupported ?? (input && output ? null : "UNSUPPORTED_OPERATION_CODEC"), + binding: target, + }; + }); + const packages = workspace.packageImports.map((pkg) => ({ + revision: pkg.revisionId, + exports: pkg.exports.map((entry) => ({ + id: entry.id, + effect: entry.execution?.kind ?? "remote", + targets: entry.execution && entry.execution.kind !== "remote" ? entry.execution.targets : [], + receiver: + entry.kind === "function" + ? null + : entry.kind === "operation" && entry.receiverRequirement.kind === "exact-atom" + ? { kind: "atom", id: entry.receiverRequirement.atomId } + : "object", + input: schema(entry.inputType), + output: schema(entry.outputType), + })), + })); + return { + codec: "camino-kernel-program-v1", + plan: plan.digest, + model: { workspace: workspace.workspaceId, atoms: workspace.atoms.map((atom) => atom.id), owners, edges }, + operations, + packages, + }; +} diff --git a/test/emit-portable-reader.ts b/test/emit-portable-reader.ts index cd08753..33ffbab 100644 --- a/test/emit-portable-reader.ts +++ b/test/emit-portable-reader.ts @@ -1,6 +1,7 @@ /** Qualification artifact emitted after tests, never a production fixture dependency. */ import { mkdir, writeFile } from "node:fs/promises"; import { loadReaderWorkspace } from "./reader-fixture.js"; +import { compileKernelProgram } from "../src/execution-world/kernel.js"; import { compileExecutionPlan } from "../src/execution-world/plan.js"; import { generatePortableTypeScriptBindings } from "../src/bindings/portable.js"; const plan = compileExecutionPlan(await loadReaderWorkspace()); @@ -11,6 +12,7 @@ for (const target of ["browser", "server"]) generatePortableTypeScriptBindings(plan.definition.bindingSchema, "package:reader-runtime@1", { target }), ); await writeFile("dist/portable-reader/plan.json", JSON.stringify(plan)); +await writeFile("dist/portable-reader/kernel.json", JSON.stringify(compileKernelProgram(plan))); const serviceWorkspace = structuredClone(plan.definition.workspace); serviceWorkspace.atoms = []; serviceWorkspace.conformances = [];