high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

All TTL expiration scenarios are tested using FakeAsync and fake timers — entries must not be returned after TTL elapses
Explicit invalidation by partition key removes only the targeted partition and leaves all other partitions intact
LRU eviction test confirms that the least-recently-used entry is evicted first when the cache reaches capacity
Cache hit path test confirms the cached value is returned without invoking the underlying data fetcher
Cache miss path test confirms the data fetcher is invoked exactly once and the result is stored for subsequent hits
Force-refresh bypass test confirms that passing forceRefresh=true skips the cached value and repopulates with fresh data
Mutation event invalidation test confirms that only the partitions affected by a given mutation event are cleared; unrelated partitions remain populated
All tests pass with zero flakiness across 10 consecutive runs
Test file follows the Arrange-Act-Assert pattern and each test has a single assertion group
Code coverage for StatsCacheManager reaches ≥ 95 % line coverage as reported by flutter test --coverage

Technical Requirements

frameworks
Flutter
flutter_test
fake_async
data models
StatsCachePartition
StatsCacheEntry
MutationEvent
performance requirements
Each individual test must complete in under 500 ms wall-clock time
FakeAsync must be used for all time-dependent assertions — no real sleep() calls
security requirements
No real Supabase credentials or user data may appear in test fixtures — use anonymised stubs

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Import fake_async from the test_api package bundled with flutter_test — no additional dependency needed. Instantiate StatsCacheManager with an injected clock so FakeAsync can control time progression. For LRU eviction, set a small capacity (e.g., 3) and insert 4 entries in sequence; assert that the first-inserted entry is absent. For mutation invalidation, register listeners on a stream controller and emit a MutationEvent targeting partition key 'activities:coordinator:123'; assert only that partition is evicted.

Avoid using real Duration.seconds(30) in tests — always pass the TTL as a constructor parameter so tests can use Duration(milliseconds: 1) with FakeAsync elapsing 2 ms. Keep test data anonymous: use IDs like 'coord-001', never real names or emails.

Testing Requirements

Unit tests only using flutter_test. Use FakeAsync for all TTL and timer-dependent behaviour. Mock the underlying data fetcher with a Mockito or manual stub that counts invocations. Structure tests as one group per behaviour: ttl_expiration, explicit_invalidation, lru_eviction, cache_hit, cache_miss, force_refresh, mutation_invalidation.

Each group must have at least one happy-path test and one edge-case test (e.g., invalidating a key that does not exist, TTL = 0, capacity = 1). Run flutter test --coverage and assert ≥ 95 % line coverage for the StatsCacheManager class.

Component
Statistics Cache Manager
data low
Epic Risks (3)
high impact medium prob technical

Pre-aggregated Supabase views may still be slow for orgs with very large activity datasets (NHF with 1,400 chapters). If the view query plan performs sequential scans, dashboard load times could exceed acceptable thresholds and degrade the perceived value of the feature.

Mitigation & Contingency

Mitigation: Design views with composite indexes on (org_id, coordinator_id, month) from the start. Run EXPLAIN ANALYZE during development against a seeded dataset of realistic scale. Add materialized view refresh strategy if needed.

Contingency: If live view performance is insufficient, convert to materialized views refreshed on a schedule or on activity-write triggers. Expose the refresh delay transparently in the UI with a 'last updated' timestamp.

high impact low prob security

Supabase RLS policies for the stats views may not be configured correctly during initial migration, potentially allowing cross-coordinator data leakage before the RoleAccessValidator layer is reached. This is a security and compliance risk.

Mitigation & Contingency

Mitigation: Write RLS integration tests as part of this epic that explicitly verify a coordinator JWT cannot read another coordinator's stats rows. Apply RLS policies in the migration script itself, not as a manual step.

Contingency: If an RLS gap is discovered post-deployment, immediately disable the stats screen via a feature flag, apply the corrected RLS migration, and re-enable after verification. Log and audit all queries that ran during the gap window.

medium impact medium prob integration

Cache invalidation logic may not be triggered correctly when a new activity is registered by a peer mentor or when an expense approval is granted. Stale data could cause coordinators to make decisions based on outdated KPIs, undermining trust in the dashboard.

Mitigation & Contingency

Mitigation: Define explicit invalidation event contracts with the activity registration and expense approval pipelines. Implement an event bus subscription within StatsCacheManager. Document the invalidation contract in code.

Contingency: If event-driven invalidation proves unreliable, add a manual 'Refresh' pull-to-refresh gesture on the dashboard and reduce TTL to 5 minutes as a fallback degradation strategy.