Implement edge function invocation in BufdirExportService
epic-bufdir-report-export-orchestration-task-005 — Implement the HTTP call from BufdirExportService to the Bufdir export edge function. Pass scope, period, and format parameters in the request body. Handle network errors, non-2xx responses, and edge function timeout with typed exceptions. Return the raw edge function response payload for downstream routing.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use Supabase's `functions.invoke()` client method rather than raw http.Client to benefit from built-in JWT injection and error normalisation. Wrap the call in a try/catch hierarchy: FunctionException first (Supabase SDK typed error), then TimeoutException, then SocketException. Define the exception hierarchy in a dedicated `bufdir_export_exceptions.dart` file. Do not parse the response body here — return the raw FunctionResponse.data so that the routing layer (task-008) can decide how to handle PDF vs CSV payloads.
Log failures with severity level; do not log raw response bodies as they may contain PII.
Testing Requirements
Unit tests using flutter_test with http.Client mocked via mockito or http_mock_adapter. Cover: (1) successful 200 with raw payload returned, (2) 401 → BufdirClientException, (3) 422 → BufdirClientException with body, (4) 500 → BufdirServerException, (5) timeout → BufdirTimeoutException, (6) SocketException → BufdirNetworkException. Assert that the JWT header is present in every request. Assert organisation credentials are absent from the request body.
Minimum 90% branch coverage on BufdirExportService.
The scope selector must accurately reflect each coordinator's access rights within the org hierarchy. If a coordinator can select a scope broader than their authorised access, the edge function's RLS enforcement must catch the attempt — but a permissive RLS policy or a bug in the scope resolver could allow unauthorised data to be exported.
Mitigation & Contingency
Mitigation: Implement permission enforcement at two independent layers: (1) the scope selector only renders options permitted by the user's role record, and (2) the edge function re-validates the requested scope against the user's JWT claims before executing any queries. Write integration tests that attempt to invoke the edge function with a scope beyond the user's permissions and assert rejection.
Contingency: If a permission bypass is discovered post-launch, immediately disable the export feature via the org-level feature flag while the fix is deployed. Review all audit records for exports that may have included out-of-scope data and notify affected organisations.
The export workflow has 7+ discrete states (idle, scope selected, period selected, preview loading, preview ready, confirming, exporting, complete, failed) and several conditional transitions. An incomplete BLoC state machine could allow duplicate submissions, stale preview data to be confirmed, or error states to be unrecoverable without a restart.
Mitigation & Contingency
Mitigation: Model the state machine explicitly as a sealed class hierarchy before coding. Review the state diagram against all user story acceptance criteria. Write bloc unit tests for every valid and invalid state transition, including the happy path and all documented error states.
Contingency: If the BLoC grows too complex to test reliably, decompose it into two cooperating blocs: one for configuration (scope + period selection) and one for execution (preview + confirm + export), linked by a coordinator object.