- Add MetricsPage and useOnboarding hook - Update superadmin controller and service - Add module documentation (docs/01-modulos/) - Add CONTEXT-MAP.yml and Sprint 5 execution report - Update project status and task traces 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.1 KiB
5.1 KiB
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
- Flags globales (sistema)
- Flags por tenant
- Flags por usuario
- Porcentaje de rollout
- 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
interface FeatureFlagService {
isEnabled(key: string, context?: EvaluationContext): Promise<boolean>;
getValue<T>(key: string, context?: EvaluationContext): Promise<T>;
getAllFlags(context?: EvaluationContext): Promise<Record<string, any>>;
}
interface EvaluationContext {
tenantId?: string;
userId?: string;
attributes?: Record<string, any>;
}
Guard
@RequiresFeature('new_dashboard')
@Get('/dashboard/v2')
async getNewDashboard() {
// Solo si feature habilitada
}
Condicional en Codigo
if (await this.features.isEnabled('ai_assistant')) {
// Mostrar boton de IA
}
const maxSize = await this.features.getValue<number>('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
// 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
// Ejemplo de reglas avanzadas
{
"rules": [
{
"condition": "plan",
"operator": "in",
"values": ["pro", "enterprise"],
"enabled": true
},
{
"condition": "country",
"operator": "equals",
"values": ["MX"],
"enabled": true
}
]
}
Frontend SDK
// React hook
function useFeatureFlag(key: string): boolean {
const { flags } = useFeatureFlags();
return flags[key] ?? false;
}
// Componente
function Dashboard() {
const showNewDashboard = useFeatureFlag('new_dashboard');
return showNewDashboard ? <NewDashboard /> : <OldDashboard />;
}
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
// 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