high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

Test 'flag enabled': mock returns {is_enabled: true} → isFeatureEnabled returns true
Test 'flag disabled': mock returns {is_enabled: false} → isFeatureEnabled returns false
Test 'missing record': mock returns null (maybeSingle) → isFeatureEnabled returns false
Test 'Supabase error': mock throws PostgrestException → isFeatureEnabled returns false without re-throwing
Test 'cache hit': calling isFeatureEnabled twice for the same (orgId, featureKey) within TTL results in exactly one mock query invocation
Test 'cache invalidation': calling invalidateCache(orgId) then isFeatureEnabled triggers a fresh mock query invocation
Test 'full cache clear': calling invalidateCache() clears all entries; subsequent calls for any key trigger fresh queries
Test 'TTL expiry': after TTL elapses (use a fake clock or short TTL), the next call triggers a new query
Test 'concurrent deduplication': two simultaneous calls for the same key trigger only one mock query
DriverFeatureFlagConfig constants test: all declared constants are non-null, non-empty strings with no whitespace
OrgFeatureFlag model serialization test: fromJson(toJson(model)) round-trips correctly for both enabled and disabled states
All tests are pure unit tests (no real network calls, no real Supabase instance)

Technical Requirements

frameworks
Flutter
flutter_test
Dart
Riverpod
apis
Mocked Supabase SupabaseClient (via mockito or manual stub)
data models
OrgFeatureFlag
DriverFeatureFlagConfig
performance requirements
Entire unit test suite must complete in under 10 seconds
No async delays greater than 100ms in any test
security requirements
Verify that the fail-safe default (false) is tested for all error paths: network error, malformed response, null response

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

The clean abstract interface (OrgFeatureFlagService) defined in task-011 is the prerequisite for these tests being pure unit tests — the impl is constructed directly in tests with the injected mock client, bypassing Riverpod entirely. For the TTL/fake-clock test, define a typedef ClockFn = DateTime Function() and inject it into the impl constructor with a default of () => DateTime.now(). In tests, pass a mutable variable that the test can advance. For concurrent deduplication, use Future.wait([service.isFeatureEnabled(id, key), service.isFeatureEnabled(id, key)]) and verify the mock was called exactly once.

Keep mock setup in a shared setUp block and use addTearDown(service.dispose) to prevent state leakage between tests.

Testing Requirements

Use flutter_test exclusively. Create test/unit/feature_flag/org_feature_flag_service_test.dart. Build a manual MockSupabaseClient stub (or use mockito with build_runner) that captures query arguments and returns pre-configured responses. For the TTL test, inject a fake DateTime provider into OrgFeatureFlagServiceImpl so the test can fast-forward time without real sleeps.

Group tests logically: group('isFeatureEnabled', ...), group('cache behavior', ...), group('DriverFeatureFlagConfig', ...), group('OrgFeatureFlag model', ...). Aim for 100% branch coverage of OrgFeatureFlagServiceImpl.

Component
Organization Feature Flag Service
service low
Epic Risks (3)
high impact medium prob security

Row-level security policies for driver assignments and declarations must correctly scope data to the coordinator's chapter without leaking records across organizations. An incorrect RLS predicate could silently return empty result sets or, worse, expose cross-org data, both of which are difficult to detect in unit tests.

Mitigation & Contingency

Mitigation: Write dedicated RLS integration test scenarios with multiple org fixtures asserting both data isolation and correct data visibility. Use Supabase's built-in policy testing utilities and review policies with a second developer.

Contingency: If RLS policies prove too complex to get right quickly, implement application-layer org scoping as a temporary guard while RLS is fixed in a follow-up, with an explicit security review gate before production deployment.

high impact medium prob security

The declaration audit logger must produce tamper-evident records. If the database allows updates or deletes on audit rows, the compliance guarantee is broken. Supabase does not natively prevent row deletion by default.

Mitigation & Contingency

Mitigation: Implement an insert-only RLS policy on the audit table that denies UPDATE and DELETE for all roles including the service role. Add a database trigger that rejects mutation attempts and logs the attempt itself.

Contingency: If immutability cannot be enforced at the database level within the sprint, store audit entries in an append-only Supabase Edge Function log stream as a temporary alternative, with a migration plan to the proper table once constraints are implemented.

medium impact low prob technical

The org-feature-flag-service caches flag values to avoid repeated database reads. If the cache is not invalidated promptly after an admin toggles the flag, coordinators may see stale UI state — either seeing driver features when they should not, or not seeing them when they should.

Mitigation & Contingency

Mitigation: Use a Supabase Realtime subscription to listen for changes on the driver_feature_flag_config table and invalidate the in-memory cache immediately on change. Set a short TTL (60 seconds) as a safety net.

Contingency: If Realtime subscription proves unreliable, expose a manual cache-bust endpoint accessible from the admin toggle action, ensuring the cache is cleared synchronously on every flag change.