import { z } from "zod"; import { HISTORICAL_INFORMATION_LIMITS, HISTORICAL_INPUT_ROLES, isDiagnosticToken, isRealIsoDate, resolveHistoricalInformationSet, validateHistoricalInformationSetRequest, type HistoricalInformationSet, type HistoricalInformationSetRequest } from "@actuarial-ts/core"; import { analysisReferenceSchema, analysisSnapshotSchema } from "./reviewContracts.js"; import { parseReviewBoundary } from "./reviewBoundary.js"; const token = z.string().refine(isDiagnosticToken); const bounded = (maximum: number) => z.number().int().positive().max(maximum); /** Core validates exact timestamps, content identities, selection ambiguity and dependency consistency. */ export const historicalInformationSetRequestSchema = z.object({ id: token, version: token, valuationCutoff: z.string().refine(isRealIsoDate), knowledgeCutoff: token, requirements: z.array(z.object({ slot: token, role: z.enum(HISTORICAL_INPUT_ROLES), selection: z.discriminatedUnion("kind", [ z.object({ kind: z.literal("latest-eligible") }).strict(), z.object({ kind: z.literal("fixed"), reference: analysisReferenceSchema }).strict(), ]) }).strict()).min(1).max(HISTORICAL_INFORMATION_LIMITS.maximumSlots), revisions: z.array(z.object({ slot: token, ordinal: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER), snapshot: analysisSnapshotSchema, availability: z.discriminatedUnion("kind", [ z.object({ kind: z.literal("known"), at: token, evidence: z.array(analysisSnapshotSchema).min(1), rationale: token }).strict(), z.object({ kind: z.literal("unknown"), rationale: token }).strict(), ]), dependencies: z.array(z.object({ slot: token, reference: analysisReferenceSchema }).strict()).max(HISTORICAL_INFORMATION_LIMITS.maximumDependencies), }).strict()).max(HISTORICAL_INFORMATION_LIMITS.maximumRevisions), unknownAvailability: z.discriminatedUnion("kind", [z.object({ kind: z.literal("require-known") }).strict(), z.object({ kind: z.literal("allow-retrospective"), rationale: token }).strict()]), limits: z.object({ maximumSlots: bounded(HISTORICAL_INFORMATION_LIMITS.maximumSlots), maximumRevisions: bounded(HISTORICAL_INFORMATION_LIMITS.maximumRevisions), maximumDependencies: bounded(HISTORICAL_INFORMATION_LIMITS.maximumDependencies), maximumInputCharacters: bounded(HISTORICAL_INFORMATION_LIMITS.maximumInputCharacters) }).strict(), }).strict(); export function resolveHistoricalInformationSetFromInput(input: unknown): HistoricalInformationSet { return resolveHistoricalInformationSet(parseHistoricalInformationSetRequest(input)); } export function parseHistoricalInformationSetRequest(input: unknown): HistoricalInformationSetRequest { return validateHistoricalInformationSetRequest(parseReviewBoundary(historicalInformationSetRequestSchema, input)); }