Skip to content

[PBI] Notification read/unread state and per-user lifecycle #438

@cjlapao

Description

@cjlapao

Description

Ensure that the is_read flag is correctly initialised, propagated, and updated across the full lifecycle of a notification — from creation through WebSocket delivery to REST state updates — and that the unread count is always consistent with actual row state.

User Story

As a user, I want to see a reliable count of notifications I haven't read yet, and I want that count to update immediately when I mark notifications as read, so that I always have an accurate picture of what still needs my attention.

Acceptance Criteria

  • Default state: All newly created notification rows have is_read = false.
  • WS payload includes flag: The notification.created WebSocket message includes is_read: false so the UI can immediately increment its local unread count without a separate API call.
  • Mark-read idempotent: Calling PATCH /notifications/:id/read on an already-read notification returns 200 with no error.
  • Bulk mark-read atomic: PATCH /notifications/read-all executes as a single UPDATE query. It must not leave partial state if interrupted.
  • Unread count accuracy: GET /notifications/unread-count reflects the true database state, not a cached value, so it is always consistent after any read/delete operation.
  • Concurrent update safety: Two simultaneous mark-read calls for the same notification do not produce an error or inconsistent state.
  • Unit tests: Tests cover initial state, idempotent mark-read, bulk mark-read, count accuracy after each mutation, and concurrent update behaviour.

Definition of Done

  • Code implemented following best practices.
  • Unit tests written and passing.
  • Code reviewed and approved.
  • Merged into the main branch.
  • Documentation updated (if applicable).
  • Deployed to staging/production environment.

Assumptions and Constraints

  • Assumption: Database-level consistency is sufficient — no in-memory cache of unread counts is needed at this stage.
  • Constraint: The read-all operation must be bounded to the authenticated user's rows only.

Dependencies

No response

Additional Notes

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    pbiProduct Backlog ItemtriageSelected for triage

    Type

    Projects

    Status

    📋 Awaiting Triage

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions