high priority medium complexity frontend pending frontend specialist Tier 4

Acceptance Criteria

A TextField search bar appears at the top of OrgHierarchyNavigator; typing filters the tree in real time (debounce ≤ 300 ms) by delegating to OrgHierarchyService.searchNodes(query)
Search results show only matching nodes and their ancestor chain (ancestors are rendered as non-selectable context rows, visually muted); unmatched branches are hidden
Clearing the search field restores the full tree in its previous expansion state (expansion state must not be reset by a search operation)
A breadcrumb bar is rendered below the tree (or below the search field) showing the path from root to the currently selected node, e.g. 'National › Region East › Oslo Chapter'
Each breadcrumb segment is a tappable element that selects that ancestor node, updates the selection, and fires onNodeSelected with the ancestor's data
When no node is selected, the breadcrumb bar displays a neutral placeholder ('No selection') and takes up the same vertical space to prevent layout shift
Search field has a label='Search organisations', and returns focus to the field after results are updated (no focus trapping)
Breadcrumb segments have Semantics wrappers with role=button and descriptive labels (e.g., 'Navigate to Region East')
Both search and breadcrumb comply with WCAG 2.2 AA: minimum contrast ratio 4.5:1 for text, 3:1 for UI component boundaries, touch targets ≥ 48 × 48 dp

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
apis
OrgHierarchyService.searchNodes(query)
OrgHierarchyService.getAncestors(nodeId)
data models
OrgNode
OrgSearchResult (matchedNode, ancestorPath[])
BreadcrumbItem (id, label)
performance requirements
Debounce search input 300 ms using a Timer to avoid excessive service calls
Search results must render within 200 ms of the debounce firing for datasets ≤ 1 400 nodes
Breadcrumb update must be synchronous (ancestors derived from cached tree, no additional network call)
security requirements
Search query must be sanitised before forwarding to OrgHierarchyService to prevent injection via query string manipulation
Breadcrumb ancestor resolution must use the same scope-restricted tree as the main view; do not expose ancestor nodes outside the admin's permitted scope
ui components
OrgSearchField (TextField with debounce, clear button, search icon)
OrgSearchResultRow (muted ancestor row variant + normal selectable row)
BreadcrumbBar (horizontally scrollable Row of BreadcrumbSegment widgets)
BreadcrumbSegment (InkWell-wrapped Text with Semantics)

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Store search state (query string, filtered results) as a separate SearchState data class in the widget's local state alongside expansionState. When query is non-empty, replace the main tree ListView with a flat SearchResultsList; when cleared, reinstate the tree. This avoids complex diffing of the recursive tree widget. For breadcrumbs, call OrgHierarchyService.getAncestors(nodeId) once on node selection; if ancestors are already embedded in the OrgNode model (parentId chain), traverse the cached tree in-memory without an extra service call.

Make BreadcrumbBar a horizontally scrollable SingleChildScrollView to handle deep hierarchies without overflow. Use design tokens for breadcrumb separator (e.g., '›' character, text-secondary color) to stay consistent with the wider admin portal theme.

Testing Requirements

Widget tests (flutter_test): (1) typing a query triggers searchNodes after debounce and re-renders filtered list; (2) clearing query restores pre-search expansion state; (3) selecting a node populates breadcrumb with correct ancestor path; (4) tapping a breadcrumb segment fires onNodeSelected with that ancestor's node; (5) empty-results state renders a 'No results' message. Accessibility test: use SemanticsController to assert that search field and each breadcrumb segment have correct semantic labels. Contrast compliance verified via Flutter's debugCheckHasMediaQuery color-scheme assertions and manual design-token audit.

Epic Risks (4)
medium impact high prob technical

OrgHierarchyNavigator rendering NHF's full 1,400-chapter tree in a single widget may cause Flutter frame-rate drops below 60 fps on mid-range devices, making the navigator unusable for NHF national admins.

Mitigation & Contingency

Mitigation: Implement lazy expansion: only load immediate children on node expand rather than the full tree upfront. Use virtual scrolling for long sibling lists. Test with a synthetic 1,400-node dataset on a low-end Android device during development.

Contingency: If lazy expansion is insufficient, replace the tree widget with a paginated drill-down navigator (select level → select child) that avoids rendering more than 50 nodes at a time.

medium impact medium prob dependency

Bufdir may update their required export column structure or file format during or after development. If the AdminExportService hardcodes the current Bufdir schema, any format change requires a code release rather than a config update.

Mitigation & Contingency

Mitigation: Drive the Bufdir column mapping from a configuration repository rather than hardcoded constants. Abstract column definitions into a named schema config so that format changes require only a config update and re-deployment without service logic changes.

Contingency: If Bufdir format changes post-launch, release a config update within one sprint. If the change is structural (new required sections), scope a targeted service update and communicate timeline to partner organisations.

high impact medium prob integration

Role transition side-effects in UserManagementService (e.g., certification expiry removing mentor from chapter listing, pause triggering coordinator notification) may interact with external services like HLF's website sync. Incomplete side-effect handling could leave the system in an inconsistent state.

Mitigation & Contingency

Mitigation: Model side-effects as explicit domain events published after the primary state change is persisted. Implement event handlers as idempotent operations so re-processing is safe. Write integration tests that assert all side-effects fire correctly for each role transition type.

Contingency: If a side-effect fails after the primary change is persisted, log the failure with full context and trigger a manual reconciliation alert to the on-call team. Provide an admin-accessible re-trigger action for failed side-effects.

medium impact medium prob scope

If AdminStatisticsService cache TTL is set too long, org_admin may see significantly stale KPI values (e.g., a mentor newly paused an hour ago still appears as active), undermining trust in the dashboard.

Mitigation & Contingency

Mitigation: Default cache TTL to 5 minutes with a manual refresh action on the dashboard. Implement cache invalidation triggered by UserManagementService write operations that affect counted entities.

Contingency: If staleness causes org admin complaints post-launch, reduce TTL to 60 seconds and introduce a real-time Supabase subscription for high-impact counters (paused mentors, expiring certifications).