critical priority medium complexity backend pending backend specialist Tier 0

Acceptance Criteria

An abstract class `ScenarioPromptSchedulerService` is defined with method signatures for all 5 methods: `fetchActivities`, `runRuleEngine`, `deduplicateHistory`, `dispatchNotification`, and `recordDelivery`
A concrete implementation class `ScenarioPromptSchedulerServiceImpl` implements the abstract class with stub bodies (each method throws `UnimplementedError` with a descriptive message)
All method return types are typed with domain-specific classes or `Future<T>` — no `dynamic` or `Object` return types
A Riverpod `Provider` (or `AsyncNotifierProvider` as appropriate) is defined for `ScenarioPromptSchedulerService` and injects all required dependencies via constructor
The Riverpod provider is overridable in tests to allow dependency injection of mock implementations
Input and output types for each method are defined as separate Dart classes or typedef aliases in a `models/` subdirectory alongside the service — no anonymous Maps used as method parameters
The file compiles without errors with `flutter analyze` producing zero issues
Method signatures are documented with `///` doc comments describing the expected contract of each method

Technical Requirements

frameworks
Flutter
Riverpod
BLoC (if the service is consumed by a BLoC — wire the provider reference only, do not implement BLoC in this task)
apis
Supabase JS client (consumed downstream — referenced in interface docs, not implemented in this task)
data models
activities
prompt_history
peer_mentors
scenario_rules
performance requirements
Service interface must be stateless — all state is passed as parameters or returned as values, never held in instance fields
All methods must be async (return `Future<T>`) to allow non-blocking implementation downstream
security requirements
The service interface must not expose raw Supabase client references in its public method signatures — callers interact only with domain types
Method parameters must not include authentication tokens or service-role keys — authentication is handled by the injected Supabase client instance

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Place the service files at `lib/features/scenario_prompts/services/scenario_prompt_scheduler_service.dart` (abstract class + impl) and `lib/features/scenario_prompts/services/scenario_prompt_scheduler_provider.dart` (Riverpod provider). Define domain types in `lib/features/scenario_prompts/models/`: `ActivityRecord`, `SchedulingContext`, `RuleEngineResult`, `NotificationPayload`, `DeliveryRecord`. Use Riverpod's `@riverpod` code generation annotation if the project already uses it — check existing providers for the pattern in use. For the abstract interface, prefer `abstract interface class` (Dart 3 syntax) over `abstract class` to signal that this is a pure interface contract.

Keep the constructor of `ScenarioPromptSchedulerServiceImpl` taking only the dependencies it will need (Supabase client, notification service ref) so future implementors do not need to refactor the constructor signature.

Testing Requirements

Unit tests for this scaffold task are limited to compilation and structural validation: (1) a test that instantiates a `MockScenarioPromptSchedulerService` (hand-written mock implementing the abstract class) and verifies each method can be called and returns a Future; (2) a test that verifies the Riverpod provider resolves without throwing when given a valid ProviderContainer with required dependency overrides. Use `flutter_test` package. Full method-level tests will be added in subsequent tasks when stub bodies are replaced with real implementations.

Component
Scenario Prompt Scheduler Service
service high
Epic Risks (2)
high impact medium prob technical

If the scheduler runs concurrently (e.g., two overlapping cron invocations due to edge function retry), duplicate prompts could be dispatched before the first run's history records are committed, breaking the deduplication guarantee.

Mitigation & Contingency

Mitigation: Use a Postgres advisory lock or unique constraint on (user_id, scenario_id, activity_ref) in the prompt history table to make concurrent writes idempotent; design the scheduler to check history inside a transaction.

Contingency: If concurrency issues persist in production, add a distributed lock via Supabase Edge Function concurrency limit (max_instances=1) for the evaluation function as a hard guard.

medium impact medium prob scope

Coordinators may find scenario configuration unclear if trigger conditions are expressed as raw JSON or technical terminology, leading to misconfiguration and irrelevant prompts being sent to peer mentors.

Mitigation & Contingency

Mitigation: Design the ScenarioConfigurationScreen to display human-readable descriptions of each template's trigger condition (e.g., 'Send 3 days after first contact if wellbeing concern was flagged') rather than raw rule properties; validate with an HLF coordinator in a design review before implementation.

Contingency: If coordinators still misconfigure rules after launch, add a preview mode that shows a simulated prompt based on a test activity before the rule is enabled.