Implement ScenarioNotificationRepository for record and cooldown persistence
epic-scenario-push-engagement-foundation-task-004 — Implement ScenarioNotificationRepository in Dart with methods: recordNotificationSent(record), updateDeliveryStatus(id, status), getCooldownTimestamp(userId, scenarioType), upsertCooldown(userId, scenarioType, timestamp), and getPendingRetries(). All methods must use the Supabase client and handle network errors with typed exceptions.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Define DeliveryStatus as a Dart enum with values pending, delivered, failed, retrying and a toDbString() extension to map to the Supabase CHECK constraint values. Define a MAX_RETRY_COUNT constant (suggested: 3) in a shared constants file — do not hardcode in the query. For upsertCooldown(), use supabase.from('scenario_notification_cooldowns').upsert({'user_id': userId, 'scenario_type': scenarioType, 'last_triggered_at': timestamp.toIso8601String()}, onConflict: 'user_id,scenario_type') — the onConflict parameter must match the composite PK columns exactly. For recordNotificationSent(), always request .select() after insert to get the server-generated id and sent_at back rather than assuming client-side values.
Register the Riverpod provider adjacent to the NotificationPreferencesRepository provider in the same providers.dart file for discoverability.
Testing Requirements
Unit tests with mocked SupabaseClient covering: (1) recordNotificationSent calls insert with correct payload and maps response to model. (2) updateDeliveryStatus calls update with correct id filter and status value. (3) getCooldownTimestamp returns null when Supabase returns empty list. (4) getCooldownTimestamp returns correct DateTime when row exists.
(5) upsertCooldown calls upsert with ON CONFLICT option and correct columns. (6) getPendingRetries filters by delivery_status in ('pending', 'failed') and retry_count < max. (7) Any method wraps SupabaseException into ScenarioNotificationException. Minimum 7 unit tests.
Use a ScenarioNotificationException matcher to assert typed error wrapping.
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.
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.
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.