critical priority medium complexity backend pending backend specialist Tier 3

Acceptance Criteria

NotificationTriggerService queries Supabase for the recipient's role before constructing the FCM payload
Peer mentor payloads include fields: role_slug='peer_mentor', assignment_id, contact_id, and notification_category
Coordinator payloads include fields: role_slug='coordinator', chapter_id, batch_summary_count, and notification_category
FCM data payload keys are snake_case strings compatible with NotificationDeepLinkHandler route resolution
Role query failure results in a logged error and skipped dispatch — no unhandled exception propagates
Payload construction is covered by unit tests for each role variant (peer_mentor, coordinator, org_admin)
Unknown or missing role falls back to a generic payload with only notification_category and resource_id
Payload size does not exceed FCM data payload limit of 4 KB
Role slug in payload exactly matches the role identifiers defined in Supabase user_roles table

Technical Requirements

frameworks
Flutter
Supabase Dart client
BLoC
apis
Supabase REST API (user_roles table)
Firebase Cloud Messaging HTTP v1 API
data models
UserRole
NotificationPayload
Assignment
Contact
Chapter
performance requirements
Role lookup query must complete within 200 ms (single indexed user_id lookup)
Payload construction must not block the event queue — use async/await throughout
Batch coordinator dispatches must process role lookups concurrently using Future.wait
security requirements
FCM data payload must never include PII (names, phone numbers, email addresses)
Only resource IDs (UUIDs) are permitted in the data payload — never raw entity content
Supabase service role key used in trigger service must not be exposed to client

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Store role slug constants in a shared NotificationRoles class (e.g., NotificationRoles.peerMentor = 'peer_mentor') to avoid string literals across the codebase. Query the user_roles table with a single .select('role_slug').eq('user_id', userId).single() call — this is indexed and fast. Build a PayloadBuilder sealed class with subclasses PeerMentorPayloadBuilder and CoordinatorPayloadBuilder so payload construction is testable in isolation. For coordinator broadcasts, use Future.wait on a list of per-recipient PayloadBuilder calls to parallelize without hitting Supabase rate limits.

Always log the constructed payload keys (not values) at debug level before dispatch so tracing is possible without PII leakage.

Testing Requirements

Unit tests (flutter_test) for each role variant covering: correct payload keys and values for peer_mentor, coordinator, and org_admin roles; fallback payload when role is null or unknown; payload size assertion under 4 KB; error handling when Supabase role query returns empty or throws. Integration test verifying the full role query → payload construction → FCM dispatch path against a Supabase test project. Minimum 90% branch coverage on NotificationTriggerService payload construction methods.

Component
Notification Trigger Service
service high
Epic Risks (4)
high impact high prob technical

Flutter's background message handler for FCM must run in a separate Dart isolate. Incorrect dependency initialization in the isolate (e.g., attempting to access Riverpod providers or Supabase before initialization) will cause silent crashes on Android when the app is terminated, resulting in missed notifications that are invisible in crash reporting.

Mitigation & Contingency

Mitigation: Use a minimal top-level background handler function annotated with @pragma('vm:entry-point') that only stores the raw RemoteMessage payload to a platform channel or shared preferences. Process the payload in the main isolate on next app launch. Write an explicit test for terminated-state message handling on Android.

Contingency: If isolate crashes are observed, implement a native Android FirebaseMessagingService subclass that handles background messages without Flutter isolate complexity, falling back to a database-insert-only approach for terminated-state notifications.

medium impact medium prob technical

Supabase Edge Functions can experience cold-start latency of 1–3 seconds after periods of inactivity. For high-frequency events like assignment creation, cumulative cold starts could cause dispatch delays exceeding the 30-second SLA, reducing the perceived reliability of the notification system.

Mitigation & Contingency

Mitigation: Configure the Edge Function with a keep-warm ping mechanism or use Supabase database webhooks that invoke the function directly on row insert to minimize cold-start frequency. Batch preference lookups within the function to reduce per-invocation Supabase round-trips.

Contingency: If latency SLA is consistently breached, move to a polling or Realtime-subscription architecture within the Edge Function, or pre-compute dispatch targets at preference-save time to eliminate per-dispatch preference queries.

high impact low prob security

If the deep link handler does not perform server-side role validation before rendering the target screen, a peer mentor who receives a mis-configured notification payload containing a coordinator-only route could access restricted data, violating the role-based access control invariants.

Mitigation & Contingency

Mitigation: The deep link handler must check the user's current role from the RoleStateManager before constructing the navigation route. Coordinator-only routes must be listed in a deny-list checked against the current role. The go_router route guard is a second line of defence.

Contingency: If a role bypass is discovered in testing, immediately add the affected route to the deep link handler deny-list and add a regression test. Audit all notification payload types for route targets that could expose cross-role data.

medium impact low prob dependency

FCM v1 HTTP API enforces per-project send quotas. For large organisations with many active peer mentors receiving simultaneous assignment notifications, batch dispatch events (e.g., bulk coordinator assignments) could approach quota limits and result in dropped notifications with 429 errors logged silently.

Mitigation & Contingency

Mitigation: Implement exponential backoff retry logic in the Edge Function for 429 responses. Design bulk assignment flows to dispatch notifications in batches with a configurable delay between batches. Monitor FCM console quotas during load testing.

Contingency: If quota limits are hit, implement a notification queue table in Supabase and a separate Edge Function that processes the queue with rate limiting, ensuring eventual delivery without exceeding FCM quotas.