import type { PricingAssignmentUnit } from "./types.js"; /** * Minimal traveler shape `verifyBookingDraft` needs. Mirrors the * wire-format `BookingCreateTravelerInput` from * `@voyant-travel/bookings-react`, defined here to avoid a cyclic * dependency. The verifier doesn't care about most fields — * `firstName` / `email` / etc. — only the role + traveler-category + * primary flag that decide which pricing band each traveler * implicitly maps to. */ export interface VerifiableTraveler { clientTravelerKey?: string | null; isPrimary?: boolean | null; travelerCategory?: "adult" | "child" | "infant" | "senior" | "other" | null; } /** * Submitted itemLine shape `verifyBookingDraft` needs. Mirrors the * wire-format `BookingCreateItemLineInput`. */ export interface VerifiableItemLine { optionUnitId: string; quantity: number; travelerKeys?: string[] | null; travelerIndexes?: number[] | null; } export interface BookingDraftMismatch { /** "qty" — submitted quantity differs from resolver-derived quantity for a unit. */ /** "missing" — resolver derived a unit not present in the submitted lines. */ /** "extra" — submitted line for a unit the resolver wouldn't have produced. */ kind: "qty" | "missing" | "extra"; optionUnitId: string; submittedQuantity: number; resolvedQuantity: number; } export interface VerifyBookingDraftResult { ok: boolean; mismatches: BookingDraftMismatch[]; } /** * Re-derive what `resolveBookingDraft` would have produced from the * submitted wire-format payload and compare against the submitted * itemLines. Used server-side as a sanity check on the client's * draft resolution. Returns `ok: true` when the submitted lines * match the resolver, else lists per-unit mismatches. * * Behavior of this helper is *non-rejecting* — callers decide * whether to log, warn, or fail. The orchestrator currently logs; * a follow-up will flip to rejection once observability confirms * no legitimate clients trip the warning. * * Notes on the reconstruction: * - The wire format doesn't carry split per-traveler assignment * fields (the join-table model encodes them through * `itemLines[].travelerKeys`), so we reconstruct the relevant * pricing or inventory unit by walking item lines and matching * them to traveler keys. Deprecated `travelerIndexes` remain a * fallback for older clients. * - DOB doesn't round-trip on the wire today either; we feed the * resolver the `travelerCategory` as a role hint so age-banded * options can still be re-derived. */ export declare function verifyBookingDraft(input: { travelers: ReadonlyArray; itemLines: ReadonlyArray; units: ReadonlyArray; }): VerifyBookingDraftResult;