Cancelled booking sends a CANCEL .ics to remove the event from the customer's calendar
Why it matters
When a booking is cancelled, the customer's calendar app needs a METHOD:CANCEL invite with the original UID to remove the existing event. Without it, the customer's calendar continues to show the appointment — they may still show up. Sending a METHOD:PUBLISH invite on cancellation makes the situation worse: the calendar client treats it as a new event confirmation rather than a removal. RFC 5546 defines METHOD:CANCEL specifically for this case. The failure is silent from the system's perspective (the email is sent, the queue job succeeds) but creates a confused customer experience and potential unnecessary no-shows.
Severity rationale
Medium because without a METHOD:CANCEL invite, cancelled appointments persist on customer calendars, causing unnecessary arrivals and customer confusion that burdens support.
Remediation
Add a generateCancelICS() function to src/lib/calendar.ts that uses the same stable UID as the original event and sets METHOD:CANCEL and STATUS:CANCELLED. Attach it to the cancellation email:
export function generateCancelICS(booking: Booking): string {
const dtstamp = new Date().toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z'
return [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'METHOD:CANCEL',
'BEGIN:VEVENT',
`UID:${booking.id}@yourdomain.com`, // Same UID as original
`DTSTAMP:${dtstamp}`,
'STATUS:CANCELLED',
`SUMMARY:CANCELLED: ${booking.service_name}`,
`DTSTART:${formatICSDate(booking.start_time)}`,
`DTEND:${formatICSDate(booking.end_time)}`,
'END:VEVENT',
'END:VCALENDAR',
].join('\r\n')
}
Call this from the cancellation email worker, not from the main cancellation handler, to keep it on the retry path.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Booking Notifications & Reminders Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- external · RFC5546 — iCalendar Transport-Independent Interoperability Protocol (iTIP) — METHOD:CANCEL
Taxons
History
- 2026-04-18·v1.0.0·Initial import from booking-notifications-reminders·automated