import { z } from "zod"; import { decodeReviewEvidence, snapshotDiagnosticJson, snapshotReviewEvidenceGraphV2, REVIEW_EVIDENCE_GRAPH_CONTRACT_VERSION, REVIEW_EVIDENCE_GRAPH_CONTRACT_VERSION_V2, REVIEW_EVIDENCE_GRAPH_LIMITS, REVIEW_EVIDENCE_GRAPH_V2_EXPANSION_CEILING, type ReviewEvidenceTransport } from "@actuarial-ts/core"; import { parseReviewBoundary } from "./reviewBoundary.js"; const scalar = z.union([z.null(), z.boolean(), z.number().finite(), z.string()]); const atomV1 = z.union([z.tuple([z.literal("scalar"), scalar]), z.tuple([z.literal("vertex"), z.number().int().nonnegative()])]); const atomV2 = z.union([scalar, z.tuple([z.literal("vertex"), z.number().int().nonnegative()]), z.tuple([z.literal("prefix-array"), z.number().int().nonnegative(), z.number().int().positive()]).rest(scalar)]); const limits = z.object({ maximumVertices: z.literal(100_000), maximumEdges: z.literal(500_000), maximumEncodedCharacters: z.literal(120_000_000), maximumExpandedCharacters: z.literal(120_000_000), maximumExpandedOccurrences: z.literal(10_000_000), maximumDepth: z.literal(256) }).strict(); const v1 = z.object({ contractVersion: z.literal(REVIEW_EVIDENCE_GRAPH_CONTRACT_VERSION), root: atomV1, vertices: z.array(z.union([z.tuple([z.literal("array"), z.array(atomV1)]), z.tuple([z.literal("object"), z.array(z.tuple([z.string(), atomV1]))])])).max(REVIEW_EVIDENCE_GRAPH_LIMITS.maximumVertices), limits }).strict(); const v2Limits = limits.extend({ maximumExpandedCharacters: z.number().int().positive().max(REVIEW_EVIDENCE_GRAPH_V2_EXPANSION_CEILING.maximumExpandedCharacters), maximumExpandedOccurrences: z.number().int().positive().max(REVIEW_EVIDENCE_GRAPH_V2_EXPANSION_CEILING.maximumExpandedOccurrences) }).strict(); const v2 = z.object({ contractVersion: z.literal(REVIEW_EVIDENCE_GRAPH_CONTRACT_VERSION_V2), root: atomV2, vertices: z.array(z.union([z.tuple([z.literal("scalar-prefix"), z.number().int().nonnegative(), z.number().int().positive(), z.array(scalar)]), z.tuple([z.literal("array"), z.array(atomV2)]), z.tuple([z.literal("object"), z.array(z.tuple([z.string(), atomV2]))]), z.tuple([z.literal("records"), z.array(z.string()).min(1), z.array(z.array(atomV2))]), z.tuple([z.literal("path-records"), z.array(z.string()).min(1), z.number().int().nonnegative(), z.array(z.tuple([z.number().int().nonnegative()]).rest(scalar)).min(2), z.array(z.array(scalar))])])).max(REVIEW_EVIDENCE_GRAPH_LIMITS.maximumVertices), limits: v2Limits }).strict(); export const reviewEvidenceGraphSchema: z.ZodType = z.union([v1, v2]); /** Strict versioned transport; decoded ownership never issues calculation/source authority. */ export function parseReviewEvidenceGraph(input: unknown): ReviewEvidenceTransport { const version = input !== null && typeof input === "object" ? Object.getOwnPropertyDescriptor(input, "contractVersion") : undefined; if (version?.enumerable && "value" in version && version.value === REVIEW_EVIDENCE_GRAPH_CONTRACT_VERSION_V2) return snapshotReviewEvidenceGraphV2(input); // The descriptor-safe versioned decoder runs before Zod can read a hidden discriminator. decodeReviewEvidence(input); const graph = parseReviewBoundary(reviewEvidenceGraphSchema, input); return snapshotDiagnosticJson(graph); }