Scenario Rule
Data Entity
Description
Defines the trigger conditions and message template for a context-aware scenario notification (e.g., 'no activity logged in 21 days', '50th session milestone reached', 'certificate expiring in 30 days'). Rules are scoped to organization chapters and individually togglable by coordinators. Evaluated daily by a scheduled edge function with per-rule cooldown enforcement.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key — auto-generated UUID for each scenario rule record | PKrequiredunique |
organization_unit_id |
uuid |
Foreign key referencing the organization_units table. Rules are scoped to a chapter-level unit so coordinators can configure scenarios independently per chapter. | required |
scenario_type |
enum |
Identifies which scenario template this rule implements. Drives how trigger_condition JSON is interpreted by the rule engine. | required |
trigger_condition |
json |
Structured configuration for the trigger threshold, interpreted according to scenario_type. Examples: {"threshold_days": 21} for inactivity; {"milestone_count": 50} for milestone; {"lead_time_days": 30} for certificate_expiry. The rule engine validates this against a per-type schema. | required |
cooldown_days |
integer |
Minimum number of days that must elapse before this rule can fire again for the same peer mentor. Prevents notification fatigue from repeated identical triggers. Default is 7 for most scenario types. | required |
is_enabled |
boolean |
Coordinator-controlled toggle. When false the rule is skipped entirely during daily evaluation. Defaults to true so rules are active upon creation. | required |
message_template |
text |
Notification message template with {{placeholder}} tokens for runtime substitution. Supported tokens vary by scenario_type (e.g., {{peer_mentor_name}}, {{days_inactive}}, {{milestone_count}}, {{days_until_expiry}}). Must be in Norwegian (Bokmål) unless an org-level locale override exists. | required |
title_template |
text |
Short notification title template with {{placeholder}} support. Used for the push notification title and in-app notification header. Max 100 characters after substitution. | required |
deep_link_route |
string |
Optional go_router-compatible route path that the notification should navigate to on tap (e.g., '/activity/register', '/peer-mentor/{{peer_mentor_id}}'). Null means the notification opens the home screen. | - |
evaluation_order |
integer |
Processing order for the daily evaluation batch when multiple rules belong to the same organization unit. Lower numbers are evaluated first. Allows coordinators to prioritize critical scenarios. | - |
created_by |
uuid |
User ID of the coordinator or admin who created or last saved this rule. Used for audit and to attribute changes in coordinator-facing rule history. | - |
created_at |
datetime |
Timestamp of rule creation in UTC, set automatically by Supabase default. | required |
updated_at |
datetime |
Timestamp of last modification in UTC. Updated by a Supabase trigger on every row change. | required |
Database Indexes
idx_scenario_rule_org_unit
Columns: organization_unit_id
idx_scenario_rule_type_org_unit
Columns: scenario_type, organization_unit_id
idx_scenario_rule_enabled_org_unit
Columns: is_enabled, organization_unit_id
idx_scenario_rule_created_at
Columns: created_at
Validation Rules
cooldown_days_minimum
error
Validation failed
message_template_non_empty
error
Validation failed
message_template_valid_placeholders
error
Validation failed
trigger_condition_is_valid_json
error
Validation failed
trigger_condition_threshold_positive
error
Validation failed
organization_unit_exists
error
Validation failed
deep_link_route_format
warning
Validation failed
scenario_type_is_known_enum
error
Validation failed
Business Rules
one_rule_per_scenario_type_per_unit
Each organization unit may have at most one scenario rule of each scenario_type. This prevents conflicting duplicate rules and makes coordinator configuration predictable. Enforced by the unique index on (scenario_type, organization_unit_id).
coordinator_scoped_toggle
Only coordinators assigned to the matching organization_unit_id, or org admins in its ancestor hierarchy, may toggle is_enabled on a rule. Peer mentors have no write access to scenario rules.
cooldown_enforced_per_mentor
Before dispatching a prompt, the scheduler verifies that no ScenarioPrompt exists for the same (peer_mentor_id, scenario_rule.id) pair with sent_at within the last cooldown_days. Rules with cooldown_days = 0 are not permitted; minimum is 1.
disabled_rules_skipped_in_evaluation
During the daily scheduled evaluation, the edge function loads only rules where is_enabled = true. Disabled rules generate no prompts regardless of whether trigger conditions are met.
trigger_condition_schema_matches_scenario_type
The JSON structure of trigger_condition must conform to the schema expected for the given scenario_type. For example, inactivity requires a numeric threshold_days key; milestone requires milestone_count. The rule engine rejects rules with non-conforming conditions at load time and logs a warning.
chapter_level_unit_required
organization_unit_id must reference an organization unit at the chapter level (not a national association or regional office). This ensures rules are always tied to the unit whose coordinator manages the affected peer mentors.
default_rules_seeded_on_unit_creation
When a new organization unit is created, a set of default scenario rules (all scenario_types with org-standard defaults, is_enabled = true) is seeded via scenario-rule-repository.insertDefaultRules(). Coordinators can then customise or disable these defaults.
CRUD Operations
Storage Configuration
Entity Relationships
Scenario notification rules are configured per chapter so coordinators can enable or disable scenarios for their specific unit
A scenario rule generates multiple prompt instances over time as its trigger conditions are met for different peer mentors