Kaizen
Browse modulesBookingsbookings/serverClasses

Class: BookingService

Defined in: server/bookings/booking-service.ts:134

The bookings transition core (§8.1): every lifecycle operation is one atomic, audited transaction — policy seam → capacity seam → structural machine transition → version-CAS update + timeline append — followed by an AFTER-COMMIT outbox drain. Side-effect ports are never awaited inside the transaction.

Extended by

Constructors

Constructor

new BookingService(deps: BookingFeatureDeps): BookingService;

Defined in: server/bookings/booking-service.ts:135

Parameters

ParameterType
depsBookingFeatureDeps

Returns

BookingService

Properties

deps

protected readonly deps: BookingFeatureDeps;

Defined in: server/bookings/booking-service.ts:135

Methods

applyClaimTransitions()

protected applyClaimTransitions(
   members: readonly ClaimMember[], 
   event: string, 
   input: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}
): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}[]>;

Defined in: server/bookings/booking-service.ts:709

The batch CLAIM core (§6.6/§6.10) — every capacity-acquiring transition runs through here; a single claim is the batch of one.

One repos.transaction (15s budget) wrapping ONE explicit savepoint, so all-or-none survives a consumer's ambient outer transaction (§6.6 joined-tx contract). Inside:

  1. hydrate + policy + STRUCTURAL evaluation for EVERY member — no writes;
  2. the §6.6 batch capacity check over the union overlap set (real row locks, sorted-id order) — or, under allowOverbook, skip it and append one overbooked_by_admin event per schedule-bearing member;
  3. only then apply every member's transition: version-CAS + timeline + is_blocking maintenance + outbox rows.

Any member failure throws before/instead of step 3 and rolls back to the savepoint — none commit. A batch of one unwraps to the inner error.

Parameters

ParameterTypeDescription
membersreadonly ClaimMember[]-
eventstring-
input{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
input.actorIdstring-
input.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
input.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
input.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
input.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
input.expectedVersion?number-
input.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }[]>


applyTransition()

protected applyTransition(
   bookingId: string, 
   event: string, 
   opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}, 
   extras?: TransitionExtras
): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:597

Parameters

ParameterTypeDescription
bookingIdstring-
eventstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-
extras?TransitionExtras-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


approve()

approve(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:385

pending→confirmed — deliberately NON-claiming, unlike confirm-from-held.

Capacity was acquired at submit (the claim path), and pending blocks UNCONDITIONALLY in the §6.6 truth table — it carries no query-side expiry predicate, so its occupancy can never silently lapse between submit and approve. (pending→expired is a sweeper-driven version-CAS transition; racing it makes this approve throw StaleBookingError rather than double-book.) Contrast held, whose occupancy evaporates the moment holdExpiresAt passes: confirming an expired-but-unswept hold RE-ACQUIRES capacity, so confirm must re-check under the overlap-set lock. Approve acquires nothing — and the claim path's capacity check excludes a member's own booking rows anyway (§6.6 self-exclusion), so routing approve through that capacity check would add no protection.

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


assertPolicyAllows()

protected assertPolicyAllows(
   booking: ComposedBookingRow, 
   event: string, 
   opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}
): Promise<void>;

Defined in: server/bookings/booking-service.ts:955

POLICY seam (§8.1 step a / §8.3): approval routing from the PINNED policy bag (§6.2) + domain: "bookings" rules evaluation — throws PolicyDeniedError on deny. Protected so a consumer subclass can extend/replace the policy layer.

Parameters

ParameterTypeDescription
bookingComposedBookingRow-
eventstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<void>


cancel()

