Notificaciones: Push + Historial
Sistema de notificaciones para enterprise, client y webcheckin. Un bus de eventos genérico convierte eventos de dominio (tarea asignada, reserva, check-in) en historial duradero, actualizaciones en vivo (SSE) y push (Web Push / VAPID). El historial es la fuente de verdad: nada se pierde si el push falla o está desactivado.
Flujo de un evento
Los controllers sólo emiten un evento de dominio; no saben nada de notificaciones. El dispatcher es el único suscriptor.
task.assigned en el bus.notifications — fuente de verdad.Eventos de dominio
Catálogo en src/events/domain-events.ts; reglas en
src/notifications/rules.ts. Añadir una notificación =
añadir un evento + una regla. Los controllers no cambian su lógica.
| Evento | Origen | Destinatarios |
|---|---|---|
| task.assigned | tasks.controller (create / assign) | El asignado (≠ actor) |
| task.status_changed | tasks.controller (changeStatus / verify) | El asignado / quien completó |
| reservation.created | reservations.controller | Personal del hotel |
| experience.requested | experience-requests.controller | Personal del hotel |
| experience.booked | (reservas de experiencia) | Personal del hotel |
| checkin.requested | checkin-requests.controller (completado) | Personal del hotel |
Endpoints
| Método / Ruta | Descripción |
|---|---|
GET /notifications | Historial paginado (fuente de verdad en cada carga) |
GET /notifications/unread-count | Conteo de no leídas |
GET /notifications/stream | SSE: campana en vivo mientras la pestaña está abierta |
POST /devices | Registrar/actualizar suscripción push (upsert por endpoint) |
GET /devices | Listar dispositivos del usuario |
DELETE /devices/:id | Eliminar dispositivo (logout / desactivar push) |
Modelo de datos
| Tabla | Migración | Rol |
|---|---|---|
notifications | 037 (reusada) | Historial in-app — fuente de verdad |
user_devices | 044 | Suscripciones push (webpush ahora, fcm después) |
notification_deliveries | 044 | Auditoría de entrega ("¿llegó el push?") |
notification_preferences | 044 | Toggles push/in-app por usuario y categoría |
Transporte de push
Abstracción PushProvider en src/push/providers/.
Por defecto Web Push (VAPID) — self-hosted, sin Firebase,
acorde al despliegue VPS + Komodo. FcmProvider es un stub
intercambiable para futuras apps nativas. Sin claves VAPID el push queda
desactivado y el historial + SSE siguen funcionando.
Claves: VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY,
VAPID_SUBJECT — generar con
npx web-push generate-vapid-keys.