Summary
New notifications are written both to the Notification collection and to an embedded User.notifications array, but read/unread mutations update only the collection. Authentication responses and at least one dashboard page still consume the embedded array, so users can see stale unread counts indefinitely while the user document grows without bound.
Repository evidence
app/api/notifications/route.ts:61-81 creates a Notification and separately appends an embedded copy to User.notifications.
app/api/activity/route.ts:68-89 changes read state only in the Notification collection.
app/api/auth/me/route.ts:18 returns the embedded array, and app/dashboard/driver/kyc/status/page.tsx:232 calculates its unread count.
models/User.ts:184-187 stores the embedded array without a bound.
Scope
- Choose one authoritative notification/read-state store and migrate active consumers to it.
- Remove or boundedly retire embedded copies with a safe backfill/cleanup path.
- Ensure notification creation is not a non-atomic dual write.
Acceptance criteria
Tests
Non-goals
- Redesigning notification templates, delivery retries, or user preference policy.
Summary
New notifications are written both to the
Notificationcollection and to an embeddedUser.notificationsarray, but read/unread mutations update only the collection. Authentication responses and at least one dashboard page still consume the embedded array, so users can see stale unread counts indefinitely while the user document grows without bound.Repository evidence
app/api/notifications/route.ts:61-81creates aNotificationand separately appends an embedded copy toUser.notifications.app/api/activity/route.ts:68-89changes read state only in theNotificationcollection.app/api/auth/me/route.ts:18returns the embedded array, andapp/dashboard/driver/kyc/status/page.tsx:232calculates its unread count.models/User.ts:184-187stores the embedded array without a bound.Scope
Acceptance criteria
Tests
Non-goals