Implement ScenarioRuleRepository read/write interface
epic-scenario-based-follow-up-prompts-core-logic-task-002 — Create the ScenarioRuleRepository class backed by the scenario_rules Supabase table. Implement fetchRulesForChapter(chapterId), upsertRule(rule), deleteRule(ruleId), and fetchDefaultTemplates(). Include Riverpod provider. This is the data access layer that both the Rule Engine and Configuration Manager depend on.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Follow the repository pattern already established in the codebase — define an abstract ScenarioRuleRepository interface first, then implement SupabaseScenarioRuleRepository. This allows the Rule Engine and Configuration Manager to depend on the interface, making them testable with mock repositories. For caching: use a simple in-memory Map
For upsert: set the Prefer: resolution=merge-duplicates header via the Supabase Flutter client's upsert method. Ensure the scenario_rules Supabase table has the correct indexes: chapter_id (for fetchRulesForChapter), enabled (partial index where enabled = true). The fetchDefaultTemplates method supports the future admin portal use case where org admins can start from a template rather than creating rules from scratch.
Testing Requirements
Write unit tests in test/features/scenario_prompts/repositories/scenario_rule_repository_test.dart using a mock Supabase client (implement a MockSupabaseClient or use mockito/mocktail). Cover: (1) fetchRulesForChapter returns correctly deserialized list, (2) fetchRulesForChapter with empty result returns empty list, (3) upsertRule sends correct payload and returns updated rule, (4) deleteRule sends correct filter, (5) fetchDefaultTemplates filters on null chapter_id, (6) Supabase error propagates as ScenarioRuleRepositoryException with correct code, (7) RLS violation (403 response) maps to PermissionDeniedException. Also write one integration test against a local Supabase instance to verify the actual SQL queries and RLS policies work end-to-end.
The Rule Engine must support a flexible JSON rule schema that can express compound conditions (e.g., contact_type AND wellbeing_flag AND delay_days). Underestimating schema expressiveness may require breaking changes to the rule format after coordinators have already configured rules.
Mitigation & Contingency
Mitigation: Define and freeze the rule JSON schema (trigger_type enum, metadata_conditions structure, delay logic) before any implementation begins; validate schema against all known HLF scenarios documented in the feature spec.
Contingency: If schema changes are needed after deployment, implement a schema version field and a migration utility that upgrades stored rules to the new format without coordinator intervention.
Deep-link navigation to the activity wizard with pre-filled arguments may fail if the user's session has expired or if the wizard route is not yet mounted in the navigator stack, causing unhandled navigation exceptions.
Mitigation & Contingency
Mitigation: Implement session state check before navigation; if session is expired, redirect to biometric/login screen and store the pending deep-link URI for post-auth redirect using go_router's redirect mechanism.
Contingency: If post-auth redirect proves unreliable, fall back to navigating to the home screen with a visible action banner that re-triggers the wizard with pre-filled arguments.