// Native JSON decoding and resource admission; row-wise validation bounds errors. import { z } from "zod"; import { FactFailure } from "./fact-error.mjs"; import { NATIVE_OUTPUT_BYTES } from "./limits.mjs"; import { readCallFacet } from "./native-call-contract.mjs"; import { hex, ordinal, valueId, operationId, value, rowParser, requireFact, formatFailure, readNativeFacet, } from "./native-contract.mjs"; const edgeId = z.string().regex(/^\d+:\d+$/u); const edge = z.strictObject({ id: edgeId, target: ordinal, index: ordinal, polarity: z.enum(["true", "false"]).nullable(), condition_value: valueId.nullable(), condition_test: z.enum(["eq-zero", "ne-zero"]).nullable(), }); const operation = z.strictObject({ id: operationId, address: hex, block: ordinal, opcode: z.string(), statement: z.string(), is_dead: z.boolean(), inputs: z.array( z.strictObject({ input_index: ordinal, value_id: valueId.nullable(), phi_predecessor: ordinal.nullable(), phi_predecessor_edge: edgeId.nullable(), }), ), output: valueId.nullable(), }); const factsSchema = z.strictObject({ schema_version: z.literal(3), blocks: z .array( z.strictObject({ id: ordinal, start: hex, operations: z.array(operationId), predecessors: z.array(ordinal), successors: z.array(edge), }), ) .min(1) .max(12000), operations: z.array(operation).max(12000), values: z.array(value).max(36000), coverage: z.strictObject({ scope: z.string(), machine_semantic_equivalence: z.literal("unknown"), indirect_branch_operations: z.array(operationId), omitted_definition_ids: z.array(operationId), issues: z.array(z.string()), }), }); const documentSchema = z.object({ binary: z.string(), count: z.literal(1), language: z.string(), error: z.null(), functions: z .array( z.object({ address_hex: hex, code: z.string(), error: z.null(), atomic_facts: z.unknown().optional(), atomic_facts_error: z.string().optional(), atomic_calls: z.unknown().optional(), atomic_calls_error: z.string().optional(), }), ) .length(1), }); // Parse one row at a time: a bad provider must not expand thousands of malformed // records into a giant Zod issue list before the caller can reject the source. const nativeBlock = factsSchema.shape.blocks.element; const parseBlock = rowParser(nativeBlock, { operations: (id) => operationId.parse(id), predecessors: (id) => ordinal.parse(id), successors: (row) => edge.parse(row), }); const parseOperation = rowParser(operation, { inputs: (row) => operation.shape.inputs.element.parse(row), }); const parseFacts = rowParser(factsSchema, { blocks: parseBlock, operations: parseOperation, values: (row) => value.parse(row), }); function preflight(facts) { requireFact( facts && typeof facts === "object", "Native atomic facts facet is unavailable; inspect the retained source for its reason and C", ); requireFact( facts.schema_version === 3, "Unsupported native atomic facts schema version; expected 3", ); requireFact( facts.blocks?.length > 0, "Native recovered graph is unavailable", ); for (const [key, limit] of [ ["blocks", 12000], ["operations", 12000], ["values", 36000], ]) requireFact( Array.isArray(facts[key]) && facts[key].length <= limit, `Native ${key} exceeds resource capacity or has invalid shape`, ); const inputs = facts.operations.reduce( (sum, op) => sum + (Array.isArray(op?.inputs) ? op.inputs.length : 0), 0, ); const members = facts.blocks.reduce( (sum, block) => sum + (Array.isArray(block?.operations) ? block.operations.length : 0), 0, ); const edges = facts.blocks.reduce( (sum, block) => sum + (Array.isArray(block?.successors) ? block.successors.length : 0) + (Array.isArray(block?.predecessors) ? block.predecessors.length : 0), 0, ); requireFact( inputs <= 50000 && members <= 12000 && edges <= 100000, "Native relationships exceed resource capacity", ); } const readGraph = (fn) => readNativeFacet(fn, "atomic_facts", "recovered IR", (raw) => { preflight(raw); return parseFacts(raw); }); export function parseNativeFunction(text, entry, expectedInput) { try { requireFact( Buffer.byteLength(text) <= NATIVE_OUTPUT_BYTES, "Native JSON source exceeds transport budget", ); const raw = JSON.parse(text); requireFact( Array.isArray(raw?.functions) && raw.functions.length === 1, "Native source must describe exactly one function", ); const doc = documentSchema.parse(raw), fn = doc.functions[0]; if (expectedInput !== undefined && doc.binary !== expectedInput) throw new FactFailure( "subject_mismatch", "Native source names a different command input", { expected: expectedInput, observed: doc.binary }, ); if (fn.address_hex !== entry) throw new FactFailure( "subject_mismatch", "Native function entry differs from requested subject", ); return { code: fn.code, language: doc.language, facts: readGraph(fn), calls: readCallFacet(fn), }; } catch (error) { throw formatFailure(error); } }