high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Monthly period filter returns only activities whose date falls within the specified calendar month, verified against seeded data with activities on boundary dates
Quarterly period filter correctly groups three consecutive calendar months; no activities from adjacent quarters appear in results
Annual period filter spans exactly January 1 to December 31 of the given year
Activity-type filter returns only rows matching the requested type; mixed-type seed data confirms correct exclusion
Coordinator-scope query returns only activities belonging to the authenticated coordinator's assigned peer mentors; activities from a different coordinator are absent
Org-admin-scope query returns all activities across the entire organisation; the result count equals the total seeded for that org
Cache hit path: second identical call to StatsRepository does not produce a new Supabase network request (verified via request interceptor or spy)
Cache miss path: calling with a different period produces a fresh Supabase request and updates the cache
Access denial: a coordinator querying another coordinator's peer mentors receives a StatsAccessDeniedException or equivalent — no data leaks
P95 response time for indexed lookups (coordinator scope, single month) is under 100 ms measured against the test Supabase instance with ≥ 50 rows seeded
All tests are idempotent: the seed script is run before the suite and a teardown script restores the test schema to a clean state

Technical Requirements

frameworks
Flutter
flutter_test
Supabase Flutter SDK
apis
Supabase REST API
Supabase PostgREST RLS
data models
Activity
PeerMentor
Coordinator
Organisation
StatsPeriod
StatsFilter
performance requirements
Indexed lookups must complete in under 100 ms at the 95th percentile
Seed dataset must contain at minimum 50 activity rows spread across 3 coordinators, 2 orgs, and all supported activity types to provide meaningful coverage
security requirements
Tests must authenticate with role-specific JWT tokens (coordinator JWT, org-admin JWT) issued by the test Supabase instance — never use the service_role key in integration tests
RLS policies must be active on the test instance; tests that pass with RLS disabled are invalid
No production Supabase project URL or keys may appear in test files — use environment variables injected via .env.test

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Use supabase_flutter's SupabaseClient initialised with test credentials injected at runtime via --dart-define or a .env.test file read by flutter_dotenv. Create a TestAuthHelper that mints coordinator and org-admin JWT tokens by calling the test Supabase Auth API with pre-seeded test user credentials. Wrap each test group in a setUpAll / tearDownAll pair: setUpAll runs the seed SQL via the Supabase management API or a direct postgres connection; tearDownAll deletes seeded rows. For performance assertions, wrap the repository call in a Stopwatch, run it 5 times after a warm-up call, and assert that the median is under 100 ms.

For cache behaviour, inject a request-counting HttpClient adapter into the Supabase client so you can assert exactly how many network calls were made. For access-denial tests, catch the thrown exception and verify its type — do not rely on an empty result set as a proxy for denial because that could mask data leaks.

Testing Requirements

Integration tests using flutter_test against a dedicated Supabase test project (separate from staging and production). Maintain a SQL seed script (test/fixtures/stats_seed.sql) that inserts a deterministic dataset including: 3 coordinators across 2 organisations, 5 peer mentors per coordinator, activities spanning three calendar years with all supported types, and at least two boundary-date activities per period type. Write test groups: period_filtering (monthly, quarterly, annual, boundary dates), activity_type_filtering, scope_isolation (coordinator, org_admin, cross-coordinator denial), cache_behaviour (hit, miss, invalidation), and performance (timing assertions with Stopwatch). Teardown must DELETE only rows inserted by the seed script using a known seed_run_id column.

Run with flutter test integration_test/ --dart-define=SUPABASE_TEST_URL=... --dart-define=SUPABASE_TEST_ANON_KEY=...

Component
Stats Repository
data medium
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.