Implement coordinator role guard enforcement in ProxyRegistrationService
epic-proxy-activity-registration-orchestration-task-002 — Wire the CoordinatorRoleGuard into ProxyRegistrationService so that any attempt to invoke proxy registration by a non-coordinator principal throws a typed AuthorizationException before any downstream service is called. The guard check must be the first operation in the service entry method, short-circuiting all subsequent logic.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 7 - 84 tasks
Can start after Tier 6 completes
Implementation Notes
Inject CoordinatorRoleGuard into ProxyRegistrationService via the constructor: class ProxyRegistrationService { ProxyRegistrationService(this._guard, this._repository); ... }. In the Riverpod provider factory, read both dependencies via ref.watch/ref.read. The first line of registerProxyActivity() should be: _guard.requireCoordinator(); — no if-statement wrapper.
This keeps the authorization intent explicit and grep-able. Use a try/catch block below the guard call to catch repository/network exceptions and map them to ProxyRegistrationError variants — but specifically do NOT catch InsufficientPermissionsException there, letting it propagate up to the BLoC where it will be mapped to an unauthorized UI state. Document this exception propagation contract in a code comment above the method signature to guide future maintainers.
Testing Requirements
Unit tests using flutter_test with mockito. Test matrix: (1) coordinator role — guard does not throw, service proceeds to call repository mock, result is ProxyRegistrationSuccess; (2) peer_mentor role — guard throws InsufficientPermissionsException, repository mock is never called (verified with Mockito verify(repo, never())), exception propagates to caller; (3) org_admin role — same as peer_mentor; (4) guard throws InsufficientPermissionsException mid-execution (simulated role expiry) — verify no partial state is left. Also test that the service correctly maps a network failure from the repository into ProxyRegistrationError with error_code = network_failure (to confirm error mapping logic is in place for other codes).
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.
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.
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.