Implement ContactRepository with Supabase client wiring
epic-contact-list-management-foundation-task-006 — Build the ContactRepository class that accepts a Supabase client and a ContactRLSQueryBuilder instance via constructor injection. Implement the fetchAll() method that executes a role-scoped, organization-scoped Supabase query, relies on database-level RLS policies for final access enforcement, and maps the JSON response array to a List<Contact> using the typed model.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Create IContactRepository abstract class in lib/features/contacts/domain/repositories/. Concrete implementation goes in lib/features/contacts/data/repositories/. Use Riverpod's Provider or AsyncNotifierProvider to inject ContactRepository — keep the provider thin (just wires dependencies). The mapping loop should use a helper _mapRecord(Map
Avoid using .execute() deprecated Supabase API; use the current .select().eq() chained API. Wrap the entire async body in try/catch catching both PostgrestException and generic Exception to ensure no unhandled exceptions escape the repository boundary.
Testing Requirements
Unit tests with mocked SupabaseClient and ContactRLSQueryBuilder: (1) fetchAll returns List
Existing Supabase RLS policies for the contacts and peer_mentors tables may not align with the application-level UserRole model, causing ContactRLSQueryBuilder to construct filter expressions that are redundant, conflicting, or that allow over-fetching. In a multi-chapter context (NHF), this could expose contacts belonging to other chapters.
Mitigation & Contingency
Mitigation: Audit and document the existing RLS policies against the UserRole enum before writing a single line of query builder code. Write integration tests asserting cross-organization data isolation using separate test user tokens for each role.
Contingency: If RLS policies are misaligned at runtime, add an explicit application-level organization_id equality check in ContactRepository as a secondary guard while the database policies are corrected in a coordinated migration.
The Supabase schema for contacts and peer_mentors tables may differ from the expected typed models — missing columns, renamed fields, or type mismatches — causing deserialization failures that surface only at runtime during integration testing.
Mitigation & Contingency
Mitigation: Document expected schema fields upfront and validate against the live Supabase schema at sprint start. Use freezed and json_serializable for compile-time-safe deserialization with explicit required/optional field declarations.
Contingency: Introduce nullable fields with safe defaults for any schema mismatches discovered in testing; log deserialization errors to the monitoring service so schema drift is caught before production deployment.