docs: añade plan de sincronización de miembros

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
pull/1/head
borja 2 months ago
parent bdba776b5c
commit 69c1e13502

@ -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 624h); 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.51 día.
- Etapa 2: 11.5 días.
- Etapa 3: 0.5 día.
- Etapa 4 (opcional): 0.5 día.
Total: 23.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).
Loading…
Cancel
Save