docs: reflejar multicomunidad, gating de grupos y /admin

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
main
brobert 4 weeks ago
parent a5eedb5c7f
commit a5a3d98167

@ -46,3 +46,35 @@ TZ="Europe/Madrid" # Zona horaria usada para "hoy/mañana" y render de fe
# RQ_BASE_BACKOFF_MS=5000
# Backoff máximo en milisegundos (por defecto 3600000 = 1h).
# RQ_MAX_BACKOFF_MS=3600000
# Limpieza y mantenimiento de la cola (opcional — avanzado)
# Habilitar/deshabilitar limpieza automática (por defecto true).
# RQ_CLEANUP_ENABLED=true
# Días de retención para enviados (por defecto 14).
# RQ_RETENTION_DAYS_SENT=14
# Días de retención para fallidos (por defecto 30).
# RQ_RETENTION_DAYS_FAILED=30
# Intervalo del scheduler de limpieza en ms (por defecto 86400000 = 24h).
# RQ_CLEANUP_INTERVAL_MS=86400000
# Tamaño de lote para borrar elementos en limpieza (por defecto 1000).
# RQ_CLEANUP_BATCH=1000
# Ejecutar PRAGMA optimize tras limpieza (por defecto true).
# RQ_OPTIMIZE_ENABLED=true
# Ejecutar VACUUM cada N ejecuciones de limpieza (por defecto desactivado).
# RQ_VACUUM_ENABLED=false
# Frecuencia de VACUUM (solo si está habilitado).
# RQ_VACUUM_EVERY_N_RUNS=28
# Métricas (opcional)
# METRICS_ENABLED=true
# METRICS_FORMAT=prom # prom|json
# Control de acceso por grupos (multicomunidad)
# Modo: off|discover|enforce (por defecto off)
# GROUP_GATING_MODE=discover
# Lista de administradores (IDs/JIDs; se normalizan a dígitos)
# ADMIN_USERS="34600123456, 5554443333"
# Lista de grupos permitidos inicial (JIDs @g.us)
# ALLOWED_GROUPS="12345-67890@g.us, 11111-22222@g.us"
# Notificar a ADMIN_USERS cuando se descubra un grupo en modo discover
# NOTIFY_ADMINS_ON_DISCOVERY=true

@ -8,6 +8,7 @@ Siguiente paso de desarrollo: ejecutar el plan mínimo de CI/CD, healthcheck y b
- Endpoint /health, validación de entorno, extracción robusta de texto (conversation/extended/captions).
- Detección DM vs grupo y política “solo DM”.
- Registro/verificación de webhooks y sincronización de grupos activos con caché; sincronización periódica de miembros y handlers incrementales (alta/baja/rol) idempotentes.
- Control de acceso por grupos (allowed_groups): modos discover/enforce, aprobación/bloqueo vía /admin y notificación opcional a ADMIN_USERS en descubrimiento.
- Rate limiting por usuario (15/min por defecto; desactivado en tests; aviso con cooldown).
- Base de datos y migraciones
- Inicialización con PRAGMA FK y timestamps de alta precisión.

@ -88,5 +88,22 @@ Limitaciones y notas
- En algunos clientes, las menciones en DM no se muestran como chips.
- Límite de 15 comandos/min por usuario (configurable).
Administración
- Solo para usuarios en ADMIN_USERS (se normalizan a dígitos).
- Comandos clave:
- /admin pendientes — lista grupos en estado “pending”.
- /admin habilitar-aquí — permite el grupo actual (alias: enable).
- /admin deshabilitar-aquí — bloquea el grupo actual (alias: disable).
- /admin allow-group <group_id@g.us> — permite un grupo específico.
- /admin block-group <group_id@g.us> — bloquea un grupo específico.
- /admin sync-grupos — fuerza sincronización de grupos.
- Modos de control de acceso:
- off — sin control (no recomendado).
- discover — grupos desconocidos quedan “pending” y (opcional) se avisa por DM a ADMIN_USERS.
- enforce — solo se procesan mensajes/comandos de grupos “allowed”.
- Notas:
- La app es multicomunidad; el gating evita ruido en grupos no aprobados.
- Ver variables: GROUP_GATING_MODE, ADMIN_USERS, ALLOWED_GROUPS, NOTIFY_ADMINS_ON_DISCOVERY.
Contacto y soporte
- Si encuentras problemas o tienes ideas, abre un issue en el repositorio o contacta con el administrador de la instancia.

