high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Unit tests achieve 100% branch coverage on OrganizationRepository domain model mapping logic
Cache hit scenario: second call within TTL returns cached value without issuing a Supabase network request
Cache miss scenario: expired or absent cache triggers a new Supabase fetch and updates the cache
Cache is fully invalidated when the sign-out event is emitted, confirmed by subsequent call making a fresh network request
All error paths (network timeout, malformed JSON, null fields) are covered with unit tests that verify typed error objects are returned
Integration test: inserting a row into the organizations table triggers the Realtime stream listener within 3 seconds
Integration test: RLS scoping — authenticated user A cannot receive rows belonging to user B's tenant via the stream or direct query
Integration test: unauthenticated request returns an empty result or an authorization error, not raw data
All tests run in CI without requiring developer credentials; test Supabase project credentials sourced from environment variables
Test file names and describe blocks follow the project's naming convention (e.g., organization_repository_test.dart)

Technical Requirements

frameworks
Flutter
flutter_test
mocktail
apis
Supabase Realtime WebSocket API
Supabase REST API (RLS-scoped queries)
Supabase RPC
data models
Organization
TenantSessionData
performance requirements
Realtime stream must emit within 3 seconds of a table mutation in integration tests
Unit test suite must complete in under 10 seconds to keep CI fast
security requirements
Test Supabase credentials must not be committed to source control — use environment variables or CI secrets
Integration tests must verify RLS policies prevent cross-tenant data leakage
No production data or production Supabase project used in any test

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Use mocktail's `when(() => mockSupabase.from('organizations')...)` pattern to stub Supabase client calls — avoid real HTTP in unit tests. The cache layer is most reliably tested by injecting a controllable clock (DateTime provider) so TTL expiry can be simulated without sleeping. For integration tests, use a dedicated Supabase project with RLS policies mirroring production; seed it in a `setUpAll` block and clean up in `tearDownAll`. To test Realtime, subscribe before inserting and use a `Completer` with a timeout to await the event.

Verify RLS by authenticating two separate JWT tokens (user A and user B) and asserting the stream for user A never emits user B's rows. Parameterize the Supabase URL and anon/service-role keys via `const String.fromEnvironment` so the same test binary works in all environments.

Testing Requirements

Unit tests (flutter_test + mocktail): mock the Supabase client and verify (1) JSON-to-domain mapping covers all fields including nullable ones, (2) cache returns stale data on hit, (3) cache is bypassed and refreshed on miss, (4) sign-out clears cache, (5) each error type produces the correct typed exception. Integration tests (dedicated test Supabase instance): spin up a seeded test schema, authenticate as a test user, assert Realtime stream events fire on INSERT/UPDATE/DELETE, assert a second test user cannot observe the first user's data. Integration tests are gated behind a CI environment variable (RUN_INTEGRATION_TESTS=true) so they do not block local unit test runs. Aim for 100% branch coverage on repository logic; integration coverage report generated in CI.

Component
Organization Repository
data medium
Epic Risks (2)
high impact low prob technical

TenantSessionStore must write to both SecureStorageAdapter and Supabase session synchronously. If the Supabase write succeeds but the local secure storage write fails (or vice versa), the system ends up in an inconsistent state: local app thinks org A is selected but Supabase queries are scoped to org B (or unscoped), causing silent data leakage or empty result sets.

Mitigation & Contingency

Mitigation: Implement the dual-write with compensating rollback: if the second write fails, undo the first write and surface a typed DualWriteFailureError to callers. Add a startup integrity check in restoreSession() that validates local storage and Supabase session agree on the current org_id.

Contingency: If integrity check fails on startup, clear both stores and redirect the user to the org selection screen rather than proceeding with potentially mismatched state.

medium impact low prob integration

An organization could be deactivated in Supabase between the time the org list is cached and the time the user taps to select it. If the repository serves stale cached data the org-selection-service will attempt to seed a context for an inactive org, potentially causing RLS scope issues or confusing error states.

Mitigation & Contingency

Mitigation: The OrganizationRepository.getOrganizationById() path used during selection validation always performs a fresh network fetch (bypassing cache) to confirm the org is still active before the TenantSessionStore writes anything.

Contingency: If a freshness check finds the org is inactive, surface a localized error message on the selection screen ('This organization is no longer available') and refresh the org list to show only currently active partners.