high priority low complexity backend pending backend specialist Tier 0

Acceptance Criteria

HierarchyCache class exposes get(key), set(key, value, ttl), invalidate(key), invalidateAll(), and warmCache() methods
In-memory cache returns a value within 1ms for a cache hit without making any Supabase calls
TTL expiry: entries older than the configured TTL are treated as cache misses and trigger a fresh fetch
Cache-aside pattern: on miss, caller fetches from Supabase and calls set() to populate cache
warmCache() is callable on app startup and pre-populates the top N levels of the hierarchy
invalidate(key) removes a single entry; invalidateAll() clears all entries
Cache layer is injectable (accepts a storage backend interface) so unit tests can use an in-memory stub
No stale data is returned after explicit invalidation
Cache does not exceed a configurable max-entry limit; LRU or FIFO eviction applies when limit is reached

Technical Requirements

frameworks
Flutter
Riverpod
apis
Supabase REST/PostgREST (indirect — via repository layer)
data models
OrganizationUnit
HierarchyCacheEntry
performance requirements
Cache hit latency under 1ms
Cache warm on startup completes within 3 seconds on a typical device
Max memory footprint for cache not to exceed 5MB for typical org trees
security requirements
Cache must not store data beyond the current authenticated user's RLS scope
Cache must be cleared on logout to prevent data leakage between sessions

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Implement HierarchyCache as a singleton or Riverpod provider. Use a `Map` for the in-memory store where `_CacheEntry` holds the value and an expiry `DateTime`. Inject a `Clock` abstraction (e.g., `DateTime Function() now`) to make TTL testable without real delays. For persistent warm cache, consider using flutter_secure_storage or shared_preferences for the top-level nodes only — full tree persistence is rarely worth the complexity at this stage.

Expose the cache via a Riverpod `Provider` so downstream repositories can access it without tight coupling. Clear cache in an auth state listener (on sign-out event from Supabase auth stream).

Testing Requirements

Unit tests using flutter_test. Test cache hit, cache miss, TTL expiry (use a clock abstraction to advance time in tests), explicit invalidation, invalidateAll, max-entry eviction, and warmCache completion. Use a mock repository to verify that Supabase is called only on cache miss, not on hit. Assert that cache is empty after invalidateAll.

Aim for 100% branch coverage on the cache class.

Component
Access Scope Service
service 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.