# `modules/identity` `identity` es el runtime nuevo de autenticación, sesión y acceso por memberships del ERP. ## Documentación canónica relacionada - API de autenticación: [`../../docs/architecture/identity-auth-api.md`](../../docs/architecture/identity-auth-api.md) - Contexto tenant y middlewares públicos: [`../../docs/architecture/tenant-context.md`](../../docs/architecture/tenant-context.md) - Estado de migración: [`../../docs/architecture/identity-migration-status.md`](../../docs/architecture/identity-migration-status.md) ## Responsabilidades Gestiona: - `Account` - self-service de `Account` - login - refresh - logout - session - `RefreshToken` - `CompanyMembership` - acceso `account-company` - roles/permisos futuros No gestiona: - la ficha operativa completa de empresa - `companySlug` en auth - el tenant dentro del access token - upload físico de avatar - autorización global de superadmin, porque no existe todavía un mecanismo runtime inequívoco ## Endpoints activos ```http GET /identity/account PATCH /identity/account POST /identity/account/change-password POST /identity/auth/login POST /identity/auth/refresh POST /identity/auth/logout GET /identity/auth/session ``` El endpoint para companies accesibles es: ```http GET /companies/available ``` ## Account self-service `/identity/account` representa siempre la identidad global del usuario autenticado. No requiere: - `X-Company-Id` - company activa - contexto tenant Sí requiere: - access token válido - cuenta autenticable Campos editables en V1: - `name` - `email` - `avatar_url` - `language_code` Reglas actuales: - el cambio de email es inmediato y sin verificación adicional - `avatar_url` es una referencia externa; `identity` no implementa subida de archivos - la UI web de `/account` no expone todavía edición de avatar porque falta una infraestructura real de upload - cambio de contraseña exige `current_password` - cambio de contraseña revoca todos los refresh tokens persistidos de la cuenta - los access tokens ya emitidos siguen siendo válidos hasta expirar, porque hoy no existe un subsistema de invalidación inmediata de access tokens ### UX actual de `/account` La pantalla web `/account` se presenta como un editor focalizado de self-service para el usuario autenticado. Contenido visible actual: - información personal: `name`, `email`, `language_code` - modo `app-fullscreen`, sin sidebar principal - contenido centrado mediante `RdxPageContainer` y compuesto con `RdxPageContent` - seguridad mediante dialog para cambio de contraseña - cierre de sesión reutilizando el flujo de logout existente Pendientes explícitos: - upload real de avatar - enable/disable global administrable por un actor autorizado - administración global de memberships por compañía ## Estado global de Account `Account.status` representa el estado global de autenticación de la identidad: - `active` - `disabled` - `pending_verification` Semántica runtime actual: - `active` -> puede autenticarse - `disabled` -> no puede login, refresh, session ni self-service - `pending_verification` -> hoy también queda fuera de `canAuthenticate()` Esto no debe mezclarse con: - membership status - company status - accesibilidad tenant ## Administración global pendiente El dominio ya soporta: - `Account.enable()` - `Account.disable()` Sin embargo, el runtime actual no expone todavía endpoints HTTP administrativos para enable/disable global porque no existe un mecanismo inequívoco y cableado de "administrador global del ERP" en el módulo nuevo. Estado actual: - contratos de self-service completados - `common/dto/account` reutilizado y completado - `common/dto/company-users` sigue pendiente válido para futura administración por empresa - enable/disable global queda documentado como pendiente hasta cerrar la autorización global real Ese endpoint pertenece al flujo actual. Las reglas detalladas del flujo y los endpoints no válidos se mantienen en la documentación de arquitectura. ## Access token El access token contiene solo identidad de cuenta. Shape actual: ```ts { accountId: string; email: string; } ``` Las restricciones detalladas sobre claims y contexto tenant se documentan en `tenant-context.md`. ## Middlewares públicos Los contratos públicos de `requireIdentityAuthenticated(params)` y `requireIdentityTenant(params)` se documentan en `tenant-context.md`. En la V1 actual, `requireIdentityTenant(params)` y `companyAccess` resuelven membership activa y company activa. No debe interpretarse como enforcement de permisos granulares o RBAC. Código backend nuevo no debe usar: - `@erp/auth/api` - `mockUser` - `requireAuthenticated` legacy - `requireCompanyContext` legacy ## Servicios públicos `identity` expone el servicio: ```txt identity:general ``` Con acceso a `companyAccess` para casos como: ```ts canAccessCompany(...) findAccessibleCompanyIds(...) ``` Responsabilidad: - `identity` decide qué `companyId` puede usar una cuenta según memberships activas. - no devuelve la ficha completa de empresa. - no decide todavía permisos granulares por operación. Esto representa membership activa y accesibilidad tenant, no permisos por operación. ## Tenant context `requireIdentityTenant(params)` compone: - `identity:general.companyAccess` - `companies:general.finder` La validación esperada, la semántica de errores y el shape mínimo de `req.user` se mantienen en `tenant-context.md`. Ejemplo actual relevante: ```http PATCH /companies/current ``` usa membership activa y contexto tenant válido, no `identity:companies:update`. ## Reglas de mantenimiento - Backend nuevo: usar `@erp/identity/api`. - No duplicar aquí contratos que ya viven en documentación de arquitectura. - No borrar `modules/auth` mientras existan consumidores legacy reales. - `modules/supplier` sigue pendiente de migración si continúa usando el runtime legacy.