Arquitectura End-to-End · 2026-06-02

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.

Fase 1: Backend
3
Capas de entrega (historial · SSE · push)
6
Eventos de dominio con regla
3
Tablas nuevas (migración 044)

Flujo de un evento

Los controllers sólo emiten un evento de dominio; no saben nada de notificaciones. El dispatcher es el único suscriptor.

01
emit
Un controller emite p.ej. task.assigned en el bus.
02
resolve
La regla resuelve los destinatarios (asignado, personal del hotel).
03
history
Se escribe la fila en notifications — fuente de verdad.
04
SSE
Se empuja en vivo a las pestañas abiertas.
05
push
Si las preferencias lo permiten, se envía Web Push a cada dispositivo.

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.

EventoOrigenDestinatarios
task.assignedtasks.controller (create / assign)El asignado (≠ actor)
task.status_changedtasks.controller (changeStatus / verify)El asignado / quien completó
reservation.createdreservations.controllerPersonal del hotel
experience.requestedexperience-requests.controllerPersonal del hotel
experience.booked(reservas de experiencia)Personal del hotel
checkin.requestedcheckin-requests.controller (completado)Personal del hotel

Endpoints

Método / RutaDescripción
GET /notificationsHistorial paginado (fuente de verdad en cada carga)
GET /notifications/unread-countConteo de no leídas
GET /notifications/streamSSE: campana en vivo mientras la pestaña está abierta
POST /devicesRegistrar/actualizar suscripción push (upsert por endpoint)
GET /devicesListar dispositivos del usuario
DELETE /devices/:idEliminar dispositivo (logout / desactivar push)

Modelo de datos

TablaMigraciónRol
notifications037 (reusada)Historial in-app — fuente de verdad
user_devices044Suscripciones push (webpush ahora, fcm después)
notification_deliveries044Auditoría de entrega ("¿llegó el push?")
notification_preferences044Toggles 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.