critical priority low complexity database pending database specialist Tier 0

Acceptance Criteria

Migration file is created under supabase/migrations/ with a timestamped filename (e.g., 20260330000001_create_cert_expiry_reminders.sql)
cert_expiry_reminders table exists in the database after applying the migration with columns: id (uuid, PK, default gen_random_uuid()), mentor_id (uuid, FK to auth.users or profiles table, NOT NULL), chapter_id (uuid, FK to chapters table, NOT NULL), certification_type (text, NOT NULL), issued_date (date, NOT NULL), expiry_date (date, NOT NULL), reminder_30_day_sent (boolean, default false), reminder_7_day_sent (boolean, default false), reminder_1_day_sent (boolean, default false), expired_notification_sent (boolean, default false), created_at (timestamptz, default now()), updated_at (timestamptz, default now())
UNIQUE constraint on (mentor_id, certification_type) to prevent duplicate active certification records per mentor per type
Index on (expiry_date) for efficient scheduled reminder queries
Index on (mentor_id) for per-mentor certification lookups
updated_at column is auto-updated via a trigger on row modification
Migration applies cleanly with zero errors on a fresh Supabase project
Migration is idempotent or guarded with IF NOT EXISTS to support re-runs
A corresponding rollback (down) migration is provided

Technical Requirements

frameworks
Supabase CLI (supabase db push / supabase migration new)
apis
Supabase Database (PostgreSQL)
data models
CertificationStatus
CertExpiryReminder
performance requirements
Queries filtering by expiry_date for scheduled reminder jobs must use the index (EXPLAIN ANALYZE confirms index scan)
Queries filtering by mentor_id must use the index
security requirements
Table created without RLS enabled at this step — RLS is added in the next task (foundation-task-002)
Foreign key to mentor profiles table enforces referential integrity — no orphaned certification records
Migration file must not contain any hardcoded UUIDs or environment-specific values

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Use the Supabase CLI workflow: supabase migration new create_cert_expiry_reminders, then write the SQL in the generated file. For the updated_at auto-update trigger, use the standard Supabase pattern of creating a moddatetime extension trigger (already available in Supabase projects). The certification_type column should be constrained to a known set of values using a CHECK constraint or a separate enum type — consult with the domain team on valid values (e.g., 'peer_mentor_basic', 'peer_mentor_advanced') before finalizing. Use uuid_generate_v4() or gen_random_uuid() for the default PK depending on the PostgreSQL version available in the Supabase project.

Commit both the up and down migration files to version control.

Testing Requirements

After applying the migration against the local Supabase development instance (supabase start), verify: (1) all columns exist with correct types using \d cert_expiry_reminders in psql or the Supabase Studio table editor; (2) insert a test row and confirm updated_at auto-updates on modification; (3) attempt to insert a duplicate (mentor_id, certification_type) pair and confirm the unique constraint rejects it; (4) run EXPLAIN ANALYZE on a query filtering by expiry_date to confirm index usage. No Dart tests at this layer — schema validation is sufficient.

Component
Certification Status Repository
data low
Epic Risks (3)
high impact medium prob security

Supabase RLS policies for coordinator-scoped status queries may be difficult to express correctly, especially for peer mentors assigned to multiple coordinators or chapters, leading to data leakage or overly restrictive access blocking valid queries.

Mitigation & Contingency

Mitigation: Design RLS policies using security-definer RPCs rather than table-level policies for complex multi-coordinator scenarios. Write a comprehensive RLS test matrix covering all role and assignment permutations before marking complete.

Contingency: Fall back to application-level filtering in the repository layer with explicit coordinator_id parameter checks if RLS proves intractable, and document the trade-off for security review.

high impact medium prob dependency

The HLF Dynamics portal API contract may be undocumented or subject to change, causing the DynamicsPortalClient to break during development or production rollout.

Mitigation & Contingency

Mitigation: Obtain the full Dynamics portal API specification and credentials early in the sprint. Build the client behind a well-defined interface so the HLF-specific implementation can be swapped without affecting upstream services.

Contingency: If the Dynamics API is unavailable or unstable, stub the client with a feature-flag-guarded no-op implementation so all other epics can proceed to completion independently.

medium impact low prob technical

Supabase Edge Functions used as the nightly scheduler host may have cold-start latency or execution time limits that prevent reliable nightly certification checks on large mentor rosters.

Mitigation & Contingency

Mitigation: Benchmark Edge Function execution time against the expected roster size. Design the expiry check to process in paginated batches to stay within execution limits. Use pg_cron with a direct database function as an alternative trigger if Edge Functions prove unreliable.

Contingency: Migrate the scheduler trigger to pg_cron invoking a Postgres function directly, removing the Edge Function dependency entirely for the scheduling layer.