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

2.3 KiB

Tenant Context

Objetivo

Documentar cómo se resuelve el contexto tenant actual del ERP mediante X-Company-Id y requireIdentityTenant(params).

Header tenant

Las rutas tenant-scoped deben recibir:

Authorization: Bearer <access_token>
X-Company-Id: <uuid-company>

X-Company-Id es el identificador de la company activa en la request.

No usar:

  • X-Company-Slug
  • companySlug en token
  • req.user.companySlug

Middleware público

Para rutas tenant-scoped:

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

router.use(...requireIdentityTenant(params));

Para rutas solo autenticadas:

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

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

Validación real de requireIdentityTenant(params)

Actualmente ya valida:

  1. access token válido
  2. account autenticable
  3. X-Company-Id presente
  4. X-Company-Id con formato UUID válido
  5. membership active en identity_company_memberships
  6. company active en companies
  7. solo entonces rellena req.user.companyId

Semántica esperada de errores

sin Authorization -> 401
token inválido -> 401
cuenta inexistente/no autenticable -> 401
sin X-Company-Id -> 403
X-Company-Id inválido -> 400
company inexistente -> 403
company disabled -> 403
membership inexistente -> 403
membership disabled/invited -> 403
membership active + company active -> entra al controller

Shape mínimo de req.user

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

No añadir:

  • companySlug
  • company
  • permissions enriquecidos
  • companyStatus

Módulos tenant-scoped migrados

Actualmente usan requireIdentityTenant(params):

  • modules/catalogs
  • modules/customers
  • modules/customer-invoices
  • modules/factuges

modules/supplier queda fuera de esta migración por ahora.

Qué no debe ir en el token

El access token no debe incluir:

  • companyId
  • companySlug
  • roles
  • permisos

El contexto tenant se resuelve por request con X-Company-Id.

Document context

Si un flujo documental necesita companySlug, debe resolverlo desde companies, por ejemplo:

companyId -> companies:general.finder.findById(...) -> slug