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 #
- Define feature in
/config/features/index.yaml - Run
mise run sync-feature-flagsto generate types and sync - Use
isFeatureEnabled('feature_name')in your code - Enable feature in Organization Settings UI
For detailed instructions, see the full documentation.
Architecture #
Components #
-
Configuration File (
/config/features/index.yaml)- Single source of truth for all feature definitions
- Validated against JSON schema
- Three stability levels: early, preview, ready
-
Clerk Storage
- Organization metadata stores boolean flags
- User metadata stores feature preferences
- Simple key-value pairs for efficiency
-
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
-
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.,
_integrationsuffix 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
FeatureNameunion 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:
- Pass feature state from frontend in API requests
- 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 #
- Search for feature usage:
grep -r "my_old_feature" apps/webapp/src
-
Remove or replace feature checks with appropriate logic
-
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 #
-
Feature Definitions (
FEATURE_DEFINITIONS)- Validated feature configuration
- Runtime type checking with Zod
-
Type Definitions
FeatureNameunion type (e.g.,'dropbox_integration' | 'onedrive_sync' | ...)FeatureStatustype ('early' | 'preview' | 'ready')Featureinterface with name, title, description, status, and warningOverride
-
Helper Functions
getFeatureDefinitions()getFeatureByName()getDefaultWarningForStatus()
Sync Behavior #
How Sync Works #
-
Reads YAML Configuration
- Validates against JSON schema
- Collects all feature names
-
Fetches Organizations
- Paginates through all orgs (100 at a time)
- Or single org in development
-
Updates Metadata
- Preserves existing feature values
- Adds new features as
false - Removes obsolete features
- Only updates if changes detected
-
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 #
-
Code Changes
- Push changes to branch
- GitHub Actions runs on push
-
Build Process
- name: Generate Feature Types run: mise run generate-feature-types - name: Build Applications run: mise run build -
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 keyTEST_ORG_ID: (Optional) Single org for testing
Testing Features #
Local Development #
-
Set Test Organization
export TEST_ORG_ID=org_your_test_org_id mise run sync-feature-flags -
Enable Feature in UI
- Navigate to Organization Settings
- Find “Feature Flags” section
- Toggle desired feature
-
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 #
-
Check YAML Configuration
cat config/features/index.yaml | grep my_feature -
Verify Sync Completed
# Check org metadata in Clerk dashboard -
Verify Permissions
- User needs
org:feature:updatepermission - Check in Organization Settings > Roles
- User needs
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:
-
Early → Preview
- Update status in YAML from
earlytopreview - Adjust warning message to be less severe
- Document known issues and improvements made
- Update status in YAML from
-
Preview → Ready
- Move from
previewtoreadysection - Remove warning override (ready features have no warnings)
- Update documentation to reflect stable status
- Ensure full testing and support processes are in place
- Move from
Security Considerations #
-
Permission Checks
- Always verify
org:feature:updatepermission - Don’t expose internal feature names to unauthorized users
- Always verify
-
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-500background, white text) - Icon: Check mark (✓)
- Tooltip: “Released and supported.”
- Meaning: Fully stable, production-ready features
Preview Status #
- Color: Blue (
blue-500background, white text) - Icon: Sparkles (✨)
- Tooltip: “Try what’s coming next.”
- Meaning: Features being refined for wider release
Early Status #
- Color: Violet (
violet-500background, 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