Skip to main content
A role is a collection of permissions that can be assigned to users, groups, or service accounts. Roles simplify access management by grouping related permissions together.

Role Structure

type Role struct {
    ID          string
    OrgID       string           // Empty for platform-wide roles
    Name        string           // e.g., "app_organization_owner"
    Title       string           // e.g., "Organization Owner"
    Permissions []string         // Permission slugs
    State       string           // "enabled" or "disabled"
    Scopes      []string         // Used for filtering
    Metadata    map[string]any
    CreatedAt   time.Time
    UpdatedAt   time.Time
}

How Roles Work

When a role is assigned to a user:
  1. A policy is created binding the role to the user on a resource
  2. The user inherits all permissions from that role
  3. SpiceDB creates relationships between the role and permissions
  4. Permission checks traverse these relationships to determine access

Predefined Roles

Frontier includes several predefined platform-wide roles.

Organization Roles

app_organization_ownerFull administrative control over the organization and all resources within it.Permissions:
  • app_organization_administer
The administer permission hierarchically includes all other organization permissions.

Project Roles

RolePermissionsDescription
app_project_ownerapp_project_administerFull project administrative access
app_project_managerapp_project_update
app_project_get
app_project_resourcelist
app_organization_projectcreate
app_organization_projectlist
app_organization_grouplist
Manage project details and resources
app_project_viewerapp_project_getRead-only project access

Group Roles

RolePermissionsDescription
app_group_ownerapp_group_administerFull group administrative access
app_group_memberapp_group_getView group information

Billing Role

RolePermissionsDescription
app_billing_managerapp_organization_billingview
app_organization_billingmanage
Manage organization billing

Custom Roles

Create custom roles to meet specific authorization requirements beyond predefined roles.

Platform vs Organization Roles

Created by: Frontier superusersScope: Available across all organizationsUse case: Standard roles used organization-wideOrgID: Empty string

Creating Custom Roles

1

Identify Required Permissions

Determine which permissions the role needs. Use permission slugs like potato_cart_update.
2

Choose Scope

Decide if the role should be platform-wide or organization-specific.
3

Create the Role

Use the API to create the role with appropriate permissions.
4

Assign via Policies

Bind the role to users through policies on specific resources.

Example: Shopping Cart Manager

Let’s create a custom role for managing shopping carts:
Create Organization Role
curl -L -X POST 'http://127.0.0.1:7400/v1beta1/organizations/4d726cf5-52f6-46f1-9c87-1a79f29e3abf/roles' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
--data-raw '{
  "name": "cart_manager",
  "title": "Cart Manager",
  "permissions": [
    "potato_cart_update",
    "potato_cart_get",
    "potato_cart_delete"
  ],
  "metadata": {
    "description": "Manage shopping cart operations",
    "labels": {"team": "ecommerce"}
  }
}'
Permission slugs must exist before being added to a role. Create custom permissions first if needed.

Role States

Roles can be in one of two states:
Status: enabledThe role is active and can be assigned to users via policies. Users with this role can exercise its permissions.

Deactivating a Role

Temporarily disable a role without deleting it:
curl -L -X PUT 'http://127.0.0.1:7400/v1beta1/organizations/{orgId}/roles/{roleId}' \
-H 'Content-Type: application/json' \
--data-raw '{
  "state": "disabled"
}'

Reactivating a Role

Re-enable a disabled role:
curl -L -X PUT 'http://127.0.0.1:7400/v1beta1/organizations/{orgId}/roles/{roleId}' \
-H 'Content-Type: application/json' \
--data-raw '{
  "state": "enabled"
}'

Managing Roles via API

These APIs require special privileges. Authenticate with Client ID/Secret or Access Token.

List Organization Roles

Retrieve custom roles created within an organization:
List All Org Roles
curl -L -X GET 'http://127.0.0.1:7400/v1beta1/organizations/4d726cf5-52f6-46f1-9c87-1a79f29e3abf/roles' \
-H 'Accept: application/json'
Filter by state:
List Enabled Roles Only
curl -L -X GET 'http://127.0.0.1:7400/v1beta1/organizations/4d726cf5-52f6-46f1-9c87-1a79f29e3abf/roles?state=enabled' \
-H 'Accept: application/json'
This endpoint only returns organization-specific custom roles. Platform-wide default roles are not included.

