import { createHash } from "node:crypto"; import canonicalize from "canonicalize"; import { z } from "zod"; const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u); const stableIdSchema = z.string().regex(/^[A-Za-z][A-Za-z0-9._:/-]{0,199}$/u); const runtimeIdentitySchema = z.strictObject({ family: z.string().trim().min(1).max(100), provider_id: stableIdSchema, executable_path: z.string().min(1).max(4_096), executable_sha256: digestSchema, version: z.string().trim().min(1).max(500), profile_sha256: digestSchema, }); const artifactIdentitySchema = z.strictObject({ path: z.string().min(1).max(4_096), sha256: digestSchema, byte_length: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER), }); const callableIdentitySchema = z.strictObject({ callable_id: stableIdSchema, module_id: stableIdSchema, export_name: z.string().min(1).max(1_000), semantic_evidence_id: z .string() .regex(/^ev_[a-f0-9]{64}$/u) .nullable(), selector_sha256: digestSchema, }); export const runtimeCharacterizationPlanSchema = z.strictObject({ schema_version: z.literal(1), plan_sha256: digestSchema, preparation_sha256: digestSchema, artifact: artifactIdentitySchema, runtime: runtimeIdentitySchema, callable: callableIdentitySchema, working_directory: z.string().min(1).max(4_096), isolated_home: z.string().min(1).max(4_096), expected_effect: z.enum(["pure", "bounded-effects", "observation-only"]), allowed_boundaries: z.array(stableIdSchema).max(1_000), limits: z.strictObject({ max_calls: z.number().int().min(1).max(10_000), max_processes: z.number().int().min(0).max(1_000), max_files: z.number().int().min(0).max(100_000), max_bytes: z.number().int().min(1).max(Number.MAX_SAFE_INTEGER), max_handles: z.number().int().min(0).max(100_000), timeout_ms: z.number().int().min(1).max(300_000), idle_timeout_ms: z.number().int().min(1).max(300_000), }), determinism: z.strictObject({ clock: z.enum(["fixed", "real"]), randomness: z.enum(["seeded", "system"]), identifiers: z.enum(["deterministic", "runtime"]), seed: z.number().int().min(0).max(0xffff_ffff), }), authority: z.strictObject({ preparation_approved: z.literal(true), execution_approved: z.literal(false), network: z.enum(["none", "loopback"]), provider_owned_process_only: z.literal(true), }), }); export type RuntimeCharacterizationPlan = z.infer< typeof runtimeCharacterizationPlanSchema >; /** Commit a provider-neutral preparation plan; execution requires a later approval. */ export const createRuntimeCharacterizationPlan = ( input: Omit, "plan_sha256">, ): RuntimeCharacterizationPlan => { const parsed = runtimeCharacterizationPlanSchema .omit({ plan_sha256: true }) .parse(input); return runtimeCharacterizationPlanSchema.parse({ ...parsed, plan_sha256: digest(parsed), }); }; /** Parse a characterization plan and reject altered commitments. */ export const parseRuntimeCharacterizationPlan = ( input: unknown, ): RuntimeCharacterizationPlan => { const parsed = runtimeCharacterizationPlanSchema.parse(input); const { plan_sha256: planSha256, ...semantic } = parsed; if (planSha256 !== digest(semantic)) throw new TypeError("Runtime characterization plan digest is invalid"); return parsed; }; const digest = (value: unknown): string => { const encoded = canonicalize(value); if (encoded === undefined) throw new TypeError("Runtime characterization plan is not canonical JSON"); return createHash("sha256").update(encoded).digest("hex"); };