high priority high complexity frontend pending frontend specialist Tier 5

Acceptance Criteria

HierarchyTreeView widget accepts a List<HierarchyNode> parameter and renders each node as a tree item with correct parent-child indentation (24dp per depth level)
Each tree node is implemented as a standalone StatefulWidget (HierarchyNodeTile) capable of rendering its own children recursively without depth limits up to the maximum allowed depth
Widget consumes a Riverpod provider (hierarchyCacheProvider) and rebuilds automatically when the underlying HierarchyChangedEvent is emitted — no manual refresh required
Root-level nodes render without indentation; child nodes indent by exactly one level per depth increment using consistent design token spacing
Empty tree state (no nodes) renders a clearly labelled empty state widget rather than a blank screen
Widget renders correctly for organizations with at least 3 levels of nesting (e.g., Region → Chapter → Local)
No RenderFlex overflow or layout exceptions occur for node labels up to 120 characters
Widget passes flutter_test widget tests for: empty list input, single root node, three-level nested tree, and Riverpod reactive rebuild on cache change
Widget tree construction completes within 16ms frame budget for trees up to 200 nodes (no jank on mid-range devices)

Technical Requirements

frameworks
Flutter
Riverpod
data models
HierarchyNode
HierarchyCache
performance requirements
Widget build completes within 16ms for trees up to 200 nodes
Use ListView.builder or equivalent lazy rendering for trees exceeding 50 visible nodes
Avoid unnecessary rebuilds: use select() or ConsumerWidget with fine-grained provider selectors so only affected subtrees rebuild on cache update
security requirements
Widget must not render nodes that the current user's role does not have read permission for — filter at provider level before passing to widget
Do not expose raw node IDs in widget semantics labels visible to screen readers
ui components
HierarchyTreeView (root StatelessWidget / ConsumerWidget)
HierarchyNodeTile (StatefulWidget per node)
HierarchyEmptyState (empty state placeholder widget)
Indentation container using design token spacing (e.g., AppSpacing.hierarchyIndent)

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Model HierarchyNode as an immutable Dart class with id, parentId, label, unitType, memberCount, and children List. Build the tree as a pre-structured nested list from the flat cache rather than deriving parent-child relationships in the widget layer — this keeps widget code simple and pushes data transformation to the repository/provider layer. Use a ConsumerWidget at the root (HierarchyTreeView) and pass the resolved node list down as a plain parameter to avoid propagating ProviderScope deep into the recursive widget tree. For indentation, pass a `depth` integer parameter through recursive calls and multiply by a token constant.

Avoid using TreeView packages that add unvetted dependencies; Flutter's built-in approach with a recursive Column/ListView is sufficient and more controllable for accessibility. Ensure the widget file structure separates HierarchyTreeView and HierarchyNodeTile into their own files under `lib/features/hierarchy/widgets/`.

Testing Requirements

Unit tests (flutter_test): verify HierarchyNodeTile renders correct label for a given HierarchyNode; verify recursive child rendering for a 3-level tree fixture; verify empty list produces EmptyState widget. Widget tests: mount HierarchyTreeView with a ProviderScope override for hierarchyCacheProvider; assert tree renders correct node count; emit a HierarchyChangedEvent and assert widget rebuilds with updated data. Performance test: render a 200-node flat tree and assert no overflow errors. No integration tests at this layer — those are covered in task-020.

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.