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
| Parameter | Type |
|---|---|
deps | BookingFeatureDeps |
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:
- hydrate + policy + STRUCTURAL evaluation for EVERY member — no writes;
- the §6.6 batch capacity check over the union overlap set (real row
locks, sorted-id order) — or, under
allowOverbook, skip it and append oneoverbooked_by_adminevent per schedule-bearing member; - only then apply every member's transition: version-CAS + timeline +
is_blockingmaintenance + 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
| Parameter | Type | Description |
|---|---|---|
members | readonly ClaimMember[] | - |
event | string | - |
input | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
input.actorId | string | - |
input.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
event | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
booking | ComposedBookingRow | - |
event | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type |
|---|---|
bookingId | string |
opts | { actorId: string | null; expectedVersion?: number; idempotencyKey?: string; } |
opts.actorId | string | 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
bookingIds | readonly string[] | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type |
|---|---|
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.bookingTypeId | string |
raw.capacityUnits? | number |
raw.organizationId | string |
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.endsAt | unknown |
raw.schedule.resourceId | string |
raw.schedule.startsAt | unknown |
raw.schedule.timeZone | 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;
}>
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
| Parameter | Type |
|---|---|
bookingId | string |
opts | { actorId: string | null; expectedVersion?: number; idempotencyKey?: string; } |
opts.actorId | string | 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
| Parameter | Type |
|---|---|
bookingId | string |
opts | { actorId: string | null; expectedVersion?: number; idempotencyKey?: string; reason?: string; } |
opts.actorId | string | 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
| Parameter | Type |
|---|---|
repos | BookingRepositories |
organizationId | string |
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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; holdTtlSeconds: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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.holdTtlSeconds | 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;
}>
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
| Parameter | Type | Description |
|---|---|---|
bookingIds | readonly string[] | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; holdTtlSeconds: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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.holdTtlSeconds | 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;
}[]>
machineFor()
protected machineFor(vertical: string): ErasedMachine;Defined in: server/bookings/booking-service.ts:138
Checked vertical → composed-machine lookup; throws UnknownBookingTypeError.
Parameters
| Parameter | Type |
|---|---|
vertical | string |
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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type |
|---|---|
bookingId | string |
opts | { actorId: string | null; expectedVersion?: number; idempotencyKey?: string; } |
opts.actorId | string | 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type | Description |
|---|---|---|
bookingId | string | - |
opts | { actorId: string; allowLateCancel?: boolean; allowOutsideHours?: boolean; allowOverbook?: boolean; allowTransfer?: boolean; expectedVersion?: number; reason?: string; } | - |
opts.actorId | string | - |
opts.allowLateCancel? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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? | boolean | Admin 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
| Parameter | Type |
|---|---|
b | ComposedBookingRow |
Returns
ErasedBookingHost