--- 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 (