cancel(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:322

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


complete()

complete(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:401

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


completeBooking()

completeBooking(bookingId: string, opts: {
  actorId: string | null;
  expectedVersion?: number;
  idempotencyKey?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:456

System-actor confirmed→completed transition used by the completion sweeper (§11). Structural guard (endsAt <= now) must pass; the host is hydrated inside applyTransition from the schedule join.

Parameters

ParameterType
bookingIdstring
opts{ actorId: string | null; expectedVersion?: number; idempotencyKey?: string; }
opts.actorIdstring | null
opts.expectedVersion?number
opts.idempotencyKey?string

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


confirm()

confirm(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:293

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


confirmMany()

confirmMany(bookingIds: readonly string[], opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}[]>;

Defined in: server/bookings/booking-service.ts:302

Batch confirm (§6.10): one transaction, one savepoint, all-or-none.

Parameters

ParameterTypeDescription
bookingIdsreadonly string[]-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }[]>


create()

create(raw: {
  bookingTypeId: string;
  capacityUnits?: number;
  organizationId: string;
  partyEmail?: string;
  partyName?: string;
  partyRef?: string;
  payload?: Record<string, unknown>;
  schedule?: {
     endsAt: unknown;
     resourceId: string;
     startsAt: unknown;
     timeZone: string;
  };
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:155

Create a draft booking, pinning the type's published version (§6.2) and appending booking_created + terms_pinned timeline rows — one tx.

When schedule is provided, a BookingSchedules row is written at isBlocking: false — a draft never blocks capacity (spec §6.6 truth table).

Parameters

ParameterType
raw{ bookingTypeId: string; capacityUnits?: number; organizationId: string; partyEmail?: string; partyName?: string; partyRef?: string; payload?: Record<string, unknown>; schedule?: { endsAt: unknown; resourceId: string; startsAt: unknown; timeZone: string; }; }
raw.bookingTypeIdstring
raw.capacityUnits?number
raw.organizationIdstring
raw.partyEmail?string
raw.partyName?string
raw.partyRef?string
raw.payload?Record<string, unknown>
raw.schedule?{ endsAt: unknown; resourceId: string; startsAt: unknown; timeZone: string; }
raw.schedule.endsAtunknown
raw.schedule.resourceIdstring
raw.schedule.startsAtunknown
raw.schedule.timeZonestring

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


expireApproval()

expireApproval(bookingId: string, opts: {
  actorId: string | null;
  expectedVersion?: number;
  idempotencyKey?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:425

System-actor pending→expired transition used by the approval-expiry sweeper (§11). Mirrors expireHold — same CAS semantics, system actorId, deterministic idempotency key.

Parameters

ParameterType
bookingIdstring
opts{ actorId: string | null; expectedVersion?: number; idempotencyKey?: string; }
opts.actorIdstring | null
opts.expectedVersion?number
opts.idempotencyKey?string

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


expireHold()

expireHold(bookingId: string, opts: {
  actorId: string | null;
  expectedVersion?: number;
  idempotencyKey?: string;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:523

System-actor held→expired transition used by the hold sweeper (§6.3).

Uses the same version-CAS path as every other transition — the sweeper CAS races a concurrent confirm fairly: whichever commits first wins; the loser throws StaleBookingError and is skipped (§6.6 / §14).

actorId is null for the hold sweeper (system actor). expectedVersion is the version hydrated by the sweeper to participate in the CAS race.

Parameters

ParameterType
bookingIdstring
opts{ actorId: string | null; expectedVersion?: number; idempotencyKey?: string; reason?: string; }
opts.actorIdstring | null
opts.expectedVersion?number
opts.idempotencyKey?string
opts.reason?string

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


generateUid()

protected generateUid(repos: BookingRepositories, organizationId: string): Promise<string>;

Defined in: server/bookings/booking-service.ts:996

8-char external short code, retried on org-uniqueness collision.

Parameters

ParameterType
reposBookingRepositories
organizationIdstring

Returns

Promise<string>


hold()

hold(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  holdTtlSeconds: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:260

draft→held: sets holdExpiresAt = now + ttl in the same CAS update.

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; holdTtlSeconds: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.holdTtlSecondsnumber-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


holdMany()

holdMany(bookingIds: readonly string[], opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  holdTtlSeconds: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}[]>;

Defined in: server/bookings/booking-service.ts:272

Batch hold (§6.10): one transaction, one savepoint, all-or-none. Every member's structural + capacity check is evaluated BEFORE any transition applies, and the whole group shares ONE holdExpiresAt stamp so the hold sweeper can expire it as a unit.

Parameters

ParameterTypeDescription
bookingIdsreadonly string[]-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; holdTtlSeconds: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.holdTtlSecondsnumber-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }[]>


machineFor()

protected machineFor(vertical: string): ErasedMachine;

Defined in: server/bookings/booking-service.ts:138

Checked vertical → composed-machine lookup; throws UnknownBookingTypeError.

Parameters

ParameterType
verticalstring

Returns

ErasedMachine


markNoShow()

markNoShow(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:409

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


markNoShowBySystem()

markNoShowBySystem(bookingId: string, opts: {
  actorId: string | null;
  expectedVersion?: number;
  idempotencyKey?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:487

System-actor confirmed→no_show transition used by the no-show sweeper (§11). No structural guard beyond status check — the sweeper is responsible for enforcing the grace window before calling this.

Parameters

ParameterType
bookingIdstring
opts{ actorId: string | null; expectedVersion?: number; idempotencyKey?: string; }
opts.actorIdstring | null
opts.expectedVersion?number
opts.idempotencyKey?string

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


reject()

reject(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:393

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


submit()

submit(bookingId: string, opts: {
  actorId: string;
  allowLateCancel?: boolean;
  allowOutsideHours?: boolean;
  allowOverbook?: boolean;
  allowTransfer?: boolean;
  expectedVersion?: number;
  reason?: string;
}): Promise<{
  amountOwedCents: number | null;
  bookingTypeId: string;
  bookingTypeVersionId: string;
  capacityUnits: number;
  createdAt: Date;
  createdBy: string | null;
  currency: string | null;
  deletedAt: Date | null;
  deletedBy: string | null;
  groupId: string | null;
  holdExpiresAt: Date | null;
  id: string;
  organizationId: string;
  origin: BookingOrigin;
  paid: boolean;
  partyEmail: string | null;
  partyName: string | null;
  partyRef: string | null;
  payload: JsonValue;
  paymentRef: string | null;
  pendingExpiresAt: Date | null;
  status: BookingStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  supersededById: string | null;
  uid: string;
  updatedAt: Date;
  updatedBy: string | null;
  version: number;
}>;

Defined in: server/bookings/booking-service.ts:358

draft→pending — a CLAIMING transition (§6.6 truth table: pending BLOCKS capacity), so it runs the claim path: overlap-set lock + batch capacity check + window containment. On the old non-claiming path two concurrent submits could both reach pending and double-book the slot.

Parameters

ParameterTypeDescription
bookingIdstring-
opts{ actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; }-
opts.actorIdstring-
opts.allowLateCancel?booleanAdmin late-cancel override (spec §7): when true, cancel skips the rules-engine cancellation policy guard and records a cancelled_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook (§6.6). The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than cancel.
opts.allowOutsideHours?booleanAdmin outside-hours override (spec §6.9): when true, claiming transitions skip the window-containment check and record an hours_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowOverbook. The CONSUMER owns the permission decision.
opts.allowOverbook?booleanAdmin overbook override (spec §6.6): when true, claiming transitions skip the capacity/overlap check and record an overbooked_by_admin timeline event instead. The CONSUMER owns the permission decision — taproot is auth-agnostic and only honors + records the flag.
opts.allowTransfer?booleanAdmin transfer override (spec §7.1): when true, the transfer/reschedule family skips the rules-engine policy guard for the transfer event and records a transfer_overridden_by_admin timeline event instead — the same bypass-and-record contract as allowLateCancel/allowOverbook. The CONSUMER owns the permission decision; taproot only honors + records the flag. Ignored on every event other than transfer.
opts.expectedVersion?number-
opts.reason?string-

Returns

Promise<{ amountOwedCents: number | null; bookingTypeId: string; bookingTypeVersionId: string; capacityUnits: number; createdAt: Date; createdBy: string | null; currency: string | null; deletedAt: Date | null; deletedBy: string | null; groupId: string | null; holdExpiresAt: Date | null; id: string; organizationId: string; origin: BookingOrigin; paid: boolean; partyEmail: string | null; partyName: string | null; partyRef: string | null; payload: JsonValue; paymentRef: string | null; pendingExpiresAt: Date | null; status: BookingStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; supersededById: string | null; uid: string; updatedAt: Date; updatedBy: string | null; version: number; }>


toHost()

protected toHost(b: ComposedBookingRow): ErasedBookingHost;

Defined in: server/bookings/booking-service.ts:981

Map the hydrated row to the composed host the machine guards read. startsAt/endsAt/timeZone/resourceId are sourced from the joined schedule row (§5.2 hydration spec). When no schedule exists (draft with no schedule), endsAt is undefined and the completable guard (endsAt <= now) correctly fails, so complete is unreachable — by design.

offerExpiresAt is surfaced from the ACTIVE waitlist offer row (§6.4) so the §5.2 offered→confirmed structural guard reads the real accept-by deadline off the host — not undefined from a bare row (a hydration bug). offers is filtered to active rows at hydration; the single offered/ queued row's deadline (or null when none) is what the guard sees. Protected so the transfer family (§7.1) reuses the same hydration.

Parameters

ParameterType
bComposedBookingRow

Returns

ErasedBookingHost

On this page