Skip to content

feat(notifications): protect security-critical notification preferences (#1160) - #1190

Merged
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
NoahJoseph-ux:feat/protect-security-notifications
Aug 2, 2026
Merged

feat(notifications): protect security-critical notification preferences (#1160)#1190
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
NoahJoseph-ux:feat/protect-security-notifications

Conversation

@NoahJoseph-ux

Copy link
Copy Markdown
Contributor

Overview

This PR makes it impossible for a user (or a compromised session) to disable security-critical notifications. Security events — new-device login, password change, payment receipts, and account deletion — are the user's early-warning system for account compromise, so opting out of them (via updatePreferences, toggleChannel, or unsubscribe) is now rejected with a 400. It also hardens preference updates by validating every incoming key against a known allowlist, so typos or unknown fields fail fast instead of silently writing junk rows.

Related Issue

Closes #1160

Changes

Security-critical event protection

  • [ADD] src/notifications/preferences/notification-preferences.constants.tsSECURITY_CRITICAL_EVENT_TYPES, KNOWN_EVENT_TYPES, EVENT_FREQUENCIES, CHANNEL_KEYS.
  • [MODIFY] preferences.service.tsupdatePreferences rejects never frequency or false subscription for any security-critical event type; unsubscribe rejects security-critical types while still allowing non-critical opt-out and the global "all" switch.

Key validation (allowlist)

  • [MODIFY] preferences.service.tsupdatePreferences now rejects unknown top-level keys, unknown event types, and invalid frequency values with BadRequestException before any write.

Delivery-channel safety net

  • [MODIFY] preferences.service.tsupdatePreferences/toggleChannel refuse to disable the last remaining enabled delivery channel, guaranteeing security-critical notifications always keep a delivery path.

Tests

  • [ADD] preferences.service.spec.ts — 17 unit tests covering every guard and the allowed paths (non-critical opt-out, protected-type re-enable, global unsubscribe, multi-channel toggles).

Verification Results

npx jest src/notifications/preferences
  • Test Suites: 1 passed, 1 total / Tests: 17 passed, 17 total
  • eslint clean on all changed files
  • ✅ TypeScript compiles for the notifications module (pre-existing unrelated tsc errors exist elsewhere in the repo, e.g. src/rbac/roles/roles.controller.ts, untouched by this PR)

Acceptance Criteria

Status Criterion
Security-critical event types cannot be disabled via eventFrequency or topicSubscriptions
unsubscribe rejects security-critical event types
Unknown preference keys / event types / frequencies rejected with 400
Last enabled delivery channel cannot be disabled
Non-security-critical opt-out still works
Global unsubscribe ("all") still works
17/17 unit tests pass

…m opt-out (rinafcode#1160)

Security-critical notifications (new-device login, password change,
payment receipts, account deletion) can never be disabled or
unsubscribed from, and incoming preference keys are validated against a
known allowlist so unknown keys fail fast with a 400.

- Adds SECURITY_CRITICAL_EVENT_TYPES / KNOWN_EVENT_TYPES /
  EVENT_FREQUENCIES / CHANNEL_KEYS constants.
- updatePreferences rejects disabling protected event types via
  eventFrequency or topicSubscriptions, rejects unknown keys/events/
  frequencies, and refuses to disable the last enabled delivery channel.
- toggleChannel refuses to disable the last remaining enabled channel.
- unsubscribe rejects security-critical event types while still allowing
  non-critical opt-out and the global "all" switch.
- Adds 17 unit tests covering every guard.
@drips-wave

drips-wave Bot commented Aug 2, 2026

Copy link
Copy Markdown

@NoahJoseph-ux Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Thank you for contributing to the project

@RUKAYAT-CODER
RUKAYAT-CODER merged commit 1ccc5d8 into rinafcode:main Aug 2, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Protect security-critical notification types from being disabled in PreferencesService

2 participants