michangarrito/docs/01-epicas/MCH-032-feature-flags.md
rckrdmrd 5a49ad0185 [INTEGRATION] feat: Integrate template-saas scopes and database objects
## Documentation
- Align MCH-029 to MCH-032 with template-saas modules (SAAS-008 to SAAS-015)
- Create MCH-034 (Analytics) and MCH-035 (Reports) from SAAS-016/017
- Update PLAN-DESARROLLO.md with Phase 7 and 8
- Update _MAP.md indexes (35 total epics)

## Database (5 new schemas, 14 tables)
- Add storage schema: buckets, files, signed_urls
- Add webhooks schema: endpoints, deliveries
- Add audit schema: logs, retention_policies
- Add features schema: flags, tenant_flags (14 seeds)
- Add analytics schema: metrics, events, reports, report_schedules
- Add auth.oauth_connections for MCH-030
- Add timestamptz_to_date() IMMUTABLE function
- Update EXPECTED_SCHEMAS in recreate-database.sh

## Analysis Reports
- ANALISIS-INTEGRACION-TEMPLATE-SAAS-2026-01-13.md
- VALIDACION-COHERENCIA-2026-01-13.md
- GAP-ANALYSIS-BD-2026-01-13.md
- REPORTE-EJECUCION-2026-01-13.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 07:10:55 -06:00

397 lines
13 KiB
Markdown

