0010. Flujo de acceso y panel de aplicaciones (pantallas de entrada)¶
Estado: Propuesto Fecha: 2026-09-08 Autor: Duval Alcivar Módulo(s) afectado(s): svc-identidad, frontend (React 18)
Contexto¶
La plataforma tiene varias aplicaciones (ERP, CRM) y cada empresa contrata solo algunas. Además, un mismo usuario puede trabajar en varias empresas. Necesitamos definir qué pantallas ve el usuario desde que abre la app hasta que entra a trabajar, y qué valida el backend en cada paso.
El mockup de referencia (sigfa-erp-crm.html) muestra tres pantallas:
login → panel de aplicaciones → vista de módulo. Este ADR define el
comportamiento de las dos primeras; la tercera (menú del módulo) está en el
ADR 0012.
Conceptos¶
| Término | Qué es |
|---|---|
| Aplicación | Un producto de la plataforma: ERP, CRM (tabla cat_aplicaciones, ADR 0006). |
| Módulo | Una sección dentro de una aplicación (ej. Inventario, RRHH). Se muestran como tarjetas en el panel. |
| Panel | La pantalla después del login: muestra las aplicaciones contratadas por la empresa con sus módulos. |
pre_token |
Token temporal (5 min, ADR 0018) que se emite al validar la contraseña; solo sirve para elegir empresa, no da acceso a datos. |
Decisión¶
Flujo completo¶
flowchart TD
A["🖥️ LOGIN<br/>usuario + contraseña"]
B{"¿credenciales válidas?"}
C{"¿cuántas empresas?"}
E["📋 MODAL<br/>elegir empresa"]
D["📲 PANEL DE MÓDULOS<br/>carga directa"]
F["🧭 MÓDULO<br/>menú lateral por permisos"]
A --> B
B -->|"✅ sí"| C
B -.->|"❌ no"| A
C -->|"más de 1"| E
C -->|"1 sola"| D
E --> D
D --> F
classDef login fill:#eaf1fa,stroke:#2b6cb0,color:#1e4e85,stroke-width:2px;
classDef decision fill:#f5f3ff,stroke:#6d5bd0,color:#4b3a9e,stroke-width:2px;
classDef panel fill:#e8f5f0,stroke:#1f7a5c,color:#155941,stroke-width:2px;
classDef modal fill:#f7ecf2,stroke:#8a3b63,color:#63294a,stroke-width:2px;
classDef modulo fill:#fff7e6,stroke:#b4622a,color:#8a4d1a,stroke-width:2px;
class A login;
class B,C decision;
class D panel;
class E modal;
class F modulo;
Pantalla 1 — Login¶
El formulario pide solo usuario y contraseña. Al enviar:
- El backend valida las credenciales (Argon2id), que el usuario esté activo
y consulta sus empresas (
rel_usuario_empresaactivas). - Responde con la lista de empresas del usuario y un
pre_token.
Por qué no pedir la empresa junto con la contraseña: porque eso obligaría a mostrar las empresas disponibles antes de saber quién es el usuario (cualquiera podría probar usernames y ver a qué empresas pertenecen). Las empresas solo se revelan después de validar la contraseña.
Paso intermedio — ¿modal o directo?¶
Con las credenciales ya validadas, el frontend decide según cuántas empresas tenga el usuario:
- Una sola empresa → no se muestra nada: el frontend envía esa empresa al paso 2 automáticamente y carga directo el panel de módulos. El usuario ni siquiera nota el paso intermedio.
- Más de una empresa → se abre un modal (ventana emergente sobre el
login) que lista las empresas del usuario. Al elegir una, se envía
pre_token + empresa_idal paso 2, se recibe elaccess_tokeny se carga el panel.
Pantalla 2 — Panel de aplicaciones¶
Una vez autenticado, el frontend carga el panel:
GET /api/v1/navegacion/panel
El backend responde con las aplicaciones contratadas por la empresa
(rel_empresa_aplicacion) y, dentro de cada una, solo los módulos a los
que el usuario tiene permiso (ver ADR 0007/0012). La respuesta alimenta la
grilla de tarjetas del mockup, agrupadas por núcleo (Core / ERP / CRM):
{
"empresa": { "id": 1, "nombre": "Sigfa Alimentos S.A." },
"aplicaciones": [
{
"codigo": "erp",
"nombre": "ERP Sigfa",
"dominio": "sigfa.com.ec",
"modulos": [
{ "codigo": "inventario", "nombre": "Inventario", "icono": "box" },
{ "codigo": "rrhh", "nombre": "RRHH / Nómina", "icono": "users" }
]
},
{
"codigo": "crm",
"nombre": "CRM SigfaPro",
"dominio": "sigfapro.com.ec",
"modulos": [
{ "codigo": "clientes", "nombre": "Clientes", "icono": "users" }
]
}
]
}
Reglas del panel:
- Si una aplicación no tiene ningún módulo visible para el usuario, la aplicación completa no se muestra (una empresa puede tener ERP contratado pero este usuario solo ve módulos del CRM).
- El panel no muestra módulos desactivados (
is_activo = false) ni ocultos (is_visible = false), aunque el usuario tenga permiso. - Los datos del panel se cachean en el frontend por la duración de la sesión; se recargan al iniciar sesión o al cambiar de empresa.
Cambio de empresa sin cerrar sesión¶
Un usuario con varias empresas puede cambiar de empresa desde el menú de
usuario (sin volver al login): el frontend llama a
POST /api/v1/auth/login/empresa con un refresh válido y la nueva empresa_id;
el backend emite un nuevo par de tokens con el nuevo empresa_id y el panel
se recarga.
Alternativas descartadas¶
- Pedir la empresa junto con usuario y contraseña en un solo formulario — obliga a listar empresas antes de autenticar (fuga de información) o a que el usuario se sepa el ID de memoria.
- Un subdominio por empresa (
empresa1.sigfa.com) — complejo de operar con pocas empresas; el selector en el login cubre el mismo caso. - Cargar el panel completo en el token JWT — inflaría el token; el panel se consulta una vez por sesión y se cachea en el cliente.
Consecuencias¶
- El login queda en dos pasos seguros: las empresas del usuario nunca se exponen sin contraseña válida.
- La mayoría de usuarios (los de una sola empresa) no ven ningún paso extra: entran directo al panel tras el login.
- El panel refleja exactamente lo que el usuario puede usar: ni más (no ve módulos sin permiso) ni menos (no pierde acceso a lo contratado).
- El cambio de empresa es una operación rápida sin cerrar sesión, útil para usuarios que operan varias empresas del grupo.
- La seguridad del
pre_token(expiración corta y un solo uso) quedó resuelta en el ADR 0018: JWT firmado conscope: "pre-auth", consumo registrado entrx_pre_tokensy replay tratado como fuga.
Orden de lectura (cómo encaja con los demás ADRs)¶
Este ADR narra el flujo con pantallas de la entrada del usuario. La parte técnica de la firma está en el 0011, los tipos/permisos en el 0007 y lo que se muestra dentro (menú / sidebar) en el 0012:
| # | ADR | Qué aporta |
|---|---|---|
| 0001 · 0002 | Concepto y stack | Qué es el servicio y con qué herramientas |
| 0003 · 0005 | Catálogos y modelos | Catálogos, empresas y usuarios |
| 0006 · 0007 | Navegación y permisos | Aplicaciones/módulos/menú y tipos/permisos |
| 0008 · 0009 | Gestión | Alta de empresa; gestión de usuarios y permisos |
| 0010 (este) | Flujo de acceso y panel | El flujo: login → modal de empresa → panel → módulo |
| 0011 | Login: firma JWT y claves | Cómo se firma el token que produce este flujo |
| 0012 | Menú y permisos | Qué se muestra al entrar (panel y sidebar) |
flowchart LR
A["0001 · 0002<br/>concepto y stack"] --> B["0003 · 0005<br/>catálogos y modelos"]
B --> C["0006 · 0007<br/>navegación y permisos"]
C --> D["0008 · 0009<br/>gestión"]
D --> E["0010<br/>flujo y pantallas"]
E --> F["0011<br/>firma y claves"]
E --> G["0012<br/>menú y permisos"]
El orden lógico de lectura completo (con los pendientes) está en el
README.mddel índice.