Skip to content

RBAC & Users

Backend domains:

RBAC

RBAC is path-based. Every protected mutation/query checks a Path enum against the calling user's permissions:

  • Paths — one per domain (INVOICES, RECEIPTS, PAYMENTS, PAYROLL, FIXED_ASSETS, BANK_RECONCILIATIONS, AUDIT_LOG, PERIOD_CLOSE, RECURRING_*, …). New domains must declare a path.
  • Resources — finer-grained operations under a path (CREATE, READ, UPDATE, DELETE, plus domain-specific like POST, VOID, REVERSE).
  • Roles — named bundles of (path, resource) grants (e.g. Owner, Accountant, Salesperson, Warehouse).
  • User → Role assignment governs effective permissions.

Two layers of mutation:

  • updatePathPermissions — grant/revoke at the path level (turn the menu on/off).
  • updateRolePermissions — fine-grained per-resource grants inside a path.

Key queries: pathPermissions, roleResourcePermissions, getUserRoleResourcePermissions.

Combinations of paths are precomputed in combinations.py for fast menu rendering on the frontend.

Users

User identity is federated via FusionAuth + WorkOS, but a local User row captures profile, avatar, signature image, and tenant-scoped settings.

Key mutations: createUser, updateUser, archiveUser, deleteUser, uploadSignature.

Key queries: getUserInfo, userSearch, getUserById, sessionInfo.

Session rows track logged-in sessions per user — useful for audit and remote-logout. OTC (one-time-code) settings under otc/ govern 2FA / OTP if enabled.

Billing

app/graphql/billing/ tracks the tenant's plan, seat count, and invoice line items for the SaaS bill itself (distinct from the customer invoices the tenant issues). Most PYME-facing pricing logic lives here.

Frontend notes

  • Menu visibility is driven entirely by pathPermissions.
  • Resource-level checks should be done on each mutation button (e.g. a Salesperson sees the invoice but cannot click "Void").
  • Show a friendly "Hablá con tu admin" error rather than a raw 403 — RBAC errors carry a structured code from the backend.