high priority medium complexity backend pending frontend specialist Tier 1

Acceptance Criteria

ScenarioDeepLinkRouter exposes a handlePayload(Map<String, dynamic> payload) method that parses scenario_type, entity_id, and target_route fields
For each defined ScenarioType, a corresponding navigation target is resolved; unknown scenario_type values navigate to the app home screen without crashing
Cold-start handling: when the app is launched from a terminated state via notification tap, the payload is read from FirebaseMessaging.instance.getInitialMessage() and routed correctly after app initialisation completes
Foreground handling: when a notification arrives while the app is active, the payload is available for optional in-app banner display or direct navigation based on user action
Background-to-foreground handling: when the app is in background and user taps the notification, FirebaseMessaging.onMessageOpenedApp stream is listened to and routed correctly
Back-stack integrity: navigating to a deep route (e.g. a specific contact detail) pushes the correct ancestor routes (home → contacts list → contact detail) so the back button works as expected
entity_id is validated before navigation; if the entity no longer exists in the local cache or database, the router navigates to the parent list screen with an informational snackbar
All navigation calls are executed on the main isolate; no navigation calls from background isolates
Router integrates with the existing GoRouter configuration without duplicating route definitions
Unit tests cover all ScenarioType routing paths, cold-start, and invalid entity_id fallback

Technical Requirements

frameworks
Flutter
GoRouter
Riverpod
firebase_messaging
apis
Firebase Cloud Messaging (FCM) API v1
data models
assignment
contact
activity
performance requirements
Cold-start route resolution must complete within 500ms of app ready state
Navigation to deep route must not cause a perceptible jank — avoid synchronous blocking calls in routing path
security requirements
Payload fields scenario_type, entity_id, and target_route must be validated and sanitised before use in navigation — reject payloads with unexpected types or excessively long strings
entity_id must be validated as a valid UUID format before any database lookup to prevent injection
Navigation must not expose routes or data beyond the authenticated user's RLS-enforced permissions
ui components
SnackBar (for entity not found fallback)
Bottom navigation bar (for tab restoration on cold-start)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use FirebaseMessaging.instance.getInitialMessage() in the root widget's initState (or a Riverpod provider with autoDispose) to capture cold-start payloads. Use FirebaseMessaging.onMessageOpenedApp.listen() for background-to-foreground. Store initial payload in a Riverpod StateProvider so it can be consumed once after the router is ready. For back-stack integrity with GoRouter, use router.go() with a full path rather than router.push() to ensure ancestor routes are in the stack — or implement a helper that builds the full route stack using router.pushReplacement() for each ancestor.

Avoid handling navigation in a firebase_messaging background handler (background isolate) — only record the payload there and process on foreground resume.

Testing Requirements

Write unit tests using flutter_test. Test handlePayload for every ScenarioType enum value with a valid entity_id. Test cold-start path by simulating getInitialMessage() returning a RemoteMessage. Test onMessageOpenedApp stream handling.

Test invalid scenario_type falls back to home. Test missing entity_id falls back gracefully. Test UUID validation rejects malformed entity_id strings. Integration test: install debug build on a real device via TestFlight; trigger each scenario push type and verify correct screen is reached with correct back-stack.

Achieve 90% branch coverage.

Component
Scenario Deep-Link Router
service medium
Epic Risks (3)
high impact medium prob dependency

FCM service account key and APNs certificate configuration may be missing or misconfigured in the Supabase Edge Function secrets store, blocking end-to-end push delivery testing until resolved by the infrastructure owner.

Mitigation & Contingency

Mitigation: Raise a credentials-setup task in the project board at epic start; document the exact secret names required in scenario-evaluation-config so the infrastructure owner can provision them independently of development work.

Contingency: Implement a mock push-notification-dispatcher stub that records payloads to the database for local testing, allowing the rest of the feature to proceed while credentials are obtained.

high impact low prob security

Incorrect RLS policies on the scenario_notifications or notification_preferences tables could allow one user to read or modify another user's notification records, constituting a data privacy breach.

Mitigation & Contingency

Mitigation: Write dedicated RLS policy tests using Supabase's built-in test framework before any application code touches the tables; require a peer security review of all policy definitions before merging.

Contingency: If a policy gap is discovered post-merge, immediately disable the affected table's read policy, notify the security lead, and deploy a hotfix with corrected policies before re-enabling access.

medium impact medium prob dependency

Norwegian Bokmål ARB localisation strings for all scenario message templates may not be available at implementation time, causing content-builder tests to fail and delaying integration.

Mitigation & Contingency

Mitigation: Define all required ARB message keys in a tracked document shared with the content owner at epic kickoff; use English placeholder strings that follow the final format so template injection logic can be tested independently.

Contingency: Ship with English-only strings in the first release and gate Norwegian strings behind a feature flag that is enabled once translations are reviewed and approved.