@ -0,0 +1,42 @@
# 0003 — Control de acceso por grupos (multicomunidad) y /admin
Estado
- aceptada
Contexto
- El bot debe convivir con múltiples comunidades/grupos.
- Evitar ruido/abuso en grupos donde el bot no está aprobado.
- Requerimos un flujo de aprobación simple, auditable y consistente con el diseño “solo DM”.
Decisión
- Añadir tabla allowed_groups con:
- group_id (PK), label (opcional), status ('pending'|'allowed'|'blocked'),
discovered_at, updated_at, discovered_by (opcional).
- Modos de gating:
- off — sin control.
- discover — grupos desconocidos pasan a 'pending'; detener procesamiento y (opcional) notificar por DM a ADMIN_USERS.
- enforce — solo se procesan mensajes/comandos de grupos 'allowed'.
- Servicio AllowedGroups con caché en memoria e interfaz:
- isAllowed(groupId), setStatus(groupId, status), upsertPending(groupId, discoveredBy), listByStatus(status), seedFromEnv().
- Comandos /admin (solo ADMIN_USERS normalizados):
- pendientes, habilitar-aquí, deshabilitar-aquí, allow-group <jid>, block-group <jid>, sync-grupos.
- Métricas:
- Gauges: allowed_groups_total_pending|allowed|blocked.
- Counters: unknown_groups_discovered_total, messages_blocked_group_total, commands_blocked_total, sync_skipped_group_total.
- Variables de entorno:
- GROUP_GATING_MODE, ADMIN_USERS, ALLOWED_GROUPS, NOTIFY_ADMINS_ON_DISCOVERY.
Consecuencias
- Despliegues multicomunidad más seguros y con menos ruido.
- Complejidad moderada (tabla + caché + comandos de admin).
- Operativa documentada y métricas para observabilidad.
Alternativas consideradas
- Lista blanca hardcodeada: poca flexibilidad y sin trazabilidad.
- Restringir a una única comunidad: limita casos de uso.
- Sin control: riesgo de abuso y ruido.
Notas de implementación
- Gate aplicado en server.ts y CommandService (retorno temprano según modo).
- GroupSyncService ignora grupos no allowed (incluye scheduler).
- Reminders y TaskService filtran por grupos válidos en modo enforce.

@ -18,6 +18,9 @@ Esquema funcional (resumen)
- alias (PK), user_id (FK → users), source, created_at, updated_at.
- groups
- id (PK, JID), name, active (boolean), last_verified (timestamp).
- allowed_groups
- group_id (PK, JID), label (TEXT | null), status ('pending'|'allowed'|'blocked'),
discovered_at, updated_at, discovered_by (TEXT | null).
- group_members
- group_id (FK → groups), user_id (FK → users), is_admin (boolean), is_active (boolean),
first_seen_at, last_seen_at, last_role_change_at.
@ -31,7 +34,10 @@ Esquema funcional (resumen)
- task_id (FK → tasks), user_id (FK → users), assigned_by (user_id), assigned_at.
- response_queue
- id (PK), recipient (user_id/JID), message (texto), metadata (JSON | null),
attempts (int), available_at (timestamp), created_at (timestamp).
status ('queued'|'processing'|'sent'|'failed'),
attempts (int), next_attempt_at (timestamp | null),
last_error (TEXT | null), last_status_code (INT | null),
created_at (timestamp), updated_at (timestamp).
Nota: El detalle exacto está en las migraciones (src/db/migrations). Usa tableHasColumn para detectar columnas en migraciones idempotentes.

@ -4,6 +4,7 @@ Qué hace el sistema
- Ingesta de webhooks de WhatsApp (Evolution API) y ruteo de eventos.
- Parsing de comandos de texto y operaciones sobre tareas.
- Sincronización periódica de grupos y miembros.
- Control de acceso por grupos (allowed_groups) con modos off/discover/enforce y comandos /admin.
- Recordatorios a usuarios según preferencias.
- Cola de respuestas con reintentos/backoff.
- Métricas y health para operación.

Loading…
Cancel
Save