high priority medium complexity testing pending testing specialist Tier 3

Acceptance Criteria

Test file compiles and all tests pass with `flutter test`
Successful batch insert test: mock returns valid UUID list; adapter returns the same list without modification
Partial payload rollback test: mock throws a Supabase PostgrestException mid-insert; adapter surfaces a typed domain exception (e.g., BatchInsertException) and does NOT return partial IDs
Network error propagation test: mock throws a generic network/socket exception; adapter wraps it in the correct typed exception with the original cause preserved
Empty list test: passing an empty activities list returns an empty list immediately without making any Supabase RPC call
Serialization test: the JSON payload sent to Supabase RPC contains recorded_by_user_id as a non-null UUID string for every record in a proxy batch
Serialization test: recorded_by_user_id equals the attributed peer mentor's user_id (not the coordinator's) in the serialized payload
Minimum 90% branch coverage on BatchInsertRpcAdapter as reported by `flutter test --coverage`
No real Supabase network calls are made during any test (all calls go through the mock)

Technical Requirements

frameworks
Flutter
flutter_test
apis
Supabase RPC (batch_insert_activities or equivalent)
data models
ActivityRecord
BatchActivityPayload
performance requirements
All tests must complete in under 2 seconds total (pure unit tests, no I/O)
security requirements
Mock must not log or print real user IDs or tokens to test output

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

The adapter likely wraps `supabase.rpc('batch_insert_activities', params: {...})`. Mock the SupabaseClient by injecting it via constructor — avoid using static singletons like `Supabase.instance` directly inside the adapter, as those cannot be mocked cleanly. If the adapter currently uses the singleton, refactor the constructor to accept an optional client parameter (dependency injection pattern). For the rollback test, verify that the adapter does not catch-and-swallow the exception silently — it should always rethrow as a typed exception.

For serialization tests, capture the `params` argument passed to the mock's `rpc()` call using an argument captor and assert its structure. Use `group()` blocks to organize tests by scenario for readability.

Testing Requirements

Pure unit tests using flutter_test. Use Mockito or mocktail to mock the Supabase client's RPC interface. Test groups: (1) happy path, (2) error paths (PostgrestException, network error), (3) edge cases (empty list, single item, maximum batch size if defined). Run `flutter test --coverage` and inspect lcov report to confirm 90%+ branch coverage on the adapter file specifically.

Do not test Supabase internals — only the adapter's behavior given mock responses.

Component
Batch Insert RPC Adapter
infrastructure medium
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.