@voyant-travel/trips) owns the composition layer that turns several independent commitments into one customer experience. A real itinerary is rarely a single booking: it is a tour plus a hotel stay plus a flight plus a transfer, each supplied, confirmed, taxed, and cancelled on its own terms. Trips groups those parts into a single Trip Envelope so the customer sees one itinerary, one price, one checkout, one set of documents, and one cancellation preview, without erasing the lifecycle boundaries underneath.
It is a deterministic composer, not a new commitment primitive. It aggregates pricing, runs a reserve workflow across components, hands off to checkout, and previews and executes per-component cancellations. Checkout and cancellation are dependency-injected, so the app and runtime keep owning the payment provider, bank transfer, storefront URL, supplier, and staff-remediation policy. The trip itself does not become a Booking; it references the component bookings that are.
Key concepts
A customer-facing aggregate that groups one or more component bookings (and provider or source order refs) into one itinerary, checkout, support, document, and cancellation-preview experience. It is not necessarily one Booking, and it does not erase the lifecycle boundaries of its components. See Trip Envelope.
One independently committed part of a Trip Envelope, with its own supplier or provider reference, cancellation rules, tax treatment, fulfillment state, and operational owner. A component is independent: cancelling one does not implicitly cancel its siblings. See Component Booking.
An individually composed Trip Envelope assembled from independent commitments such as a product, stay, flight, transfer, cruise, or staff-confirmed placeholder. This is the bespoke, build-it-yourself itinerary, distinct from a single packaged product. See Composed FIT Trip.
A child line that modifies or extends a component booking and shares that component’s lifecycle closely enough to be cancelled, fulfilled, taxed, and supported with it. Product-internal bundles and dependent extras stay inside their component booking; they do not become siblings. See Extra.
A cruise-specific pre or post-cruise hotel or land program. Its offer definition can be shared across cruises and sailings; a selected extension is an Extra when cruise-owned and lifecycle-dependent, or a sibling component booking when independently supplied and confirmed. The module ships
./cruise-extension helpers for the link and the selection representation. See Cruise Extension.A trip snapshot freezes the composed itinerary for reserve and provenance; a trip reservation plan captures what reserve secured (and what failed) before the component bookings are created. A booking’s Booking Origin can point back at the trip snapshot.
How independent commitments group into one itinerary
The load-bearing rule is the lifecycle boundary. What groups into one envelope, and what stays nested inside a component, is decided by whether the part has independent supplier, cancellation, tax, and fulfillment state.- Independent commitments become sibling component bookings. A customer-composed addition with its own supplier, its own cancellation rules, and its own fulfillment state is a sibling Component Booking under the same Trip Envelope. Cancelling it previews and executes against that component alone.
- Dependent parts stay nested. Product-internal bundles and dependent Extras stay inside their component booking. They share that component’s lifecycle and are cancelled, fulfilled, taxed, and supported with it.
- A Cruise Extension is decided by the same rule. Its catalog definition may be reused across cruises, but the selected extension is an Extra when cruise-owned and lifecycle-dependent, or a sibling component when independently supplied and confirmed.
What it owns
Trips landed as a composition layer with a deliberately narrow, deterministic surface.- The durable schema (
./schema): trip envelopes, trip components, component events, trip snapshots, and trip reservation plans. - The deterministic trip service (
./service): create, get, list, add and update and reorder components, and update component refs. - Price aggregation (
priceTrip) that rolls component prices into one envelope total, andapplyQuoteToComponent. - The reserve workflow (
reserveTrip) that runs across components and produces a reservation plan. - Checkout handoff (
startCheckout,completeTripCheckout), dependency-injected so the runtime owns payment, bank transfer, and storefront URL policy. - Component-level cancellation (
previewCancellation,cancelComponents), so support can preview and cancel one component without touching siblings. - Cruise Extension helpers (
./cruise-extension) and a catalog component adapter (./catalog-component-adapter) that maps catalog entities into trip components. - MCP tools (
./mcp-tools): AI-safe trip planning, revision, pricing, and reserve operations.
Working with it
Mount the module routes and compose a trip from components.Checkout and cancellation are dependency-injected. The trips package stays deterministic and side-effect-free at its core; the app supplies the payment provider, bank-transfer, storefront-URL, supplier, and staff-remediation policy when it wires the routes.
Links to other modules
- bookings owns each Component Booking’s commitment truth. A booking’s origin can point at the trip snapshot the envelope froze.
- quotes produces quote versions whose Trip Envelope snapshot mirrors a composed itinerary; reserve crosses from accepted version into component reservation.
- catalog is the source the catalog component adapter maps into trip components, so owned and sourced inventory compose into one envelope.
- The cruises vertical pairs with the Cruise Extension helpers to decide whether an extension nests as an Extra or splits into a sibling component.
- The finance module collects against the envelope’s checkout while each component keeps its own tax treatment.
React package
@voyant-travel/trips-react provides admin and public API clients, validation-aware operations, TanStack Query keys and options, cache writers, provider wiring (VoyantTripsProvider under ./provider), and hooks (./hooks) for Trip Envelope composition. It supports trip creation, component add, pricing, reserve, checkout handoff, and support-facing component cancellation preview and cancel. Draft is a trip lifecycle status, not a separate object name. Fetcher and error utilities live under ./client, and stable query keys under ./query-keys.
Next steps
Bookings
The component bookings each envelope references, with their own lifecycles.
Quotes
The proposal whose Trip Envelope snapshot a composed itinerary mirrors.
Cruises
The vertical behind Cruise Extensions that nest as Extras or split as siblings.
Glossary
The shared vocabulary: Trip Envelope, Component Booking, Composed FIT Trip, Extra.