high priority medium complexity frontend pending frontend specialist Tier 6

Acceptance Criteria

Each HierarchyNodeTile with children has a toggle control (chevron icon) that independently expands or collapses its subtree without affecting sibling branches
Expanded/collapsed state is maintained locally per node using StatefulWidget state — expanding one branch does not reset the state of other branches
A top-level 'Expand All' button expands every node in the tree; a 'Collapse All' button collapses every node to root level only
Collapse/expand transitions use an AnimatedSize or SizeTransition with 200ms duration by default
When the system-level 'reduce motion' accessibility setting is enabled (MediaQuery.disableAnimations), all animations are replaced with instant show/hide with zero transition duration
Leaf nodes (no children) do not render a toggle chevron and are not interactive for expand/collapse
Tree state is preserved across widget rebuilds triggered by Riverpod cache updates — a cache refresh must not reset user's expand/collapse choices
Expand/collapse toggle target is at minimum 44×44dp to meet WCAG 2.2 AA touch target size requirements
flutter_test widget tests confirm: toggle hides children, toggle again shows children, expand-all expands all nodes, collapse-all collapses all nodes, reduced-motion disables animation

Technical Requirements

frameworks
Flutter
Riverpod
data models
HierarchyNode
performance requirements
AnimatedSize must not cause layout thrashing; wrap only the children container, not the entire node row
Expand-all on a 200-node tree must complete within one frame budget (16ms) — use a single setState call at root level with a notifier, not 200 individual setState calls
security requirements
Expand/collapse state is purely UI state — do not persist it to database or transmit it to backend
ui components
Animated chevron icon (rotates 90° on expand using AnimatedRotation)
AnimatedSize wrapper around children container
ExpandAllButton and CollapseAllButton at tree root (using AppButton design token component)
Minimum 44×44dp InkWell tap target for chevron

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Store expanded state in HierarchyNodeTile as a bool _isExpanded in local State<>. For expand-all/collapse-all, lift state management using a ValueNotifier passed down from HierarchyTreeView, but allow individual node state to override it after user interaction — use a 'controlled after first override' pattern. Specifically: node listens to the root notifier until the user taps the chevron, after which the node manages its own local state. Use AnimatedSize for the children container and AnimatedRotation for the chevron.

Check MediaQuery.of(context).disableAnimations at build time and set duration to Duration.zero if true — this is the WCAG 2.2 AA reduced motion compliance pattern in Flutter. Do not use ExpansionTile from Flutter's material library unless you can fully override its animation — it has opinionated sizing and header padding that conflicts with the design token system.

Testing Requirements

Widget tests (flutter_test): mount a 3-level tree; tap chevron on root node and assert children are hidden; tap again and assert children are visible. Test that expand-all makes all nodes' children visible. Test that collapse-all hides all children. Test that expanding node A and collapsing node B does not affect node A's state.

Accessibility test: set MediaQuery.disableAnimations = true in test scope and assert no AnimationController is running after toggle. Verify chevron tap target is at least 44×44dp using a Size assertion.

Component
Hierarchy Tree View
ui high
Epic Risks (4)
high impact medium prob security

Injecting all unit assignment IDs into JWT claims for users assigned to many units (up to 5 for NHF peer mentors, many more for national coordinators) may exceed JWT size limits, causing authentication failures.

Mitigation & Contingency

Mitigation: Store unit IDs in a Supabase session variable or a dedicated Postgres function rather than embedding them directly in the JWT payload. Use set_config('app.unit_ids', ...) within RLS helper functions querying the assignments table at policy evaluation time.

Contingency: Fall back to querying the unit_assignments table directly within RLS policies using the authenticated user ID, accepting a small per-query overhead in exchange for removing the JWT size constraint.

medium impact medium prob technical

Rendering 1,400+ nodes in a recursive Flutter tree widget may cause jank or memory pressure on lower-end devices used by field peer mentors, degrading the admin experience.

Mitigation & Contingency

Mitigation: Implement lazy tree expansion — only the root level is rendered on initial load. Child nodes are rendered on demand when the parent is expanded. Use const constructors and ListView.builder for all node lists to minimize rebuild scope.

Contingency: Add a search/filter bar that scopes the visible tree to matching nodes, reducing the visible node count. Provide a 'flat list' fallback view for administrators who prefer searching over browsing the tree.

medium impact medium prob scope

Requirements for what constitutes a valid hierarchy structure may expand during NHF sign-off (e.g., mandatory coordinator assignments per chapter, minimum member counts per region), requiring repeated validator redesign.

Mitigation & Contingency

Mitigation: Design the validator as a pluggable rule engine where each check is a discrete, independently testable function. New rules can be added without changing the core validation orchestration. Surface all rules in a configuration table per organization.

Contingency: Defer non-blocking validation rules to warning-level feedback rather than hard blocks, allowing structural changes to proceed while flagging potential issues for admin review.

high impact low prob integration

Deploying RLS policy migrations to a shared Supabase project used by multiple organizations simultaneously could lock tables or interrupt active sessions, causing downtime during production migration.

Mitigation & Contingency

Mitigation: Write all RLS policies as CREATE POLICY IF NOT EXISTS statements. Schedule migrations during off-peak hours. Use Supabase's migration preview environment to validate policies against production data shapes before applying.

Contingency: Prepare rollback migration scripts for every RLS policy. If a migration causes issues, execute the rollback immediately and re-test the policy logic in staging before reattempting.