diff --git a/docs/plan-sincronizacion-miembros.md b/docs/plan-sincronizacion-miembros.md new file mode 100644 index 0000000..ead88d3 --- /dev/null +++ b/docs/plan-sincronizacion-miembros.md @@ -0,0 +1,142 @@ +# Plan de Sincronización de Miembros (Grupos de WhatsApp) + +Este documento define el plan para implementar una sincronización robusta de miembros por grupo, usando Evolution API como fuente de verdad y una réplica local en SQLite para consultas rápidas y lógica de negocio. + +## Objetivos y alcance +- Mantener una lista actualizada de miembros por grupo (JID @g.us), con: + - Estado: activo/inactivo (soft delete). + - Rol: admin/miembro. + - Trazabilidad temporal: first_seen_at, last_seen_at, last_role_change_at. +- Fuente: Evolution API (full sync + eventos incrementales por webhook). +- Consistencia: idempotencia, tolerancia a webhooks perdidos (reconciliación periódica). +- Privacidad: almacenar solo IDs normalizados y metadatos mínimos. + +## Modelo de datos (migración inicial) +- Tabla groups + - group_id TEXT PK (JID completo, p.ej. 123@g.us) + - name TEXT + - active BOOLEAN + - last_verified TEXT (ISO) opcional + - updated_at TEXT +- Tabla group_members + - group_id TEXT NOT NULL + - user_id TEXT NOT NULL (teléfono normalizado; dígitos) + - is_admin BOOLEAN NOT NULL DEFAULT 0 + - is_active BOOLEAN NOT NULL DEFAULT 1 + - first_seen_at TEXT NOT NULL + - last_seen_at TEXT NOT NULL + - last_role_change_at TEXT + - PK compuesta (group_id, user_id) + - Índices: + - group_members(group_id, is_active) + - group_members(user_id, is_active) +- Normalización: + - group_id: mantener sufijo @g.us + - user_id: usar normalizeWhatsAppId existente + +## Estrategia de sincronización +1) Full sync (reconciliación periódica) +- Listar grupos bajo WHATSAPP_COMMUNITY_ID. +- Para cada grupo activo: + - Obtener miembros (paginado si aplica). + - Upsert de cada miembro presente: + - is_active=true, last_seen_at=now. + - is_admin si el rol viene en la respuesta; actualizar last_role_change_at cuando cambie. + - Marcar como inactivos los que ya no aparezcan (is_active=false, last_seen_at=now). +- Intervalo configurable (e.g., cada 6–24h); en test/desarrollo puede ser menor. + +2) Incremental por webhooks (near-real-time) +- Suscripción a eventos de Evolution API: + - Alta de participante (join/add). + - Baja de participante (leave/remove). + - Cambio de rol (promote/demote). + - Renombrado/archivado de grupo. +- Handler idempotente: + - Upsert por (group_id, user_id). + - Cambios de estado/rol atómicos (transacción si se tocan varias filas). + - Si el payload es parcial (sin rol), no pisar is_admin. + +## Consistencia y fallos +- La app consulta siempre is_active=true. +- Full sync corrige drift por webhooks perdidos o desordenados. +- Backoff y rate limiting al hablar con Evolution API. +- Logs con contexto: group_id, user_id, evento/tipo, resultado. + +## Uso en la aplicación (consumidores) +- “/t ver todo” y recordatorios: + - Incluir “sin responsable” únicamente de grupos donde el usuario sea miembro activo. + - Fallback: si aún no hay snapshot de membresías, usar heurística (grupos con tareas del usuario). +- Validación (opcional por fase): + - Antes de operar sobre una tarea de grupo, comprobar membresía activa. + +## Privacidad y seguridad +- Solo almacenar user_id normalizado y rol/fechas. +- No persistir nombres salvo que ya exista caché controlada. +- Webhook y full sync preferiblemente en red interna; si no, proteger con allowlist/proxy. + +## Plan por etapas +Etapa 1 — Esquema + servicio +- Migración: crear groups y group_members + índices. +- Servicio GroupSync: + - syncGroups(): lista grupos + reconcilia miembros. + - reconcileGroup(groupId, membersSnapshot). + - Utilidades: timestamps ISO, normalización de IDs. +- Tests: + - Migración up-only. + - Reconciliación: de [A,B,C] a [A,C,D] → B inactivo, D añadido; tiempos/roles actualizados. + +Etapa 2 — Integración con Evolution API +- Full sync: llamadas reales a endpoints (respetando paginación y límites). +- Webhooks: registro y handlers idempotentes (alta/baja/rol/rename). +- Tests: + - Fixtures de payloads típicos (duplicados, orden alterado). + - Reintentos/backoff en errores de red/5xx. + +Etapa 3 — Consumidores (comandos y recordatorios) +- “/t ver todo” y RemindersService usan membership real. +- Fallback heurístico si no hay snapshot aún. +- Validaciones opcionales de pertenencia. +- Tests: + - Cobertura de ambos caminos (con y sin membership). + +Etapa 4 — Observabilidad y mantenimiento +- Métricas: + - grupos sincronizados, miembros activos, difs por sync, errores de webhook. +- Estado de salud: + - último sync OK, edad de la snapshot. +- Mantenimiento: + - Re-sync diario. + - Purgado opcional de inactivos antiguos. + +## Criterios de aceptación +- Tras una full sync, group_members refleja fielmente miembros activos por grupo. +- Webhooks de alta/baja actualizan el estado en <1s y son idempotentes. +- “/t ver todo” y recordatorios respetan la membresía y no rompen UX preexistente. +- 100% de tests existentes siguen pasando; nuevos tests cubren sync/reconciliación/handlers. + +## Métricas y trazas sugeridas +- Contadores: sync_runs_total, sync_errors_total, webhook_events_total, webhook_errors_total. +- Gauges: active_groups, active_members. +- Logs estructurados: action, group_id, user_id, outcome, diff_counts. + +## Riesgos y mitigaciones +- Webhooks perdidos: reconciliación periódica. +- Cambios de API o límites: backoff + degradación controlada. +- Coste de consultas: índices adecuados; joins simples. +- Privacidad: minimización de datos, documentación en README/STATUS. + +## Estimación +- Etapa 1: 0.5–1 día. +- Etapa 2: 1–1.5 días. +- Etapa 3: 0.5 día. +- Etapa 4 (opcional): 0.5 día. +Total: 2–3.5 días netos. + +## Dependencias y archivos a tocar (cuando implementemos) +- src/db.ts (esquema base para nuevas instalaciones). +- src/db/migrations/index.ts (migración up-only: tablas e índices). +- src/services/webhook-manager.ts (registro y handlers de eventos). +- src/services/group-sync.ts (full sync y reconciliación). +- src/services/command.ts (consumo en “/t ver todo”; validaciones opcionales). +- src/services/reminders.ts y src/tasks/service.ts (consultas usando membresía). +- tests/unit/services/* (sync, reconciliación, webhooks, consumidores).