Build phase-based rollout condition configuration UI
epic-organization-feature-flags-ui-task-007 — Implement the per-flag rollout condition configuration panel in the admin screen. Allow admins to set minimum app version requirement (semver input with validation) and activation date (date picker) per flag. Display current rollout conditions alongside each flag in the list. Persist condition changes through FeatureFlagRepository and reflect them immediately in the RolloutEvaluator.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Use a local Riverpod StateNotifierProvider
Prefer an inline ExpansionTile panel over a bottom sheet to keep the admin workflow on one screen and reduce navigation cognitive load—consistent with the WCAG 2.2 AA principle of predictable UI.
Testing Requirements
Widget tests: (1) rollout conditions summary displays correctly for flags with and without conditions; (2) panel opens on edit tap; (3) invalid semver input shows error and disables save; (4) past activation date shows error and disables save; (5) valid inputs enable save button; (6) save calls repository with correct RolloutConditions model; (7) cancel discards changes without repository call; (8) repository failure shows error and keeps panel open; (9) after successful save, the inline summary updates to reflect new conditions. Integration test: full edit flow from list view → panel open → input → save → verify summary updated.
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.
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.
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.