Implement PeerMentorStatusRepository data layer
epic-peer-mentor-pause-management-core-workflows-task-002 — Build the data access layer for pause status persistence. Implement methods: getPauseStatus(mentorId), savePauseRecord(record), updatePauseStatus(mentorId, status), getActivePausedMentors(coordinatorId), and streamStatusChanges(mentorId). Use Supabase client with proper RLS-aware queries and error handling.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Define a PauseRecord Dart class with fromJson/toJson using explicit field mapping — do not rely on generated code for this small model. Define PauseStatus as a Dart enum with a fromString factory handling all three values. For streamStatusChanges, use supabase.from('pause_records').stream(primaryKey: ['id']).eq('mentor_id', mentorId) — this returns a Stream> from which you take the first element. Cancel the subscription in a dispose method.
Expose the repository via a Riverpod Provider
Testing Requirements
Write unit tests using flutter_test with a mocked Supabase client. Test: (1) getPauseStatus returns correct PauseRecord when row exists. (2) getPauseStatus returns null when no row found. (3) savePauseRecord maps returned JSON to PauseRecord correctly.
(4) updatePauseStatus sends correct filter and update payload. (5) getActivePausedMentors filters by coordinator_id and status correctly. (6) All methods propagate typed exceptions on Supabase error responses (400, 401, 403, 503). (7) streamStatusChanges emits new value on simulated Realtime event.
Achieve 90%+ line coverage on repository class. Integration test: run against a local Supabase instance seeded with test data.
Concurrent status transitions (e.g., coordinator and automated scheduler both attempting to update the same mentor's status simultaneously) may produce race conditions or inconsistent state in the database, leading to audit log gaps or incorrect notifications.
Mitigation & Contingency
Mitigation: Implement all status transitions as atomic Postgres RPC functions with optimistic locking (version column or updated_at check). Use database-level constraints rather than application-level guards as the final enforcement point.
Contingency: Add a compensation job that reconciles status and log table consistency on each nightly scheduler run, surfacing any discrepancies to coordinator dashboards.
The coordinator-to-mentor assignment relationship may not always be 1:1 or may be stale (coordinator reassigned after a pause was set), causing notifications to be sent to the wrong coordinator or not sent at all.
Mitigation & Contingency
Mitigation: Query the assignment relationship at notification dispatch time rather than caching it at pause creation time. Add a fallback to notify the chapter administrator if no active coordinator assignment exists.
Contingency: Log all undeliverable notification attempts with the originating mentor ID so administrators can manually follow up, and surface undelivered notification counts on the coordinator dashboard.
The CoordinatorPauseRosterScreen may load slowly for coordinators managing large rosters with many concurrent certification expiry queries, degrading usability on low-bandwidth mobile connections.
Mitigation & Contingency
Mitigation: Use a single Supabase RPC that joins mentor status, certification expiry, and assignment data in one query rather than N+1 individual calls. Implement pagination with a configurable page size and skeleton loading states.
Contingency: Add an offline cache of the last-fetched roster state using Riverpod with SharedPreferences, ensuring coordinators can at minimum view stale data when connectivity is poor.