Summary
Follow-up hardening from PR #161.
notification_events, notification_deliveries, and push_devices are currently related by independent foreign keys. That means the database can accept a notification_deliveries row that pairs one user's event with another user's device unless the application always constructs rows correctly.
Why this is worth tracking
- Current enqueue code appears safe today because it loads devices by
request.user_id and inserts deliveries from that in-memory set within one transaction.
- The schema still leaves room for a future cross-user pairing bug to turn into a notification leak.
- There is also a smaller queue-invariant cleanup worth considering:
notification_deliveries.attempt_count currently has no >= 0 check.
Affected migration
migrations/2026-03-07-120000_push_notifications_v1
Follow-up direction
- Add DB-level delivery ownership validation, likely by storing enough principal data on
notification_deliveries for composite FKs or by using a trigger.
- Add an explicit non-negative check on
notification_deliveries.attempt_count.
- Preserve the existing Feb/Mar migration lineage by addressing this in a new forward migration rather than editing the historical migration files.
Summary
Follow-up hardening from PR #161.
notification_events,notification_deliveries, andpush_devicesare currently related by independent foreign keys. That means the database can accept anotification_deliveriesrow that pairs one user's event with another user's device unless the application always constructs rows correctly.Why this is worth tracking
request.user_idand inserts deliveries from that in-memory set within one transaction.notification_deliveries.attempt_countcurrently has no>= 0check.Affected migration
migrations/2026-03-07-120000_push_notifications_v1Follow-up direction
notification_deliveriesfor composite FKs or by using a trigger.notification_deliveries.attempt_count.