high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

Test file compiles and all tests pass with `flutter test`
Initial fetch test: provider transitions through AsyncLoading then AsyncData states; returned list maps raw Supabase rows to PeerMentorContact objects with all fields correctly populated
Cache hit test: reading the provider a second time without invalidation does NOT trigger a second Supabase query (mock's method is called exactly once)
Cache invalidation test: calling `ref.invalidate(proxyContactListProvider)` causes the provider to re-fetch and mock is called a second time
Empty roster test: mock returns an empty list; provider resolves to AsyncData([]) without throwing
Error surfacing test: mock throws a PostgrestException; provider resolves to AsyncError with the exception accessible via `.error`
RLS query test: the Supabase query captured by the mock includes a filter scoped to the coordinator's organisation_id (or equivalent RLS-aware parameter)
No real Supabase network calls are made during any test

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
apis
Supabase PostgREST (peer_mentor_contacts table or equivalent view)
data models
PeerMentorContact
performance requirements
All tests complete in under 1 second total
security requirements
Assert that the query includes RLS-aware scoping — test must fail if the query is issued without an organisation filter

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

If ProxyContactListProvider uses a repository abstraction (e.g., `IProxyContactRepository`), override the repository provider in ProviderContainer for clean isolation. If it calls Supabase directly, inject a mock via a `supabaseClientProvider` override. For the caching test, ensure the provider uses Riverpod's `keepAlive()` or equivalent caching strategy — if it does not, the cache test should document this as a known limitation rather than falsely passing. For RLS assertion: capture the `.eq()` or `.match()` call arguments on the mock query builder and assert the correct column/value pair.

Use `expectAsync` or `completes` matchers for async state assertions.

Testing Requirements

Use Riverpod's `ProviderContainer` with `overrides` to inject a mock Supabase repository or data source. Do not test Riverpod internals — test the provider's observable state transitions (AsyncLoading → AsyncData / AsyncError). Use `container.listen()` or `container.read()` with `await container.pump()` as appropriate for async providers. Group tests: (1) happy path with data, (2) empty data, (3) error path, (4) caching behaviour, (5) cache invalidation.

Verify mock call counts explicitly for cache tests.

Component
Proxy Contact List Provider
data low
Epic Risks (2)
high impact medium prob security

Adding recorded_by_user_id to the activities table and writing correct RLS policies is error-prone: overly permissive policies would allow coordinators to record activities under arbitrary user IDs they do not manage, while overly restrictive policies would silently block valid proxy inserts. A policy defect here would either create a security vulnerability or break the entire proxy feature at runtime.

Mitigation & Contingency

Mitigation: Write RLS policies in a local Supabase emulator first. Include policy unit tests using pg_tap or supabase test helpers. Have a second reviewer check the migration SQL before merging. Explicitly test the three cases: coordinator inserting for their own mentors (should succeed), coordinator inserting for another chapter's mentors (should fail), peer mentor inserting for themselves (should succeed as before).

Contingency: If a policy defect is discovered in staging, roll back the migration with a down-migration script. Delay feature release until the policy is corrected and re-verified. Apply a feature flag to keep the proxy entry point hidden from coordinators until the fix is confirmed.

high impact low prob technical

The insert_bulk_activities RPC must behave atomically — a failure on row 7 of 12 must roll back rows 1–6. If Supabase's RPC transaction handling is misconfigured or if network interruptions cause partial acknowledgements, some peer mentors could receive duplicate or missing activity records, directly corrupting Bufdir statistics for the coordinator's chapter.

Mitigation & Contingency

Mitigation: Implement the RPC as a PostgreSQL function with explicit BEGIN/EXCEPTION/END block to guarantee atomicity. Add an integration test that inserts a batch where one row violates a unique constraint and asserts zero rows are committed. Document the transaction semantics in code comments.

Contingency: If atomicity cannot be guaranteed via RPC (e.g., due to Supabase plan limitations), fall back to a sequential insert loop with a compensating DELETE in case of partial failure, and surface a clear error to the coordinator listing which mentors failed and which succeeded.