Access control in La Oficina Nítida is built around three roles that define what each user can see and do within their organization. Every user belongs to exactly one tenant and carries exactly one role, encoded directly in the JWT access token. The platform enforces these roles at the route level usingDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Glemynart/SaaS/llms.txt
Use this file to discover all available pages before exploring further.
RolesGuard, which inspects the token before any controller logic runs.
Roles
| Role | Description |
|---|---|
ADMIN | Full access to all modules. Can create, edit, and delete employees, manage contracts and bulk batches, access billing and invoicing, upload branding assets, manage branches, invite and update users, and change organization settings. The first user created for any organization is always an ADMIN. |
OPERADOR | Day-to-day operational access. Can create and edit employees (including bulk import), create and manage contracts, generate documents, access the expedient and alerts, and work with billing and invoicing. Cannot delete records, cannot manage users, and cannot change organization-level settings. |
VIEWER | Read-only access across all modules. Intended for stakeholders who need visibility without the ability to make changes. |
UserRole enum in the database defines these three values: ADMIN, OPERADOR, VIEWER. The default role assigned to new users created through the service is OPERADOR.
How Role Enforcement Works
Every controller that requires a specific role is decorated with@Roles(UserRole.ADMIN) (or the appropriate role). The RolesGuard reads the rol claim from the verified JWT and rejects requests from users whose role does not match. Role guards always run after JwtAuthGuard and ActiveTenantGuard, so a request must be both authenticated and from an active tenant before roles are even evaluated.
User Data Model
Each user belongs to a single tenant. The email address is unique within a tenant, but two users in different organizations can share the same email.| Field | Type | Description |
|---|---|---|
id | String (UUID) | Primary key |
tenantId | String | The organization this user belongs to |
email | String | Login email — unique per tenant, stored in lowercase |
nombre | String | First name |
apellido | String | Last name |
rol | UserRole | Role: ADMIN, OPERADOR, or VIEWER |
activo | Boolean | Whether the user can log in; defaults to true |
lastLoginAt | DateTime? | Timestamp of the most recent successful login |
Creating Users
There is no standalone user invitation endpoint in the current MVP. New users are created viaUsersService.create(), which is called by authorized flows within the platform (such as the admin user interface). The service enforces the following rules:
- The email must not already exist for the same tenant
- The password is hashed with bcrypt (10 rounds) before storage
- The
tenantIdis always supplied by the calling service, never by the client
409 Conflict.
Inviting Users: Expected Flow
When an admin adds a new user through the platform UI:- The admin fills in the new user’s name, email, password, and role
- The platform calls
UsersService.create()with the admin’stenantId(from the JWT) injected automatically - The new user can immediately log in using
POST /auth/loginwith the organization’s NIT, their email, and the assigned password
tenantNit), the user’s email, and their password. This three-factor login model ensures that email addresses can be reused across different organizations without collision.
The first
ADMIN user for every organization is created automatically during tenant registration via POST /auth/register. This user is the organization’s initial super-user and is the only way to bootstrap access to the platform for a new tenant. Subsequent users must be created by an existing ADMIN within that organization.