high priority medium complexity testing pending testing specialist Tier 5

Acceptance Criteria

Unit test: payload with category='new_assignment' and valid assignment_id resolves to '/assignment/:id' route
Unit test: payload with category='coordinator_summary' and valid chapter_id resolves to '/coordinator/summary/:chapterId' route
Unit test: payload missing resource_id field resolves to the role-appropriate home route (no crash)
Unit test: payload with unknown/unsupported category resolves to home route (graceful fallback)
Unit test: cold-start payload is stored in PendingDeepLink notifier and applied after auth state becomes authenticated
Unit test: role guard violation (peer mentor payload arriving for coordinator-only route) redirects to peer mentor home
Unit test: go_router is called with the correct route string and parameters for each valid scenario
All tests use mocked Supabase client and mocked go_router — no real network calls
Test file achieves 100% branch coverage on NotificationDeepLinkHandler route resolution logic
Tests run in under 10 seconds total (pure unit tests, no async delays)

Technical Requirements

frameworks
flutter_test
mockito or mocktail
go_router
Riverpod (for PendingDeepLink state)
BLoC
apis
go_router GoRouter.go() / GoRouter.push()
FirebaseMessaging.instance.getInitialMessage() (mocked)
data models
NotificationPayload
DeepLinkRoute
AuthState
UserRole
performance requirements
All unit tests must complete in under 10 seconds — no real async delays or timers
Use fake async (fakeAsync / FakeAsync) for testing deferred cold-start navigation timing
security requirements
Tests must verify that routes containing resource IDs do not navigate if the resource_id is malformed (non-UUID format)
Test that role verification is applied before route construction — not after

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Implement NotificationDeepLinkHandler route resolution as a pure function (or a class with no side effects) that takes a NotificationPayload and a UserRole and returns a String route. This makes it trivially unit-testable without mocking a router at all for the core logic tests. Reserve the mocked GoRouter tests for the navigation-side-effect tests (verifying GoRouter.go() is called with the correct argument). Define a sealed class or enum NotificationRouteResult with variants: Resolved(String route), Fallback(String reason), and RoleViolation(String redirectRoute) so test assertions are type-safe rather than string comparisons.

Use const test data fixtures defined at the top of the test file for all payload variants.

Testing Requirements

Pure unit tests (flutter_test) with no widget tree or real routing. Use mockito or mocktail to create MockGoRouter and MockSupabaseClient. Organize tests into describe groups matching each acceptance criterion. Use fakeAsync for the cold-start deferred navigation test to control the async timing of auth state arrival.

Parameterize the route resolution tests using a table-driven approach (list of input payloads → expected output routes) to ensure all category/role combinations are covered without repetitive test code. Add a test that verifies the route resolution map is exhaustive — i.e., every NotificationCategory enum value has a corresponding route entry.

Component
Notification Deep Link Handler
service medium
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.