Implementar un centro de notificaciones en tiempo real en el panel /admin de CULTIVA Platform usando Supabase Realtime (canal nativo, sin dependencias externas). Los eventos de negocio clave — registro de cliente, compra de skill, error de agente e inactividad — se persistirán en una nueva tabla notifications y se renderizarán en un panel deslizante (bell icon + badge) integrado en el layout del admin. Cada notificación es persistente, con estado leído/no leído recuperable tras recarga. Entregable en 4 fases independientes, cada una mergeable por separado, con una cobertura de tests del 80 %+.
- 4 tipos de eventos: nuevo cliente, skill comprada (webhook LS), error de agente, cliente inactivo +7 días.
- Bell icon en header del admin con badge de contador de no leídas.
- Panel deslizante con lista, marcar como leída, filtrar por tipo.
- Persistencia en Supabase: tabla notifications con estado read/unread.
- No romper rutas ni layout existentes en src/app/admin/.
- Sin librerías de terceros para el canal real-time (solo Supabase Realtime nativo).
- Máximo 2 sprints × 2 semanas para 1 developer.
| Tipo | Archivo / Recurso | Descripción |
|---|---|---|
| Nuevo | supabase/migrations/005_notifications.sql | Tabla notifications con RLS, índices y políticas por rol admin. |
| Nuevo | src/lib/notifications/types.ts | Tipos TypeScript: NotificationType, Notification, NotificationPayload. |
| Nuevo | src/lib/notifications/service.ts | CRUD de notificaciones: create, markRead, markAllRead, getUnreadCount. |
| Nuevo | src/hooks/useNotifications.ts | Hook React: suscripción Supabase Realtime, estado local, hydration SSR. |
| Nuevo | src/components/admin/NotificationBell.tsx | Icono campana + badge animado de contador de no leídas. |
| Nuevo | src/components/admin/NotificationPanel.tsx | Panel deslizante (slide-over): lista, filtros por tipo, marcar leída/todas. |
| Nuevo | src/app/api/notifications/route.ts | API Route: GET (list/paginar), PATCH (marcar leída), POST (crear interna). |
| Nuevo | src/app/api/webhooks/lemon-squeezy/route.ts | Handler webhook LS: valida firma, crea notificación skill_purchased. |
| Nuevo | src/app/api/cron/inactive-clients/route.ts | Cron diario (Vercel Cron): detecta clientes +7 días inactivos y emite notificaciones. |
| Modifica | src/app/admin/layout.tsx | Inyectar NotificationBell + NotificationPanel en el header del admin. |
| Extiende | vercel.json | Añadir cron job 0 9 * * * apuntando a /api/cron/inactive-clients. |
- service.createNotification
- service.markAsRead
- service.getUnreadCount
- Webhook HMAC validation
- Cron deduplicación
- Hook: Realtime INSERT
- API GET paginación
- API PATCH marcar leída
- Webhook LS end-to-end
- Cron → DB inactive
- Bell badge aparece en admin
- Panel se abre al click
- Filtro por tipo funciona
- Marcar todas leídas → badge 0
- Persiste tras recarga
- Bell badge muestra el contador correcto de no leídas al entrar al admin.
- Una compra en Lemon Squeezy genera una notificación visible en <3 segundos.
- Las notificaciones persisten y se recuperan correctamente al recargar la página.
- Filtros por tipo (NEW_CLIENT / SKILL_PURCHASED / AGENT_ERROR / CLIENT_INACTIVE) funcionan sin recarga.
- El cron diario detecta clientes inactivos sin generar duplicados.
- Las rutas existentes en /admin no se ven afectadas (smoke test de todas las páginas).
- Cobertura de tests ≥ 80 % en service.ts y useNotifications.ts.
- Un developer puede empezar a codificar el lunes sin reuniones adicionales.