04 — Information Architecture (Notifications Module)
- 1. Entity Model (source of truth:
notification.schema.ts) - 2. Planned Entities (blueprint, not implemented)
- 3. Type Taxonomy (current)
- 4. App Navigation Placement
- 5. Data Flow
Global IA baseline in 00-shared/05; this file adds the module slice.
1. Entity Model (source of truth: notification.schema.ts)
Notification (collection: "notifications", timestamps)
├── tenantId (from BaseSchema — every doc tenant-scoped, `base.schema.ts`)
├── recipientId ObjectId, indexed — the owning user (`notification.schema.ts:16-17`)
├── type enum: email_verified | password_reset | verification_resent | welcome
│ (`notification.schema.ts:7-12`)
├── title string, required — user-visible headline
├── body string, required — user-visible copy
├── data Record<string, unknown> — raw domain-event payload (`schema:28-29`)
├── readAt Date | null — null = unread (`schema:31-32`)
└── BaseSchema createdAt / updatedAt / version / deletedAt (soft delete)
Indexes (notification.schema.ts:37-38):
{ tenantId, recipientId, readAt }— unread-count queries.{ tenantId, recipientId, createdAt: -1 }— inbox ordering.
2. Planned Entities (blueprint, not implemented)
| Entity | Collection | Source |
|---|---|---|
| NotificationTemplate | notification_templates | Notifications.md:7 |
| NotificationPreference | notification_preferences | Notifications.md:7 |
3. Type Taxonomy (current)
NotificationType | Source Event | Title (title-cased constant) |
|---|---|---|
email_verified | EmailVerified | Email Verified — handler.ts:16-20 |
verification_resent | EmailVerificationResent | Verification Email Sent — handler.ts:21-25 |
password_reset | PasswordResetCompleted | Password Reset — handler.ts:26-30 |
welcome | UserRegistered | Welcome to StudyLyon — handler.ts:41-49 |
Types are a closed enum on the server; the client renders by type and must
treat unknown enum values as generic "system notification".
4. App Navigation Placement
- Bell/badge icon in the app shell (see
05_Screen_Inventory §2). - Inbox route
/notifications— top-level destination, reachable from the shell icon and from deep links. - Detail — no server route; derived from list item +
data(see06). - Preferences (planned) —
GET/PATCH /api/v1/notifications/preferences(Notifications.md:27-28) will live behind the inbox, (planned).
5. Data Flow
Domain module ──emit──> EventBus (onAny)
└──> NotificationsHandler.handle() (handler.ts:61-99)
└──> recipientId = payload.userId ?? recipientId ?? actorId (handler.ts:76-79)
└──> NotificationsService.create() (service.ts:35-37, internal only)
└──> NotificationsRepository.create() (tenant-scoped, BaseRepository)
└──> Mongo "notifications"
Client <── authenticated API (controller.ts:21-47)
There is no HTTP write path — creation is event-only; NotificationsService
is exported from the module (notifications.module.ts:28) for in-process reuse.