Load scenario evaluation config in trigger engine
epic-scenario-push-engagement-core-engine-task-004 — Integrate the scenario-evaluation-config (from Epic 1, component 583) into the trigger engine. Fetch configurable values — inactivity window in days, milestone session counts, certification expiry lead time in days, and cooldown durations per scenario type — at engine startup so all evaluations use live config without redeployment.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Store the scenario-evaluation-config in a single jsonb column or a structured row — avoid EAV (Entity-Attribute-Value) tables for config as they require N queries to assemble. A single row per organization_id with a jsonb `config` column is the simplest pattern that supports future field additions without schema migrations. In the Edge Function (Deno/TypeScript), define an interface `ScenarioEvaluationConfig` and use a parse function that applies defaults for each field individually using `?? defaultValue` — this way a partially-specified config row still works correctly.
Pass the config object as the first argument to each evaluator function rather than making it a module-level singleton — this makes unit testing evaluators trivial as each test can supply its own config.
Testing Requirements
Unit tests: verify default config is used when DB returns no row; verify config fields are correctly parsed from a mock DB response; verify malformed config (missing field, wrong type) falls back to defaults without throwing. Integration test: insert a config row in a test Supabase instance, invoke engine startup, assert the returned config matches the inserted row. Test that cooldownByScenarioType correctly maps per-type values and that missing keys default to a global fallback cooldown value.
The scenario-edge-function-scheduler must evaluate all active peer mentors within the 30-second Supabase Edge Function timeout. For large organisations, a sequential evaluation loop may exceed this limit, causing partial runs and missed notifications.
Mitigation & Contingency
Mitigation: Design the trigger engine to batch mentor evaluations using database-side SQL queries (bulk inactivity check via a single query rather than per-mentor calls), and add a performance test against 500 mentors during development. Document the evaluated mentor count per scenario type in scenario-evaluation-config to allow selective scenario execution per run.
Contingency: If single-run execution is insufficient, split evaluation into per-scenario-type scheduled functions (inactivity check, milestone check, expiry check) on separate cron schedules, dividing the computational load across multiple invocations.
A race condition between concurrent scheduler invocations or retried cron triggers could cause the same scenario notification to be dispatched multiple times to a mentor, severely degrading trust in the feature.
Mitigation & Contingency
Mitigation: Implement cooldown enforcement using a database-level upsert with a unique constraint on (user_id, scenario_type, cooldown_window_start) so that a second invocation within the same window is rejected at the persistence layer rather than the application layer.
Contingency: Add an idempotency key derived from (user_id, scenario_type, evaluation_date) to the notification record insert; if a duplicate key violation is caught, log it as a warning and skip dispatch without error.
The trigger engine queries peer mentor activity history across potentially multiple organisations and chapters. RLS policies configured for app-user roles may block the Edge Function's service-role queries, or query performance may degrade on large activity tables.
Mitigation & Contingency
Mitigation: Confirm the Edge Function runs with the Supabase service role key (bypassing RLS) and add composite indexes on (user_id, activity_date) to the activity tables before implementing the inactivity detection query.
Contingency: If service-role access is restricted by organisational policy, implement a dedicated database function (SECURITY DEFINER) that performs the inactivity aggregation and is callable by the Edge Function with limited scope.