high priority medium complexity testing pending testing specialist Tier 11

Acceptance Criteria

Test file compiles and all tests pass with `flutter test` without warnings
Authorization rejection path: when CoordinatorRoleGuard.check() returns false, the method returns ProxyRegistrationError(type: unauthorized) and ProxyActivityRepository is never called (verified with verifyNever)
Duplicate detection path: when ProxyDuplicateDetectionService.detect() returns a conflict, the method returns a conflict result and ProxyActivityRepository is never called
Happy path: ActivityAttributionService.attribute() is called exactly once with the correct mentor ID and coordinator ID; ProxyActivityRepository.save() is called exactly once with the attributed record; method returns ProxyRegistrationSuccess
Repository error path: when ProxyActivityRepository.save() throws a PostgrestException, the method returns ProxyRegistrationError with a mapped error type and does not rethrow
Each test is independent — setUp() resets all mocks between tests
Test descriptions clearly state the scenario in plain English (Given/When/Then or equivalent)
No real Supabase connections are made in any test — all external collaborators are mocked
Total test count: minimum 4 tests covering the 4 documented paths, plus at least 1 additional edge case (e.g., null mentor ID input)

Technical Requirements

frameworks
Flutter
flutter_test
mocktail
apis
CoordinatorRoleGuard.check()
ProxyDuplicateDetectionService.detect()
ActivityAttributionService.attribute()
ProxyActivityRepository.save()
data models
ProxyRegistrationRequest
ProxyRegistrationSuccess
ProxyRegistrationError
ActivityAttribution
DuplicateConflict
performance requirements
All tests must complete in under 2 seconds total — no async delays, no real network calls
security requirements
Tests must not contain hardcoded real user IDs, tokens, or credentials — use generated UUIDs or fixture constants

Execution Context

Execution Tier
Tier 11

Tier 11 - 5 tasks

Can start after Tier 10 completes

Dependencies (10)
epic-proxy-activity-registration-core-services-task-001 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-002 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-003 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-008 component Cross-Epic Component proxy-registration-service depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-004 component Cross-Epic Component proxy-registration-service depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-005 component Cross-Epic Component proxy-registration-service depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-006 component Cross-Epic Component proxy-registration-service depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-007 component Cross-Epic Component proxy-registration-service depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-009 component Cross-Epic Component proxy-registration-service depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-010 component Cross-Epic Component proxy-registration-service depends on activity-attribution-service
Dependents (18)
epic-proxy-activity-registration-ui-task-001 component Cross-Epic Component bulk-participant-list depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-002 component Cross-Epic Component bulk-participant-list depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-003 component Cross-Epic Component bulk-participant-list depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-004 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-005 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-006 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-007 component Cross-Epic Component proxy-peer-mentor-selector depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-008 component Cross-Epic Component proxy-peer-mentor-selector depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-009 component Cross-Epic Component proxy-peer-mentor-selector depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-010 component Cross-Epic Component proxy-activity-form depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-011 component Cross-Epic Component proxy-activity-form depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-012 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-013 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-014 component Cross-Epic Component proxy-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-015 component Cross-Epic Component bulk-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-016 component Cross-Epic Component bulk-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-017 component Cross-Epic Component bulk-registration-screen depends on proxy-registration-service
epic-proxy-activity-registration-ui-task-018 component Cross-Epic Component proxy-registration-bloc depends on proxy-registration-service

Implementation Notes

Create mock classes at the top of the test file using mocktail's `class MockCoordinatorRoleGuard extends Mock implements CoordinatorRoleGuard {}` pattern — one mock class per collaborator. In setUp(), instantiate a fresh ProxyRegistrationService with injected mocks before each test. Define shared fixture data (valid coordinator ID, valid mentor ID, sample activity template) as top-level constants to keep tests readable. For the duplicate path, ensure the mock returns a DuplicateConflict value object rather than throwing — the service should handle conflicts as control flow, not exceptions.

For the repository error path, use `thenThrow(PostgrestException(message: 'conflict', code: '23505'))` to simulate a unique constraint violation. Document each test's purpose with a comment referencing the acceptance criterion it validates.

Testing Requirements

This task IS the test implementation. Use flutter_test as the test runner and mocktail for mocking (preferred over mockito due to null-safety ergonomics in Dart 3). Structure tests in a single file: `test/orchestration/proxy_registration_service_test.dart`. Group tests by scenario using `group()`.

Each `test()` block should follow Arrange-Act-Assert structure. Use `when()` and `thenReturn()` / `thenThrow()` from mocktail. Assert return types with `isA()` and `isA()`. Assert mock interaction counts with `verify(() => mock.method()).called(1)` and `verifyNever(() => mock.method())`.

Component
Proxy Registration Service
service medium
Epic Risks (3)
high impact low prob integration

If the Supabase batch RPC partial-inserts some records before encountering an error and does not roll back cleanly, the bulk service may report failure while orphaned records exist in the database, corrupting reporting data.

Mitigation & Contingency

Mitigation: Wrap the bulk insert in an explicit Supabase transaction via the RPC function. Write an integration test that simulates a mid-batch constraint violation and asserts zero records were written.

Contingency: If a partial-write incident occurs, the registered_by audit field allows identification and deletion of the orphaned records. Implement a coordinator-facing bulk submission status screen to surface any such anomalies.

medium impact medium prob scope

When a bulk submission of 15 participants has 4 duplicates, the aggregated conflict summary may be too complex for coordinators to process quickly, leading to blanket override decisions that defeat the purpose of duplicate detection.

Mitigation & Contingency

Mitigation: Design the conflict result type to support per-participant override flags, so the UI can present a clear list of conflicting participants with individual cancel/override toggles rather than a single global decision.

Contingency: If coordinator usability testing reveals the conflict review screen is too complex, simplify to a 'skip all conflicts and submit the rest' mode as an immediate fallback while a more granular UI is designed.

high impact low prob security

If the coordinator role check inside proxy-registration-service is inconsistent with the route-level guard, a regression in the guard could allow peer mentors to call the service directly via deep links, submitting records with incorrect attribution.

Mitigation & Contingency

Mitigation: Enforce role authorization at both the route guard level (coordinator-role-guard) and inside each service method independently. Write a security test that calls the service directly with a peer mentor session token and asserts rejection.

Contingency: If a bypass is discovered, immediately enable the server-side RLS policy as the final enforcement layer and audit any records written during the exposure window using the registered_by field.