critical priority medium complexity backend pending backend specialist Tier 1

Acceptance Criteria

Edge function file exists at supabase/functions/badge-criteria-edge-function/index.ts and deploys without errors via Supabase CLI
HTTP handler returns 200 OK with JSON body when receiving a valid Supabase database webhook POST payload
Handler extracts peer_mentor_id and org_id from the webhook payload record field and makes them available as typed variables
Handler returns 400 Bad Request with descriptive error message when payload is missing record, peer_mentor_id, or org_id fields
Handler returns 401 Unauthorized when the incoming request does not carry a valid Supabase service-role Authorization header
Handler returns 405 Method Not Allowed for all HTTP methods other than POST
Execution context object is constructed containing { peer_mentor_id, org_id, triggered_at: ISO timestamp, event_type } before pipeline invocation
Function respects SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY environment variables and does not hardcode credentials
Cold start time measured and documented; function must respond to the initial validation within 2 seconds
Unhandled exceptions inside the handler are caught at the top level and return 500 with a safe error message (no stack traces exposed to caller)

Technical Requirements

frameworks
Supabase Edge Functions (Deno runtime)
Deno std/http serve
apis
Supabase Database Webhooks (POST payload format)
Supabase Edge Functions REST API
data models
badge_definition
activity
performance requirements
Payload validation and context construction must complete within 200ms
Function must handle at least 50 concurrent invocations without errors
Cold start must not exceed 2 seconds under normal Supabase infrastructure load
security requirements
Validate Authorization header against SUPABASE_SERVICE_ROLE_KEY before processing any payload
Never log peer_mentor_id or org_id at INFO level in production; use DEBUG level only
org_id extracted from JWT claims must match org_id in the webhook payload to prevent cross-tenant processing
Service role key must never appear in function response body or logs
Input payload size capped at 64KB to prevent memory exhaustion

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use Deno's native `serve` from `https://deno.land/std/http/server.ts`. Define a strict TypeScript interface for the expected webhook payload shape (Supabase sends `{ type, table, record, old_record, schema }`). Extract `record.peer_mentor_id` and `record.organization_id` (check actual column name against the activity table schema). Build an `EvaluationContext` typed object before calling any downstream service so the pipeline always receives a strongly-typed context.

Use a top-level try/catch wrapping the entire handler body to guarantee no unhandled promise rejections escape. Do NOT call `Deno.exit()` inside the handler. Store the Supabase client creation (using service role) outside the serve loop for connection reuse across invocations. Follow the existing edge function file structure already established in the project.

Testing Requirements

Unit tests using Deno's built-in test runner: (1) mock HTTP request with valid webhook payload → assert 200 + context object fields, (2) missing peer_mentor_id → assert 400 with correct error string, (3) missing org_id → assert 400, (4) non-POST method → assert 405, (5) missing Authorization header → assert 401, (6) malformed JSON body → assert 400. All tests must run offline with no Supabase connection. Aim for 100% branch coverage of the HTTP handler entrypoint file.

Component
Badge Criteria Edge Function
infrastructure medium
Epic Risks (3)
medium impact medium prob technical

Supabase Edge Functions may experience cold start latency of 500ms–2s when they have not been invoked recently. If evaluation latency consistently exceeds the 2-second UI expectation, the celebration overlay timing SLA cannot be met without the optimistic UI fallback from the UI epic.

Mitigation & Contingency

Mitigation: Keep the edge function warm by scheduling a lightweight health-check invocation every 5 minutes in production. Optimise the function size to minimise Deno module load time. Implement the optimistic UI path in badge-bloc (from the UI epic) as the primary UX path so cold start only affects server-side reconciliation, not perceived responsiveness.

Contingency: If cold starts remain problematic, migrate badge evaluation to a Supabase database function (pl/pgsql) triggered directly by a database trigger on activity insert, eliminating the Edge Function overhead entirely for the evaluation logic while keeping Edge Function only for FCM notification dispatch.

high impact low prob integration

Supabase database webhooks can fail silently if the edge function returns a non-2xx response or times out. A missed webhook means a peer mentor does not receive a badge they earned, which is both a functional defect and a trust issue for organisations relying on milestone tracking.

Mitigation & Contingency

Mitigation: Implement idempotent webhook processing: the edge function reads the activity ID from the webhook payload and checks whether evaluation for this activity has already run (via an audit log query) before proceeding. Add Supabase webhook retry configuration (3 retries with exponential backoff). Monitor webhook failure rates via Supabase logs alert.

Contingency: Implement a nightly reconciliation job (Supabase scheduled function) that scans all activities from the past 24 hours, re-evaluates badge criteria for any peer mentor with no corresponding evaluation log entry, and awards any missing badges. Alert operations if reconciliation awards more than 5% of badges, indicating systematic webhook failure.

high impact low prob security

The evaluation service loads badge definitions per organisation, but a misconfigured RLS policy or incorrect organisation scoping in the edge function could cause one organisation's badge criteria to be evaluated against another organisation's peer mentor activity data, leading to incorrect or cross-contaminated badge awards.

Mitigation & Contingency

Mitigation: The edge function must extract organisation_id from the webhook payload activity record and pass it explicitly to every database query. Write a security test that seeds two organisations with distinct badge definitions and verifies that evaluating a peer mentor in org A never reads or awards org B definitions. Use Supabase service role key only within the edge function, never the anon key.

Contingency: If cross-org contamination is detected in audit logs, immediately disable the edge function webhook, run a targeted SQL query to identify and revoke incorrectly awarded badges, notify affected organisations, and perform a full security review of all RLS policies on badge-related tables before re-enabling.