Define ExportScope models and Riverpod state
epic-bufdir-report-export-orchestration-task-001 — Define the ExportScope enum (local_chapter, region, national), the ExportScopeState class, and the Riverpod StateNotifierProvider that will hold the currently selected scope. Include serialisation helpers and ensure the scope model integrates cleanly with the downstream BufdirExportRequest payload.
Acceptance Criteria
Technical Requirements
Implementation Notes
Follow the existing Riverpod patterns in the codebase — check how other providers are structured (e.g., auth provider, activity provider) and mirror the file/naming conventions. Use freezed or manual copyWith depending on what the rest of the project uses. Keep ExportScope as a simple Dart enum without additional package dependencies. The toJson string values ('local_chapter', 'region', 'national') must exactly match what the Supabase edge function expects in the BufdirExportRequest payload — confirm this contract with the backend task owner before finalising.
Export all public symbols from a barrel file at lib/features/bufdir_export/models/export_scope.dart.
Testing Requirements
Write unit tests using flutter_test. Test ExportScopeNotifier state transitions: (1) initial state is correct, (2) selectScope transitions selectedScope, (3) setPermittedScopes updates the list, (4) reset() returns to initial state. Test ExportScope serialisation: toJson() and fromJson() round-trip for all three values, fromJson throws on unknown string. Use ProviderContainer in tests to avoid Flutter widget binding.
Aim for 100% line coverage of the models and notifier files.
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.