Omnibase

RBAC Overview

Role-based access control in OmniBase

Role-Based Access Control (RBAC)

OmniBase uses a fine-grained, relationship-based access control (ReBAC) system powered by Ory Keto. Each tenant has its own set of roles with configurable permissions.

UI Components

OmniBase provides pre-built shadcn components in @omnibase/shadcn:

ComponentDescription
RoleCreatorCreate and edit roles with permission selector
PermissionsSelectorLow-level permission picker for namespaces and relations
UserViewerView team members and manage role assignments

See Role Configuration for usage examples.

How It Works

Permissions are stored as relationship tuples:

(Namespace, Object, Relation, Subject)

Examples:

(Tenant, acme-corp-uuid, delete_tenant, User:alice)
(Tenant, acme-corp-uuid, invite_user, User:bob)
(Project, proj-123-uuid, can_write, User:carol)

When checking permissions, OmniBase verifies the relationship exists between the subject and object.

Key Concepts

Tenant Permissions vs Resource Permissions

Only tenant# permissions support auto-scoping. The active tenant ID is automatically injected when checking these permissions.

TypeFormatAuto-Scoped
Tenant permissionstenant#relationYes - uses active tenant
Resource permissions(Namespace, uuid, relation, subject)No - requires explicit UUID

No Resource-Wide Wildcards

There is no project#can_read permission that grants access to all projects. Resource permissions always require a specific UUID.

To grant access to resources like projects or documents, you must create relationships for each resource individually:

// Grant access to a specific project
await permissionsApi.createRelationship({
  createRelationshipRequest: {
    namespace: 'Project',
    object: projectId,        // Specific project UUID
    relation: 'can_write',
    subjectId: userId,
    subjectNamespace: 'User',
  },
});

RBAC Guides

Quick Example

import { V1PermissionsApi } from '@omnibase/core-js';

const permissionsApi = new V1PermissionsApi(config);

// Check if user can delete tenant (auto-scoped to active tenant)
const { data } = await permissionsApi.checkPermission({
  checkPermissionRequest: {
    namespace: 'Tenant',
    object: tenantId,
    relation: 'delete_tenant',
    subjectId: userId,
    subjectNamespace: 'User',
  },
});

if (data.data.allowed) {
  // User has permission
}

On this page