Notification Preference
Data Entity
Description
Stores a user's opt-in or opt-out decision for each notification category (assignment_reminders, certificate_expiry, pause_status, scenario_prompts). Preferences are consulted by the trigger service before any notification is dispatched. Managed through the notification settings screen and default to opted-in when no record exists.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Surrogate primary key generated by the database on insert | PKrequiredunique |
user_id |
uuid |
Foreign key to the user who owns this preference record. Combined with category it forms the logical unique key for the table. | required |
category |
enum |
The notification category this preference controls. Exactly one record per (user_id, category) pair is allowed. | required |
is_enabled |
boolean |
Whether the user has opted in (true) or opted out (false) of notifications for this category. The absence of a record is treated as true (opted-in by default). | required |
created_at |
datetime |
UTC timestamp when the preference record was first created. Set once on insert, never updated. | required |
updated_at |
datetime |
UTC timestamp of the most recent change to is_enabled. Updated automatically by a database trigger on every row update. | required |
Database Indexes
idx_notification_preference_user_category
Columns: user_id, category
idx_notification_preference_user_id
Columns: user_id
idx_notification_preference_category
Columns: category
Validation Rules
user_id_must_reference_existing_user
error
Validation failed
category_must_be_valid_enum
error
Validation failed
is_enabled_must_not_be_null
error
Validation failed
no_duplicate_user_category_pair
error
Validation failed
updated_at_must_reflect_latest_change
warning
Validation failed
Business Rules
default_opted_in
When no preference record exists for a given (user_id, category) pair, the system treats the user as opted in (is_enabled = true). No record must be created proactively; the absence itself encodes the default state. This prevents unnecessary rows for the majority of users who never change their settings.
one_preference_per_category
Each user may have at most one preference record per notification category. Attempts to insert a duplicate (user_id, category) pair must upsert (update is_enabled) rather than create a second row. This is enforced by the unique index idx_notification_preference_user_category and by service-layer upsert semantics.
trigger_service_must_check_preference
Before dispatching any notification, the trigger service must call isCategoryEnabled(userId, category). If the result is false (or if the lookup fails with an error), the notification must be suppressed for that user. This enforces user consent across all delivery channels (push, in-app).
preference_change_takes_effect_immediately
When a user toggles a category on the notification settings screen, the preference is persisted to Supabase synchronously before the UI confirms success. In-flight notifications already dispatched before the toggle are not recalled, but all subsequent dispatch decisions use the updated value.
cascade_delete_on_user_removal
When a user account is deleted, all associated notification_preference rows must be deleted via cascading foreign key constraint on user_id. No orphaned preference rows are permitted.
CRUD Operations
Storage Configuration
Entity Relationships
A user has one preference record per notification category controlling opt-in and opt-out state