Create Supabase tables for peer mentor pause status
epic-peer-mentor-pause-management-foundation-task-004 — Create the peer_mentor_status and peer_mentor_status_log Supabase database tables. Define columns for pause state, reason, expected return date, activated_by, timestamps, and chapter association. Apply indexes on mentor_id and status fields for query performance.
Acceptance Criteria
Technical Requirements
Implementation Notes
The UNIQUE constraint on peer_mentor_status.mentor_id means there is exactly one status record per mentor, updated in-place on each transition — the full history lives in peer_mentor_status_log. This is a deliberate design choice that simplifies lookups (no need to query for the latest record) but requires a trigger to write log entries. Consider implementing the audit trigger in this same migration using a PostgreSQL trigger function: CREATE OR REPLACE FUNCTION log_mentor_status_change() RETURNS TRIGGER AS $$ BEGIN INSERT INTO peer_mentor_status_log (mentor_id, chapter_id, previous_status, new_status, changed_by, changed_at) VALUES (OLD.mentor_id, OLD.chapter_id, OLD.status, NEW.status, NEW.activated_by, now()); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_mentor_status_log AFTER UPDATE OF status ON peer_mentor_status FOR EACH ROW EXECUTE FUNCTION log_mentor_status_change(); This ensures the audit log is always in sync regardless of which service performs the update.
Testing Requirements
After applying the migration to the local Supabase instance: (1) verify all columns on both tables with \d+ peer_mentor_status and \d+ peer_mentor_status_log; (2) insert a row with status='active' and confirm it succeeds; (3) attempt to insert status='unknown_value' and confirm CHECK constraint rejects it; (4) insert two rows with the same mentor_id in peer_mentor_status and confirm UNIQUE constraint rejects the second; (5) run EXPLAIN ANALYZE on the composite index query (chapter_id + status filter) to confirm index scan; (6) insert a log row and attempt to UPDATE it, confirming it is blocked if the append-only policy/rule is already in place. Document results in a test_schema_verification.sql file.
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.
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.
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.