Implement PeerMentorRepository profile fetch method
epic-peer-mentor-detail-screen-data-layer-task-002 — Implement the fetchPeerMentorProfile(String mentorId) method in PeerMentorRepository using the Supabase client provider. The method must query the peer_mentors table, map the raw JSON response to a typed PeerMentorProfile model, handle missing records with a typed exception, and respect RLS policies enforced at the Supabase layer without client-side re-filtering.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Check whether the project already has a base Repository class or interface — if so, extend it. Define a PeerMentorRepositoryProvider using Riverpod's riverpod_annotation or plain Provider/StateNotifierProvider as the project convention dictates. The repository should expose an abstract interface (IPeerMentorRepository) to allow easy mocking in BLoC tests. Catch PostgrestException specifically before catching the base Exception to ensure correct error classification.
The PGRST116 code indicates 'JSON object requested, multiple (or no) rows returned' from PostgREST — this is the standard not-found signal when using .single(). Avoid using .maybeSingle() unless a null return is semantically valid for this use case (a missing profile should be an error state, not a null state).
Testing Requirements
Unit tests using flutter_test with a mocked SupabaseClient (use mockito or mocktail, whichever the project already uses). Test file: test/features/peer_mentor/data/repositories/peer_mentor_repository_test.dart. Required test cases: (1) returns PeerMentorProfile when Supabase returns valid JSON, (2) throws MentorNotFoundException when Supabase returns PGRST116 error code, (3) throws RepositoryException for unexpected PostgrestException, (4) throws ArgumentError or RepositoryException when mentorId is empty string. Mock the Supabase .from().select().eq().single() call chain.
Do not make real network calls in tests.
Supabase RLS policies for peer mentor data may block coordinator queries if the RLS rules are written for peer-mentor-self access only, requiring policy updates that affect other features sharing the same tables.
Mitigation & Contingency
Mitigation: Review existing RLS policies on peer_mentors, certification_records, and activity_log tables before writing repository queries. Coordinate with the database team to add coordinator-role predicates without weakening existing mentor-self policies.
Contingency: If policy changes are blocked, implement a Supabase Edge Function as a secure query proxy that enforces authorization server-side, avoiding direct RLS policy modification.
The activity log table schema may not have a mentor_id foreign key column or may require a JOIN through an intermediate table, making the aggregation query significantly more complex than anticipated.
Mitigation & Contingency
Mitigation: Inspect the actual Supabase activity_log table schema before starting the MentorActivityLogRepository implementation. Document the exact JOIN path needed and validate it returns correct results for a known mentor.
Contingency: If schema requires complex multi-table aggregation, implement a Supabase database function (RPC) and expose it via the repository's fetchSummary method to keep Dart code clean.
The Blindeforbundet assignment table may not yet exist in the shared Supabase schema or may have a different structure than assumed, blocking the AssignmentHistoryRepository implementation.
Mitigation & Contingency
Mitigation: Verify the assignments table exists and confirm its column structure with the Contact Detail & Edit Screen team which also depends on assignment data (assignment-repository in that feature).
Contingency: If the assignments table is not yet available, implement the AssignmentHistoryRepository with a stub returning empty list and a TODO marker, unblocking the aggregation service while the schema is finalized.