high priority medium complexity testing pending testing specialist Tier 6

Acceptance Criteria

All interactive elements (rows, filter chips, toggle buttons, dropdowns, text fields, submit button) pass WCAG 2.2 AA contrast ratio: 4.5:1 for normal text, 3:1 for large text and UI components
Role and status badge colours meet 3:1 contrast ratio against their background in both light and dark themes
All interactive elements have a minimum touch target of 44×44 dp (WCAG 2.2 criterion 2.5.8)
Every interactive element has a non-empty Semantics label readable by VoiceOver (iOS) and TalkBack (Android)
Screen reader focus order is logical: follows visual reading order top-to-bottom, left-to-right
Toggle buttons (activate/deactivate) announce their current state (e.g., 'Active, toggle button, double-tap to deactivate') to screen readers
Filter controls announce their current value when changed (e.g., 'Role filter: Coordinator')
The invitation form announces validation errors to screen readers without requiring the user to navigate to the error manually (use Semantics.liveRegion or equivalent)
No keyboard trap exists anywhere on the screen: the user can always navigate forward and backward through all elements
Focus is managed correctly after modal/bottom sheet dismiss: returns to the triggering element
Audit findings are documented in a structured report listing each WCAG criterion tested, pass/fail status, and remediation applied

Technical Requirements

frameworks
Flutter
Flutter Accessibility (Semantics API)
performance requirements
Accessibility audit must not introduce any widget rebuilds that degrade scroll performance below 55 fps
security requirements
Ensure sensitive user data fields (e.g., personal identification numbers, health-related role labels) are not announced unnecessarily by screen readers — use excludeSemantics where appropriate
ui components
Semantics widget wrappers on all custom components
MergeSemantics for list row items to ensure row is announced as a single unit
ExcludeSemantics on decorative icons/images
Tooltip widgets for icon-only buttons

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Start by enabling Flutter's accessibility scanner overlay (import 'package:flutter/rendering.dart'; debugSemanticsDisableAnimations = true) to get a quick map of the semantics tree. Use MergeSemantics on each user list row so TalkBack/VoiceOver reads the row as 'John Doe, Coordinator, Active' rather than three separate focusable elements. For toggle buttons, set Semantics(toggled: isActive, button: true, label: 'Activate/Deactivate user') explicitly — Flutter's Switch widget already handles this, but custom row toggles may not. For role/status badges, check contrast against both the card background and any gradient backgrounds using the design token colour values.

Pay particular attention to low-contrast combinations like light yellow text on white. For the invitation form's live error announcements, wrap the error Text widget in a Semantics(liveRegion: true) so screen readers announce changes automatically. This audit is a remediation task — fix all identified issues in the same PR rather than logging them as separate tickets, unless a fix requires significant rework (in which case log a blocked issue).

Testing Requirements

Automated accessibility tests using Flutter's `SemanticsController` in widget tests: (1) verify every interactive widget has a non-empty Semantics label; (2) verify toggle buttons include `toggled` property in their Semantics node. Manual testing checklist: (1) test full screen navigation with TalkBack on Android and VoiceOver on iOS using a real device or emulator with accessibility enabled; (2) verify contrast ratios for all badge colour combinations using a contrast checker tool (e.g., Colour Contrast Analyser or Chrome DevTools); (3) verify touch target sizes using Flutter's accessibility inspector overlay (`flutter run --enable-software-rendering` + DevTools). Document each test result in an audit table. Run `flutter test --tags=accessibility` for automated checks.

Component
User Account Management Screen
ui high
Epic Risks (3)
medium impact medium prob technical

Displaying NHF users with membership in up to 5 local chapters in a flat list view without duplicating entries requires a non-trivial aggregation query. Incorrect query design could result in duplicated user rows or missing chapter affiliations, confusing admins and causing incorrect role assignments.

Mitigation & Contingency

Mitigation: Design the user list query to GROUP BY user_id and aggregate chapter affiliations as an array field. Use AdminRepository's typed models to surface this aggregated structure to the UI. Validate with a test dataset containing users in 5 chapters.

Contingency: If aggregation query complexity proves too high for real-time filtering, implement a separate multi-chapter affiliation fetch triggered only when a specific user row is expanded, reducing query complexity for the base list.

medium impact medium prob technical

Composable multi-dimensional filters (role + chapter + status + certification state) applied server-side against an org with 2,000+ users may produce slow queries, particularly when filtering by certification state requires joining an additional table.

Mitigation & Contingency

Mitigation: Ensure the relevant filter columns (role, status, chapter_id, certification_expiry) are indexed in Supabase. Use cursor-based pagination rather than OFFSET to maintain consistent performance at high page numbers. Profile filter query combinations against a large dataset during development.

Contingency: If multi-filter performance degrades in production, introduce a denormalised search index table updated on user status changes, allowing the list query to filter from a single table.

medium impact medium prob integration

Deactivating a user account that has ongoing activity assignments, open expense claims, or active chapter affiliations may leave orphaned records or break downstream workflows if the deactivation does not trigger correct cascade handling.

Mitigation & Contingency

Mitigation: Define and document the expected state of each dependent record type on user deactivation before implementing the toggle. Implement deactivation as a UserManagementService operation that checks for and warns about open dependencies before persisting. Write integration tests covering each dependency type.

Contingency: If orphaned record issues are discovered post-launch, provide an admin-accessible reconciliation view that surfaces users with inconsistent dependency states and allows manual resolution without requiring a code deploy.