ConstReadonlyDirect: "direct"Staff entered it — the front desk, the phone, a group booking.
ReadonlyOta: "ota"A channel manager sent it. source_ota names which.
ReadonlyPlatform: "platform"The guest booked themselves on a site we operate. source_domain names which.
Where a booking came from —
bookings.source, as widened by NexHub migration 0072.⚠️
directCHANGED MEANING in that migration, andmanualis gone. It used to cover the guest website AND the front desk together, which is why nothing could tell them apart. It now means the desk alone; the website isplatform.Named here because
BookingResponse.sourceis typedstrby the generator (only the query param carries the Literal), so a consumer comparing raw strings gets no help from the compiler — and a stale=== 'direct'now silently means the opposite of what its author intended.⚠️ Rows created before 2026-09-06 all say
directwhether the guest booked themselves or the desk did. They were not backfilled, because nothing left in the row could tell the two apart. Any rule keyed on this is therefore right for new bookings and pessimistic for old ones — decide deliberately which way that should fail.