critical priority low complexity backend pending backend specialist Tier 3

Acceptance Criteria

TransitionEvent enum (or const object) defines exactly two values: PAUSE (active→paused) and RESUME (paused→active)
detectTransition(oldStatus, newStatus) function returns TransitionEvent.PAUSE when oldStatus is 'active' and newStatus is 'paused'
detectTransition returns TransitionEvent.RESUME when oldStatus is 'paused' and newStatus is 'active'
detectTransition returns null (or a NoOp sentinel value) when oldStatus === newStatus (no actual status change in the UPDATE)
detectTransition returns null for any other old/new status combination (future-proofing against additional status values)
The webhook handler returns HTTP 200 with a JSON 'skipped' acknowledgement when detectTransition returns null
The function is pure — no side effects, no I/O, no external dependencies
TransitionEvent type is exported from types.ts alongside the webhook payload types defined in task-001

Technical Requirements

frameworks
Deno
Supabase Edge Functions
data models
TransitionEvent
PeerMentorStatus
performance requirements
Function executes in O(1) time — simple string comparison
security requirements
Do not expose internal status values in external API responses
Treat any unrecognized status value as a no-op to prevent unexpected behavior on schema changes

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Keep detectTransition() as a standalone exported pure function in a separate transition-detector.ts file — do not inline it into the handler. This makes it trivially testable and reusable. Use a lookup table pattern (a Map or switch statement) rather than nested if/else for clarity. Since the pause feature is a SHOULD HAVE in Phase 2 per the product roadmap, design the TransitionEvent type to be extensible — a const object as enum replacement (export const TransitionEvent = { PAUSE: 'pause', RESUME: 'resume' } as const) is more Deno-idiomatic than TypeScript enum.

The null return for no-ops is intentional — it signals to the orchestrator 'nothing to do' without throwing, which keeps error handling clean.

Testing Requirements

Pure unit tests for detectTransition() — no mocks needed. Test matrix: (1) 'active' → 'paused' returns PAUSE, (2) 'paused' → 'active' returns RESUME, (3) 'active' → 'active' returns null, (4) 'paused' → 'paused' returns null, (5) 'active' → unknown_value returns null, (6) unknown_value → 'active' returns null, (7) both unknown returns null. Test the webhook handler integration: inject a no-op transition context and verify HTTP 200 with skipped body. All edge cases documented as test names for future maintainers.

Component
Pause Status Webhook Handler
infrastructure low
Epic Risks (3)
medium impact medium prob technical

Supabase Edge Functions have cold start latency that may push coordinator notification delivery beyond the 5-second SLA, particularly during low-traffic periods when the function is not warm.

Mitigation & Contingency

Mitigation: Keep the Edge Function lightweight — delegate all heavy logic to the orchestrator layer and avoid large dependency bundles. Measure p95 end-to-end latency in staging and document actual SLA achievable.

Contingency: If cold start latency consistently breaches 5 seconds, introduce a keep-warm ping from the nightly-scheduler or document the actual p95 latency in the feature spec and adjust the acceptance criterion to reflect the realistic bound.

medium impact medium prob technical

Supabase database webhooks may fire duplicate events for a single status change under retry conditions, causing coordinators to receive multiple identical notifications for one pause event.

Mitigation & Contingency

Mitigation: Add idempotency checking in the webhook handler using the event timestamp and peer mentor ID. Store a notification dispatch record in the pause-status-record-repository and skip dispatch if a record for the same event already exists.

Contingency: If duplicates slip through in production, add a de-duplication filter in the notification centre UI layer so the coordinator sees at most one card per event, and implement a cleanup job for the notifications table.

medium impact low prob scope

A peer mentor with multi-chapter membership may have more than one responsible coordinator. The orchestrator design currently targets a single coordinator, and resolving multiple recipients may require schema changes to the org membership query.

Mitigation & Contingency

Mitigation: Review the multi-chapter-membership-service patterns before implementing the orchestrator's coordinator resolution. Design the dispatcher call to accept an array of coordinator IDs from the outset so adding multiple recipients is non-breaking.

Contingency: If multi-coordinator dispatch is out of scope for this epic, document the limitation and create a follow-up task. Default to the primary coordinator (lowest chapter hierarchy level) as the single recipient in the interim.