Inventory System enforces access control through a two-layer model: a coarse role that determines what a user can manage, and a set of fine-grained permission flags that govern which specific features a regular user can access. Roles are stored on theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/juadariasmar/inventory_project/llms.txt
Use this file to discover all available pages before exploring further.
Usuario record in the rol column; permissions are stored as a Postgres array in the permisos column.
Roles
| Role | Description |
|---|---|
SUPER_ADMIN | Platform-level administrator. Can view and manage all companies and their data. Auto-promoted at login for any email listed in the ADMIN_EMAILS environment variable. |
ADMIN | Company administrator. Has unrestricted access to every feature within their own company, including user management, product catalogue, sales, reports, and configuration. |
USUARIO | Regular company member. Access to individual features is controlled entirely by the Permiso flags assigned by an admin. |
SUPER_ADMIN is a superset of ADMIN. Both roles bypass all Permiso checks. The distinction is that SUPER_ADMIN can also cross company boundaries (e.g. accessing /admin/empresas), while ADMIN is scoped to their own empresaId.Permissions (Permiso enum)
Permission flags apply only to users with the USUARIO role. ADMIN and SUPER_ADMIN users always pass every permission check.
| Permission | What it grants |
|---|---|
VER_ANALISIS | Access to the analytics dashboard — charts, KPIs, and sales summaries. |
EXPORTAR_REPORTES | Download inventory and sales data as Excel or PDF reports. |
REGISTRAR_MOVIMIENTOS | Create manual stock movement entries (entries and exits outside of sales or purchase orders). |
REALIZAR_VENTAS | Process sales from the point-of-sale terminal. |
AGREGAR_STOCK | Add stock entries (positive adjustments). |
DESCONTAR_STOCK | Deduct stock (negative adjustments). |
AGREGAR_STOCK and DESCONTAR_STOCK were added to support sibling branches of the application. All values must be present in the Prisma enum so that Prisma can hydrate records from the database without errors, even if a given deployment only exposes a subset of them in its UI.How permission checks work in code
All permission and session helpers live insrc/lib/permisos.ts. They are async functions that call obtenerSesion() internally and are safe to use in Server Components, Route Handlers, and Server Actions.
tienePermiso(permiso)
Returns true if the current user is allowed to perform the action associated with permiso. ADMIN and SUPER_ADMIN always return true; USUARIO must have the flag in their permisos array.
validarAccesoEmpresa()
A stricter guard intended for every API route that reads or writes tenant data. It verifies three conditions in sequence and throws an AppError if any fail:
- A valid session exists (
usuariois not null). usuario.estado === 'ACTIVO'— suspended or pending users are rejected.usuario.empresaIdis present — the user belongs to a company.
{ usuarioId, empresaId, rol, usuario } for use in the route handler.
esAdmin() and esSuperAdmin()
Boolean helper functions for branching logic that depends on role level. Both require estado === 'ACTIVO'.
Checking a permission in a full Route Handler
The following example shows a complete pattern for a route that requires both an active company session and a specific permission flag:User states
TheEstadoUsuario enum governs whether a user’s session is honoured by the permission layer, regardless of their role.
PENDIENTE
The user self-registered without an invitation. They can sign in but
validarAccesoEmpresa() throws a 403 and tienePermiso() returns false until an admin promotes them to ACTIVO.ACTIVO
The account is fully operational. All role and permission checks proceed normally.
SUSPENDIDO
The account has been manually blocked by an admin. Sign-in still succeeds at the Neon Auth layer, but all application-level guards reject requests with
403.Managing user permissions
Permissions are assigned and updated by anADMIN through the user management interface or directly via the API:
Permiso enum are accepted. Unknown strings are silently stripped by UsuariosService.actualizarUsuario() before the database write.