Feature Flags

Features Documentation #

This section contains comprehensive documentation for the BonsAI feature management system.

Overview #

The Early Access Feature Flags system replaces the previous domain-based approach with a scalable, permission-based system that provides:

  • Configuration-driven feature definitions in YAML
  • Type-safe TypeScript integration with auto-generation
  • Permission-based access control
  • User opt-in requirements for all features
  • Three stability levels: early, preview, and ready
  • Analytics integration for tracking adoption

Quick Start #

  1. Define feature in /config/features/index.yaml
  2. Run mise run sync-feature-flags to generate types and sync
  3. Use isFeatureEnabled('feature_name') in your code
  4. Enable feature in Organization Settings UI

For detailed instructions, see the full documentation.

Architecture #

Components #

  1. Configuration File (/config/features/index.yaml)

    • Single source of truth for all feature definitions
    • Validated against JSON schema
    • Three stability levels: early, preview, ready
  2. Clerk Storage

    • Organization metadata stores boolean flags
    • User metadata stores feature preferences
    • Simple key-value pairs for efficiency
  3. Sync Tool (apps/bonsapi/src/bin/sync_feature_flags.rs)

    • Rust binary that syncs YAML to Clerk
    • Preserves existing feature states
    • Removes obsolete features automatically
  4. Frontend Integration

    • TypeScript definitions generated from YAML
    • Legend-state for reactive feature management
    • Permission-based UI components
    • Visual status indicators with color-coded badges and icons

Adding New Features #

Step 1: Define the Feature #

Edit /config/features/index.yaml:

# Choose the appropriate stability level
early:
  - name: my_new_feature
    title: "My New Feature"
    description: "Brief description of what this feature does"
    warningOverride: "Optional custom warning message" # If not provided, uses default for status

preview:
  - name: another_feature
    title: "Another Feature"
    description: "A feature in preview stage"

ready:
  - name: stable_feature
    title: "Stable Feature"
    description: "A production-ready feature"

Feature naming conventions:

  • Use snake_case
  • Be descriptive but concise
  • Use consistent naming patterns (e.g., _integration suffix for integrations)

Step 2: Generate TypeScript Definitions #

# Manual generation
mise run generate-feature-types

# Or start dev server (auto-generates)
mise run dev

This creates/updates:

  • /apps/webapp/src/shared/lib/features/definitions.ts
  • Type-safe FeatureName union type
  • Feature helper functions

Step 3: Sync to Organizations #

# Development (single org)
mise run sync-feature-flags
# Will prompt for org ID in dev_local environment

# Production (all orgs) - happens automatically on deploy
# Or manually:
doppler run --config prod -- cargo run --bin sync_feature_flags

Step 4: Apply in Code #

Frontend Usage #

import { isFeatureEnabled } from "@/shared/sync/features";

function MyComponent() {
  const { isFeatureEnabled } = usePermissions();

  if (isFeatureEnabled("my_new_feature")) {
    return <NewFeatureUI />;
  }

  return <StandardUI />;
}

Backend Usage (if needed) #

Currently, feature flags are frontend-only. For backend feature flags:

  1. Pass feature state from frontend in API requests
  2. Or implement backend feature checking (not yet available)

Removing Features #

Step 1: Remove from Configuration #

Delete the feature entry from /config/features/index.yaml.

Step 2: Update Code #

  1. Search for feature usage:
grep -r "my_old_feature" apps/webapp/src
  1. Remove or replace feature checks with appropriate logic

  2. Regenerate types:

mise run generate-feature-types

Step 3: Sync Removal #

# The sync tool automatically removes features not in YAML
mise run sync-feature-flags

The sync tool will:

  • Remove the feature from all organization metadata
  • Log which features are being removed
  • Preserve all other feature states

Code Generation #

Automatic Generation #

During development, types are auto-generated when:

  • Running mise run dev (watches for changes)
  • Running mise run webapp-build
  • Running mise run sync-feature-flags

Manual Generation #

mise run generate-feature-types

What Gets Generated #

  1. Feature Definitions (FEATURE_DEFINITIONS)

    • Validated feature configuration
    • Runtime type checking with Zod
  2. Type Definitions

    • FeatureName union type (e.g., 'dropbox_integration' | 'onedrive_sync' | ...)
    • FeatureStatus type ('early' | 'preview' | 'ready')
    • Feature interface with name, title, description, status, and warningOverride
  3. Helper Functions

    • getFeatureDefinitions()
    • getFeatureByName()
    • getDefaultWarningForStatus()

Sync Behavior #

How Sync Works #

  1. Reads YAML Configuration

    • Validates against JSON schema
    • Collects all feature names
  2. Fetches Organizations

    • Paginates through all orgs (100 at a time)
    • Or single org in development
  3. Updates Metadata

    • Preserves existing feature values
    • Adds new features as false
    • Removes obsolete features
    • Only updates if changes detected
  4. Rate Limiting

    • 150ms delay between org updates
    • Exponential backoff on failures
    • Max 3 retries per organization

