Integrate CoordinatorNotificationService into status transitions
epic-peer-mentor-pause-core-logic-task-005 — Extend MentorStatusService to call CoordinatorNotificationService after every successful status transition. For each transition (pause, reactivate, deactivate), the service must identify the responsible coordinator(s), construct a notification payload including mentor name, new status, reason, and timestamp, and dispatch the notification. Failures in notification dispatch must not roll back the status transition.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Implement the notification dispatch using Future.unawaited() or a fire-and-forget pattern with error boundary to ensure the status result is returned immediately without waiting for notification delivery. The coordinator lookup should reuse the same Supabase client session as the status transition — avoid opening a second session. Define a NotificationPayload value object with all required fields and a toJson() method to keep the payload construction testable. Consider using a try/catch + logger.warn pattern specifically for the notification section, isolated from the transition result.
This decoupling is a business rule: notifications are best-effort, transitions are authoritative.
Testing Requirements
Unit tests using mocked CoordinatorNotificationService verifying: notification is called after each successful transition type, notification is NOT called after a failed transition, failure in notification does not change the return value of the transition method. Integration test verifying the notification payload shape matches what CoordinatorNotificationService expects. Test the fallback behavior when no coordinator is found. Test that notification failure is logged with the correct severity level.
The status state machine must handle race conditions where two concurrent callers (e.g., a mentor self-pausing and a coordinator force-pausing simultaneously) attempt to update the same mentor's status. Without a concurrency guard, both writes could succeed, leaving the audit log in an inconsistent state.
Mitigation & Contingency
Mitigation: Use a Supabase RPC with a row-level lock (SELECT FOR UPDATE) inside a transaction so only one transition wins. Return a clear error to the losing caller. Test with concurrent requests in the integration test suite.
Contingency: If row-level locking proves unreliable in the Supabase environment, add an optimistic-locking version field to peer_mentors and have the service retry up to three times on version conflict before surfacing an error to the caller.
If the CertificationExpiryJob Edge Function fails silently (network timeout, Supabase cold start), HLF mentors with expired certifications could remain in active status and continue appearing on the chapter website, creating a compliance breach.
Mitigation & Contingency
Mitigation: Implement structured error logging inside the Edge Function, write a monitoring query that checks for mentors with expired certifications still in active status, and set up an alert if any are detected 30 minutes after the scheduled nightly run.
Contingency: Provide a coordinator-accessible manual trigger for the expiry check that can be invoked via the admin interface if the scheduled job is known to have failed. Document the manual recovery procedure for HLF coordinators.
pg_cron registration in Supabase requires superuser-level access that may not be available in all environments (local dev, staging, CI). If the cron job cannot be registered automatically, the Edge Function will never execute on schedule, breaking the HLF certification expiry workflow.
Mitigation & Contingency
Mitigation: Use Supabase's recommended pg_cron setup via the SQL editor migration script and document the exact commands. Validate cron registration in the staging environment as part of the epic's deployment checklist.
Contingency: If pg_cron is unavailable, switch to a Supabase scheduled Edge Function invocation via an external cron service (e.g., a GitHub Actions scheduled workflow calling the Edge Function endpoint with a service-role key) until the pg_cron approach is resolved.