import { reviewScalarUnitMapSchema } from "./reviewScalarUnitContracts.js"; import { z } from "zod"; import { REVIEW_PREMIUM_ADJUSTMENT_LIMITS, REVIEW_PREMIUM_ADJUSTMENT_CONTRACT_VERSION, ADJUSTED_MODEL_PRIOR_CALIBRATION_CONTRACT_VERSION, isDiagnosticToken, isRealIsoDate, composeReviewPremiumAdjustments, validateReviewPremiumAdjustmentRequest, replayReviewPremiumAdjustment, calibrateBfPriorFromAdjustedModel, validateAdjustedModelPriorCalibrationRequest, replayAdjustedModelPriorCalibration, type ReviewPremiumAdjustmentRequest, type ReviewPremiumAdjustment, type AdjustedModelPriorCalibrationRequest, type AdjustedModelPriorCalibrationResult } from "@actuarial-ts/core"; import { analysisContextSchema, analysisReferenceSchema, analysisSnapshotSchema, assumptionSnapshotSchema, quantitySemanticsSchema, modelExposureAdjustmentsSchema, bfPriorCalibrationRequestSchema } from "./reviewContracts.js"; import { reviewOnLevelRequestSchema } from "./reviewOnLevelContracts.js"; import { retainedModelInputSchema } from "./modelCalibrationContracts.js"; import { parseReviewBoundary } from "./reviewBoundary.js"; const token = z.string().refine(isDiagnosticToken), date = z.string().refine(isRealIsoDate), numeric = z.number().finite(); const clock = z.enum(["calendar-year-fraction", "month-start-years"]); export const reviewPremiumAdjustmentLimitsSchema = z.object({ maximumOrigins: z.number().int().positive().max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumOrigins), maximumAssumptions: z.number().int().positive().max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumAssumptions), maximumInputCharacters: z.number().int().positive().max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumInputCharacters), maximumOutputCharacters: z.number().int().positive().max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumOutputCharacters) }).strict(); export const reviewPremiumTargetMeaningSchema = z.discriminatedUnion("kind", [ z.object({ kind: z.literal("on-level-and-premium-trend"), rateLevelDate: date, economicDefinition: token, economicClock: clock, rateActionTreatment: z.literal("net-of-on-level-rate-action"), economicLevels: z.array(z.object({ origin: token, levelDate: date }).strict()).min(1).max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumOrigins) }).strict(), z.object({ kind: z.literal("on-level-only"), rateLevelDate: date, economicBasis: z.object({ kind: z.literal("original-earned-premium"), definition: token, sourceRevisions: z.array(analysisReferenceSchema), premiumAdjustments: z.array(analysisReferenceSchema), contextAdjustments: z.array(analysisReferenceSchema) }).strict() }).strict(), ]); export function reviewPremiumTrendSchemaForRate(rate: R) { return z.discriminatedUnion("kind", [ z.object({ kind: z.literal("premium-trend"), rate, clock, definition: token, rateActionTreatment: z.literal("net-of-on-level-rate-action"), rows: z.array(z.object({ origin: token, fromLevelDate: date, toLevelDate: date, rationale: token }).strict()).min(1).max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumOrigins) }).strict(), z.object({ kind: z.literal("not-applied"), rationale: token }).strict(), ]); } /** Shape-check the request while retaining every original result field for full core replay. */ export const retainedReviewOnLevelSchema = z.unknown().superRefine((value, context) => { const parsed = z.object({ request: reviewOnLevelRequestSchema }).passthrough().safeParse(value); if (!parsed.success) parsed.error.issues.forEach(issue => context.addIssue(issue)); }); export const reviewPremiumAdjustmentRequestSchema = z.object({ id: token, version: token, onLevel: retainedReviewOnLevelSchema, trend: reviewPremiumTrendSchemaForRate(assumptionSnapshotSchema), order: z.enum(["on-level-then-premium-trend", "on-level-only"]), arithmetic: z.enum(["raw-premium-times-on-level-times-trend-product", "raw-premium-times-on-level-factor"]), application: z.discriminatedUnion("kind", [z.object({ kind: z.literal("standalone") }).strict(), z.object({ kind: z.literal("expected-loss-calibration"), target: reviewPremiumTargetMeaningSchema, rationale: token }).strict(), z.object({ kind: z.literal("expected-loss-prior"), assumption: analysisReferenceSchema, target: reviewPremiumTargetMeaningSchema, rationale: token }).strict()]), policies: z.object({ unavailable: z.enum(["retain-unavailable", "reject"]), unadoptedAssumption: z.enum(["reject", "allow-qualified"]) }).strict(), declaration: z.object({ actorId: token, knownDate: date, rationale: token }).strict(), snapshots: z.array(analysisSnapshotSchema), limits: reviewPremiumAdjustmentLimitsSchema, }).strict(); const finding = z.object({ code: token, path: token, message: token, coordinates: z.record(z.union([z.string(), numeric, z.boolean(), z.null()])).optional(), remedies: z.array(z.string()) }).strict(); const premiumRow = z.object({ origin: token, rawValue: numeric.nullable(), onLevelFactor: numeric.positive().nullable(), fromLevelDate: date.nullable(), toLevelDate: date.nullable(), elapsedYears: numeric.nullable(), annualRate: numeric.nullable(), trendFactor: numeric.positive().nullable(), factor: numeric.positive().nullable(), factorReason: token.nullable(), adjustedValue: numeric.nullable(), reason: token.nullable() }).strict(); /** An output shape is transport validation; current-SDK replay still supplies calculation authority. */ export const reviewPremiumAdjustmentResultSchema = z.object({ contractVersion: z.literal(REVIEW_PREMIUM_ADJUSTMENT_CONTRACT_VERSION), sdkVersion: token, request: reviewPremiumAdjustmentRequestSchema, context: analysisContextSchema, quantity: quantitySemanticsSchema, target: reviewPremiumTargetMeaningSchema, knownDate: date, rows: z.array(premiumRow).max(REVIEW_PREMIUM_ADJUSTMENT_LIMITS.maximumOrigins), evidenceUnits: reviewScalarUnitMapSchema, adjustment: analysisSnapshotSchema, trendDependency: analysisSnapshotSchema.nullable(), modelAdjustments: modelExposureAdjustmentsSchema, snapshots: z.array(analysisSnapshotSchema), findings: z.array(finding), assurance: z.object({ calculation: z.enum(["native-on-level-and-trend-composition", "native-on-level-only"]), arithmetic: z.enum(["raw-premium-times-on-level-times-trend-product", "raw-premium-times-on-level-factor"]), rate: z.enum(["replayed-trend-calibration", "declared-assumption", "not-applied"]), targetMeaning: z.literal("caller-declared-and-exactly-bound"), sourceAuthenticity: z.literal("not-verified"), uncertainty: z.literal("not-propagated") }).strict(), reference: analysisReferenceSchema }).strict(); /** Internal typed graph builder, with no arbitrary paths or writable prepared exposure input. */ export function adjustedModelPriorCalibrationSchemaForInputs(run: R, adjustment: A) { return z.object({ id: token, version: token, run, adjustment, target: reviewPremiumTargetMeaningSchema, snapshots: z.array(analysisSnapshotSchema), selection: bfPriorCalibrationRequestSchema.shape.selection, sourceRelationship: bfPriorCalibrationRequestSchema.shape.sourceRelationship, assumption: bfPriorCalibrationRequestSchema.shape.assumption, limits: reviewPremiumAdjustmentLimitsSchema }).strict(); } export const adjustedModelPriorCalibrationRequestSchema = adjustedModelPriorCalibrationSchemaForInputs(retainedModelInputSchema, reviewPremiumAdjustmentResultSchema); const modelCoordinate = z.discriminatedUnion("status", [z.object({ origin: token, ageMonths: numeric.nonnegative().nullable(), valuationDate: date, status: z.literal("available"), value: numeric, reason: z.null() }).strict(), z.object({ origin: token, ageMonths: numeric.nonnegative().nullable(), valuationDate: date, status: z.literal("unavailable"), value: z.null(), reason: token }).strict()]); const coordinate = z.object({ origin: token, modelCoordinate, ultimate: numeric.nullable(), developedProportion: numeric.nonnegative().nullable(), maturityEvidence: z.enum(["native-developed-proportion", "native-growth-at-age", "effective-cdf", "unavailable"]), reason: token.nullable() }).strict(); const nativeCalibration = z.object({ contractVersion: z.literal("actuarial-bf-prior-calibration/1"), sdkVersion: token, request: bfPriorCalibrationRequestSchema, status: z.enum(["available", "unavailable"]), rate: numeric.nullable(), rateQuantity: quantitySemanticsSchema, contributors: z.array(z.object({ origin: token, ultimate: numeric, exposure: numeric.positive() }).strict()), exclusions: z.array(z.object({ origin: token, reason: token }).strict()), fallbackUsed: z.boolean(), findings: z.array(finding), reference: analysisReferenceSchema }).strict(); export const adjustedModelPriorCalibrationResultSchema = z.object({ calibration: z.object({ contractVersion: z.literal(ADJUSTED_MODEL_PRIOR_CALIBRATION_CONTRACT_VERSION), sdkVersion: token, request: adjustedModelPriorCalibrationRequestSchema, target: reviewPremiumTargetMeaningSchema, evidenceUnits: reviewScalarUnitMapSchema, coordinates: z.array(coordinate), denominatorCoordinates: z.array(z.object({ origin: token, rawPremiumRowIndex: z.number().int().nonnegative().nullable(), adjustmentRowIndex: z.number().int().nonnegative(), rawValue: numeric.nullable(), factor: numeric.positive().nullable(), value: numeric.nullable(), reason: token.nullable() }).strict()), result: nativeCalibration, findings: z.array(finding), assurance: z.object({ model: z.literal("replayed-current-sdk"), coordinates: z.literal("native-model"), denominator: z.literal("replayed-original-premium-and-native-composite"), targetMeaning: z.literal("caller-declared-and-exactly-bound"), sourceRelationship: z.literal("caller-declared"), independence: z.literal("not-established"), sourceAuthenticity: z.literal("not-verified"), uncertainty: z.literal("not-propagated") }).strict(), reference: analysisReferenceSchema }).strict(), assumption: assumptionSnapshotSchema.nullable(), snapshots: z.array(analysisSnapshotSchema) }).strict(); export function parseReviewPremiumAdjustmentRequest(input: unknown): ReviewPremiumAdjustmentRequest { return validateReviewPremiumAdjustmentRequest(parseReviewBoundary(reviewPremiumAdjustmentRequestSchema, input) as ReviewPremiumAdjustmentRequest).request; } export function composeReviewPremiumAdjustmentsFromInput(input: unknown): ReviewPremiumAdjustment { return composeReviewPremiumAdjustments(parseReviewPremiumAdjustmentRequest(input)); } export function replayReviewPremiumAdjustmentFromInput(input: unknown): ReviewPremiumAdjustment { return replayReviewPremiumAdjustment(parseReviewBoundary(reviewPremiumAdjustmentResultSchema, input) as ReviewPremiumAdjustment); } export function parseAdjustedModelPriorCalibrationRequest(input: unknown): AdjustedModelPriorCalibrationRequest { return validateAdjustedModelPriorCalibrationRequest(parseReviewBoundary(adjustedModelPriorCalibrationRequestSchema, input) as AdjustedModelPriorCalibrationRequest).request; } export function calibrateBfPriorFromAdjustedModelInput(input: unknown): AdjustedModelPriorCalibrationResult { return calibrateBfPriorFromAdjustedModel(parseAdjustedModelPriorCalibrationRequest(input)); } export function replayAdjustedModelPriorCalibrationFromInput(input: unknown): AdjustedModelPriorCalibrationResult { return replayAdjustedModelPriorCalibration(parseReviewBoundary(adjustedModelPriorCalibrationResultSchema, input) as AdjustedModelPriorCalibrationResult); }