Traducción. Autoritativo: ../../standards/notifications.md.
Catálogo de canales (core.notification_channels, paramétrico)
email · in_app · webhook · push · sms (adaptador en F1b tras el ADR del proveedor) · whatsapp (F2) ·
live_activity (F2). La fila del canal y el NotificationChannelPort existen desde el día 1 aunque el
adaptador llegue después.
Resolución en cascada (niveles 0–3 + destinatario)
resolveChannels(evento, tenant, módulo, destinatario) — función PURA en packages/core, con
cobertura unitaria completa:
- Plataforma: el adaptador existe y está operativo (flag operacional de Vercel Flags, espejado en
messaging.platform_channel_status). - Tenant: canal activo para este tenant (entitlement + credenciales o dominio de envío configurados)
—
messaging.tenant_channel_settings. - Módulo: canal habilitado para el módulo emisor en este tenant —
messaging.module_channel_settings. - Tipo de evento: entrada de enrutamiento (canales, plantilla por canal, categoría) —
messaging.event_channel_routing.
messaging.suppressions ∧
centro de preferencias ∧ (solo marketing: quiet hours + frequency caps).
Resultado: un job por canal resuelto en notif.{canal}.{carril} (standards/jobs.md).
Categorías y controles del destinatario
- Categoría por enrutamiento de evento:
transactional | marketing | product. El transaccional NO es opt-out (solo lo detiene una supresión por rebote duro). - Centro de preferencias del member: por canal Y por categoría. Quiet hours: default por tenant, override por campaña. Frequency caps: solo marketing.
Trazabilidad (end to end)
- Cadena: evento de origen → regla o campaña → job de notificación →
messaging.sends→messaging.send_status_history(queued→sent→delivered→opened→clicked / bounced / complained / failed) → webhooks salientes. Todo unido porcorrelation_id+origin_event_id. - Ingesta de estados por webhooks del proveedor (hoy Resend); cada canal futuro trae su adaptador de estados.
- Los rebotes duros y las quejas escriben automáticamente en
messaging.suppressions. CADA envío verifica supresiones — sin excepciones.