high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

All four model classes have at least one test file each under test/models/
CoordinatorRoleGuard has a dedicated test file under test/guards/
JSON round-trip tests: fromJson(toJson(model)) == model for all model classes with all optional fields present and all optional fields absent
copyWith tests verify that providing a field returns a new instance with that field updated and all other fields unchanged
Equality tests verify that two instances with identical fields are equal (== returns true) and differing instances are not equal
Enum boundary tests cover every declared value of every enum used in the models, including any 'unknown'/'other' sentinel values
CoordinatorRoleGuard tests cover: coordinator role allows, peer_mentor role denies, org_admin role denies, null/unauthenticated denies
All tests pass with flutter test --no-pub and zero skipped tests
Test coverage for the tested files is at or above 90% line coverage
No test uses real Supabase connections — all external dependencies are mocked

Technical Requirements

frameworks
Flutter
flutter_test
mockito
Riverpod (ProviderContainer for guard tests)
data models
ProxyActivityRecord
BulkParticipant
DuplicateConflict
BulkRegistrationRequest
CoordinatorRoleGuard
UserRole enum
performance requirements
Full unit test suite for these files must complete in under 10 seconds
security requirements
Test fixtures must not contain real user IDs, organisation IDs, or PII — use clearly fake UUIDs (e.g., '00000000-0000-0000-0000-000000000001')

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Generate mockito mocks with build_runner (@GenerateMocks annotation) placed in a test/helpers/mocks.dart file shared across test files. Use fixtures (static factory methods or JSON files in test/fixtures/) to reduce boilerplate. For copyWith edge cases, test: updating every field individually, updating no fields (returns equal object), and chaining copyWith twice. For enum boundary tests, iterate over MyEnum.values in a for-loop test rather than writing one test per value — this ensures new enum values automatically get tested.

For CoordinatorRoleGuard, create a thin FakeAuthStateNotifier that extends StateNotifier and exposes a setRole(UserRole?) method to drive guard state without async complexity.

Testing Requirements

Pure unit tests using flutter_test. No widget tests or integration tests in this task. Use ProviderContainer (not ProviderScope) for Riverpod-dependent guard tests to keep them lightweight. Use mockito-generated mocks for any auth state dependency injected into CoordinatorRoleGuard.

Organise tests in describe-style group() blocks: one group per class, nested groups per method/scenario. Each test must have a descriptive name following the pattern 'given [state] when [action] then [expectation]'. Verify that fromJson raises a meaningful FormatException (not a null crash) when required fields are missing.

Component
Proxy Activity Data Models
data low
Dependencies (5)
Implement the `BulkParticipant` Dart class representing a single peer mentor selected for bulk registration. Fields: peerId, displayName, selected (bool), conflictStatus (none | warning | duplicate). Include `fromJson`/`toJson`, `copyWith`, and Equatable. Cover edge cases in unit tests (null safety, enum parsing). epic-proxy-activity-registration-foundation-task-005 Implement the `DuplicateConflict` Dart class capturing a detected duplicate activity. Fields: conflictingActivityId, attributedTo, activityDate, activityTypeId, severity (warning | blocking), resolvedAt (nullable). Include `fromJson`/`toJson`, `copyWith`, and Equatable. Used by upstream duplicate detection services. epic-proxy-activity-registration-foundation-task-006 Implement the `BulkRegistrationRequest` Dart class that wraps a list of `BulkParticipant` and a shared `ProxyActivityRecord` template. Fields: participants (List<BulkParticipant>), activityTemplate (ProxyActivityRecord), submittedAt, organizationId. Include `fromJson`/`toJson`, `copyWith`, and Equatable. Write unit tests for participant filtering helpers. epic-proxy-activity-registration-foundation-task-007 Implement the `ProxyActivityRecord` Dart class with fields: id, registeredBy (coordinator user id), attributedTo (peer mentor user id), activityTypeId, date, durationMinutes, notes, createdAt. Include `fromJson`/`toJson`, `copyWith`, and Equatable. Annotate fields as immutable. Add unit tests covering serialisation round-trips. epic-proxy-activity-registration-foundation-task-004 Implement `CoordinatorRoleGuard` as a Riverpod provider that reads the current user's role from the session/role state and exposes `requireCoordinator()` which throws `InsufficientPermissionsException` when the role is not coordinator. Also expose `isCoordinator` bool stream. Wire into route guards and repository call sites. epic-proxy-activity-registration-foundation-task-009
Epic Risks (3)
high impact medium prob technical

The activities table migration adding registered_by and attributed_to columns may conflict with existing RLS policies or FK constraints if the user profile table structure differs from assumptions, blocking all subsequent epics.

Mitigation & Contingency

Mitigation: Review existing activities table schema and RLS policies before writing the migration. Run the migration against a staging database clone first. Write rollback scripts alongside the migration.

Contingency: If migration fails in staging, isolate the conflict with a targeted schema audit, adjust FK references or RLS policy scope, and re-run before touching production.

high impact medium prob security

The RLS policy must filter proxy inserts to the coordinator's chapter scope. If the chapter-scope resolver pattern differs between organisations (multi-chapter coordinators in NHF vs single-chapter in HLF), the policy may be too broad or too restrictive.

Mitigation & Contingency

Mitigation: Design the RLS policy to accept a coordinator's full set of assigned chapter IDs (array) rather than a single chapter_id. Validate the policy against NHF multi-chapter test fixtures during the integration test phase.

Contingency: If the policy is found to be incorrect after deployment, introduce a server-side validation edge function as a safety net while the RLS policy is corrected.

medium impact low prob technical

The bulk_register_activities RPC function may time out or cause lock contention when inserting large participant batches (e.g. 40+ peer mentors in a single group session), degrading the user experience.

Mitigation & Contingency

Mitigation: Benchmark the RPC function with 50-participant batches during development. Use unnest-based bulk insert rather than row-by-row PL/pgSQL loops. Set a reasonable statement_timeout.

Contingency: If performance is insufficient, split the client-side submission into chunks of 20 participants with progress feedback, rather than a single RPC call.