Create scenario_rules database migration
epic-scenario-based-follow-up-prompts-foundation-task-001 — Write and apply a Supabase database migration that creates the scenario_rules table. The table must store JSON-configured rule definitions per chapter, including columns for rule_id, chapter_id, scenario_type, trigger_conditions (JSONB), prompt_content (JSONB), active flag, and timestamps. Include appropriate indexes on chapter_id and scenario_type for efficient lookups.
Acceptance Criteria
Technical Requirements
Implementation Notes
Use supabase/migrations/ directory structure with Supabase CLI conventions. The updated_at auto-update can be implemented with a PostgreSQL trigger function (moddatetime extension if available, or a custom trigger). Define the scenario_type CHECK constraint as an exhaustive list matching the EvaluationResult enum cases — this creates a contract between the database and Dart code. For JSONB columns, document the expected schema in a SQL comment on the column (COMMENT ON COLUMN scenario_rules.trigger_conditions IS '...') rather than enforcing full JSON schema validation in PostgreSQL (too complex).
The RLS policy pattern should follow the existing patterns already established in the project for other tables (check existing migrations for the chapter access control approach). If the project uses a chapters table with a members junction, the RLS SELECT policy should be: USING (chapter_id IN (SELECT chapter_id FROM chapter_members WHERE user_id = auth.uid())).
Testing Requirements
Write a migration smoke test that: (1) applies the migration to the Supabase test instance; (2) inserts one valid row for each scenario_type enum value and asserts INSERT succeeds; (3) attempts to insert a row with an invalid scenario_type and asserts CHECK constraint violation; (4) queries by chapter_id and asserts the correct rows are returned; (5) asserts EXPLAIN ANALYZE for a chapter_id lookup uses the index (not a seq scan). Run these via the Supabase test project in CI. Additionally verify RLS by attempting a SELECT as an unauthenticated user and asserting zero rows returned.
Supabase RLS policies for chapter-scoped rule access may interact unexpectedly with service-role keys used by the Edge Function, potentially blocking backend reads or leaking cross-chapter data.
Mitigation & Contingency
Mitigation: Write and review RLS policies in isolation with automated policy tests before merging; define a dedicated service-role bypass policy scoped to the edge function's Postgres role.
Contingency: If RLS blocks the edge function, temporarily use a bypass policy with audit logging while a permanent fix is implemented; escalate to a Supabase security review.
FCM device tokens become invalid when users reinstall the app or revoke permissions; stale tokens cause silent delivery failures that are hard to detect without explicit error handling.
Mitigation & Contingency
Mitigation: Implement token invalidation handling in PushNotificationDispatcher that removes stale tokens from the database on FCM 404/410 responses; log all delivery failures with structured output.
Contingency: If token hygiene proves unreliable, add a periodic token refresh job that re-registers all active users' tokens via the FCM registration endpoint.