Implement Supabase Realtime subscription for banner trigger
epic-scenario-push-engagement-ui-task-005 — Wire the in-app-notification-banner to a Supabase Realtime subscription on the scenario_notifications table filtered by the current user. When a new record is detected, show the banner overlay. Use a Riverpod StreamProvider backed by supabase-realtime-subscription-service (527) to propagate the event to the widget layer.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Use supabase.channel('scenario-notifications-
Ensure the StreamProvider is kept alive (keepAlive: true) only while the user is authenticated — use ref.onDispose to cancel the subscription and ref.listen to react to auth state changes.
Testing Requirements
Write unit tests for the StreamProvider: mock supabase-realtime-subscription-service (527) to emit fake INSERT payloads and assert the provider emits corresponding ScenarioNotificationBannerData objects. Assert UPDATE events are filtered out. Assert that stream closes when the mock service is disposed. Write widget tests using a ProviderScope override: inject a fake stream that emits one event and assert the banner widget appears in the widget tree within one pump cycle.
Test the queue behaviour: emit two rapid events and assert the second banner appears only after the first is dismissed. Integration test (device or emulator): subscribe to a real Supabase local instance, INSERT a row, and confirm the banner appears — run as part of CI if a Supabase local dev environment is available. Verify via Supabase dashboard that RLS prevents cross-user event delivery.
The in-app notification banner depends on a Supabase Realtime subscription to detect new notification records. If the subscription reconnects slowly after an app resume from background, or if Realtime delivery is delayed under high load, the banner may not appear within the 2-second acceptance criterion.
Mitigation & Contingency
Mitigation: Implement an explicit subscription reconnect handler on app foreground events using Flutter's AppLifecycleState.resumed hook, and add a polling fallback that queries for unread notifications once per app foreground event as a safety net against missed Realtime events.
Contingency: If Realtime proves unreliable in production, promote the polling fallback to the primary mechanism with a 30-second interval, accepting slight latency in exchange for reliability.
Cold-start deep linking (app not running when push notification is tapped) requires deferred navigation after the Flutter engine and Supabase session are fully initialised. If the deep link is consumed before authentication completes, the router may navigate to a protected route without a valid session, causing an error or redirect loop.
Mitigation & Contingency
Mitigation: Implement a deferred navigation queue in scenario-deep-link-router that holds the parsed deep-link target until the auth session restoration lifecycle event fires, following the existing deep-link-handler pattern used in the BankID and Vipps authentication flows.
Contingency: If deferred navigation is not achievable within the epic's scope, fall back to navigating the user to the notification centre (which is always accessible post-login) where the relevant notification record is visible and tappable.