Documentation Index
Fetch the complete documentation index at: https://docs.emergence.ai/llms.txt
Use this file to discover all available pages before exploring further.
Authorization
CRAFT uses OpenFGA for authorization, implementing Relationship-Based Access Control (ReBAC). Unlike traditional RBAC where roles grant flat permission sets, ReBAC models permissions as relationships between users and resources, enabling fine-grained, hierarchical access control.OpenFGA is the open-source implementation of Google’s Zanzibar authorization system. It evaluates permission checks in single-digit milliseconds, making it suitable for per-request authorization in API endpoints.
Core Concepts
Relationship Tuples
Relationship Tuples
A relationship tuple is the fundamental building block. It states: “This user/group has this relation on this resource.”Tuples are stored in OpenFGA and queried during permission checks.
Resource Types
Resource Types
The authorization model defines types for every resource in the platform:
| Type | Service | Description |
|---|---|---|
organization | Governance | Top-level tenant boundary |
project | Governance | Resource grouping within an organization |
artifact | Assets | Generated outputs (reports, visualizations) |
file | Assets | Uploaded files and documents |
data_connection | Assets | External data source connections |
mcp_server | Assets | Model Context Protocol servers |
api_server | Assets | API server registrations |
model | Assets | ML model registrations |
Relations (Roles)
Relations (Roles)
Relations represent the roles a user or group can have on a resource:
| Relation | Scope | Description |
|---|---|---|
owner | All types | Full control including deletion |
admin | Organization, Project | Administrative access, user/project management |
member | Organization | Standard membership with read access |
developer | Project, Resources | Create and manage resources |
operator | Project, Resources | Execute and operate resources |
viewer | Project, Resources | Read-only access |
Computed Permissions
Computed Permissions
Computed permissions are derived from relations using OR logic. For example, The full set of computed permissions:
can_read is granted to anyone with viewer, operator, developer, admin, or owner relation:| Permission | Description |
|---|---|
can_read | View the resource |
can_write | Modify the resource |
can_delete | Remove the resource |
can_execute | Run/invoke the resource (agents, MCP servers, data connections) |
can_create_resources | Create child resources (project-level) |
can_share | Share with other users |
can_read_secrets | View associated secrets |
can_manage_secrets | Create/update/delete secrets |
can_read_metadata | View resource metadata |
can_manage_metadata | Modify resource metadata |
can_manage_projects | Create/delete projects (organization-level) |
can_manage_users | Manage user memberships (organization-level) |
Permission Inheritance
The authorization model uses OpenFGA’sfrom keyword to implement hierarchical permission inheritance:
admin automatically has appropriate access to all projects and resources within their organization, without needing explicit tuples on each resource:
Computed delegation: can_delete from project
For resource types like data_connection, the schema computes resource-level permissions from project-level permissions. For example, can_delete on a data connection is satisfied if the user has delete rights on the parent project:
can_delete on every project (via the org-from-project chain above) can also delete every project-scoped resource without per-resource tuples.
Service worker permissions on data_connection
Service workers (background tasks like the data-readiness worker, scheduled enrichment runs, and dataset sync jobs) need to invoke data connections. The schema grants can_execute on data_connection to the service-worker role at the project level so workers can POST /assets/data/{resource_uri}/verify and GET /assets/data/{resource_uri}/secret against any connection in their assigned project, without needing a per-connection tuple.
This follows the same pattern as can_create_resources on project for service workers: a single role binding at the parent grants narrow operational permissions across all child resources.
Authorization Schema (OpenFGA DSL)
The schema is defined inopenfga-schema.fga and compiled to openfga-schema.json for runtime use. Here is a simplified excerpt showing the project type:
The require_permission Pattern
All API endpoints use therequire_permission() dependency to enforce authorization. This is implemented in the shared common package and used consistently across all services:
Permission Check Flow
Whenrequire_permission() is invoked, the following occurs:
Extract Resource ID
The resource ID is resolved from path parameters, query parameters, or headers based on the configuration.
Get Auth Context
The
Auth object is extracted from the validated JWT, providing sub (user ID) and teams (group memberships).Check OpenFGA
The permission checker queries OpenFGA with:
- User:
user:{sub}and eachgroup:{group_name}#member - Relation: The computed permission (e.g.,
can_delete) - Object:
{resource_type}:{resource_id}
true, access is granted.Permission API
The Governance service exposes a Permissions API for programmatic permission management:| Endpoint | Method | Description |
|---|---|---|
/governance/permissions/check | GET | Check if a user has a specific permission on a resource |
/governance/permissions/grant | POST | Grant a relation to a user or group on a resource |
/governance/permissions/revoke | POST | Revoke a relation from a user or group |
/governance/permissions/set-parent | POST | Establish a parent-child relationship for inheritance |
/governance/permissions/delete-all | POST | Remove all permission tuples for a resource (cleanup) |
Keycloak Groups and OpenFGA
The bridge between Keycloak (identity) and OpenFGA (authorization) is Keycloak groups:- Users are assigned to groups in Keycloak (e.g.,
org-admins,project-developers) - A groups mapper on the realm ensures group memberships appear in the JWT
groupsclaim - During bootstrap, permission tuples map groups to OpenFGA relations (e.g.,
group:org-admins#member->adminonorganization) - At runtime,
require_permission()checks both the user’s direct tuples and their group-based tuples
Next Steps
Authentication
Understand how JWT tokens carry group claims for authorization.
Organizations
See how organization-level permissions are bootstrapped.
Projects
Learn about project-level role assignments and inheritance.
Multi-Tenancy
Explore the full tenant isolation architecture.

