docs: crear ADRs y guía de arquitectura y migraciones
Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>pull/1/head
parent
8b701e9435
commit
ce223a2955
@ -0,0 +1,23 @@
|
|||||||
|
# Documentación del Proyecto
|
||||||
|
|
||||||
|
Este directorio contiene documentación técnica viva, orientada a:
|
||||||
|
- Entender la arquitectura y los flujos principales.
|
||||||
|
- Operar el sistema (variables de entorno, métricas, schedulers).
|
||||||
|
- Mapear la cobertura de tests.
|
||||||
|
- Guías prácticas (how-to) para extender funcionalidades con seguridad.
|
||||||
|
- Decisiones de arquitectura (ADRs) y su motivación.
|
||||||
|
|
||||||
|
Índice recomendado:
|
||||||
|
- overview.md — visión general y flujos clave.
|
||||||
|
- architecture.md — responsabilidades por módulo y dependencias.
|
||||||
|
- database.md — esquema funcional, PRAGMAs y migraciones.
|
||||||
|
- operations.md — operación y configuración (env, métricas, schedulers).
|
||||||
|
- tests-map.md — qué cubre cada suite y huecos de cobertura.
|
||||||
|
- how-to/
|
||||||
|
- adding-command.md
|
||||||
|
- adding-migration.md
|
||||||
|
- adjusting-group-sync.md
|
||||||
|
- adding-env.md
|
||||||
|
- adr/
|
||||||
|
- 0001-wal.md
|
||||||
|
- 0002-up-only-migrations.md
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
# 0001 — Activar WAL en SQLite
|
||||||
|
|
||||||
|
Estado
|
||||||
|
- Aceptada
|
||||||
|
|
||||||
|
Contexto
|
||||||
|
- El servicio escribe y lee con frecuencia; necesitamos concurrencia razonable sin introducir un servidor externo.
|
||||||
|
|
||||||
|
Decisión
|
||||||
|
- Activar `PRAGMA journal_mode = WAL`, `PRAGMA synchronous = NORMAL`, `PRAGMA busy_timeout = 5000` y `PRAGMA wal_autocheckpoint = 1000`.
|
||||||
|
|
||||||
|
Consecuencias
|
||||||
|
- Mejora de concurrencia lectura/escritura.
|
||||||
|
- Posible crecimiento de archivos WAL hasta checkpoint; mitigado con autocheckpoint.
|
||||||
|
- Requiere revisar compatibilidad con entornos que no soporten WAL (SQLite puede devolver otro modo).
|
||||||
|
|
||||||
|
Alternativas
|
||||||
|
- DELETE journal (peor concurrencia).
|
||||||
|
- Migrar a otro motor (más complejidad operativa).
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
# 0002 — Migraciones up-only con checksums
|
||||||
|
|
||||||
|
Estado
|
||||||
|
- Aceptada
|
||||||
|
|
||||||
|
Contexto
|
||||||
|
- El repositorio usa SQLite embebido y despliegues sencillos; las revertencias complejas son raras pero el control de integridad del esquema es esencial.
|
||||||
|
|
||||||
|
Decisión
|
||||||
|
- Mantener migraciones “up-only” registradas en `src/db/migrations/index.ts` con `checksum` estático y `version` incremental.
|
||||||
|
- Evitar `down`; para correcciones, introducir nuevas migraciones.
|
||||||
|
|
||||||
|
Consecuencias
|
||||||
|
- Simplicidad operativa y de test.
|
||||||
|
- Reversiones requieren una migración correctiva.
|
||||||
|
- Necesidad de disciplina en pruebas de migraciones en memoria.
|
||||||
|
|
||||||
|
Alternativas
|
||||||
|
- Framework de migraciones con up/down completo (más complejidad).
|
||||||
|
- Esquemas generados ad-hoc (menos trazabilidad).
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
# ADRs (Architecture Decision Records)
|
||||||
|
|
||||||
|
Propósito
|
||||||
|
- Registrar decisiones técnicas significativas, su contexto y consecuencias.
|
||||||
|
- Evitar debates cíclicos y documentar por qué se eligió una opción.
|
||||||
|
|
||||||
|
Formato sugerido
|
||||||
|
- Título y número incremental.
|
||||||
|
- Estado: aceptada/propuesta/superseded.
|
||||||
|
- Contexto → Decisión → Consecuencias → Alternativas consideradas.
|
||||||
|
|
||||||
|
ADRs existentes
|
||||||
|
- 0001-wal.md — Modo WAL en SQLite.
|
||||||
|
- 0002-up-only-migrations.md — Migraciones solo “up” con checksums.
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
# Arquitectura y responsabilidades
|
||||||
|
|
||||||
|
Módulos principales
|
||||||
|
- src/server.ts
|
||||||
|
- Expone endpoints (webhook, /metrics), valida entorno, lanza migraciones y arranque.
|
||||||
|
- Extrae texto de mensajes con lógica tolerante a formatos (texto/caption).
|
||||||
|
- src/db.ts
|
||||||
|
- Abre la base de datos (data/…), aplica PRAGMAs por defecto y expone helpers.
|
||||||
|
- initializeDatabase() ejecuta migraciones up-only.
|
||||||
|
- src/db/migrations/index.ts
|
||||||
|
- Registro de migraciones con versión, nombre, checksum y función up.
|
||||||
|
- Helpers para inspección del esquema (tableHasColumn).
|
||||||
|
|
||||||
|
Servicios (src/services)
|
||||||
|
- command.ts: orquesta el manejo de comandos. Entrada: { sender, groupId, message, mentions }.
|
||||||
|
- contacts.ts: resolución de nombres de contactos vía Evolution API con caché en memoria y TTL.
|
||||||
|
- group-sync.ts: sincronización de grupos y miembros, cachés en memoria, schedulers configurables.
|
||||||
|
- identity.ts: gestión de alias ↔ user_id real; caché en memoria y tabla user_aliases.
|
||||||
|
- maintenance.ts: limpieza programada de miembros inactivos según retención.
|
||||||
|
- metrics.ts: contadores y gauges in-memory con render a Prometheus o JSON.
|
||||||
|
- rate-limit.ts: token bucket por usuario, con burst, refill y cooldown de notificación.
|
||||||
|
- reminders.ts: recordatorios según preferencias (zona horaria, frecuencia, hora).
|
||||||
|
- response-queue.ts: cola de respuestas con intentos, backoff y limpieza.
|
||||||
|
- webhook-manager.ts: configuración de webhooks salientes (si aplica).
|
||||||
|
|
||||||
|
Utilidades (src/utils)
|
||||||
|
- whatsapp.ts: normalización de IDs, helpers para distinguir usuario/grupo.
|
||||||
|
- formatting.ts: utilidades de representación (IDs, fechas abreviadas, etc.).
|
||||||
|
|
||||||
|
Tareas (src/tasks)
|
||||||
|
- model.ts: interfaces Task, TaskAssignment, etc.
|
||||||
|
- service.ts: operaciones de alto nivel sobre tareas (crear, asignar, soltar, etc.).
|
||||||
|
|
||||||
|
Dependencias internas
|
||||||
|
- La mayoría de servicios aceptan/injectan una instancia Database estática configurable para test.
|
||||||
|
- utils no dependen de servicios; servicios pueden usar utils y db.
|
||||||
|
- server.ts invoca servicios y metrics; no debe contener lógica de dominio pesada.
|
||||||
|
|
||||||
|
Puntos de extensión
|
||||||
|
- Nuevos comandos: ver how-to/adding-command.md.
|
||||||
|
- Nuevas tablas/campos: ver how-to/adding-migration.md.
|
||||||
|
- Ajustes de sincronización de grupos/miembros: ver how-to/adjusting-group-sync.md.
|
||||||
|
- Nuevas variables de entorno: ver how-to/adding-env.md.
|
||||||
|
- Nuevas métricas: usar Metrics.inc/set/get y documentar en operations.md.
|
||||||
|
|
||||||
|
Observabilidad y errores
|
||||||
|
- Logging pragmático en operaciones críticas; errores de migración detienen el arranque.
|
||||||
|
- Métricas:
|
||||||
|
- sync_runs_total, contadores de alias resueltos, etc.
|
||||||
|
- Estados de gauges/counters expuestos en /metrics (Prom/JSON).
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
# Base de datos, PRAGMAs y migraciones
|
||||||
|
|
||||||
|
PRAGMAs por defecto (src/db.ts)
|
||||||
|
- busy_timeout = 5000 ms
|
||||||
|
- journal_mode = WAL (si no es soportado, SQLite ajusta)
|
||||||
|
- synchronous = NORMAL
|
||||||
|
- wal_autocheckpoint = 1000
|
||||||
|
- foreign_keys = ON
|
||||||
|
|
||||||
|
Formato de timestamps
|
||||||
|
- Persistencia como 'YYYY-MM-DD HH:MM:SS[.mmm]'.
|
||||||
|
- Uso de strftime('%Y-%m-%d %H:%M:%f', 'now') en inserciones/updates.
|
||||||
|
|
||||||
|
Esquema funcional (resumen)
|
||||||
|
- users
|
||||||
|
- user_id (PK), created_at, updated_at.
|
||||||
|
- user_aliases
|
||||||
|
- alias (PK), user_id (FK → users), source, created_at, updated_at.
|
||||||
|
- groups
|
||||||
|
- id (PK, JID), name, active (boolean), last_verified (timestamp).
|
||||||
|
- 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.
|
||||||
|
- user_preferences
|
||||||
|
- user_id (FK → users), reminder_freq ('daily'|'weekly'|'weekdays'|'off'),
|
||||||
|
reminder_time ('HH:MM' | null), last_reminded_on ('YYYY-MM-DD' | null), updated_at.
|
||||||
|
- tasks
|
||||||
|
- id (PK autoinc), description, due_date ('YYYY-MM-DD' | null), group_id (JID | null),
|
||||||
|
created_by (user_id), created_at.
|
||||||
|
- task_assignments
|
||||||
|
- 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).
|
||||||
|
|
||||||
|
Nota: El detalle exacto está en las migraciones (src/db/migrations). Usa tableHasColumn para detectar columnas en migraciones idempotentes.
|
||||||
|
|
||||||
|
Migraciones
|
||||||
|
- Política up-only con checksum estático por migración.
|
||||||
|
- Migrator.migrateToLatest(instancia, opciones) se invoca en initializeDatabase() y en server.start().
|
||||||
|
- Tests utilizan Database(':memory:') y initializeDatabase(memdb) para asegurar el esquema.
|
||||||
|
|
||||||
|
Integridad y rendimiento
|
||||||
|
- foreign_keys = ON asegura relaciones consistentes.
|
||||||
|
- WAL mejora concurrencia de lectura/escritura.
|
||||||
|
- busy_timeout y synchronous=NORMAL balancean seguridad y rendimiento.
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
# Cómo añadir un nuevo comando
|
||||||
|
|
||||||
|
Objetivo
|
||||||
|
- Incorporar un comando de texto que procese mensajes entrantes y responda por la cola.
|
||||||
|
|
||||||
|
Pasos
|
||||||
|
1) Parseo en CommandService
|
||||||
|
- Ubicación: src/services/command.ts
|
||||||
|
- Añade lógica para detectar el patrón (p.ej., "/t listar", "/t info 0012").
|
||||||
|
- Normaliza IDs con utils/whatsapp.normalizeWhatsAppId cuando corresponda.
|
||||||
|
- Registra métricas si procede (Metrics.inc).
|
||||||
|
|
||||||
|
2) Lógica de dominio
|
||||||
|
- Si afecta a tareas, delega en src/tasks/service.ts.
|
||||||
|
- Asegúrate de crear usuarios con ensureUserExists si se persisten referencias.
|
||||||
|
|
||||||
|
3) Respuesta al usuario
|
||||||
|
- Encola la respuesta en src/services/response-queue.ts con el destinatario adecuado (usuario o grupo).
|
||||||
|
- Incluye metadata JSON si mencionas usuarios (@) para formateo posterior.
|
||||||
|
|
||||||
|
4) Rate limiting y UX
|
||||||
|
- Verifica RateLimiter.checkAndConsume(sender) si el comando puede ser abusado.
|
||||||
|
- Usa RateLimiter.shouldNotify para evitar spam de notificaciones de rate limit.
|
||||||
|
|
||||||
|
5) Tests
|
||||||
|
- Crea una prueba en tests/unit/services/command.<tu-comando>.test.ts
|
||||||
|
- Usa Database(':memory:') + initializeDatabase(memdb) e inyecta CommandService/TaskService.dbInstance.
|
||||||
|
|
||||||
|
6) Documentación
|
||||||
|
- Añade una breve descripción del comando a docs/overview.md (flujos) si es relevante.
|
||||||
|
- Si el comando expone nuevas métricas o env vars, actualiza docs/operations.md.
|
||||||
|
|
||||||
|
Consejos
|
||||||
|
- Mantén CommandService como orquestador; la lógica compleja debe vivir en servicios dedicados.
|
||||||
|
- Usa nombres y mensajes consistentes con el resto de comandos.
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
# Añadir una nueva variable de entorno
|
||||||
|
|
||||||
|
Pasos
|
||||||
|
1) Definir uso y por defecto
|
||||||
|
- Elige un nombre claro (prefijos existentes si aplica, p.ej. GROUP_, RATE_LIMIT_, METRICS_).
|
||||||
|
- Define valor por defecto sensato si procede.
|
||||||
|
|
||||||
|
2) Leer y validar
|
||||||
|
- Lee la variable en el módulo correspondiente.
|
||||||
|
- Si es global u obligatoria, extiende `src/server.ts::validateEnv()` para loggear o fallar si falta.
|
||||||
|
|
||||||
|
3) Documentar
|
||||||
|
- Añade la variable a docs/operations.md con:
|
||||||
|
- significado, rango válido, default y efectos.
|
||||||
|
|
||||||
|
4) Tests
|
||||||
|
- Cubre ramas con valores válidos/ inválidos y ausencia de la variable.
|
||||||
|
- Evita efectos secundarios en test (p.ej., schedulers no deben arrancar).
|
||||||
|
|
||||||
|
Consejos
|
||||||
|
- Normaliza formatos (booleans como 'true'/'1'/'yes').
|
||||||
|
- Mantén consistencia en nombres y semánticas con variables similares.
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
# Cómo añadir una migración
|
||||||
|
|
||||||
|
Contexto
|
||||||
|
- Migraciones up-only con checksum estático y función `up(db)`.
|
||||||
|
|
||||||
|
Pasos
|
||||||
|
1) Crear migración
|
||||||
|
- Edita src/db/migrations/index.ts y añade una entrada `Migration` con:
|
||||||
|
- version (número incremental),
|
||||||
|
- name (descriptivo),
|
||||||
|
- checksum (string calculado una vez),
|
||||||
|
- up: (db) => { ... } con SQL idempotente cuando sea posible (usa helpers como tableHasColumn).
|
||||||
|
|
||||||
|
2) SQL y convenciones
|
||||||
|
- Timestamps como 'YYYY-MM-DD HH:MM:SS[.mmm]' con strftime.
|
||||||
|
- FOREIGN KEYs explícitas y `PRAGMA foreign_keys = ON`.
|
||||||
|
- Usa `ON CONFLICT` para upserts cuando aplique.
|
||||||
|
|
||||||
|
3) Pruebas
|
||||||
|
- En un test, crea `const memdb = new Database(':memory:')` y ejecuta `initializeDatabase(memdb)`.
|
||||||
|
- Valida que la tabla/columna existe y que el esquema es el esperado.
|
||||||
|
|
||||||
|
4) Despliegue
|
||||||
|
- El arranque (`server.start`) invoca `Migrator.migrateToLatest`. No necesitas pasos manuales.
|
||||||
|
|
||||||
|
Notas
|
||||||
|
- No hay “down”; si necesitas revertir, crea una nueva migración correctiva.
|
||||||
|
- Evita cambios destructivos sin plan de migración de datos.
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
# Ajustar la sincronización de grupos y miembros
|
||||||
|
|
||||||
|
Configuración por entorno
|
||||||
|
- GROUP_SYNC_INTERVAL_MS: intervalo para refrescar lista de grupos activos.
|
||||||
|
- GROUP_MEMBERS_SYNC_INTERVAL_MS: intervalo para refrescar miembros de grupos activos.
|
||||||
|
- WHATSAPP_COMMUNITY_ID: comunidad a sincronizar desde Evolution API.
|
||||||
|
|
||||||
|
Operaciones comunes
|
||||||
|
- Forzar refresco de caché de grupos:
|
||||||
|
- Llama `GroupSyncService.refreshActiveGroupsCache()` tras cambios relevantes.
|
||||||
|
- Sincronizar miembros de un grupo concreto:
|
||||||
|
- `await GroupSyncService.syncMembersForGroup(groupId)`.
|
||||||
|
- Comprobar frescura de snapshot:
|
||||||
|
- `GroupSyncService.isSnapshotFresh(groupId)` en función de `MAX_SNAPSHOT_AGE_MS`.
|
||||||
|
|
||||||
|
Puntos de extensión
|
||||||
|
- API de origen:
|
||||||
|
- Implementa/ajusta `(GroupSyncService as any).fetchGroupMembersFromAPI(groupId)` si se mockea/inyecta.
|
||||||
|
- Reconciliación:
|
||||||
|
- `reconcileGroupMembers(groupId, snapshot)` espera objetos `{ userId, isAdmin }`.
|
||||||
|
|
||||||
|
Buenas prácticas
|
||||||
|
- No correr schedulers en test (el servicio ya lo evita).
|
||||||
|
- Usa transacciones al actualizar tablas de grupos/miembros (ya integrado en upsert).
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
# Operación y configuración
|
||||||
|
|
||||||
|
Variables de entorno (principales)
|
||||||
|
- EVOLUTION_API_URL: base URL de Evolution API.
|
||||||
|
- EVOLUTION_API_INSTANCE: nombre/ID de instancia en Evolution.
|
||||||
|
- EVOLUTION_API_KEY: API key para peticiones salientes (contacts, etc.).
|
||||||
|
- WEBHOOK_URL: URL pública del webhook (puede usarse para auto-registro/config).
|
||||||
|
- WHATSAPP_COMMUNITY_ID: comunidad cuyos grupos se sincronizan.
|
||||||
|
- PORT: puerto HTTP (por defecto 3007).
|
||||||
|
- NODE_ENV: 'development' | 'test' | 'production'.
|
||||||
|
- METRICS_ENABLED: 'true'|'false'|'1'|'0' (por defecto habilitado salvo en test).
|
||||||
|
- RATE_LIMIT_PER_MIN: tokens por minuto por usuario (default 15).
|
||||||
|
- RATE_LIMIT_BURST: capacidad del bucket (default = RATE_LIMIT_PER_MIN).
|
||||||
|
- GROUP_SYNC_INTERVAL_MS: intervalo de sync de grupos (default 24h; min 10s en dev).
|
||||||
|
- GROUP_MEMBERS_SYNC_INTERVAL_MS: intervalo de sync de miembros (default 6h; min 10s en dev).
|
||||||
|
- GROUP_MEMBERS_INACTIVE_RETENTION_DAYS: días para borrar miembros inactivos (default 180).
|
||||||
|
- TZ: zona horaria para recordatorios (default Europe/Madrid).
|
||||||
|
|
||||||
|
Endpoints operativos
|
||||||
|
- GET /metrics
|
||||||
|
- 200 si Metrics.enabled() y formato Prometheus por defecto.
|
||||||
|
- 404 si métricas deshabilitadas; 405 si método no permitido.
|
||||||
|
|
||||||
|
Arranque y servicios
|
||||||
|
- src/server.ts::start()
|
||||||
|
- Valida entorno (logs de variables presentes/faltantes).
|
||||||
|
- Aplica migraciones up-only.
|
||||||
|
- Inicia HTTP y (según entorno) schedulers.
|
||||||
|
|
||||||
|
Schedulers
|
||||||
|
- GroupSyncService.startGroupsScheduler() y .startMembersScheduler()
|
||||||
|
- Saltan en test; intervalos controlados por env.
|
||||||
|
- RemindersService.start()
|
||||||
|
- Tick cada minuto, filtra por zona horaria y preferencias.
|
||||||
|
- MaintenanceService.start()
|
||||||
|
- Tarea diaria; borra miembros inactivos según retención.
|
||||||
|
|
||||||
|
Datos y backups
|
||||||
|
- Data path: data/tasks.db (por defecto).
|
||||||
|
- Migraciones con backup opcional (withBackup=false por defecto en initializeDatabase).
|
||||||
|
- Recomendación: planificar copia de seguridad periódica del directorio data/ y retención externa.
|
||||||
|
|
||||||
|
Métricas de referencia
|
||||||
|
- sync_runs_total, identity_alias_resolved_total, contadores/gauges específicos de colas y limpieza.
|
||||||
|
- Añadir nuevas métricas usando Metrics.inc/set y documentarlas aquí.
|
||||||
|
|
||||||
|
Buenas prácticas
|
||||||
|
- No arrancar schedulers en test salvo que FORCE_SCHEDULERS='true'.
|
||||||
|
- Validar nuevas env en src/server.ts::validateEnv() y documentarlas aquí.
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
# Visión general
|
||||||
|
|
||||||
|
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.
|
||||||
|
- Recordatorios a usuarios según preferencias.
|
||||||
|
- Cola de respuestas con reintentos/backoff.
|
||||||
|
- Métricas y health para operación.
|
||||||
|
|
||||||
|
Flujos principales
|
||||||
|
1) Mensaje entrante
|
||||||
|
- src/server.ts recibe webhook → extrae texto → delega en src/services/command.ts (CommandService).
|
||||||
|
- CommandService puede interactuar con src/tasks/service.ts (crear/actualizar/consultar tareas) y encolar respuestas en src/services/response-queue.ts.
|
||||||
|
2) Schedulers
|
||||||
|
- src/services/group-sync.ts sincroniza grupos activos y sus miembros.
|
||||||
|
- src/services/reminders.ts consulta preferencias y encola recordatorios.
|
||||||
|
- src/services/maintenance.ts aplica retención de miembros inactivos.
|
||||||
|
3) Persistencia
|
||||||
|
- src/db.ts abre SQLite (data/tasks.db por defecto), aplica PRAGMAs (WAL, FK, etc.) y migraciones (src/db/migrations).
|
||||||
|
4) Observabilidad
|
||||||
|
- src/services/metrics.ts expone contadores/gauges; /metrics en src/server.ts.
|
||||||
|
|
||||||
|
Glosario
|
||||||
|
- JID: identificador completo de WhatsApp (p.ej., 12345@s.whatsapp.net, 999@g.us).
|
||||||
|
- user_id: número normalizado (solo dígitos) sin dominio.
|
||||||
|
- groupId: JID de grupo, termina en @g.us.
|
||||||
|
- Alias: identificador alternativo que mapea a user_id real (src/services/identity.ts).
|
||||||
|
|
||||||
|
Mapa rápido
|
||||||
|
- Entrada HTTP: src/server.ts
|
||||||
|
- DB y migraciones: src/db.ts, src/db/migrations/index.ts
|
||||||
|
- Servicios: src/services/*.ts (command, contacts, group-sync, identity, maintenance, metrics, rate-limit, reminders, response-queue, webhook-manager)
|
||||||
|
- Utilidades: src/utils/*.ts (whatsapp, formatting, etc.)
|
||||||
|
- Tareas: src/tasks/*.ts (modelo y servicio)
|
||||||
|
- Tests: tests/unit/**/*.test.ts
|
||||||
|
|
||||||
|
Siguientes lecturas
|
||||||
|
- architecture.md para responsabilidades por módulo.
|
||||||
|
- database.md para entender tablas y PRAGMAs.
|
||||||
|
- operations.md para variables de entorno, métricas y schedulers.
|
||||||
|
- tests-map.md para ver qué se valida y dónde extender cobertura.
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
# Mapa de tests
|
||||||
|
|
||||||
|
Cobertura actual (resumen)
|
||||||
|
- tests/unit/server.test.ts
|
||||||
|
- Valida flujo de WebhookServer: health/metrics, manejo de payloads, normalización básica y encolado simulado.
|
||||||
|
- tests/unit/services/cleanup-inactive.test.ts
|
||||||
|
- Verifica MaintenanceService.cleanupInactiveMembersOnce con fechas umbral.
|
||||||
|
- tests/unit/services/command.claim-unassign.test.ts
|
||||||
|
- Flujo de tomar/soltar tareas a través de CommandService y TaskService, creando datos en memoria.
|
||||||
|
- tests/unit/services/command.date-parsing.test.ts
|
||||||
|
- Parsing de fechas y helpers relacionados con zona horaria para comandos.
|
||||||
|
- tests/unit/services/command.reminders-config.test.ts
|
||||||
|
- Configuración de recordatorios por comando y persistencia en user_preferences.
|
||||||
|
- tests/unit/services/group-sync.members.test.ts
|
||||||
|
- Reconciliación de miembros de grupos (added/updated/deactivated) y timestamps.
|
||||||
|
- tests/unit/services/group-sync.scheduler.test.ts
|
||||||
|
- Semántica de shouldSync, intervalos y control de schedulers.
|
||||||
|
- tests/unit/services/metrics-health.test.ts
|
||||||
|
- Habilitación/inhabilitación de métricas y formato de salida.
|
||||||
|
- tests/unit/services/reminders.test.ts
|
||||||
|
- Lógica de recordatorios: ventanas horarias, frecuencias y encolado.
|
||||||
|
- tests/unit/services/response-queue.cleanup.test.ts
|
||||||
|
- Limpieza de cola de respuestas según políticas temporales.
|
||||||
|
- tests/unit/services/response-queue.test.ts
|
||||||
|
- Reintentos y backoff de la cola de respuestas.
|
||||||
|
|
||||||
|
Huecos de cobertura sugeridos
|
||||||
|
- contacts.ts: errores de red, timeouts y caché negativa.
|
||||||
|
- identity.ts: interacción entre caché en memoria y tabla user_aliases (miss/hit/actualización).
|
||||||
|
- rate-limit.ts: escenarios de burst y cooldown de notificación.
|
||||||
|
- webhook-manager.ts: configuración y comportamiento condicional por eventos.
|
||||||
|
- tasks/service.ts: rutas menos comunes (edición, vencimientos complejos).
|
||||||
Loading…
Reference in New Issue