09 — User Behaviour (Notifications Module)
- 1. Badge-First Behaviour
- 2. Read-on-Tap
- 3. Mark-All-Read Session
- 4. Ordering Expectation
- 5. Notification Fatigue (planned-feature guard)
- 6. Time Perception
- 7. Deep-Link Navigation (proposed)
- 8. Error Resilience
Behavioural patterns observed/assumed for the inbox, grounded in the API contract (
notifications.controller.ts) and the event fan-in (notifications.handler.ts).
1. Badge-First Behaviour
- Users judge the inbox by the badge number before opening it; they expect
the number to equal what the list shows. Contract requirement:
unread-count(controller.ts:31-35) must agree with the count ofreadAt == nullrows in the list — same source collection, same filter (repository.ts:31-35vsrepository.ts:45-50), so it is consistent by construction. Client must still reconcile after mark-read mutations (see 13_State_Management).
2. Read-on-Tap
- Typical pattern: tap item → mark read → return. The read flag must update
optimistically on the tile and the badge; server
200 null(foreign id) must not crash the tile (service.ts:54-59).
3. Mark-All-Read Session
- Users batch-clear the inbox when unread exceeds ~10. After
read-all, they expect the badge to drop to 0 immediately; partial failures are invisible server-side (bulk update has no per-item error —repository.ts:45-50). Client treats the response as success if the request succeeds.
4. Ordering Expectation
- Users read newest-first and assume page 1 = today's items. Server sorts
createdAt: -1(repository.ts:66); never client-sort.
5. Notification Fatigue (planned-feature guard)
- Per
docs/IMPLEMENTATION_PLAN.md:769coaching tenants will generate high-volume events (test reminders, DPP due alerts, batch starts). Without per-type preferences (Notifications.md:27-28— (planned)) the inbox will flood. V1 mitigation: only four account-lifecycle events are wired today (handler.ts:8-50) — the event map is the volume governor. Add prefs before fanning out homework/exam events (14_QA_Checklist §G).
6. Time Perception
- Relative timestamps ("5m ago") dominate; absolute timestamps only in
accessibility text. Derived from
createdAt(timestamps: true,schema:14).
7. Deep-Link Navigation (proposed)
- Users expect a notification tap to open the thing it announces. Today
datais the raw event payload (handler.ts:96— e.g.{ userId }), with notargetUrlconvention. Until v2 definesdata.targetUrl, most taps only mark read — acceptable for v1 account-lifecycle content (welcome/verify/reset).
8. Error Resilience
- Users retry after transient failures; pagination failure must not nuke the loaded list (footer retry, 06 §1.4). Offline first-load shows cached copy when available (00-shared/06 hydration).