critical priority low complexity infrastructure pending backend specialist Tier 0

Acceptance Criteria

A Dart file exists at a well-known path (e.g., `lib/core/feature_flags/feature_flag_keys.dart`) containing all feature flag string constants
Constants follow the naming convention `kFlag<FeatureName>` (e.g., `kFlagTravelReimbursement`, `kFlagGamification`, `kFlagEncryptedAssignmentDispatch`, `kFlagCourseCertification`, `kFlagBufdirReporting`, `kFlagSpeechToText`, `kFlagPausePeerMentor`, `kFlagBulkRegistration`)
Each constant value string matches the exact database column key used in organization_configs (snake_case, e.g., `'travel_reimbursement'`)
An accompanying `FeatureFlagKeys` abstract class or sealed class groups all constants for namespace clarity — no top-level pollution
A `kAllFeatureFlagKeys` constant (List<String>) enumerates every defined key, enabling validation and cache warm-up iteration
Every constant has a single-line Dart doc comment (`///`) describing the feature and which organization(s) it applies to
The file compiles with zero warnings or linting errors under `dart analyze`
No other file in the codebase uses raw string literals for flag keys — all references use the constants from this file (verified by a grep check in CI)

Technical Requirements

frameworks
Dart (latest)
Flutter
performance requirements
Compile-time constants only — zero runtime cost
security requirements
Flag key strings must not contain any personally identifiable information — they are metadata identifiers only
No secrets or API keys should be placed in this file

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Use an `abstract final class FeatureFlagKeys` (Dart 3 style) with `static const String` members — this prevents instantiation while grouping constants logically. Group constants by feature domain using block comments (e.g., `// --- Expense & Travel ---`, `// --- Gamification ---`, `// --- Accessibility ---`). The `kAllFeatureFlagKeys` list should be derived from the class fields using a hand-maintained list rather than reflection, since Flutter tree-shaking can affect mirror-based approaches. Ensure the snake_case values align exactly with the column names planned in the database migration (task-001) — coordinate with the database_specialist to confirm naming before finalising.

This file will be imported by the FeatureFlagRepository (task-004), FeatureFlagCache (task-005), and RolloutEvaluator (task-006), so stable naming is critical from the start.

Testing Requirements

Unit tests are lightweight for this task but should confirm: (1) `kAllFeatureFlagKeys` contains no duplicate values; (2) every value in `kAllFeatureFlagKeys` matches the `^[a-z][a-z0-9_]*$` regex pattern (enforcing snake_case database column compatibility); (3) the list length equals the expected number of defined flags (hard-coded assertion catches accidental omissions). A CI grep step should assert zero occurrences of hard-coded flag string literals outside of the constants file. Use `flutter_test` for the unit tests.

Component
Feature Flag Key Constants
infrastructure low
Epic Risks (3)
high impact medium prob security

Supabase RLS policies for organization_configs may have gaps that allow cross-organization reads if the JWT claim for organization_id is absent or malformed, leading to data leakage between tenants.

Mitigation & Contingency

Mitigation: Implement RLS policies using auth.uid() joined against a memberships table to derive organization_id rather than trusting a client-supplied claim. Write integration tests that simulate a cross-org read attempt and assert it returns zero rows.

Contingency: If a gap is discovered post-launch, immediately disable the affected RLS policy, roll back the migration, and re-implement with a parameterized policy tested against all organization fixture data.

medium impact medium prob technical

Dart does not have a built-in semantic version comparison library; a naive string comparison (e.g., '2.10.0' < '2.9.0' lexicographically) would cause rollout evaluator to produce incorrect eligibility results for organizations on different app versions.

Mitigation & Contingency

Mitigation: Use the pub.dev `pub_semver` package or implement a proper three-segment integer comparison. Add parameterized unit tests covering 20+ version pairs including double-digit minor/patch segments.

Contingency: If incorrect comparison is discovered in production, push a hotfix with corrected comparison logic and temporarily disable phase-gated flags until all affected organizations have updated to the corrected version.

medium impact low prob technical

Persistent local cache written to shared_preferences or Hive could become corrupted or deserialized incorrectly after an app update changes the FeatureFlag schema, causing startup crashes or all flags defaulting to disabled.

Mitigation & Contingency

Mitigation: Wrap all cache reads in try/catch with explicit fallback to the all-disabled default map. Version the cache key (e.g., `feature_flags_v2_{orgId}`) so schema changes automatically invalidate old entries.

Contingency: If cache corruption is detected in a release, publish an app update that clears the versioned cache key on first launch and re-fetches from Supabase.