Uecko_ERP/docs/architecture/identity-backend-architecture.md
2026-07-06 14:04:47 +02:00

2.5 KiB

Identity Backend Architecture

Objetivo del módulo identity

identity sustituye progresivamente al módulo legacy auth.

Responsabilidades actuales:

  • cuentas autenticables
  • login/password
  • access token
  • refresh token rotado
  • logout
  • sesión actual
  • memberships
  • validación de acceso account-company
  • base para roles/permisos futuros

Dominio actual

Agregados y conceptos relevantes:

Account
RefreshToken
CompanyMembership
Role

Company funcional no pertenece a identity; vive en modules/companies.

Seguridad

Servicios definidos:

IPasswordHasher
IAccessTokenIssuer
IAccessTokenVerifier
IRefreshTokenGenerator
IRefreshTokenHasher

Decisiones vigentes:

  • password hashing con bcrypt
  • access token JWT con accountId y email
  • refresh token aleatorio
  • refresh token persistido como hash
  • no incluir companyId, companySlug, roles ni permisos en access token

Builders públicos

identity expone desde @erp/identity/api:

requireIdentityAuthenticated(params: StartParams): RequestHandler[];
requireIdentityTenant(params: StartParams): RequestHandler[];

Uso correcto:

import { requireIdentityTenant } from "@erp/identity/api";

router.use(...requireIdentityTenant(params));
import { requireIdentityAuthenticated } from "@erp/identity/api";

router.use(...requireIdentityAuthenticated(params));

req.user

Shape mínimo esperado:

{
  userId: UniqueID;
  email?: EmailAddress;
  companyId?: UniqueID;
  roles?: string[];
}

req.user.companyId solo se debe poblar cuando el middleware tenant valida correctamente la request.

No añadir:

  • companySlug
  • company
  • permissions enriquecidos
  • companyStatus

Tenant validation

requireIdentityTenant(params) ya no es solo validación sintáctica.

Valida:

  1. token válido
  2. account autenticable
  3. X-Company-Id presente
  4. UUID válido
  5. membership active
  6. company active

Relación con companies

  • identity resuelve membership y accesibilidad
  • companies resuelve la ficha operativa de empresa
  • no introducir dependencia identity -> companies

Si un consumidor necesita slug, debe resolverlo desde companies, no desde auth.

Prohibiciones de diseño

No usar en módulos consumidores:

IdentityInternalDeps;
authenticateUserDependencies;
getInternal("identity");

No crear helpers locales de auth por módulo como patrón estable.

No añadir al access token:

  • companyId
  • companySlug
  • roles
  • permisos