critical priority medium complexity infrastructure pending infrastructure specialist Tier 1

Acceptance Criteria

Edge Function is deployed to Supabase and responds to POST requests at /bufdir-export
Request body is parsed and validated for all required fields: org_id (UUID), scope_id (UUID), scope_level (enum: chapter|region|national), date_from (ISO8601), date_to (ISO8601), format (enum: csv|pdf|preview)
JWT is extracted from Authorization header and decoded to retrieve user claims including user_id and org_id
User role is verified against the database — only coordinator or admin roles for the specified scope are allowed; all others receive HTTP 403
date_from must be before date_to and both must be valid ISO8601 dates; invalid ranges return HTTP 400 with descriptive message
scope_level must match one of the three accepted enum values; unknown values return HTTP 400
Missing required fields return HTTP 400 with a JSON body listing exactly which fields are absent
org_id in request body must match org_id in JWT claims; mismatches return HTTP 403 to prevent cross-org access
All error responses follow a consistent shape: { error: string, code: string, field?: string }
CORS headers are set correctly to allow requests from the Flutter app's expected origin
Function logs structured request metadata (org_id, scope_level, format, user_id) for audit without logging sensitive payload data
OPTIONS preflight requests are handled and return 204 with correct CORS headers

Technical Requirements

frameworks
Supabase Edge Functions (Deno runtime)
Deno std/http
apis
Supabase Auth Admin API (JWT verification)
Supabase PostgreSQL (role lookup)
data models
bufdir_export_audit_log
bufdir_column_schema
performance requirements
Validation phase must complete in under 200ms before any DB queries
Role verification query must use indexed lookup on user_id + org_id
Function cold start must not exceed 1.5s
security requirements
Service role key used only server-side — never returned in response
JWT must be verified using Supabase Auth Admin API, not decoded client-side
org_id cross-check between JWT claims and request body prevents cross-org data access
All input strings sanitized before use in DB queries
GDPR: org_id and user_id logged for audit; no PII in function logs

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Structure the function as: (1) CORS preflight handler, (2) JSON body parser with try/catch returning 400 on malformed JSON, (3) field presence validator returning 400 with field list, (4) type/enum validator per field, (5) JWT extraction and Supabase Admin Auth verification, (6) role authorization DB query, (7) pass validated request context to downstream pipeline. Keep validation logic in a separate `validateRequest.ts` module for testability. Use Deno's built-in crypto for any hashing needs — do not bring in external deps unless already in the project. The scope_level enum validation should use a TypeScript union type to get compile-time safety.

Avoid any await inside the validation phase to keep it synchronous and fast.

Testing Requirements

Write Deno unit tests for each validation branch: missing fields, invalid enum values, invalid date range, reversed date range, JWT missing, JWT with wrong org, and valid request passing all checks. Integration test using a real Supabase test project: deploy the function, send a valid request with a coordinator JWT and assert HTTP 200; send the same request with a peer mentor JWT and assert HTTP 403. Test OPTIONS preflight returns 204 with CORS headers. Aim for 100% branch coverage on the validation module.

Use Deno's built-in test runner.

Component
Bufdir Export Edge Function
infrastructure high
Epic Risks (3)
high impact medium prob technical

Supabase Edge Functions have a default execution timeout. For large national-scope exports aggregating tens of thousands of activities across 1,400 chapters, the edge function may time out before completing, leaving coordinators with a failed export and no partial output.

Mitigation & Contingency

Mitigation: Optimise the aggregation SQL using pre-materialised aggregation views or RPC functions that run inside the database rather than iterating records in Deno. Profile query execution time against realistic production data volumes early. Request an elevated timeout limit from Supabase if needed. Implement progress checkpointing so the export can be resumed from the last completed aggregation batch.

Contingency: For organisations exceeding a configurable threshold (e.g. >5,000 activities), switch to an asynchronous export pattern: the edge function writes a 'pending' audit record and enqueues the job; the client polls for completion and is notified via Supabase Realtime when the file is ready.

medium impact medium prob technical

Server-side PDF generation in a Deno Edge Function environment restricts library choices. Many popular PDF libraries require Node.js APIs not available in Deno, or produce large bundle sizes that exceed edge function limits. Choosing the wrong library could block the entire PDF generation path.

Mitigation & Contingency

Mitigation: Spike PDF library selection as the first task of this epic, evaluating at least two Deno-compatible options (e.g. pdf-lib, jsPDF with Deno compatibility shim). Test bundle size and basic rendering before committing to an implementation. Document the chosen library's constraints.

Contingency: If no suitable Deno-native PDF library is found, generate a well-structured HTML report from the edge function and use a headless Chromium service (e.g. Browserless, Gotenberg) for HTML-to-PDF conversion, or temporarily ship CSV-only export while the PDF path is resolved.

high impact high prob technical

Peer mentors affiliated with multiple chapters (a documented NHF scenario) must not be double-counted in participant totals. Incorrect deduplication logic would overreport participation figures to Bufdir, which could be discovered during audit and damage organisational credibility.

Mitigation & Contingency

Mitigation: Define and document the deduplication contract explicitly before coding: deduplication is per-person per-period, not per-activity. Build dedicated unit tests with fixtures containing the exact multi-chapter membership patterns described in NHF's documentation. Have a NHF representative validate test fixture outputs against known-good manual counts.

Contingency: If deduplication logic produces results that cannot be verified against manual counts before launch, surface a deduplication warning in the export preview listing the affected peer mentor IDs, and require explicit coordinator acknowledgement before finalising the export.