erp-core/docs/01-fase-foundation/MGN-001-auth/especificaciones/auth-domain.md

6.4 KiB

MODELO DE DOMINIO: Autenticación y Autorización

Módulos: MGN-001 (Fundamentos), MGN-002 (Empresas) Fecha: 2025-11-24 Referencia Odoo: base, auth_signup Referencia Gamilit: auth_management schema


Diagrama de Entidades (Texto UML)

[Tenant]
  - id: UUID (PK)
  - name: String
  - subdomain: String
  - schema_name: String
  - status: ENUM (active, suspended)
  - settings: JSONB

  1 <----> * [Company]
  1 <----> * [User]

[Company]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - name: String
  - tax_id: String
  - currency_id: UUID (FK)
  - settings: JSONB

  1 <----> * [User]

[User]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - email: String (UNIQUE per tenant)
  - password_hash: String
  - full_name: String
  - status: ENUM (active, inactive, suspended)
  - is_superuser: Boolean

  * <----> * [Role] (through UserRole)
  1 <----> * [Session]

[Role]
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - name: String
  - code: String
  - description: Text

  * <----> * [Permission] (through RolePermission)

[Permission]
  - id: UUID (PK)
  - resource: String (ej: 'purchase_orders')
  - action: ENUM (create, read, update, delete, approve)
  - description: Text

[Session]
  - id: UUID (PK)
  - user_id: UUID (FK)
  - token: String
  - expires_at: Timestamp
  - ip_address: String
  - user_agent: String

[UserRole] (many-to-many)
  - user_id: UUID (FK)
  - role_id: UUID (FK)

[RolePermission] (many-to-many)
  - role_id: UUID (FK)
  - permission_id: UUID (FK)

Entidades Principales

1. Tenant (Multi-Tenancy)

Descripción: Representa un tenant (empresa matriz o grupo). Cada tenant tiene su propio schema PostgreSQL.

Atributos:

  • id: Identificador único
  • name: Nombre del tenant
  • subdomain: Subdominio (ej: 'acme' → acme.erp.com)
  • schema_name: Nombre del schema PostgreSQL (ej: 'tenant_acme')
  • status: Estado (active, suspended)
  • settings: Configuración JSON (logo, tema, etc.)

Relaciones:

  • 1 Tenant → N Companies
  • 1 Tenant → N Users

Patrón Odoo: Similar a res.company pero en un nivel superior Patrón Gamilit: Implementado con schema-level isolation

RLS Policy:

-- Usuarios solo ven su tenant
CREATE POLICY tenant_isolation ON tenants
USING (id = get_current_tenant_id());

2. Company (Empresa)

Descripción: Empresa dentro de un tenant. Permite multi-empresa.

Atributos:

  • id: UUID
  • tenant_id: Tenant propietario
  • name: Nombre empresa
  • tax_id: RFC/Tax ID
  • currency_id: Moneda por defecto
  • settings: JSONB (dirección, contacto, etc.)

Relaciones:

  • N Companies → 1 Tenant
  • 1 Company → N Users (usuarios pueden estar en múltiples empresas)

Patrón Odoo: res.company Validaciones:

  • Un tenant debe tener al menos 1 company
  • tax_id único por tenant

3. User (Usuario)

Descripción: Usuario del sistema con roles y permisos.

Atributos:

  • id: UUID
  • tenant_id: Tenant propietario
  • email: Email (único por tenant)
  • password_hash: bcrypt hash
  • full_name: Nombre completo
  • status: active, inactive, suspended
  • is_superuser: Admin total del tenant

Relaciones:

  • N Users → 1 Tenant
  • N Users ←→ N Roles (many-to-many)
  • 1 User → N Sessions

Patrón Odoo: res.users Patrón Gamilit: auth.users con tenant_id

Validaciones:

  • email único por tenant (no global)
  • password mínimo 8 caracteres
  • is_superuser requiere aprobación

RLS Policy:

CREATE POLICY users_own_tenant ON users
USING (tenant_id = get_current_tenant_id());

4. Role (Rol)

Descripción: Rol con permisos asignados (RBAC).

Atributos:

  • id: UUID
  • tenant_id: Tenant propietario
  • name: Nombre del rol
  • code: Código único (ej: 'admin', 'buyer')
  • description: Descripción

Relaciones:

  • N Roles → 1 Tenant
  • N Roles ←→ N Permissions

Patrón Odoo: res.groups Roles predefinidos:

  • admin: Administrador del tenant
  • manager: Gerente (full access transaccional)
  • user: Usuario normal
  • readonly: Solo lectura

5. Permission (Permiso)

Descripción: Permiso granular sobre recursos.

Atributos:

  • id: UUID
  • resource: Recurso (tabla/endpoint) (ej: 'purchase_orders')
  • action: create, read, update, delete, approve, cancel

Ejemplo de permisos:

Resource: purchase_orders
Actions: create, read, update, delete, approve

Patrón Odoo: ir.model.access + ir.rule Implementación: Validado en backend + RLS policies en BD

6. Session (Sesión)

Descripción: Sesión JWT de usuario.

Atributos:

  • id: UUID
  • user_id: Usuario propietario
  • token: JWT token
  • expires_at: Expiración
  • ip_address: IP de origen
  • user_agent: Navegador

Patrón Gamilit: auth.sessions

Reglas de Negocio

RN-AUTH-001: Multi-Tenancy Obligatorio

  • TODO usuario pertenece a exactamente 1 tenant
  • TODO dato transaccional tiene tenant_id
  • Aislamiento completo entre tenants (schema-level)

RN-AUTH-002: RBAC Granular

  • Usuario puede tener múltiples roles
  • Permisos se calculan como UNION de permisos de roles
  • is_superuser bypassa todos los checks

RN-AUTH-003: Sesiones JWT

  • Expiración: 8 horas
  • Refresh token: 30 días
  • Invalidación: Logout o expiración

RN-AUTH-004: Passwords Seguros

  • Mínimo 8 caracteres
  • Debe incluir: mayúscula, minúscula, número
  • bcrypt hash (cost factor 12)

Casos de Uso Principales

  1. UC-AUTH-001: Login de usuario
  2. UC-AUTH-002: Registro de nuevo tenant
  3. UC-AUTH-003: Asignar rol a usuario
  4. UC-AUTH-004: Validar permisos para acción
  5. UC-AUTH-005: Reset password
  6. UC-AUTH-006: Cambiar de empresa (multi-company)

Validaciones y Constraints

-- Email único por tenant
UNIQUE (tenant_id, email)

-- Status válidos
CHECK (status IN ('active', 'inactive', 'suspended'))

-- Al menos 1 admin por tenant
-- (trigger custom)

-- Session expiration
CHECK (expires_at > created_at)

Índices Requeridos

CREATE INDEX idx_users_tenant_id ON auth.users(tenant_id);
CREATE INDEX idx_users_email ON auth.users(email);
CREATE INDEX idx_sessions_user_id ON auth.sessions(user_id);
CREATE INDEX idx_sessions_token ON auth.sessions(token);
CREATE INDEX idx_user_roles_user_id ON auth.user_roles(user_id);

Referencias