Skip to Content
Agentlang is open source now!
ReferenceRole-Based Access Control

Role-Based Access Control (RBAC)

Agentlang provides a declarative, schema-level mechanism for specifying role-based access control (RBAC). This system governs who can perform specific actions (Create, Read, Update, Delete) on entities or records in an Agentlang application.

RBAC rules are expressed using the @rbac annotation on entity definitions or attributes.


3.1 Overview

The @rbac annotation defines one or more permission specifications, each describing:

  • roles — which user roles the rule applies to
  • allow — what operations are permitted
  • where (optional) — an expression constraining when the rule applies

Syntax

@rbac [ (roles: [<role1>, <role2>, ...], allow: [<op1>, <op2>, ...] [, where: <condition>]) ... ]

Operations

The following operations are supported:

OperationMeaning
createPermission to create new instances
readPermission to read or query instances
updatePermission to modify instances
deletePermission to delete instances

Example

entity Department { deptNumber Int @id, deptName String, @rbac [(roles: [manager], allow: [create])] }

Meaning: Only users with the manager role can create instances of Department.


3.2 Ownership Semantics

When a user creates an entity instance:

  • That user automatically becomes the owner of the instance.
  • The owner has full CRUD permissions on that instance and all child entities in a contains hierarchy.
  • Users with the admin role have full CRUD access to all entities, regardless of RBAC rules.

3.3 Fine-Grained User Permissions

Permissions can also be assigned at the user level using RBAC rules that include a where clause.

Example

entity User { id UUID @id, name String, @rbac [ (roles: [*], allow: [create]), (allow: [read], where: auth.user = this.id) ] }

Explanation:

  • Any user (* wildcard role) can create new User entities.
  • A user can only read their own user record (where auth.user equals this.id).

3.4 The agentlang.auth Module

The built-in agentlang.auth module defines the core schema for managing users, roles, and permissions.

It is automatically available in every Agentlang application.

Module Overview

module agentlang.auth

Core Entities

User

entity User { id UUID @id @default(uuid()), email Email @unique @indexed, firstName String, lastName String, @rbac [(allow: [read, delete, update, create], where: auth.user = this.id)], @after {delete AfterDeleteUser} }
  • Represents an authenticated user.
  • Can read, update, or delete its own record.
  • @after {delete AfterDeleteUser} denotes a post-delete hook.

Role

entity Role { name String @id }

Defines a user role (e.g., admin, manager, employee).


Permission

entity Permission { id String @id, resourceFqName String @indexed, c Boolean, r Boolean, u Boolean, d Boolean }

Each Permission corresponds to CRUD access on a specific resource.


Relationships

relationship UserRole between (User, Role) relationship RolePermission between (Role, Permission)
  • UserRole links users to their assigned roles.
  • RolePermission links roles to their permissions.

3.5 RBAC Workflows

The agentlang.auth module includes several public workflows for managing users, roles, and permissions.

Assign a User to a Role

@public workflow AssignUserToRole { {User {id? AssignUserToRole.userId}} @as [user]; {Role {name? AssignUserToRole.roleName}} @as [role]; {UserRole {User user, Role role}, @upsert} }

Associates a user (by ID) with a specified role. @upsert ensures the relationship is created or updated atomically.


Assign a Role by Email

@public workflow AssignUserToRoleByEmail { {User {email? AssignUserToRoleByEmail.email}} @as [user]; {Role {name? AssignUserToRoleByEmail.roleName}} @as [role]; {UserRole {User user, Role role}, @upsert} }

Convenience variant that assigns roles based on a user’s email.


Create a Permission

@public workflow CreatePermission { {Permission { id CreatePermission.id, resourceFqName CreatePermission.resourceFqName, c CreatePermission.c, r CreatePermission.r, u CreatePermission.u, d CreatePermission.d }, RolePermission {Role {name? CreatePermission.roleName}}, @upsert} }

Creates a new permission and associates it with a role.


Add an Existing Permission to a Role

@public workflow AddPermissionToRole { {Role {name? AddPermissionToRole.roleName}} @as [role]; {Permission {id? AddPermissionToRole.permissionId}} @as [perm]; {RolePermission {Role role, Permission perm}, @upsert} }

Adds a pre-existing Permission entity to a Role.


3.6 Authentication Provider

By default, Agentlang uses AWS Cognito as its authentication and identity provider.

To enable Cognito-based authentication, configure the following environment variables:

export COGNITO_USER_POOL_ID=<cognito-pool-id> export COGNITO_CLIENT_ID=<cognito-client-id> export AWS_ACCESS_KEY_ID=<aws-access-key> export AWS_SECRET_ACCESS_KEY=<secret-key> export AWS_REGION=<aws-region>

Login API

Users can authenticate via an HTTP POST request:

POST agentlang.auth/login Content-Type: application/json {"email": "<cognito-user-id>", "password": "<cognito-password>"}

Response:

{ "id-token": "<jwt-token>" }

The token must be included in subsequent requests as:

Authorization: Bearer <id-token>

Automatic Role Synchronization

  • On first login, a local User entity is created automatically.
  • Cognito groups are mapped to roles in Agentlang.
  • Thus, role memberships in Cognito are reflected in application-level RBAC.

3.7 Runtime Behavior Summary

ConceptDescription
@rbacDeclaratively specifies who can perform which actions
rolesLogical groups of users (from Cognito or app-defined)
allowAllowed operations: [create, read, update, delete]
whereConditional expression limiting applicability
ownerCreator of an instance with full CRUD on it and children
adminGlobal role with unrestricted access
agentlang.auth moduleProvides built-in user, role, and permission schema
@upsertEnsures idempotent relationship updates
auth.userCurrent authenticated user identifier
AWS Cognito integrationProvides user identity and role mapping

Complete Example

module acme.hr entity Department { deptNumber Int @id, deptName String, @rbac [(roles: [manager], allow: [create])] } entity Employee { id Int @id, name String, department Path, @rbac [ (roles: [manager], allow: [read, update]), (allow: [read], where: auth.user = this.owner) ] }
  • Only managers can create departments.
  • Managers can read or update employees.
  • An employee can read their own record.

Last updated on