Implement Re-download Signed URL Generation in Edge Function
epic-bufdir-report-export-core-backend-task-015 — Add a secondary endpoint or query parameter to the edge function that accepts an export_id and returns a fresh signed download URL for a previously generated file. The function must verify the requesting user has read access to the export record via RLS, then generate a new signed URL from the storage bucket. This enables the export history list UI to offer re-download without regenerating the file.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 7 - 84 tasks
Can start after Tier 6 completes
Implementation Notes
Implement this as a route branch within the existing edge function: check for `action=redownload` query param at the top of the request handler and dispatch to a separate `handleRedownload(request, context)` function. This avoids creating a second edge function deployment. The `handleRedownload` function should: (1) extract export_id from query params and validate it is a UUID, (2) call `generatedReportsRepo.getById(exportId)` using the user's JWT (not service role) so RLS applies naturally, (3) null result → 404, (4) status=failed → 422, (5) call `supabase.storage.from('exports').createSignedUrl(record.file_path, 86400)` using service role (required to access private bucket), (6) return response. Keep the re-download logic under 50 lines — this is intentionally a thin endpoint.
Testing Requirements
Unit test: mock getById returning null and assert HTTP 404. Mock getById returning a failed-status record and assert HTTP 422. Mock getById returning a valid record and mock createSignedUrl returning a URL; assert HTTP 200 with correct response shape. Integration test: create a real export record in the test DB, call the re-download endpoint with the coordinator's JWT and the export_id, assert the signed URL is returned and is fetchable.
Test with a peer mentor JWT and assert HTTP 403/404. Test with a non-existent export_id and assert HTTP 404. Verify audit log entry created on success.
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.
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.
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.