high priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

AdminExportPanel renders as a full-screen modal or dedicated page with clearly labelled form sections: Scope, Date Range, Format
Scope selector allows choosing between whole-org or a specific chapter; chapter list is restricted to the admin's privilege scope
Date range picker defaults to the previous calendar month and validates that end date is not before start date (inline validation error shown)
Format selector is a segmented control or radio group with two options: CSV and Excel (.xlsx)
Export trigger button ('Generate Export') is disabled while any export job is in-flight; it shows a loading spinner inside the button during submission
After triggering, a progress section appears below the form showing a LinearProgressIndicator and a status label ('Preparing export…', 'Processing…', 'Ready')
When the export job completes, the progress section is replaced by a download section containing: file name, file size, and a prominent 'Download' button that opens the file URL
Download button opens the export file URL using url_launcher; on mobile, this triggers the device's share sheet or file manager
If the export job fails, an inline error message replaces the progress section with a 'Try again' button that re-triggers the same export configuration
Admins can navigate away from the panel during export generation; returning shows the current job status (state preserved in BLoC)
All form controls are accessible with semantic labels; form validates before submission and shows field-level errors; WCAG 2.2 AA compliant

Technical Requirements

frameworks
Flutter
flutter_bloc
BLoC
url_launcher
apis
AdminExportService.triggerExport(scopeId, dateRange, format)
AdminExportService.getExportJobStatus(jobId)
AdminExportService.getDownloadUrl(jobId)
data models
ExportConfig
ExportJob
ExportJobStatus
ExportFormat (csv/xlsx)
AdminPrivilegeScope
performance requirements
Export panel must open and render within 400ms (no blocking async on open)
Export job status polling (if server-sent events are unavailable) must use exponential backoff starting at 2s, capped at 10s
Download URL must be fetched only when job status is 'completed' — no premature fetch
security requirements
Export scope must be validated server-side against the admin's privilege scope (Supabase RLS or Edge Function) — client scope selector is a UX convenience only
Download URL must be a signed, time-limited URL (e.g., Supabase Storage signed URL, valid for ≤ 15 minutes)
Export files must not be cached locally beyond the download action; no persistent local file storage of exported data
ui components
ScopeSelector (dropdown or segmented control restricted to admin scope)
DateRangePicker (accessible, with inline validation)
FormatSelector (segmented control: CSV / Excel)
ExportTriggerButton (with inline loading state)
ExportProgressSection (LinearProgressIndicator + status label)
ExportDownloadSection (file info + Download button via url_launcher)
InlineErrorBanner (with retry)

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use BlocBuilder with buildWhen targeting only the exportJob-related sub-state fields to avoid unnecessary rebuilds when other BLoC state changes. Model the export flow as an ExportJobSubState with states: idle, submitting, processing(progress: double), completed(downloadUrl, fileName, fileSize), failed(error). For export job polling, implement a Stream-based poller in AdminExportService that the BLoC subscribes to via emit.forEach() — this keeps polling logic out of the BLoC and makes it testable. Use url_launcher's launchUrl with LaunchMode.externalApplication for the download link on mobile.

Signed URL expiry: display a countdown timer or a 'Link expired — regenerate' button if the user does not tap Download within the validity window. Follow the design token system for all styling — no hardcoded colours or spacings. Bufdir reporting export is a key long-term use case for this panel; ensure the ExportConfig model can accommodate future Bufdir-specific report types as an extension without structural changes.

Testing Requirements

Widget tests: (1) panel renders all form sections with correct defaults, (2) date range validation shows error when end < start, (3) Export button disabled while job in-flight (BLoC in processing state), (4) progress section appears after successful trigger emission, (5) download section shows with correct filename on BLoC success state, (6) Download button calls url_launcher with correct URL (mock url_launcher), (7) error state shows retry button that re-dispatches TriggerExport event, (8) navigating away and back preserves job status from BLoC. Mock AdminExportService and url_launcher. Accessibility test: verify Semantics for all controls. Integration test: full export flow from scope selection to download link rendered.

Component
Admin Export Panel
ui medium
Epic Risks (3)
high impact medium prob technical

If org node selection in AdminStateBLoC does not correctly propagate to all dependent data streams (statistics, activity log, user list, certification panel), some panels may show data from the previously selected org scope, creating a confusing and potentially dangerous mixed-scope view.

Mitigation & Contingency

Mitigation: Model org node selection as a single source of truth in AdminStateBLoC. All downstream providers derive their query parameters from this single stream via Riverpod's watch pattern. Write integration tests that verify every data stream emits a reload event when the selected node changes.

Contingency: If scope propagation bugs are detected in QA, add an explicit full-state reset on org node change (clear all cached data and refetch from scratch) as a safe but less efficient fallback until the targeted propagation is fixed.

medium impact medium prob technical

The Admin Dashboard Screen must adapt its layout for Flutter Web (wider viewports, mouse interaction, larger grid) and mobile embedding. Flutter Web responsive layout support has historically required non-trivial workarounds, and the adaptive grid may introduce significant additional development time.

Mitigation & Contingency

Mitigation: Define breakpoints and grid behaviour in the design system before implementation. Use LayoutBuilder with explicit breakpoint constants rather than MediaQuery scattered across widgets. Prototype the web layout with a skeleton screen before implementing live data binding.

Contingency: If web layout proves intractable within sprint, deliver a mobile-first layout for all platforms initially and track a dedicated web-optimisation task for the next sprint.

high impact low prob security

A bug in the Role Assignment Panel's permission scope validation could allow an org_admin to assign roles beyond their authority (e.g., assigning super_admin to a user), representing a serious privilege escalation vulnerability.

Mitigation & Contingency

Mitigation: Enforce role assignment scope on both the client (disable unavailable roles in the panel UI) and the server (UserManagementService validates the target role is within the admin's permitted scope before persisting). Write security-focused tests that attempt out-of-scope role assignments and assert rejection.

Contingency: If an escalation vulnerability is discovered, immediately disable the role assignment panel via feature flag, revoke any incorrectly assigned roles, and deploy a server-side fix before re-enabling.