high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Integration test: ProviderContainer can be created with the full provider graph without throwing any circular dependency errors
Integration test: organizationLabelsNotifierProvider transitions from loading to loaded state with the stub repository's labels
Integration test: labelProvider('key_a') returns the correct resolved value after labels are loaded
Integration test: mutating only 'key_b' in the label map does NOT trigger a rebuild notification for a listener on labelProvider('key_a')
Integration test: terminologySyncServiceProvider starts the sync service (verified via mock invocation count) when first read
Integration test: simulating auth logout (emitting unauthenticated auth state) causes terminologySyncServiceProvider to be disposed and the sync service's dispose() called
Integration test: org switch (changing org ID) causes organizationLabelsNotifierProvider to reload and emit a new label map without requiring a full container reset
Integration test: after container.dispose(), no providers hold live references or active timers (verified by asserting no pending timer callbacks fire post-dispose)
All tests use stub/fake implementations — no real Supabase or network calls

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
apis
Supabase (stubbed)
data models
OrganizationLabelsNotifier
TerminologySyncService
labelProvider family
AuthState
performance requirements
Full integration test suite completes in under 10 seconds
No memory leaks — container.dispose() must cleanly tear down all providers
security requirements
Test container overrides must not expose any production Supabase credentials

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

This integration test suite serves as the canonical proof that the provider graph design is sound. Structure as: (1) graph topology test — just create the container and read all providers to confirm no circular deps; (2) state lifecycle tests — step through the expected state machine; (3) granular rebuild tests — use listener spy pattern; (4) disposal tests — simulate logout and container.dispose(). Use `ProviderObserver` to log all state changes during the test run for easier debugging. Create a shared `buildTestContainer()` helper that wires all stubs to avoid boilerplate across test cases.

Document the expected provider dependency order in a comment block at the top of the test file.

Testing Requirements

Integration tests using ProviderContainer with dependency overrides for all external services (Supabase, connectivity, auth stream). Use a single container instance per test group (setUp/tearDown) with container.dispose() in tearDown. Test rebuild granularity by attaching multiple listeners to different labelProvider family instances and counting invocations. Use StreamController for auth state simulation.

Verify service lifecycle by injecting a spy/mock TerminologySyncService and asserting start() and dispose() call counts. Run tests with `flutter test` — no device or emulator required.

Component
Terminology Riverpod Providers
infrastructure low
Epic Risks (3)
high impact medium prob technical

When a user switches organization context (e.g., a coordinator with multi-org access), a race condition between the outgoing organization's map disposal and the incoming organization's fetch could briefly expose the wrong organization's terminology to the widget tree.

Mitigation & Contingency

Mitigation: Implement an explicit loading state in OrganizationLabelsNotifier that widgets check before rendering any resolved labels. The provider graph should cancel the previous organization's fetch via Riverpod's ref.onDispose before initiating the next.

Contingency: If the race manifests in production, fall back to English defaults during the transition window and emit a Sentry error event for investigation; the UX impact is a brief English flash rather than wrong-org terminology.

high impact low prob security

Supabase Row Level Security policies on organization_configs may inadvertently restrict the authenticated user from reading their own organization's labels JSONB column, causing silent empty maps that appear as English fallbacks.

Mitigation & Contingency

Mitigation: Write and test explicit RLS policies that grant SELECT on the labels column to any authenticated user whose organization_id matches. Add an integration test that verifies label fetch succeeds for each role (peer mentor, coordinator, admin).

Contingency: If RLS blocks are discovered in production, temporarily escalate label fetch to a service-role edge function while the RLS policy is corrected, ensuring no labels are exposed cross-organization.

medium impact medium prob scope

A peer mentor who installs the app for the first time with no internet connection will have no cached terminology map and will see only English defaults, which may be confusing for organizations like NHF that use Norwegian-specific role names exclusively.

Mitigation & Contingency

Mitigation: Bundle a default fallback terminology map for each known organization as a compile-time asset (Dart asset file) so that even fresh installs without connectivity render correct organizational terminology immediately.

Contingency: If bundled assets are out of date, display a one-time informational banner noting that terminology will update on next connectivity restore, with no functional blocking of the app.