critical priority high complexity backend pending backend specialist Tier 3

Acceptance Criteria

getTree(organizationId) returns a fully populated HierarchyNode tree with children nested recursively, loaded in a single query using a recursive CTE
createNode(parentId, name, type) runs HierarchyStructureValidator before any database write; on validation failure throws HierarchyValidationException with the full error list
renameNode(nodeId, newName) checks duplicate sibling constraint before persisting; returns updated HierarchyNode on success
moveNode(nodeId, newParentId) validates circular reference and depth constraints before persisting; if invalid throws HierarchyValidationException
deleteNode(nodeId) only succeeds when the node has zero children and zero active member assignments; otherwise throws NodeNotEmptyException with counts of blocking children and assignments
getMemberCount(nodeId) returns the count of active user assignments within the node and all its descendants (recursive)
searchNodes(organizationId, query) performs case-insensitive partial name match and returns matching nodes with their breadcrumb path
All write operations are wrapped in Supabase transactions where possible; partial failures roll back
Service exposes a Stream<HierarchyNode> watchSubtree(nodeId) that emits an updated subtree whenever Supabase Realtime detects a change in the organization_units table

Technical Requirements

frameworks
Flutter
Dart
Riverpod
BLoC
apis
Supabase PostgreSQL 15
Supabase Realtime
data models
assignment
contact_chapter
contact
performance requirements
Tree load for an organization with up to 1400 nodes (NHF scale) must complete within 1.5 seconds on a standard mobile connection
Recursive CTE used server-side for tree fetch — no client-side recursive assembly of flat rows
Member count query uses a single recursive SQL count — not N+1 queries per node
Hierarchy cache invalidated on write operations; consumers receive updated tree via Riverpod invalidation
security requirements
All Supabase queries scoped to the caller's organization_id extracted from the verified JWT — service must not accept organizationId as a client-supplied parameter without JWT verification
Node names must be sanitized before database writes to prevent SQL injection via Supabase RPC parameters
RLS enforced at database level as a backstop even if service-level checks are bypassed

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Implement as a Riverpod-managed service class HierarchyService injected via a Provider. Internal dependencies: OrganizationUnitRepository (data layer), HierarchyStructureValidator (task-005), and HierarchyCache (in-memory LRU cache keyed by organizationId). The repository handles raw Supabase queries; the service handles business rules. Use a recursive CTE Postgres function (get_organization_tree) invoked via supabase.rpc() to fetch the full tree in one round-trip — avoid assembling the tree client-side from a flat list.

For moveNode, fetch the ancestor path of the proposed new parent before calling the validator (one additional query). For Realtime subscriptions, subscribe to the organization_units table filtered by organization_id and pipe changes through a StreamController exposed as watchSubtree(). The cache should store the last fetched tree per organizationId and be invalidated on any write operation to force a fresh fetch on next read. NHF's 1400-chapter structure makes caching especially important for the admin portal's performance.

Testing Requirements

Unit tests with mocked OrganizationUnitRepository covering all service methods including edge cases: moving a node to its own descendant (circular), deleting a node with children, renaming to a name that conflicts with a sibling. Integration tests against a local Supabase instance for: tree load with 50+ nodes, concurrent write conflict handling, Realtime stream emission on update. Use flutter_test and mockito for unit tests. Test coverage target: 90% of service class lines.

Performance test: load NHF-scale mock tree (1400 nodes) and assert response within 1.5s.

Component
Hierarchy Admin Portal Screen
ui high
Epic Risks (3)
high impact medium prob security

If the AccessScopeService and the Supabase RLS policies use different logic to determine accessible units, a coordinator could see data in the client that RLS blocks server-side, causing confusing empty states, or worse, RLS could block data the scope service declares accessible.

Mitigation & Contingency

Mitigation: Define the canonical scope computation in a single Supabase Postgres function shared by both the RLS policies and the RPC endpoint called by AccessScopeService. The client-side service calls this RPC rather than reimplementing the logic, ensuring a single source of truth.

Contingency: Add integration tests that execute the same access decision through both the RLS policy path and the AccessScopeService path and assert identical results. Use these as regression guards in the CI pipeline.

medium impact medium prob integration

When a user switches active chapter via the ChapterSwitcher, widgets that are already built may not receive the context-change event if they subscribe incorrectly to the ActiveChapterState BLoC, leading to stale data being displayed under the new chapter context.

Mitigation & Contingency

Mitigation: Use Riverpod's ref.watch on the active chapter provider at the root of each scoped data subtree rather than at individual leaf widgets. Trigger a global data refresh by invalidating all scoped providers when the chapter changes.

Contingency: Add an app-level chapter-change listener that forces a full navigation stack reset to the home screen on chapter switch, guaranteeing all widgets rebuild from scratch with the new context. Accept the UX cost of navigation reset for correctness.

medium impact medium prob scope

Non-technical organization administrators may find the hierarchy management interface too complex for the structural changes they need to make frequently (e.g., chapter renaming, coordinator reassignment), leading to low adoption and continued reliance on manual processes.

Mitigation & Contingency

Mitigation: Conduct usability testing with at least one NHF administrator before finalizing the admin portal screen layout. Prioritize the most common operations (rename, reparent, add child) as primary actions in the UI. Include inline help text and confirmation dialogs with plain-language descriptions of consequences.

Contingency: Provide a simplified 'quick edit' mode that exposes only the three most common operations (rename, deactivate, add child) and hides advanced structural operations behind an 'Advanced' toggle.