ACL: Permission Storage and Inheritance
The ACL (Access Control List) system stores all permissions and handles permission checking at runtime. ACL entries are stored in theacls table, with each row linking a principal to a dataset with a specific permission.
Runtime permission calculation — The system doesn’t store “effective permissions” anywhere—it calculates them on demand by querying ACL entries.
How ACL Works
When a user tries to access data, the system queries all relevant ACL entries and aggregates the permissions. The permission checking functionget_all_user_permission_datasets() unions the user’s direct permissions with those inherited from their tenant and roles, combining all three sources: direct user permissions, tenant-level permissions, and role-level permissions.
This approach ensures permissions are always current and allows for complex permission inheritance without data duplication.
ACL Storage Schema
The ACL system uses a simple but powerful schema to store permissions:ACL Model Fields
ACL Model Fields
The ACL model defines what gets stored in the SQL database. The
acls table contains:Permission Checking Functions
Permission Checking Functions
Permission Resolution Order
The system evaluates permissions in a specific order:- Direct user permissions — Explicitly granted to the user
- Role permissions — Inherited through the user’s role memberships
- Tenant permissions — Inherited through the user’s tenant membership
ACL Operations
The ACL system supports several key operations:- Grant permissions — Add new ACL entries to grant access
- Revoke permissions — Remove ACL entries to revoke access
- Check permissions — Query ACL entries to determine access
- List permissions — Get all permissions for a principal or dataset
Permission Inheritance
The ACL system implements a three-tier inheritance model:- User level — Direct permissions granted to individual users
- Role level — Permissions granted to roles, inherited by role members
- Tenant level — Permissions granted to tenants, inherited by all tenant members
Performance Considerations
The ACL system is designed for performance:- Indexed queries — Database indexes on principal_id, dataset_id, and permission_id
- Efficient lookups — Single query to get all permissions for a user
- Caching opportunities — Permission results can be cached for frequently accessed datasets
- Batch operations — Support for granting/revoking multiple permissions at once
Security Features
The ACL system includes several security features:- Immutable ownership — Dataset ownership cannot be changed
- Permission validation — All permission checks go through the ACL system
- Audit trail — All permission changes are logged with timestamps
- Isolation — Users can only access datasets they have permissions for
Troubleshooting
Common ACL-related issues and solutions:PermissionDeniedError on add or cognify (Error code #403)
PermissionDeniedError on add or cognify (Error code #403)
Error: HTTP API (requires authentication as the dataset owner):To retrieve the user’s
Request owner does not have necessary permission: [write] for all datasets requestedThis error occurs when ENABLE_BACKEND_ACCESS_CONTROL=true and the calling user does not have write permission on the target dataset. This commonly happens when adding data to or running cognify on a dataset owned by a different user.Check the following:- Required permission —
addandcognifyrequirewritepermission on every target dataset. Havingreadaccess is not enough. - ACL entries — Verify that ACL rows actually exist for the expected principal and dataset. If no matching ACL entries exist, the user will not inherit access.
- Role or tenant inheritance — If access should come from a role or tenant, confirm that the user is a member of that role or tenant. Effective permissions are the union of direct user grants plus inherited tenant and role grants.
write, the dataset owner (or any user with share permission on the dataset) must grant it.Python SDK:id, call GET /v1/users/me. To list available datasets and their IDs, call GET /v1/datasets.See Permission Snippets for complete setup examples.Dataset not accessible during delete (Error code #401)
Dataset not accessible during delete (Error code #401)
If you get Grant Wrong user context — When
UnauthorizedDataAccessError: Dataset ... not accessible (401) when deleting data, the most common causes are:delete permission not granted — read and write access are not sufficient for deletion. The delete permission must be granted separately.Verify which datasets a user can delete:delete permission (requires the granting user to have share permission on the dataset):ENABLE_BACKEND_ACCESS_CONTROL is enabled, every operation runs as a specific user. Ensure the user object passed to delete functions is the user that owns or has delete access to the dataset.Dataset owned by another user — Only the dataset owner and users with an explicit delete grant can delete data. If the dataset was created by user1, user2 cannot delete from it without a permission grant from user1.Slow permission checks
Slow permission checks
Review database indexes and query patterns, especially on
principal_id, dataset_id, and permission_id, since those fields drive ACL lookups.Snippets
See practical snippets of ACL operations
Setup Configuration
Learn how to configure ACL and multi-tenant mode