high priority medium complexity testing pending testing specialist Tier 5

Acceptance Criteria

All tests pass with `flutter test` using only mocked dependencies — no live Supabase connection required
Test: permission granted for in-scope mentor → mock scope validator returns allowed → registerProxyActivity reaches the duplicate check step
Test: permission denied for out-of-scope mentor → mock scope validator returns denied → method returns ProxyRegistrationResult.permissionDenied and does NOT call the duplicate detector or repository
Test: duplicate detected → mock duplicate detector returns one MentorDuplicateWarning → method returns ProxyRegistrationResult.duplicateWarning without calling the repository
Test: duplicateWarning result is non-blocking → the returned result carries both the warning list and the pending ActivityPayload so the caller can proceed
Test: successful registration → all mocks return clean results → repository.insert returns a record ID → method returns ProxyRegistrationResult.success(recordId)
Test: payload.recorded_by_user_id equals the mocked session coordinator ID even when a different coordinatorId is passed as the method argument
Test: repository throws a Supabase exception → method returns ProxyRegistrationResult.persistenceError with a non-null message
Test: repository throws a network timeout → method returns ProxyRegistrationResult.persistenceError (no exception propagates to caller)
All four ProxyRegistrationResult variants are exercised in at least one test each
Test file follows the existing test file naming convention (proxy_registration_service_test.dart)
Mock setup uses mockito or mocktail — no real Supabase client is instantiated

Technical Requirements

frameworks
Flutter
Dart
flutter_test
mockito or mocktail
data models
ProxyRegistrationResult
ActivityPayload
MentorDuplicateWarning
PeerMentorScopeRecord
performance requirements
All unit tests complete in under 5 seconds total (no I/O, all mocked)
security requirements
Tests must verify that the session coordinator ID overrides caller-supplied coordinatorId — this is the critical security invariant

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Structure the test file with a setUp() block that initialises all mocks and creates a fresh ProxyRegistrationService instance with injected mocks. Use when(mock.method()).thenReturn() for synchronous stubs and when(mock.method()).thenAnswer((_) async => value) for async stubs. For the 'payload uses session coordinator ID' test, configure the mock auth session to return a specific coordinator UUID and then assert that the ActivityPayload passed to repository.insert() contains that UUID regardless of the coordinatorId argument. For the DuplicateWarning non-blocking test, verify the pendingPayload in the result is structurally equal to what would have been persisted — use equatable or freezed equality on ActivityPayload.

Cover the PersistenceError path by throwing both a generic Exception and a PostgrestException from the mocked repository.

Testing Requirements

Use flutter_test as the test framework. Create mock classes for ProxyActivityRepository, ProxyDuplicateDetector, and the coordinator scope/permission validator using mockito @GenerateMocks or mocktail Mock base class. Group tests by scenario using group() blocks: 'permission checks', 'duplicate detection', 'successful registration', 'error handling', 'payload integrity'. Each group should have at least 2 test cases.

Use expect() with matcher isA() and pattern matching on the sealed type variants. Verify call counts on mocks (e.g., verifyNever(mockRepository.insert) when permission is denied). Aim for 100% branch coverage of the registerProxyActivity method.

Component
Proxy Registration Service
service medium
Epic Risks (2)
high impact low prob security

The Proxy Registration Service must verify that the coordinator has a legitimate assignment relationship with the target peer mentor before creating a record. If this check is implemented only in application code and not enforced at the DB/RLS level, a compromised or buggy client could bypass it by calling the Supabase endpoint directly, creating fraudulent proxy records for arbitrary peer mentors.

Mitigation & Contingency

Mitigation: Implement permission validation at two levels: (1) application-layer check in Proxy Registration Service that queries the assignments table before constructing the payload, and (2) RLS policy on the activities table that restricts INSERT to rows where recorded_by_user_id matches the authenticated user AND peer_mentor_id is in the set of peer mentors assigned to that coordinator. The RLS policy is the authoritative guard; the service-layer check provides early user-facing feedback.

Contingency: If RLS policy implementation is blocked by Supabase plan constraints, implement a Supabase Edge Function as a proxy endpoint that enforces the permission check server-side before forwarding to the DB. Disable direct client inserts entirely for proxy activities.

medium impact medium prob technical

For a bulk session with 30 selected peer mentors, the Proxy Duplicate Detector must query existing activities for each mentor. If implemented as 30 sequential Supabase queries, round-trip latency could make the bulk confirmation screen feel slow (>3s), degrading coordinator experience and potentially causing timeouts.

Mitigation & Contingency

Mitigation: Implement the duplicate check as a single Supabase query using an IN clause on peer_mentor_id combined with the activity_type and date filters, returning all potential duplicates for the entire batch in one network round-trip. Group results client-side by mentor ID to produce the per-mentor warning structure.

Contingency: If the single-query approach returns too much data for very large chapters, add a database index on (peer_mentor_id, activity_type, date) and profile query time. If still insufficient, accept a short loading state on the confirmation screen with a progress indicator rather than pre-loading duplicates before navigation.