high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Test suite located at integration_test/feature_flag_admin_screen_test.dart and runnable via flutter test integration_test/
Test: non-admin user navigating to admin screen is redirected to the no-access screen
Test: admin user sees flag list with correct enabled/disabled states matching mocked repository data
Test: two-step toggle — first tap shows staged state, second tap opens confirmation dialog, confirm dispatches toggle and list updates
Test: confirmation dialog cancel — tapping cancel reverts toggle to original state without calling repository
Test: audit log initial load renders first page of entries with all required fields
Test: 'Load more' in audit log appends second page without replacing first page entries
Test: stale-cache banner appears when cache TTL is exceeded (using fake clock)
Test: manual refresh dismisses stale-cache banner and updates flag list
Test: rollout condition edit — open panel, enter valid semver and date, save, verify inline summary updated
All tests use mocked FeatureFlagRepository; no real Supabase calls
Each test is independent with its own ProviderScope setup and teardown

Technical Requirements

frameworks
Flutter
flutter_test
Riverpod
apis
FeatureFlagRepository (fully mocked via mocktail or mockito)
FeatureFlagCache (injectable fake with controllable lastSyncAt)
ProviderScope.overrides for all providers consumed by admin screen
data models
FeatureFlag
AuditLogEntry
AuditLogPage
RolloutConditions
FeatureFlagCache
performance requirements
Full integration test suite must complete in under 60 seconds
Use tester.pumpAndSettle() with explicit duration bounds to avoid indefinite waits
security requirements
Role guard test must assert that no flag data is loaded or rendered for non-admin users
Mock repository must not accept any calls in the non-admin test scenario
ui components
FeatureFlagAdminScreen under test
All child widgets (toggle, dialog, audit log, cache banner, rollout panel)

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Use a TestFeatureFlagRepository class (implements FeatureFlagRepository) with stubbed async methods returning predefined data—this avoids mockito/mocktail complexity for simple cases while remaining controllable. For the two-step toggle test, use find.byType(Switch) and tester.tap() in sequence, then find.byType(AlertDialog) to assert dialog presence before confirming. For audit log pagination, override the repository to return page 1 on first call and page 2 on second call using a call counter. For the stale-cache test, initialize FeatureFlagCache.lastSyncAt to DateTime.now().subtract(Duration(seconds: ttl + 1)) in the provider override.

Ensure each test pumps the widget tree with tester.pumpWidget(ProviderScope(overrides: [...], child: MaterialApp(home: FeatureFlagAdminScreen()))) for full routing context. Consider organizing tests in a describe-style using group() blocks per feature area for readability.

Testing Requirements

Integration tests use flutter_test IntegrationTestWidgetsFlutterBinding. Each test wraps the admin screen in a full ProviderScope with overridden repository and cache providers. Use mocktail to stub repository methods with controlled return values and verify call counts. For the fake clock test (stale-cache), inject a FakeClock or use DateTime override via dependency injection—do not rely on real time passage.

Structure tests with setUpAll for shared mock setup and setUp for per-test state reset. Assert both UI state (finder queries) and behavior (mock verify calls). Aim for coverage of every user-visible branch in the admin screen's state machine.

Component
Feature Flag Admin Screen
ui medium
Epic Risks (3)
high impact low prob security

The feature flag admin screen allows persisting changes to organization_configs. If the role guard is implemented only client-side (checking role state in Riverpod), a user who manipulates their local role state could toggle flags for their organization without proper server-side authorization, potentially exposing features prematurely.

Mitigation & Contingency

Mitigation: Implement server-side authorization for flag update operations using Supabase RLS UPDATE policies that check the user's role in the memberships table. The client-side guard is UX only; the database enforces the actual restriction.

Contingency: If an unauthorized update is detected, audit the RLS policies and add a Supabase Edge Function as an authorization middleware for flag toggle operations, rejecting requests from non-admin role JWTs.

medium impact medium prob scope

Developers on other feature teams may use FeatureGate incorrectly — for example, wrapping business logic rather than UI, or using it before flag initialization completes — leading to features that are visible but non-functional or cause runtime errors when flags are queried in a loading state.

Mitigation & Contingency

Mitigation: Add assert statements in FeatureGate's build method that throw in debug mode if the provider is still in a loading state. Write developer documentation with a clear usage contract: FeatureGate is UI-only; logic gating must use the provider's isEnabled method directly. Include lint examples in the codebase.

Contingency: If misuse is found in code reviews, add a custom Dart lint rule via custom_lint that flags FeatureGate usage outside of the widget tree, and conduct a codebase audit to find existing violations.

medium impact low prob technical

If the audit log is stored in the same organization_configs table without pagination or archival strategy, high-frequency flag changes during pilot testing could produce an unbounded number of rows, degrading query performance on the admin screen.

Mitigation & Contingency

Mitigation: Store audit log entries in a separate feature_flag_audit_log table with an index on (organization_id, changed_at DESC). Implement cursor-based pagination in the repository and limit the initial load to 50 entries.

Contingency: If table size becomes a performance concern, add a Supabase scheduled function to archive entries older than 90 days to cold storage, and add a database index on changed_at for range queries.