---
id: EPIC-MCH-032
type: Epic
title: "MCH-032: Feature Flags por Plan"
code: MCH-032
status: Planificado
phase: 7
priority: P1
created_at: 2026-01-10
updated_at: 2026-01-10
simco_version: "4.0.1"
dependencies:
blocks: []
depends_on: ["MCH-029", "MCH-018"]
---
# MCH-032: Feature Flags por Plan
## Metadata
- **Codigo:** MCH-032
- **Fase:** 7 - Expansion
- **Prioridad:** P1
- **Estado:** Planificado
- **Story Points:** 5
- **Sprint Objetivo:** Sprint 8
## Descripcion
Implementar sistema de feature flags que permite habilitar/deshabilitar funcionalidades por plan de suscripcion, tenant o usuario individual. Permite diferenciacion de ofertas, beta testing controlado y rollouts graduales.
## Objetivos
1. Definir flags globales con valores por defecto
2. Asociar flags a planes de suscripcion
3. Permitir overrides por tenant para beta testing
4. Evaluar flags en tiempo real con cache
5. SDK para frontend (React hook)
## Alcance
### Incluido
- Feature flags por plan (Basic, Pro, Enterprise)
- Overrides por tenant y usuario
- Expiracion de overrides
- Cache en Redis
- Guard de NestJS para backend
- Hook useFeatureFlag para React
### Excluido
- A/B testing (futuro)
- Percentage rollouts
- Feature usage analytics
## Arquitectura
```
┌─────────────────────────────────────┐
│ MCH-032: Feature Flags │
└─────────────────────────────────────┘
┌─────────────────────────────┼─────────────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Flags │ │ Plans │ │ Overrides │
│ (global) │ │ (MCH-018) │ │ (por tenant) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└──────────────────────────┼──────────────────────────┘
┌─────────────────────────────────────┐
│ FeatureFlagEvaluator │
│ (Redis cache + fallback DB) │
└─────────────────────────────────────┘
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│FeatureFlagGuard│ │useFeatureFlag│ │ Admin UI │
│ (Backend) │ │ (React) │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
```
## Entregables
| Entregable | Estado | Sprint | Ubicacion |
|------------|--------|--------|-----------|
| Schema feature_flags (DDL) | Planificado | 8 | `database/schemas/13-feature-flags.sql` |
| FeatureFlagService | Planificado | 8 | `apps/backend/src/modules/feature-flags/` |
| FeatureFlagEvaluator | Planificado | 8 | `apps/backend/src/modules/feature-flags/` |
| FeatureFlagGuard | Planificado | 8 | `apps/backend/src/common/guards/` |
| useFeatureFlag hook | Planificado | 8 | `apps/web/src/hooks/` |
| Admin UI | Planificado | 8 | `apps/web/src/pages/admin/feature-flags/` |
## Dependencias
### Depende de
- MCH-029 (Redis para cache de evaluaciones)
- MCH-018 (Plans para asociar flags)
### Bloquea a
- Ninguna
---
## Historias de Usuario
### MCH-US-109: Feature Flags por Plan
**Como** administrador del sistema
**Quiero** habilitar/deshabilitar features segun el plan del tenant
**Para** diferenciar la oferta entre planes
**Story Points:** 3
**Criterios de Aceptacion:**
- [CA-109-1] Definicion de flags globales con key, descripcion, valor por defecto
- [CA-109-2] Asociacion de flags a planes (Basic: false, Pro: true, Enterprise: true)
- [CA-109-3] Evaluacion en tiempo real (latencia <10ms con cache)
- [CA-109-4] Cache en Redis con invalidacion al cambiar flag
- [CA-109-5] Hook useFeatureFlag(key) retorna boolean
**Tareas:**
| ID | Tarea | Tipo | SP |
|----|-------|------|-----|
| MCH-TT-109-01 | DDL schema feature_flags | DDL | 0.25 |
| MCH-TT-109-02 | FeatureFlagService (CRUD de flags) | Backend | 0.5 |
| MCH-TT-109-03 | FeatureFlagEvaluator con cache Redis | Backend | 0.5 |
| MCH-TT-109-04 | FeatureFlagGuard para proteger endpoints | Backend | 0.25 |
| MCH-TT-109-05 | FeatureFlagsController (API) | Backend | 0.25 |
| MCH-TT-109-06 | Hook useFeatureFlag en frontend | Frontend | 0.5 |
| MCH-TT-109-07 | Tests | Test | 0.5 |
| MCH-TT-109-08 | Documentacion | Docs | 0.25 |
---
### MCH-US-110: Overrides por Tenant
**Como** administrador del sistema
**Quiero** habilitar features especificos para ciertos tenants
**Para** dar acceso beta o promociones especiales
**Story Points:** 2
**Criterios de Aceptacion:**
- [CA-110-1] Override por tenant_id habilita feature aunque plan no lo incluya
- [CA-110-2] Override por user_id para usuarios especificos
- [CA-110-3] Expiracion configurable del override (fecha/hora)
- [CA-110-4] UI de administracion para gestionar overrides
**Tareas:**
| ID | Tarea | Tipo | SP |
|----|-------|------|-----|
| MCH-TT-110-01 | DDL tabla flag_overrides | DDL | 0.25 |
| MCH-TT-110-02 | Logica de override en evaluador | Backend | 0.5 |
| MCH-TT-110-03 | UI para superadmin | Frontend | 0.5 |
| MCH-TT-110-04 | Tests | Test | 0.25 |
| MCH-TT-110-05 | Documentacion de uso | Docs | 0.5 |
---
## Resumen de Story Points
| Historia | SP | Sprint |
|----------|-----|--------|
| MCH-US-109: Feature Flags por Plan | 3 | 8 |
| MCH-US-110: Overrides por Tenant | 2 | 8 |
| **TOTAL** | **5** | 8 |
---
## Criterios de Aceptacion de Epica
- [ ] Flags evaluados correctamente por plan
- [ ] Cache Redis funcional (<10ms latencia)
- [ ] Overrides aplicandose correctamente
- [ ] UI de administracion funcional
- [ ] Hook React integrado
- [ ] Cobertura de tests >80%
## Notas Tecnicas
### Schema feature_flags
```sql
CREATE SCHEMA IF NOT EXISTS feature_flags;
CREATE TABLE feature_flags.flags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
key VARCHAR(100) UNIQUE NOT NULL,
description TEXT,
default_value BOOLEAN DEFAULT false,
type VARCHAR(20) DEFAULT 'boolean', -- boolean, string, number
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE feature_flags.plan_flags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
flag_id UUID REFERENCES feature_flags.flags(id),
plan_id UUID REFERENCES billing.plans(id),
value BOOLEAN NOT NULL,
UNIQUE(flag_id, plan_id)
);
CREATE TABLE feature_flags.flag_overrides (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
flag_id UUID REFERENCES feature_flags.flags(id),
tenant_id UUID,
user_id UUID,
value BOOLEAN NOT NULL,
expires_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CHECK (tenant_id IS NOT NULL OR user_id IS NOT NULL)
);
```
### Ejemplo de Flags Iniciales
| Flag Key | Descripcion | Basic | Pro | Enterprise |
|----------|-------------|-------|-----|------------|
| ai_assistant | Asistente IA en chat | false | true | true |
| advanced_reports | Reportes avanzados | false | true | true |
| api_access | Acceso a API publica | false | false | true |
| white_label | Sin branding MiChangarrito | false | false | true |
| multi_location | Multiples ubicaciones | false | true | true |
### Uso en Backend
```typescript
@UseGuards(FeatureFlagGuard)
@FeatureFlag('ai_assistant')
@Get('ai/suggestions')
async getAISuggestions() {
// Solo accesible si flag habilitado
}
```
### Uso en Frontend
```tsx
function Dashboard() {
const hasAI = useFeatureFlag('ai_assistant');
return (
<div>
{hasAI && <AIAssistantWidget />}
</div>
);
}
```
## ADRs Relacionados
- [ADR-0005: Feature Flags Strategy](../97-adr/ADR-0005-feature-flags.md)
---
## Especificaciones Tecnicas Detalladas (Ref: SAAS-009)
Esta seccion documenta las especificaciones del modulo de feature flags segun template-saas para garantizar alineacion arquitectonica.
### Estructura de Tabla feature_flags
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | Identificador unico |
| key | VARCHAR (unique) | Clave del flag |
| name | VARCHAR | Nombre descriptivo |
| description | TEXT | Descripcion del flag |
| type | VARCHAR | Tipo: boolean/string/number/json |
| default_value | JSONB | Valor por defecto |
| is_enabled | BOOLEAN | Si el flag esta activo |
| rollout_percentage | INTEGER | Porcentaje de rollout (0-100) |
| targeting_rules | JSONB | Reglas de targeting avanzado |
| created_at | TIMESTAMP | Fecha de creacion |
| updated_at | TIMESTAMP | Fecha de actualizacion |
### Tablas de Overrides
**tenant_feature_overrides**
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | Identificador unico |
| tenant_id | UUID | Tenant afectado |
| feature_key | VARCHAR | Clave del flag |
| value | JSONB | Valor override |
| enabled | BOOLEAN | Estado del override |
| expires_at | TIMESTAMP | Fecha de expiracion |
**user_feature_overrides**
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | Identificador unico |
| user_id | UUID | Usuario afectado |
| feature_key | VARCHAR | Clave del flag |
| value | JSONB | Valor override |
| enabled | BOOLEAN | Estado del override |
| expires_at | TIMESTAMP | Fecha de expiracion |
### Endpoints API del Modulo
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /features | Listar todos los flags |
| GET | /features/:key | Obtener flag especifico |
| POST | /features | Crear nuevo flag |
| PUT | /features/:key | Actualizar flag |
| DELETE | /features/:key | Eliminar flag |
| GET | /features/evaluate | Evaluar todos los flags para contexto actual |
| POST | /features/:key/override/tenant | Crear override para tenant |
| POST | /features/:key/override/user | Crear override para usuario |
| DELETE | /features/:key/override/tenant | Eliminar override de tenant |
### Tipos de Flags Soportados
| Tipo | Descripcion | Ejemplo |
|------|-------------|---------|
| boolean | Verdadero/Falso | `true` |
| string | Texto | `'dark'` |
| number | Numerico | `10` |
| json | Objeto JSON | `{"limit": 100}` |
### Flags Predefinidos de Referencia
| 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 de archivo en MB |
| theme | string | 'light' | Tema por defecto |
### 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
El rollout por porcentaje es deterministico, es decir, el mismo usuario siempre obtendra el mismo resultado:
```typescript
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 (Reglas Avanzadas)
```typescript
{
"rules": [
{
"condition": "plan",
"operator": "in",
"values": ["pro", "enterprise"],
"enabled": true
},
{
"condition": "country",
"operator": "equals",
"values": ["MX"],
"enabled": true
}
]
}
```
### Caching con Redis
```typescript
// Cache key format
const cacheKey = `features:${tenantId}:${userId}`;
// TTL: 5 minutos
await redis.setex(cacheKey, 300, JSON.stringify(flags));
```
### Referencia
> Documentacion fuente: `/projects/template-saas/docs/01-modulos/SAAS-009-feature-flags.md`
> Version: 1.0.0
---
**Ultima actualizacion:** 2026-01-13
**Autor:** Architecture Team