high priority medium complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

RoleAssignmentPanel renders as a modal bottom sheet (DraggableScrollableSheet) with a drag handle and accessible close affordance
The panel header displays the target user's full name and their current role label (localised from org labels system)
The selectable role list shows only roles within the acting admin's privilege scope β€” roles above the admin's level are absent from the list
Currently assigned role is pre-selected and visually distinguished; selecting a different role enables the Continue button
Tapping Continue transitions to a confirmation step showing: target user name, old role, new role, and a prominent Confirm button
Tapping Confirm calls UserManagementService.assignRole() and shows a CircularProgressIndicator while the request is in-flight; both Continue and Confirm buttons are disabled during loading
On success: panel closes, a SnackBar with a success message is shown on the parent screen, and the user list item reflects the updated role without a full reload
On failure: an inline error message is shown within the panel (not a SnackBar) with a Retry option; the panel does not close automatically
The panel is fully accessible: all interactive elements have semantic labels, minimum touch target 48Γ—48dp, and passes WCAG 2.2 AA contrast ratio
Back navigation from the confirmation step returns to the role selection step without closing the panel

Technical Requirements

frameworks
Flutter
flutter_bloc
BLoC
apis
UserManagementService.assignRole(userId, newRole)
UserManagementService.getAssignableRoles(adminScopeId)
data models
UserProfile
UserRole
AdminPrivilegeScope
RoleAssignmentRequest
performance requirements
Panel open animation must complete within 300ms
Assignable roles list must render within 200ms of panel open (roles should be pre-fetched or passed as argument)
Role assignment API call must not block UI β€” show loading indicator immediately on tap
security requirements
Assignable roles list must be derived server-side from the admin's privilege scope β€” client must not filter a full roles list locally as the sole guard
UserManagementService.assignRole() must validate admin authority server-side (Supabase RLS or Edge Function policy)
No role data above the admin's privilege level may be rendered, even if accidentally returned by a misconfigured query
ui components
DraggableScrollableSheet (modal bottom sheet host)
RoleOptionTile (selectable radio-style list tile with role name and description)
ConfirmationStep widget (summary card with old→new role change)
AppButton (primary Confirm, secondary Cancel)
InlineErrorBanner (error message with retry)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use showModalBottomSheet with isScrollControlled: true and a DraggableScrollableSheet for the host. Manage the two-step flow (select β†’ confirm) with a local StatefulWidget or a simple step index β€” this does not need BLoC since it is a transient UI flow; BLoC integration for persisting the result is handled in task-007. Pass the target user and pre-fetched assignable roles as constructor arguments to avoid async loading inside the modal. Use the org labels system for role name localisation (never hardcode role display strings).

Implement the back-from-confirmation step with a PageController or an AnimatedSwitcher. Ensure the panel respects the device's bottom safe area (MediaQuery.viewInsets.bottom) when the keyboard is not involved. Follow the design token system for all colours, spacing, and typography β€” no hardcoded style values.

Testing Requirements

Widget tests using flutter_test. Test cases: (1) panel renders with correct user name and current role pre-selected, (2) roles above admin scope are absent, (3) selecting a new role enables Continue, (4) Continue shows confirmation step with correct summary, (5) Back from confirmation returns to selection, (6) Confirm calls UserManagementService with correct arguments, (7) success closes panel and triggers parent SnackBar, (8) failure shows inline error with retry. Mock UserManagementService. Accessibility test: verify all Semantics labels present and contrast ratios via flutter_test semantics API.

Golden test for both role-selection and confirmation steps.

Component
Role Assignment 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.