Autenticación
La API soporta dos formas de autenticarse, seleccionadas por el mismo guard según qué credencial venga en el pedido.
JWT (para el frontend)
Sección titulada «JWT (para el frontend)»POST /auth/login devuelve un token que se manda como Authorization: Bearer <token>. Vence según JWT_EXPIRATION (default 24h). También hay login con Google OAuth (GET /auth/google).
API Key (para integraciones externas)
Sección titulada «API Key (para integraciones externas)»Se crea desde POST /auth/api-keys (requiere plan Pro, o ser admin) y se manda en el header x-api-key. Pensada para que un servicio externo pueda crear sesiones, enviar mensajes o programar recordatorios sin loguearse como usuario.
El guard híbrido
Sección titulada «El guard híbrido»Los endpoints de negocio (sessions, templates, schedules) están protegidos con @Hybrid() + HybridAuthGuard: aceptan cualquiera de las dos credenciales indistintamente. Los endpoints de cuenta (/auth/profile, /auth/api-keys) exigen JWT específicamente (@JwtOnly()), porque no tendría sentido generar una API Key usando otra API Key.
Roles y admin
Sección titulada «Roles y admin»Cada usuario tiene un role: "admin" o "user".
- El primer usuario que se registra en la instancia se vuelve admin automáticamente.
- Un admin no tiene límites de plan: bypassea cuotas de mensajes, límite de sesiones, límite de templates y el gate de Pro plan para API Keys. Esto está resuelto centralizadamente con un helper
isAdmin(user)que se llama al principio de cada guard/chequeo de límite — no hay que acordarse de repetirlo por endpoint nuevo, pero si agregás un chequeo de plan nuevo, agregá el bypass ahí también.
Ownership
Sección titulada «Ownership»Todos los recursos (sessions, templates, schedules) están scopeados al usuario dueño. Los repositorios filtran por userId en la query, no solo en el controller — así un ID adivinado de otro usuario nunca matchea, en vez de depender únicamente de una validación en la capa de servicio.