Implement synchronous isEnabled API on provider
epic-organization-feature-flags-runtime-task-005 — Expose a synchronous isEnabled(flagKey) method on the FeatureFlagProvider that performs O(1) lookup against the resolved in-memory map. The method must apply the rollout evaluator's phase conditions before returning the boolean result, so widgets receive the correct gating decision without any async overhead.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
The resolved map should be a final field set during initialization (task-004). Use a `Map
In Riverpod, expose the provider as a `Provider
Testing Requirements
Unit tests using flutter_test. Test cases: (1) isEnabled returns true when flag is present and enabled in map; (2) isEnabled returns false when flag is present but disabled; (3) isEnabled returns false for unknown flag key; (4) isEnabled returns false before initialization completes; (5) rollout phase condition 'phase not started' returns false even when flag is enabled; (6) rollout phase condition 'phase active' returns true when flag is enabled; (7) Stopwatch assertion that method completes under 1ms for 1000 consecutive calls. Use mockito/mocktail to mock the underlying resolved flag map and rollout evaluator.
The feature-flag-initializer must complete before any screen that checks feature flags renders. If the navigation shell is pushed concurrently with initialization (e.g., via a parallel Riverpod provider chain), some screens may query flags before they are loaded and incorrectly receive all-disabled defaults.
Mitigation & Contingency
Mitigation: Gate the main navigation shell render behind the feature-flag-initializer's Future by using a splash/loading screen that awaits the initialization provider. Use Riverpod's ref.watch on an initialization state enum (loading/ready/error) to block rendering.
Contingency: If race conditions are observed in testing, introduce an explicit initialization barrier using a ChangeNotifier or a dedicated `featureFlagsReadyProvider` that the router guard checks before allowing navigation.
If feature-flag-provider is watched by many widgets simultaneously and a flag map refresh triggers all of them to rebuild at once (e.g., after an organization switch), the app could experience a significant UI jank or dropped frames.
Mitigation & Contingency
Mitigation: Use select() on the provider to have each widget watch only the specific flag key it needs rather than the entire map. Ensure the provider uses equality checks so rebuilds only propagate when the specific flag value changes.
Contingency: If rebuild storms are measured via Flutter DevTools, refactor to a family provider keyed by flag key, so each widget subscribes only to its own flag's changes.