179 lines
3.3 KiB
Markdown
179 lines
3.3 KiB
Markdown
# Identity And Companies
|
|
|
|
## Objetivo
|
|
|
|
Documentar la separación actual entre `modules/identity` y `modules/companies`, evitando mezclar autenticación, memberships y ficha operativa de empresa.
|
|
|
|
## Responsabilidades por módulo
|
|
|
|
### `modules/identity`
|
|
|
|
Gestiona:
|
|
|
|
- `Account`
|
|
- login
|
|
- refresh
|
|
- logout
|
|
- session
|
|
- `RefreshToken`
|
|
- `CompanyMembership`
|
|
- acceso `account-company`
|
|
- roles/permisos futuros
|
|
|
|
Endpoints activos:
|
|
|
|
```http
|
|
POST /identity/auth/login
|
|
POST /identity/auth/refresh
|
|
POST /identity/auth/logout
|
|
GET /identity/auth/session
|
|
```
|
|
|
|
El access token contiene solo:
|
|
|
|
```ts
|
|
{
|
|
accountId: string;
|
|
email: string;
|
|
}
|
|
```
|
|
|
|
No debe contener:
|
|
|
|
- `companyId`
|
|
- `companySlug`
|
|
- roles
|
|
- permisos
|
|
|
|
### `modules/companies`
|
|
|
|
Es la fuente de verdad de la ficha operativa de empresa.
|
|
|
|
`Company` funcional vive en `modules/companies`.
|
|
|
|
Campos actuales de `companies`:
|
|
|
|
```txt
|
|
id
|
|
legal_name
|
|
trade_name
|
|
tin
|
|
slug
|
|
email
|
|
phone
|
|
website
|
|
status
|
|
created_at
|
|
updated_at
|
|
```
|
|
|
|
Índices actuales:
|
|
|
|
```txt
|
|
UNIQUE(slug)
|
|
INDEX(status)
|
|
INDEX(tin)
|
|
```
|
|
|
|
`slug` pertenece a `companies`, no a auth ni al token.
|
|
|
|
## Relación entre ambos módulos
|
|
|
|
- `CompanyMembership` vive en `identity`.
|
|
- `Company` vive en `companies`.
|
|
- No mover memberships a `companies`.
|
|
- No evolucionar `identity.Company` como ficha operativa ERP.
|
|
- No usar `customers` para representar la empresa tenant.
|
|
|
|
## Servicios públicos
|
|
|
|
### `identity:general`
|
|
|
|
Expone autenticación y acceso por membership.
|
|
|
|
Uso conceptual:
|
|
|
|
```ts
|
|
companyAccess.canAccessCompany(...)
|
|
companyAccess.findAccessibleCompanyIds(...)
|
|
```
|
|
|
|
`identity` devuelve IDs accesibles por membership, no fichas completas de empresa.
|
|
|
|
### `companies:general`
|
|
|
|
Expone consulta de empresas y validación de empresa activa.
|
|
|
|
Uso conceptual:
|
|
|
|
```ts
|
|
ICompanyPublicServices {
|
|
finder: ICompanyPublicFinder;
|
|
}
|
|
```
|
|
|
|
## Por qué no existe `GET /identity/companies`
|
|
|
|
No se documenta `GET /identity/companies` como endpoint válido porque produciría acoplamiento circular:
|
|
|
|
```txt
|
|
identity -> companies -> identity
|
|
```
|
|
|
|
Si `identity` devolviera fichas completas de company, tendría que depender de `companies`.
|
|
|
|
Como `companies` ya depende de `identity` para autenticación, el diseño correcto es:
|
|
|
|
- `identity` resuelve membership y accesibilidad por ID
|
|
- `companies` resuelve la ficha completa de empresa
|
|
|
|
El endpoint vigente para el frontend es:
|
|
|
|
```http
|
|
GET /companies/available
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
Tampoco debe documentarse ni introducirse `GET /account/companies` como variante válida.
|
|
|
|
## Dependencias permitidas
|
|
|
|
Para módulos tenant-scoped que usan `requireIdentityTenant(params)`, la dependencia explícita debe ser hacia:
|
|
|
|
- `identity`
|
|
- `companies`
|
|
|
|
Porque el middleware tenant compone:
|
|
|
|
```txt
|
|
identity:general.companyAccess
|
|
companies:general.finder
|
|
```
|
|
|
|
## Dependencias prohibidas
|
|
|
|
No introducir:
|
|
|
|
- `identity -> companies`
|
|
- recomposición manual de internals de `identity`
|
|
- `IdentityInternalDeps`
|
|
- `getInternal("identity")` desde módulos consumidores
|
|
- helpers locales de auth por módulo como patrón estable
|
|
|
|
## `GET /companies/available`
|
|
|
|
Semántica actual:
|
|
|
|
- requiere `Authorization`
|
|
- no requiere `X-Company-Id`
|
|
- usa `requireIdentityAuthenticated(params)`
|
|
- devuelve companies activas accesibles para la cuenta autenticada
|
|
|
|
La disponibilidad se calcula con:
|
|
|
|
```txt
|
|
membership active en identity
|
|
+
|
|
company active en companies
|
|
```
|