workspace-v1/shared/libs/feature-flags/README.md
rckrdmrd 66161b1566 feat: Workspace-v1 complete migration with NEXUS v3.4
Sistema NEXUS v3.4 migrado con:

Estructura principal:
- core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles)
- core/catalog: Catalogo de funcionalidades reutilizables
- shared/knowledge-base: Base de conocimiento compartida
- devtools/scripts: Herramientas de desarrollo
- control-plane/registries: Control de servicios y CI/CD
- orchestration/: Configuracion de orquestacion de agentes

Proyectos incluidos (11):
- gamilit (submodule -> GitHub)
- trading-platform (OrbiquanTIA)
- erp-suite con 5 verticales:
  - erp-core, construccion, vidrio-templado
  - mecanicas-diesel, retail, clinicas
- betting-analytics
- inmobiliaria-analytics
- platform_marketing_content
- pos-micro, erp-basico

Configuracion:
- .gitignore completo para Node.js/Python/Docker
- gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git)
- Sistema de puertos estandarizado (3005-3199)

Generated with NEXUS v3.4 Migration System
EPIC-010: Configuracion Git y Repositorios
2026-01-04 03:37:42 -06:00

361 lines
8.5 KiB
Markdown

# Feature Flags Dinámicos
**Versión:** 1.0.0
**Origen:** projects/gamilit
**Estado:** Producción
**Última actualización:** 2025-12-08
---
## Descripción
Sistema de feature flags para activación gradual de funcionalidades:
- Activar/desactivar features sin redespliegue
- Rollout gradual por porcentaje de usuarios
- Target por usuarios específicos o roles
- Condiciones personalizadas via JSONB
- Período de validez (starts_at/ends_at)
- Multi-tenant opcional
---
## Características
| Característica | Descripción |
|----------------|-------------|
| Toggle dinámico | On/off sin redespliegue |
| Rollout gradual | 0-100% con hash consistente |
| Target users | Early access para usuarios específicos |
| Target roles | Habilitar por rol (admin, user, etc.) |
| Condiciones | Reglas personalizadas vía JSONB |
| Período | Fecha inicio/fin automático |
| Multi-tenant | Flags globales o por tenant |
| Auditoría | Tracking de quién creó/modificó |
---
## Stack Tecnológico
```yaml
backend:
framework: NestJS
orm: TypeORM
database: PostgreSQL
algoritmos:
- SHA256 hash para rollout consistente
- Determinístico por userId + featureKey
```
---
## Dependencias NPM
```json
{
"typeorm": "^0.3.x",
"@nestjs/typeorm": "^10.x"
}
```
**Nota:** No requiere librerías externas de feature flags (LaunchDarkly, Unleash, etc.)
---
## Tablas Requeridas
| Tabla | Propósito |
|-------|-----------|
| system_configuration.feature_flags | Configuración de flags |
---
## Estructura del Módulo
```
feature-flags/
├── entities/
│ └── feature-flag.entity.ts
├── services/
│ └── feature-flags.service.ts
├── controllers/
│ └── feature-flags.controller.ts
├── dto/
│ ├── create-feature-flag.dto.ts
│ ├── update-feature-flag.dto.ts
│ └── feature-flag-query.dto.ts
├── decorators/
│ └── feature-flag.decorator.ts # @FeatureFlag('key')
└── guards/
└── feature-flag.guard.ts
```
---
## Modelo de Datos
### FeatureFlag
```typescript
interface FeatureFlag {
id: string; // UUID
tenant_id?: string; // null = global
feature_key: string; // "new_checkout" (único)
feature_name: string; // "Nuevo Checkout v2"
description?: string;
is_enabled: boolean; // Toggle principal
rollout_percentage: number; // 0-100
target_users?: string[]; // UUIDs con early access
target_roles?: string[]; // ['admin', 'beta_tester']
target_conditions: Record<string, any>; // { min_level: 5 }
starts_at?: Date; // Fecha inicio
ends_at?: Date; // Fecha fin
metadata: Record<string, any>; // { category: 'checkout' }
created_by?: string;
updated_by?: string;
created_at: Date;
updated_at: Date;
}
```
---
## Flujo de Evaluación
```
isEnabled(key, userId, userRoles)?
1. Feature habilitada globalmente?
└─► NO → return false
2. Usuario en target_users?
└─► SÍ → return true (early access)
3. Usuario tiene target_role?
└─► SÍ → return true
4. rollout_percentage == 100?
└─► SÍ → return true
5. rollout_percentage == 0?
└─► SÍ → return false
6. Hash(userId + key) < rollout_percentage?
└─► SÍ → return true
└─► NO → return false
```
---
## Uso Rápido
### 1. Verificar feature programáticamente
```typescript
import { FeatureFlagsService } from '@/modules/feature-flags/services';
// En un servicio
const result = await featureFlagsService.isEnabled(
'new_checkout', // feature key
userId, // opcional
userRoles, // opcional: ['admin', 'user']
);
if (result.enabled) {
// Usar nueva funcionalidad
} else {
// Usar funcionalidad legacy
}
```
### 2. Guard para proteger rutas
```typescript
// Proteger endpoint completo
@Get('beta-feature')
@UseGuards(JwtAuthGuard, FeatureFlagGuard)
@FeatureFlag('beta_feature')
async betaFeature() {
return { message: 'Solo para usuarios con feature habilitada' };
}
```
### 3. Decorador para check inline
```typescript
@Get('dashboard')
async getDashboard(
@CurrentUser() user: User,
@CheckFeature('new_dashboard') hasNewDashboard: boolean,
) {
if (hasNewDashboard) {
return this.newDashboardService.getData(user.id);
}
return this.legacyDashboardService.getData(user.id);
}
```
### 4. En frontend (API call)
```typescript
// GET /api/feature-flags/check/new_checkout
const response = await api.get(`/feature-flags/check/${featureKey}`, {
params: { userId },
});
if (response.data.enabled) {
showNewCheckout();
} else {
showLegacyCheckout();
}
```
---
## Rollout Gradual
El rollout usa un hash SHA256 del `userId + featureKey` para determinar si un usuario está en el porcentaje:
```typescript
// Algoritmo de hash consistente
private hashUserId(userId: string, featureKey: string): number {
const hash = createHash('sha256')
.update(`${userId}:${featureKey}`)
.digest('hex');
const hashInt = parseInt(hash.substring(0, 8), 16);
return hashInt % 101; // 0-100
}
// Verificación
const userHash = hashUserId(userId, featureKey);
const isInRollout = userHash < rollout_percentage;
```
**Beneficios:**
- Mismo usuario siempre obtiene mismo resultado
- Distribución uniforme entre usuarios
- Diferente distribución por feature (gracias al featureKey)
---
## Estrategias de Rollout
### Canary Release
```typescript
// 1. Crear flag deshabilitada
await featureFlagsService.create({
key: 'new_payment_gateway',
name: 'Nuevo Gateway de Pagos',
isEnabled: false,
rolloutPercentage: 0,
});
// 2. Habilitar para equipo interno
await featureFlagsService.update('new_payment_gateway', {
isEnabled: true,
targetUsers: ['dev-team-uuid-1', 'dev-team-uuid-2'],
});
// 3. Expandir a 5% de usuarios
await featureFlagsService.updateRollout('new_payment_gateway', 5);
// 4. Si todo OK, expandir gradualmente
await featureFlagsService.updateRollout('new_payment_gateway', 25);
await featureFlagsService.updateRollout('new_payment_gateway', 50);
await featureFlagsService.updateRollout('new_payment_gateway', 100);
```
### Beta por Roles
```typescript
await featureFlagsService.create({
key: 'advanced_analytics',
name: 'Analytics Avanzados',
isEnabled: true,
rolloutPercentage: 0, // No rollout general
targetRoles: ['admin', 'premium_user'],
});
```
### Feature Temporal
```typescript
await featureFlagsService.create({
key: 'black_friday_banner',
name: 'Banner Black Friday',
isEnabled: true,
rolloutPercentage: 100,
startsAt: new Date('2025-11-25'),
endsAt: new Date('2025-11-30'),
});
```
---
## Variables de Entorno
```env
# Feature flags
FEATURE_FLAGS_CACHE_TTL=300 # Cache de 5 minutos
FEATURE_FLAGS_DEFAULT_ENABLED=false
```
---
## Endpoints Principales
| Método | Ruta | Descripción |
|--------|------|-------------|
| GET | /admin/feature-flags | Listar todas las flags |
| GET | /admin/feature-flags/:key | Obtener flag por key |
| POST | /admin/feature-flags | Crear nueva flag |
| PUT | /admin/feature-flags/:key | Actualizar flag |
| DELETE | /admin/feature-flags/:key | Eliminar flag |
| POST | /admin/feature-flags/:key/enable | Habilitar flag |
| POST | /admin/feature-flags/:key/disable | Deshabilitar flag |
| PUT | /admin/feature-flags/:key/rollout | Actualizar porcentaje |
| POST | /feature-flags/:key/check | Verificar si está habilitada |
---
## Casos de Uso Comunes
| Caso | Configuración |
|------|---------------|
| A/B Testing | Rollout 50%, metadata con grupo |
| Beta cerrada | targetUsers con UUIDs específicos |
| Kill switch | is_enabled = false cuando hay problemas |
| Feature por plan | targetRoles: ['premium', 'enterprise'] |
| Lanzamiento programado | starts_at + ends_at |
| Migración gradual | Rollout 10% → 25% → 50% → 100% |
---
## Adaptaciones Necesarias
1. **Roles**: Ajustar enum de roles según tu sistema
2. **Cache**: Implementar cache si hay muchas verificaciones
3. **Multi-tenant**: Decidir si flags son globales o por tenant
4. **UI Admin**: Crear interfaz para gestionar flags
5. **Métricas**: Integrar con sistema de analytics
---
## Referencias
- [Feature Flags Best Practices](https://martinfowler.com/articles/feature-toggles.html)
- [Gradual Rollout Strategies](https://docs.launchdarkly.com/home/targeting-flags)
---
**Mantenido por:** Sistema NEXUS
**Proyecto origen:** Gamilit Platform