# SAAS-009: Feature Flags ## Metadata - **Codigo:** SAAS-009 - **Modulo:** Feature Flags - **Prioridad:** P2 - **Estado:** Pendiente - **Fase:** 4 - Advanced ## Descripcion Sistema de feature flags para control granular de funcionalidades: flags globales, por tenant, por usuario, con porcentaje de rollout y A/B testing basico. ## Objetivos 1. Flags globales (sistema) 2. Flags por tenant 3. Flags por usuario 4. Porcentaje de rollout 5. A/B testing basico ## Alcance ### Incluido - Feature flags booleanos - Flags con valores (string/number) - Override por tenant - Override por usuario - Rollout gradual (%) - UI de administracion ### Excluido - A/B testing avanzado - usar servicio dedicado - Analytics de experimentos - Machine learning para targeting ## Modelo de Datos ### Tablas (schema: features) **feature_flags** - id, key (unique), name, description - type (boolean/string/number/json) - default_value, is_enabled - rollout_percentage (0-100) - targeting_rules (JSONB) - created_at, updated_at **tenant_feature_overrides** - id, tenant_id, feature_key - value, enabled - expires_at **user_feature_overrides** - id, user_id, feature_key - value, enabled - expires_at ## Flags Predefinidos | Key | Tipo | Default | Descripcion | |-----|------|---------|-------------| | new_dashboard | boolean | false | Nuevo dashboard beta | | ai_assistant | boolean | false | Asistente IA | | export_v2 | boolean | false | Nueva exportacion | | max_file_size_mb | number | 10 | Limite archivo | | theme | string | 'light' | Tema default | ## Endpoints API | Metodo | Endpoint | Descripcion | |--------|----------|-------------| | GET | /features | Listar flags | | GET | /features/:key | Obtener flag | | POST | /features | Crear flag | | PUT | /features/:key | Actualizar flag | | DELETE | /features/:key | Eliminar flag | | GET | /features/evaluate | Evaluar todos para usuario | | POST | /features/:key/override/tenant | Override tenant | | POST | /features/:key/override/user | Override usuario | | DELETE | /features/:key/override/tenant | Quitar override | ## Implementacion ### Servicio ```typescript interface FeatureFlagService { isEnabled(key: string, context?: EvaluationContext): Promise; getValue(key: string, context?: EvaluationContext): Promise; getAllFlags(context?: EvaluationContext): Promise>; } interface EvaluationContext { tenantId?: string; userId?: string; attributes?: Record; } ``` ### Guard ```typescript @RequiresFeature('new_dashboard') @Get('/dashboard/v2') async getNewDashboard() { // Solo si feature habilitada } ``` ### Condicional en Codigo ```typescript if (await this.features.isEnabled('ai_assistant')) { // Mostrar boton de IA } const maxSize = await this.features.getValue('max_file_size_mb'); ``` ## Logica de Evaluacion ``` 1. Usuario solicita feature 2. Buscar override de usuario 3. Si existe, usar ese valor 4. Si no, buscar override de tenant 5. Si existe, usar ese valor 6. Si no, evaluar rollout % 7. Si pasa rollout, usar default_value 8. Si no pasa, feature deshabilitada ``` ### Rollout Deterministico ```typescript // Mismo usuario siempre obtiene mismo resultado function shouldEnableForUser(userId: string, percentage: number): boolean { const hash = crypto.createHash('md5').update(userId).digest('hex'); const value = parseInt(hash.substring(0, 8), 16) % 100; return value < percentage; } ``` ## Targeting Rules ```typescript // Ejemplo de reglas avanzadas { "rules": [ { "condition": "plan", "operator": "in", "values": ["pro", "enterprise"], "enabled": true }, { "condition": "country", "operator": "equals", "values": ["MX"], "enabled": true } ] } ``` ## Frontend SDK ```typescript // React hook function useFeatureFlag(key: string): boolean { const { flags } = useFeatureFlags(); return flags[key] ?? false; } // Componente function Dashboard() { const showNewDashboard = useFeatureFlag('new_dashboard'); return showNewDashboard ? : ; } ``` ## Entregables | Entregable | Estado | Archivo | |------------|--------|---------| | features.module.ts | Pendiente | `modules/features/` | | feature-flag.service.ts | Pendiente | `services/` | | feature.guard.ts | Pendiente | `guards/` | | DDL features schema | Pendiente | `ddl/schemas/features/` | | Seeds flags default | Pendiente | `seeds/prod/features/` | ## Dependencias ### Depende de - SAAS-001 (Auth) - SAAS-002 (Tenants) - SAAS-003 (Users) ### Bloquea a - Rollouts graduales - Experimentos de producto ## Criterios de Aceptacion - [ ] Flags booleanos funcionan - [ ] Override por tenant funciona - [ ] Override por usuario funciona - [ ] Rollout % es deterministico - [ ] UI admin permite gestion - [ ] Cache funciona correctamente ## Caching ```typescript // Redis cache con invalidacion const cacheKey = `features:${tenantId}:${userId}`; const cached = await redis.get(cacheKey); if (cached) return JSON.parse(cached); const flags = await this.evaluateAllFlags(context); await redis.setex(cacheKey, 300, JSON.stringify(flags)); // 5 min return flags; ``` --- **Ultima actualizacion:** 2026-01-07