Skip to main content
The operator-settings module owns the per-tenant configuration that the rest of the platform reads but does not own. It holds the operator’s legal and trading identity, its customer-facing payment instructions and default payment policy, and its booking-tax knobs. Standard modules such as finance and bookings inject these readers rather than carrying operator identity or tax defaults themselves. It ships as @voyant-travel/operator-settings: a Drizzle schema plus transport-agnostic readers and writers, with HTTP routes. It is a standard schema-owning module in the product graph, resolved into the application at build time rather than mounted by hand.

Key concepts

The domain is split into narrow single-row tables, each with its own TypeID prefix, rather than one catch-all settings blob.
  • Operator profile. The single-row legal and trading identity that contracts with the traveler: name, legalName, vatId, registrationNumber, contact fields, travel license, and the signing officer. Table operator_profile, TypeID prefix oppf. Contract variables and public booking-preview legal blocks read from it.
  • Payment instructions. Single-row customer-facing collection details such as the bank-transfer beneficiary, IBAN, bank, and notes. Table operator_payment_instructions, TypeID prefix opin.
  • Payment defaults. The operator-level default customer payment policy plus checkout and invoice pay-URL templates. The booking payment-policy cascade uses this only when supplier, category, listing, and booking-level policies do not override it. Table operator_payment_defaults, TypeID prefix opdp. The policy is stored as jsonb mirroring the PaymentPolicy shape in @voyant-travel/finance.
  • Booking-tax settings. Single-row booking tax configuration (taxPriceMode, taxPolicyProfileId) used by booking-create previews, quote recomputation, and booking item tax-line materialization. Table booking_tax_settings, TypeID prefix btxs.
An older catch-all operator_settings table (TypeID prefix opset) is retained for migration parity from the first booking-journey settings pass. Runtime code reads and writes the narrower tables above.

What it owns

Schema

The ./schema subpath exports the Drizzle tables (operatorProfile, operatorPaymentInstructions, operatorPaymentDefaults, bookingTaxSettings, and the retained operatorSettings) with their inferred select and insert types. A deployment lists this package in voyant.config so its tables fold into the combined migration history.

Service

The ./service subpath exports transport-agnostic readers and writers plus the resolvers that standard modules inject. Readers and upserts are single-row by convention (getOperatorProfile, upsertOperatorProfile, and the same pair for payment instructions, payment defaults, and the catch-all settings). Two resolvers are the consumption seam:
  • resolveOperatorDefaultPaymentPolicy(db) returns the configured default PaymentPolicy or null, so the booking cascade can fall through to its hard-coded policy.
  • resolveBookingTaxSettings(db) returns the effective taxPriceMode and taxPolicyProfileId, defaulting to inclusive.
The service also exports toPublicOperatorProfile and toPublicOperatorSettings projections plus the Zod update schemas (updateOperatorProfileSchema, updateOperatorPaymentInstructionsSchema, updateOperatorPaymentDefaultsSchema, updateOperatorSettingsSchema).

Routes

The ./routes subpath exports mountOperatorSettingsRoutes(hono). Routes are thin: they parse the request body with parseJsonBody, call a service function, and serialize the result. The paths are stable absolute paths:
  • GET and PATCH /v1/admin/settings/operator-profile
  • GET and PATCH /v1/admin/settings/operator-payment-instructions
  • GET and PATCH /v1/admin/settings/operator-payment-defaults
  • GET and PATCH /v1/admin/settings/operator (the catch-all settings)
  • GET /v1/public/operator-profile (profile plus payment defaults, cached)
  • GET /v1/public/settings/operator (the public settings projection, cached)

Working with it

Read settings directly through the service from any runtime that has a database handle:
Inject a resolver into a standard module rather than coupling that module to operator settings. The operator application passes resolveBookingTaxSettings into the booking tax-line rebuild:
Standard modules are not registered by hand. @voyant-travel/operator-settings is part of the standard product graph, so its routes, services, subscribers, and jobs are resolved into the application at build time. See Configuration.
In the operator application you do not call this factory by hand. Listing @voyant-travel/operator-settings in voyant.config registers the schema for migration and the platform composition mounts the module at its stable paths.
  • Finance. The default customer payment policy stored on payment defaults mirrors the PaymentPolicy shape in @voyant-travel/finance, and resolveOperatorDefaultPaymentPolicy feeds the booking payment-policy cascade. See Finance.
  • Bookings. Booking-create previews, quote recomputation, and tax-line materialization read resolveBookingTaxSettings. See Bookings.
  • Legal. Contract document variables and public booking-preview legal blocks read the operator profile for the operator-side signing identity. See Legal.

Next steps

Configuration

How a deployment lists a schema-owning module in voyant.config.

Finance

The PaymentPolicy shape behind the default payment policy.

Bookings

The booking previews and tax-line materialization that read these settings.

Modules

What it means to be a standard schema-owning module.