List Platform Roles

Retrieve all predefined platform-wide roles:
curl -L -X GET 'http://127.0.0.1:7400/v1beta1/roles' \
-H 'Accept: application/json'
Filter by state:
curl -L -X GET 'http://127.0.0.1:7400/v1beta1/roles?state=enabled' \
-H 'Accept: application/json'

Create Organization Role

Create a custom role scoped to an organization:
curl -L -X POST 'http://127.0.0.1:7400/v1beta1/organizations/4d726cf5-52f6-46f1-9c87-1a79f29e3abf/roles' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
--data-raw '{
  "name": "data_analyst",
  "title": "Data Analyst",
  "permissions": [
    "app_project_get",
    "app_project_resourcelist"
  ],
  "metadata": {
    "description": "Read-only access to project data"
  }
}'

Update Organization Role

Modify an existing custom role:
curl -L -X PUT 'http://127.0.0.1:7400/v1beta1/organizations/4d726cf5-52f6-46f1-9c87-1a79f29e3abf/roles/c2d85306-96f4-4895-98b4-c3e5c2f3084d' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
--data-raw '{
  "name": "cart_manager",
  "title": "Cart Manager",
  "permissions": [
    "potato_cart_update",
    "potato_cart_get",
    "potato_cart_delete"
  ],
  "metadata": {
    "description": "Full cart management access"
  }
}'
Updating a role’s permissions automatically updates SpiceDB relationships for all existing policy assignments.

Delete Organization Role

Caution: Deleting a role is irreversible and permanently removes:
  • The role definition
  • All policies using this role
  • All user access granted through this role
Users will immediately lose access to resources granted via this role.
curl -L -X DELETE 'http://127.0.0.1:7400/v1beta1/organizations/4d726cf5-52f6-46f1-9c87-1a79f29e3abf/roles/c2d85306-96f4-4895-98b4-c3e5c2f3084d' \
-H 'Accept: application/json'

Role Implementation Details

When a role is created in Frontier:

1. Role-Permission Relations Created

For each permission in the role, Frontier creates SpiceDB relations:
// For user principals
app/role:cart_manager#potato_cart_update@app/user:*
app/role:cart_manager#potato_cart_get@app/user:*
app/role:cart_manager#potato_cart_delete@app/user:*

// For service user principals  
app/role:cart_manager#potato_cart_update@app/serviceuser:*
app/role:cart_manager#potato_cart_get@app/serviceuser:*
app/role:cart_manager#potato_cart_delete@app/serviceuser:*
The * wildcard means “all users who have this role will have these permissions.”

2. Dynamic Permission Updates

When updating a role:
1

Fetch Existing Role

Retrieve current role definition from database
2

Delete Old Relations

Remove all existing role-permission relationships from SpiceDB
3

Create New Relations

Establish new relationships for updated permissions
4

Update Database

Persist the updated role definition
5

Audit Record

Create audit trail of the role modification

3. Role Deletion Process

Deleting a role:
  1. Removes all SpiceDB relations for the role
  2. Deletes all policies using the role (cascading delete)
  3. Removes the role from the database
  4. Creates audit record of deletion

Best Practices

Leverage built-in roles like app_organization_owner before creating custom roles. They’re battle-tested and cover common scenarios.
Grant only the minimum permissions required. Create narrow, focused roles rather than overly permissive ones.
Choose clear role names that indicate purpose (e.g., billing_viewer, project_deployer) rather than vague terms.
Always add metadata with descriptions explaining the role’s purpose and intended users.
Temporarily disable roles instead of deleting them when access needs to be revoked. This preserves audit history.
Periodically audit custom roles to ensure permissions still match organizational needs.

Next Steps

Policies

Learn how to assign roles to users via policies

Examples

See real-world role usage patterns

Build docs developers (and LLMs) love