Permify Schema
Permify has its own language that you can model your authorization logic with it. The language allows to define arbitrary relations between users and objects, such as owner, editor, commenter or roles like admin, manager, member and also dynamic attributes such as boolean variables, IP range, time period, etc.

Developing a Schema
This guide will show how to develop a Permify Schema from scratch with a simple example, yet it will show almost every aspect of our modeling language. We’ll follow a simplified version of the GitHub access control system, where teams and organizations have control over the viewing, editing, or deleting access rights of repositories. Before start I want to share the full implementation of simple Github access control example with using Permify Schema.You can start developing Permify Schema on VSCode. You can install the extension by searching for Perm in the extensions marketplace.
Defining Entities
The very first step to build Permify Schema is creating your Entities. Entity is an object that defines your resources that held role in your permission system. Think of entities as tables in your database. We are strongly advice to name entities same as your database table name that its corresponds. In that way you can easily model and reason your authorization as well as eliminating the error possibility. You can create entities usingentity
keyword. Let’s create some entities according to our example GitHub authorization logic.”
- relations
- actions or permissions
Defining Relations
Relations represent relationships between entities. It’s probably the most critical part of the schema because Permify mostly based on relations between resources and their permissions. Keyword relation need to used to create a entity relation with name and type attributes. Relation Attributes:- name: relation name.
- type: relation type, basically the entity it’s related to (e.g. user, organization, document, etc.)
User Entity
→ The user entity is a mandatory entity in Permify. It generally will be empty but it will used a lot in other entities as a relation type to referencing users.Roles and User Types
You can define user types and roles within the entity. If you specifically want to define a global role, such asadmin
, we advise defining it at the entity with the most global hierarchy, such as an organization. Then, spread it to the rest of the entities to include it within permissions.
For the sake of simplicity, let’s define only 2 user types in an organization, these are administrators and direct members of the organization.
Parent-Child Relationship
→ Let’s say teams can belong organizations and can have a member inside of it as follows,Ownership
In Github workflow, organizations and users can have multiple repositories, so each repository is related with an organization and with users. We can define repository relations as as follows.Multiple Relation Types
As you can see we have new syntax above,user
as well as this user can be a team member
.
You can use # to reach entities relation. When we look at the When you define it like this, you can only add users directly as tuples (you can find out what relation tuples is in next section):You will then be able to specify not only individual users but also members of an organization:
@team#member
it specifies that if the user has a relation with the team, this relation can only be the member
. We called that feature locking, because it basically locks the relation type according to the prefixed entity.Actual purpose of feature locking is to giving ability to specify the sets of users that can be assigned.For example:- organization:1#viewer@user:U1
- organization:1#viewer@user:U2
- organization:1#viewer@user:U1
- organization:1#viewer@user:U2
- organization:1#viewer@organization:O1#member
organization:1#viewer@organization:O1#member
all members of the organization O1 will have the right to perform the relevant action.In other words, all members in O1 now end up having the relevant viewer
relation.You can think of these definitions as a precaution taken against creating undesired user set relationships.Defining Permissions
Actions describe what relations, or relation’s relation can do. Think of actions as permissions of the entity it belongs. So actions defines who can perform a specific action on a resource in which circumstances. The basic form of authorization check in Permify is Can the user U perform action X on a resource Y ?.Intersection and Exclusion
The Permify Schema supportsand
, or
and not
operators to achieve permission intersection and exclusion. The keywords action or permission can be used with those operators to form rules for your authorization logic.
Intersection
Lets get back to our github example and create a read action on repository entity to represent usage ofand
&, or
operators,
read
action rules; user that is organization admin
and following users can read the repository: owner
of the repository, or maintainer
, or member
of the organization which repository belongs to.
The same Using
read
can also be defined using the permission keyword, as follows:action
and permission
will yield the same result for defining permissions in your authorization logic. See why we have 2 keywords for defining an permission from the Nested Hierarchies section.and
operation: it creates an intersection between relations but is not necessarily tied to specific entities.
For example, in the following model, users can see a repository if they are a member or admin of any organization.
Let’s say user:1
is a member of organization:1
and an admin of organization:2
. If repository:1
belongs to organization:1
(via the parent relationship), then user:1
is granted access to edit repository:1
.
Exclusion
After this point, we’ll move beyond the GitHub example and explore more advanced abilities of Permify DSL. Before delving into details, let’s examine thenot
operator and conclude Intersection and Exclusion section.
Here is the post entity from our sample Instagram Authorization Structure example,
restricted
attribute — details of defining attributes can be found in the Attribute Based Permissions (ABAC) section — won’t be able to like or comment on the specific post.
This is a simple example to demonstrate how you can exclude users, resources, or any subject from permissions using the not
operator.
Permission Union
Permify allows you to set permissions that are effectively the union of multiple permission sets. You can define permissions as relations to union all rules that permissions have. Here is an simple demonstration how to achieve permission union in our DSL, you can use actions (or permissions) when defining another action (or permission) like relations,delete
action inherits the rules from the edit
action. By doing that, we’ll be able to state that only organization administrators and any relation capable of performing the edit action (member or manager) can also perform the delete action.
Permission union is super beneficial in scenarios where a user needs to have varied access across different departments or roles.
Let’s examine our modeling guides for common permission use cases.
Attribute Based Permissions (ABAC)
To support Attribute Based Access Control (ABAC) in Permify, we’ve added two main components into our schema language:attribute
and rule
.
Defining Attributes
Attributes are used to define properties for entities in specific data types. For instance, an attribute could be an IP range associated with an organization, defined as a string array:attribute
.
Defining Rules
Rules are structures that allow you to write specific conditions for the model. You can think rules as simple functions of every software language have. They accept parameters and are based on condition to return a true/false result. In the following example schema, a rule could be used to check if a given IP address falls within a specified IP range:Using Attributes Across Entities
This feature is currently in beta and available upon request. Let us know, and we’ll give you early access!
edit
permission of the repository to check whether the organization:X has edit access or not, depending on the authority level it possess.
We design our schema language based on Common Expression Language (CEL). So the syntax looks nearly identical to equivalent expressions in C++, Go, Java, and TypeScript.Please let us know via our Discord channel if you have questions regarding syntax, definitions or any operator you identify not working as expected.
Modeling Guides
Let’s examine our modeling guides for common permission use cases. Role-Based Access Control (RBAC) Relationship Based Access Control (ReBAC) Attribute Based Access Control (ABAC)More Comprehensive Examples
You can check out more comprehensive schema examples from the Real World Examples section. Here is what each example focuses on,- Google Docs: how users can gain direct access to a document through organizational roles or through inherited/nested permissions.
- Facebook Groups: how users can perform various actions based on the roles and permissions within the groups they belong.
- Notion: how one global entity (workspace) can manage access rights in the child entities that belong to it.
- Instagram: how public/private attributes play role in granting access to specific users.
- Mercury: how attributes and rules interact within the hierarchical relationships.