Sync Schedule #

  • Automatic: On every deployment (dev and prod)
  • Manual: Via mise tasks
  • Local Dev: Single org sync for safety

Sync Output #

✓ Schema validation passed
Processing organizations 1 to 100
✓ Updated features for org: Acme Corp
→ No changes needed for org: org_xyz123
→ Removing features: ["old_feature_1", "old_feature_2"]

Sync complete: 95 successful, 0 errors

Deployment Process #

Development Deployment #

  1. Code Changes

    • Push changes to branch
    • GitHub Actions runs on push
  2. Build Process

    - name: Generate Feature Types
      run: mise run generate-feature-types
    
    - name: Build Applications
      run: mise run build
    
  3. Deployment

    - name: Deploy to Dev
      run: mise run deploy-dev
    
    - name: Sync Feature Flags
      env:
        CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
      run: cargo run --bin sync_feature_flags
    

Production Deployment #

Same as development but:

  • Requires PR approval
  • Runs on merge to main
  • Syncs to all production organizations

Environment Variables #

Required for sync tool:

  • CLERK_SECRET_KEY: Clerk API key
  • TEST_ORG_ID: (Optional) Single org for testing

Testing Features #

Local Development #

  1. Set Test Organization

    export TEST_ORG_ID=org_your_test_org_id
    mise run sync-feature-flags
    
  2. Enable Feature in UI

    • Navigate to Organization Settings
    • Find “Feature Flags” section
    • Toggle desired feature
  3. Test Feature

    • Verify feature appears/works as expected
    • Check warning dialogs for early/preview features
    • Test enable/disable behavior

Troubleshooting #

Common Issues #

Feature Not Appearing #

  1. Check YAML Configuration

    cat config/features/index.yaml | grep my_feature
    
  2. Verify Sync Completed

    # Check org metadata in Clerk dashboard
    
  3. Verify Permissions

    • User needs org:feature:update permission
    • Check in Organization Settings > Roles

Best Practices #

Feature Naming #

  • Use descriptive names that indicate what the feature does
  • Group related features with common prefixes
  • Examples:
    • ai_document_extraction (AI features)
    • dropbox_integration (Integration features)
    • batch_operations (Operation features)

Status Guidelines #

Early #

  • Features in early development
  • New ideas and concepts
  • May have significant bugs or change drastically
  • Data loss is possible and bugs are expected
  • No support provided - use at users’ own risk

Preview #

  • Features being refined for wider release
  • More stable than early features but not fully supported
  • Basic functionality works but may undergo changes
  • Try with caution

Ready #

  • Production-ready features
  • Released and fully supported
  • Backward compatibility maintained
  • Safe for production use
  • Still polishing for GA

Warning Messages #

  • Be specific about risks
  • Include mitigation steps if possible
    • Update warnings as feature stabilizes
    • Remove warnings when promoting to ready status

Migration Strategy #

When moving features between statuses:

  1. Early → Preview

    • Update status in YAML from early to preview
    • Adjust warning message to be less severe
    • Document known issues and improvements made
  2. Preview → Ready

    • Move from preview to ready section
    • Remove warning override (ready features have no warnings)
    • Update documentation to reflect stable status
    • Ensure full testing and support processes are in place

Security Considerations #

  1. Permission Checks

    • Always verify org:feature:update permission
    • Don’t expose internal feature names to unauthorized users
  2. Data Validation

    • Validate feature names against known list
    • Sanitize user inputs
    • Use TypeScript types for safety

UI Components and Visual Design #

Status Badges #

Each feature status is visually represented with distinct badges:

Ready Status #

  • Color: Teal (teal-500 background, white text)
  • Icon: Check mark (✓)
  • Tooltip: “Released and supported.”
  • Meaning: Fully stable, production-ready features

Preview Status #

  • Color: Blue (blue-500 background, white text)
  • Icon: Sparkles (✨)
  • Tooltip: “Try what’s coming next.”
  • Meaning: Features being refined for wider release

Early Status #

  • Color: Violet (violet-500 background, white text)
  • Icon: Sprout (🌱)
  • Tooltip: “Help test a new idea.”
  • Meaning: Experimental features for testing new concepts

Default Warning Messages #

The system provides default warning messages for non-ready features:

Early Features #

This feature is early and not yet fully defined. It may change drastically without notice, data loss is possible, and bugs are expected. By enabling this feature, you acknowledge that you use it at your own risk and support will not be provided for any issues that arise.

Preview Features #

This feature is in preview. While more refined than early features, it may still undergo changes and is not fully supported. Use with caution and report any issues you encounter.

Ready Features #

  • No warning message (undefined)
  • Features are considered stable and fully supported

Feature Toggle UI #

Features are displayed in the Organization Settings with:

  • Feature title and description
  • Status badge with appropriate color and icon
  • Toggle switch for enable/disable
  • Warning dialogs for early/preview features when enabling