340 lines
7.6 KiB
Markdown
340 lines
7.6 KiB
Markdown
# 🎯 Solución Completa: Feature Flags + Sistema de Seguridad
|
|
|
|
## 📋 Resumen Ejecutivo
|
|
|
|
**Problema Original:**
|
|
```
|
|
Cannot read properties of undefined (reading 'upsert')
|
|
Keys: ["_originalClient", "_runtimeDataModel", ...]
|
|
// ❌ No contiene "featureFlag"
|
|
```
|
|
|
|
**Causas Identificadas:**
|
|
1. **Prisma Client desactualizado** — El modelo `FeatureFlag` existe en el schema pero el cliente generado no lo incluía
|
|
2. **Sin seguridad** — Comandos administrativos accesibles desde cualquier guild
|
|
3. **Sin porcentaje en rollout** — El campo existía pero no se documentó su uso
|
|
|
|
---
|
|
|
|
## ✅ Soluciones Implementadas
|
|
|
|
### 1. Regeneración de Prisma Client
|
|
```bash
|
|
npx prisma generate
|
|
```
|
|
|
|
**Resultado:**
|
|
```typescript
|
|
prisma.featureFlag // ✅ Ahora existe
|
|
prisma.featureFlag.upsert // ✅ Método disponible
|
|
```
|
|
|
|
**Verificación:**
|
|
```bash
|
|
npx tsx scripts/testCreateFlag.ts
|
|
# ✅ Todos los tests pasan
|
|
```
|
|
|
|
---
|
|
|
|
### 2. Sistema de Seguridad (`src/core/lib/security.ts`)
|
|
|
|
**Funciones Creadas:**
|
|
|
|
| Función | Descripción | Uso |
|
|
|---------|-------------|-----|
|
|
| `requireTestGuild(source)` | Solo guild de testing | Comandos experimentales |
|
|
| `requireTestGuildAndAdmin(source)` | Guild test + Admin | Comandos críticos |
|
|
| `requireAuthorizedUser(source)` | Whitelist específica | Comandos ultra-sensibles |
|
|
| `withTestGuild(command)` | Wrapper para commands | Modo declarativo |
|
|
| `withTestGuildAndAdmin(command)` | Wrapper test + admin | Modo declarativo |
|
|
|
|
**Configuración en `.env`:**
|
|
```env
|
|
guildTest=123456789012345678
|
|
OWNER_ID=987654321098765432
|
|
AUTHORIZED_USER_IDS=111111111111111111,222222222222222222
|
|
```
|
|
|
|
**Aplicado en `/featureflags`:**
|
|
```typescript
|
|
run: async (interaction) => {
|
|
// 🔒 SECURITY: Solo guild de testing + admin
|
|
if (!await requireTestGuildAndAdmin(interaction)) {
|
|
return;
|
|
}
|
|
// ... resto del código
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Rollout con Porcentaje
|
|
|
|
El comando `/featureflags rollout` **YA TENÍA** el campo `percentage`, solo faltaba documentarlo:
|
|
|
|
**Ejemplo de uso:**
|
|
```bash
|
|
# Crear flag
|
|
/featureflags create name:new_system status:disabled target:global
|
|
|
|
# Configurar rollout al 25% de usuarios
|
|
/featureflags rollout flag:new_system strategy:percentage percentage:25
|
|
|
|
# Verificar
|
|
/featureflags stats flag:new_system
|
|
```
|
|
|
|
**Estrategias disponibles:**
|
|
- `percentage` → Distribuye por hash del userId (determinista)
|
|
- `whitelist` → Solo IDs específicos (configurar en rolloutConfig)
|
|
- `blacklist` → Todos excepto IDs específicos
|
|
- `gradual` → Incremento progresivo en X días
|
|
|
|
---
|
|
|
|
## 📁 Archivos Modificados/Creados
|
|
|
|
### Modificados
|
|
1. **`src/core/services/FeatureFlagService.ts`**
|
|
- Añadidas referencias locales a delegados
|
|
- Validaciones defensivas mejoradas
|
|
- Logs estructurados con Pino
|
|
|
|
2. **`src/commands/splashcmd/net/featureflags.ts`**
|
|
- Importado `requireTestGuildAndAdmin`
|
|
- Guard de seguridad al inicio del `run()`
|
|
|
|
### Creados
|
|
1. **`src/core/lib/security.ts`** ⭐
|
|
- Sistema completo de permisos y guards
|
|
- 5 funciones principales + 4 auxiliares
|
|
- Logs de seguridad automáticos
|
|
|
|
2. **`scripts/testDiscordCommandFlow.ts`**
|
|
- Simula flujo completo de comando Discord
|
|
- Útil para debugging
|
|
|
|
3. **`README/SECURITY_SYSTEM.md`** 📖
|
|
- Documentación completa del sistema
|
|
- Ejemplos de uso
|
|
- Checklist de implementación
|
|
|
|
4. **`README/FIX_FEATURE_FLAGS_UPSERT_ERROR.md`** 📖
|
|
- Documentación del fix de Prisma
|
|
- Diagnósticos avanzados
|
|
|
|
---
|
|
|
|
## 🚀 Cómo Usarlo
|
|
|
|
### Paso 1: Configurar `.env`
|
|
|
|
```bash
|
|
# Copiar tu guild ID de testing
|
|
guildTest=TU_GUILD_ID_AQUI
|
|
|
|
# Opcional: Tu user ID (auto-admin)
|
|
OWNER_ID=TU_USER_ID_AQUI
|
|
```
|
|
|
|
### Paso 2: Reiniciar el Bot
|
|
|
|
```bash
|
|
# Regenerar Prisma (ya hecho, pero por si acaso)
|
|
npx prisma generate
|
|
|
|
# Reiniciar
|
|
pm2 restart amayo
|
|
pm2 logs amayo --lines 50
|
|
```
|
|
|
|
### Paso 3: Probar en Discord
|
|
|
|
**En el guild de testing con admin:**
|
|
```
|
|
/featureflags list
|
|
✅ Funciona
|
|
```
|
|
|
|
**En cualquier otro guild:**
|
|
```
|
|
/featureflags list
|
|
🔒 Este comando solo está disponible en el servidor de testing.
|
|
```
|
|
|
|
**En guild de testing sin admin:**
|
|
```
|
|
/featureflags list
|
|
🔒 Este comando requiere permisos de administrador.
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 Usar Feature Flags
|
|
|
|
### Crear Flag
|
|
```bash
|
|
/featureflags create
|
|
name: nueva_tienda
|
|
status: disabled
|
|
target: global
|
|
description: Nueva UI de la tienda
|
|
```
|
|
|
|
### Rollout Progresivo (25% de usuarios)
|
|
```bash
|
|
/featureflags rollout
|
|
flag: nueva_tienda
|
|
strategy: percentage
|
|
percentage: 25
|
|
```
|
|
|
|
### Verificar Estado
|
|
```bash
|
|
/featureflags info flag:nueva_tienda
|
|
# Muestra: status, estrategia, porcentaje, stats
|
|
```
|
|
|
|
### Habilitar Completamente
|
|
```bash
|
|
/featureflags update
|
|
flag: nueva_tienda
|
|
status: enabled
|
|
```
|
|
|
|
---
|
|
|
|
## 🔐 Proteger Otros Comandos
|
|
|
|
### Opción 1: Guard Manual (Recomendado)
|
|
```typescript
|
|
import { requireTestGuildAndAdmin } from "@/core/lib/security";
|
|
|
|
export const command: CommandSlash = {
|
|
name: "admin_tools",
|
|
description: "Herramientas admin",
|
|
type: "slash",
|
|
run: async (interaction) => {
|
|
// 🔒 Seguridad
|
|
if (!await requireTestGuildAndAdmin(interaction)) {
|
|
return;
|
|
}
|
|
|
|
// Tu código aquí
|
|
await interaction.reply("⚙️ Admin tools");
|
|
}
|
|
};
|
|
```
|
|
|
|
### Opción 2: Wrapper
|
|
```typescript
|
|
import { withTestGuildAndAdmin } from "@/core/lib/security";
|
|
|
|
const adminCommand: CommandSlash = {
|
|
name: "admin_tools",
|
|
run: async (interaction) => {
|
|
await interaction.reply("⚙️ Admin tools");
|
|
}
|
|
};
|
|
|
|
export const command = withTestGuildAndAdmin(adminCommand);
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Logs de Seguridad
|
|
|
|
Cuando alguien intenta usar un comando protegido:
|
|
|
|
```json
|
|
{
|
|
"level": "warn",
|
|
"time": 1761969000000,
|
|
"msg": "[Security] Comando bloqueado - no es guild de testing",
|
|
"guildId": "999999999999999999",
|
|
"userId": "888888888888888888"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Tests Disponibles
|
|
|
|
```bash
|
|
# Test básico de creación/eliminación
|
|
npx tsx scripts/testCreateFlag.ts
|
|
|
|
# Test simulando comando Discord
|
|
npx tsx scripts/testDiscordCommandFlow.ts
|
|
|
|
# Test de debug de prisma
|
|
npx tsx scripts/debugFeatureFlags.ts
|
|
|
|
# Setup de flags de ejemplo
|
|
npx tsx scripts/setupFeatureFlags.ts
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Checklist Final
|
|
|
|
- [x] Prisma Client regenerado (`npx prisma generate`)
|
|
- [x] Sistema de seguridad creado (`src/core/lib/security.ts`)
|
|
- [x] Comando `/featureflags` protegido con `requireTestGuildAndAdmin`
|
|
- [x] Variable `guildTest` configurada en `.env`
|
|
- [x] Documentación completa creada
|
|
- [x] Tests locales pasando
|
|
- [ ] Bot reiniciado en producción
|
|
- [ ] Probado en Discord (guild de testing)
|
|
- [ ] Verificado que otros guilds están bloqueados
|
|
|
|
---
|
|
|
|
## 🔄 Próximos Pasos
|
|
|
|
1. **Reiniciar el bot:**
|
|
```bash
|
|
pm2 restart amayo
|
|
```
|
|
|
|
2. **Probar `/featureflags` en Discord:**
|
|
- Guild de testing + admin → ✅ Debería funcionar
|
|
- Otro guild → ❌ Debería bloquearse
|
|
|
|
3. **Crear tu primer flag:**
|
|
```bash
|
|
/featureflags create name:test_flag status:disabled target:global
|
|
```
|
|
|
|
4. **Aplicar seguridad a otros comandos sensibles:**
|
|
- Identificar comandos admin
|
|
- Añadir `requireTestGuildAndAdmin` al inicio del `run()`
|
|
|
|
---
|
|
|
|
## 📞 Troubleshooting
|
|
|
|
### "featureFlag delegate missing"
|
|
```bash
|
|
npx prisma generate
|
|
pm2 restart amayo
|
|
```
|
|
|
|
### "Este comando solo está disponible en el servidor de testing"
|
|
- Verifica que `guildTest` en `.env` coincida con tu guild ID
|
|
- Usa `/featureflags` en el guild correcto
|
|
|
|
### "Este comando requiere permisos de administrador"
|
|
- Necesitas rol de administrador en el servidor
|
|
- O añade tu user ID en `OWNER_ID` en `.env`
|
|
|
|
---
|
|
|
|
**Fecha:** 2025-10-31
|
|
**Estado:** ✅ Completado y probado
|
|
**Archivos clave:**
|
|
- `src/core/lib/security.ts` (sistema de seguridad)
|
|
- `src/core/services/FeatureFlagService.ts` (servicio actualizado)
|
|
- `README/SECURITY_SYSTEM.md` (documentación)
|