Authorization and RBAC
Lana uses Casbin for role-based access control (RBAC). Policies are stored in PostgreSQL and evaluated at runtime for every API operation.
RBAC Model
The authorization model follows a three-level structure:
User → Role → PermissionSet → Permissions (Object + Action)
Predefined Roles
| Role | Description | Key Permissions |
|---|---|---|
| Superuser | Full system access | All permission sets |
| Admin | Full operational access | All except system-level |
| Bank Manager | Operations management | Customer, credit, deposits, reports (no access management or custody) |
| Accountant | Financial operations | Accounting and viewing functions |
An administrative user has one current role, stored on the user entity. That role can contain multiple permission sets, whose permissions are combined. Changing a user's role replaces the previous assignment; it does not add another role.
The configured superuser cannot be moved to another role through the API, and the superuser role cannot be assigned to another user. The authoritative seeded permission lists are in lana/app/src/authorization/seed.rs.
Permission Sets
Each domain module defines its own permission sets, typically following a viewer/writer pattern:
PERMISSION_SET_CUSTOMER_VIEWER— read-only access to customer dataPERMISSION_SET_CUSTOMER_WRITER— create/update customer dataPERMISSION_SET_CREDIT_VIEWER— read credit facilitiesPERMISSION_SET_CREDIT_WRITER— manage credit facilitiesPERMISSION_SET_EXPOSED_CONFIG_VIEWER— read system configurationPERMISSION_SET_EXPOSED_CONFIG_WRITER— modify system configuration
Casbin Policy Model
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && r.act == p.act
How Authorization Works in Code
Authorization is enforced in the application/use-case layer rather than through a role guard on each GraphQL resolver:
- The API validates the Keycloak token and constructs a Lana subject from the required application identity claim.
- The resolver invokes the application service/use case with that subject.
- The
lib/use-caseauthorization layer checks the subject's object/action permission through Casbin, including transitive role/permission-set grouping and wildcard object matching. - A denial prevents the operation from proceeding.
- The use-case audit layer records the decision according to the action's audit policy.
Audit Integration
Authorization audit entries include:
- Subject: Who attempted the action
- Object: What the action targeted
- Action: The operation type (e.g.,
customer:read,credit-facility:create) - Authorized: Whether it was allowed or denied
Both allowed and denied decisions can be recorded. Some allowed reads are cacheable according to their action's audit policy, so repeated API reads do not necessarily produce one audit row per request. See Audit System for details.