Silent state changes erode user trust and generate support load: customers who cancel, reschedule, or get confirmed without receiving a notification assume the transaction failed and either double-book, contact support, or show up to appointments that no longer exist. Missed notifications on cancellation and rescheduling are a direct user-experience failure that drives no-shows, duplicate bookings, and chargebacks. Out-of-band confirmation is also a baseline expectation under consumer protection guidance for bookings involving payment.
Medium because missing notifications cause measurable support and revenue loss but do not breach security, data, or regulated compliance boundaries.
Wire a notification call into each status-transition handler so the email or SMS fires in the same code path as the database update, after the transaction commits. Put the integration behind a small helper in src/lib/notifications.ts and call it from every handler that writes status. Example:
await db.booking.update({ where: { id }, data: { status: 'CANCELLED' } });
await sendBookingEmail(booking, 'cancelled');
ID: booking-flow-lifecycle.lifecycle.status-updates
Label: Status updates trigger notifications
Severity: medium
What to look for: Count all status transition handlers (confirm, cancel, reschedule) and verify each one triggers a notification (email, SMS, push, or in-app). Look for calls to email/SMS services (SendGrid, Resend, Twilio, AWS SES, Postmark, etc.) or notification utility functions. Enumerate: "X of Y status transitions trigger notifications." Also verify the notification is sent after a successful status update (not before, not unconditionally).
Pass criteria: Users are notified on at least 2 of the 3 key transitions: confirmed, cancelled, rescheduled. The notification must be triggered in the same handler as the status update (not a separate cron job). Each notification must include the booking details (date, time, status). Report: "X of 3 key transitions (confirmed/cancelled/rescheduled) trigger notifications via [service] in [file]."
Fail criteria: State changes happen silently with no notification. Or notifications are sent without tying them to status changes (e.g., a blanket "check your bookings" email). Do NOT pass when only 1 of 3 key transitions triggers a notification.
Skip (N/A) when: No notification requirements AND no email/SMS service is configured in the project (no SendGrid, Resend, Twilio, etc. in dependencies).
Detail on fail: "No notification logic triggered in the cancellation handler. Users must discover their cancelled booking by refreshing the page."
Cross-reference: The cancellation-state-machine check in this category verifies the cancellation handler where a notification should be sent.
Cross-reference: The customer-contact check in Booking Creation verifies the email/phone fields these notifications are sent to.
Cross-reference: The failure-handling check in Payment Integration verifies notifications for payment failure scenarios.
Remediation: Integrate a notification service in your status change handlers (e.g., src/lib/booking-service.ts or src/lib/notifications.ts).
export async function cancelBooking(bookingId: string) {
const booking = await db.booking.update({
where: { id: bookingId },
data: { status: 'CANCELLED', cancelledAt: new Date() }
});
// Send notification
await sendEmail({
to: booking.customerEmail,
subject: 'Booking Cancelled',
body: `Your booking on ${booking.startTime} has been cancelled.`
});
}