# CRM notification identity correction

The previous unique key (organization, appointment, event) prevented subsequent rescheduling emails and notifications for separate lab orders on the same visit.

The new delivery identity uses:
- Appointment booked/completed/cancelled: one event per appointment.
- Appointment rescheduled: appointment ID plus monotonically increasing notification revision.
- Appointment reminder: appointment ID plus current notification revision.
- Lab results available: appointment ID plus released lab order ID.

The sender checks that queued reschedule/reminder records still match the appointment's current scheduled time and status, marking obsolete records as skipped. A lab notice must belong to a released lab order for the same appointment. The migration preserves existing delivery rows and replaces the former unique index.

Deployment: run `php artisan migrate`, then `php artisan test`. Do not enable live patient email delivery until tests and SMTP checks pass. Existing historical reschedule rows lack their original appointment revision and retain legacy identities. The delivery process is still at-least-once at the SMTP boundary: a crash after SMTP acceptance but before database acknowledgement may cause duplicate email; provider-supported idempotency and operational monitoring are recommended.
