> ## Documentation Index
> Fetch the complete documentation index at: https://www.osohq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Resource Blocks

Resource blocks define custom types and provide built-in features for writing authorization logic in Polar. They:

* Declare types that can be referenced in rules and facts (including facts stored as data).
* Provide built-in declarations for permissions, roles, and relations, along with shorthand rules for RBAC and ReBAC.

Polar defines two abstract categories for resource blocks:

| Type       | Description                                |
| ---------- | ------------------------------------------ |
| `resource` | An object to which actions can be applied. |
| `actor`    | An entity that can be granted permissions. |

Each type you declare must be labeled as `actor` or `resource`.

Example minimal blocks:

```polar theme={null}
actor User {}  
resource Repository {}  
```

Example with features and shorthand rules:

```polar theme={null}
resource Repository {
  permissions = ["read", "push"];
  roles = ["contributor", "maintainer"];
  relations = { parent: Organization };

  # Shorthand rules

  ## An actor has the "read" permission if they have the "contributor" role.
  "read" if "contributor";
  ## An actor has the "push" permission if they have the "maintainer" role.
  "push" if "maintainer";

  ## An actor has the "contributor" role if they have the "maintainer" role.
  "contributor" if "maintainer";

  ## An actor has the "maintainer" role if they have the "internal_admin" role
  ## on the "parent" Organization.
  "maintainer" if "internal_admin" on "parent";
}
```

## Global Block

A policy can define one `global` block to store permissions and roles accessible from any other resource. This is typically used for global roles.

```polar theme={null}
global {
  roles = ["admin", "member"];
  permissions = ["invite_member", "create_tenant"];

  "create_tenant" if "member";

  "member" if "admin";
  "invite_member" if "admin";
}
```

Reference global values using the `global` keyword:

```polar theme={null}
resource Organization {
  roles = ["internal_admin"];
  permissions = ["read"];

  "internal_admin" if global "admin";
  "read" if "internal_admin";
}
```

## Permissions, Roles, and Relations

These declarations simplify writing RBAC and ReBAC shorthand rules.

| Feature       | Description                                              |
| ------------- | -------------------------------------------------------- |
| `permissions` | Actions that `Actors` can perform on this resource.      |
| `roles`       | Roles an `Actor`s can have in relation to this resource. |
| `relations`   | Links from this resource to other resources.             |

Rules for all three:

* Values must be `String` literals, e.g. `"read"` (case-sensitive).
* Each can be declared at most once per block, i.e. you cannot declare `roles` twice.
* All values across `permissions`, `roles` and `relations` must be unique within the block, e.g. you can't declare `roles` with the value `"writer"` and also declare a `relations` named `"writer"`.
* A feature must be declared before it can be referenced in shorthan

### Permissions

`Permissions` define the actions that `Actor`s can perform on a resource.  They are declared as an array of strings.

```polar theme={null}
resource Repository {
  permissions = ["read", "push"];
}
```

Rules that use permission values expect a `String` matching one of the values declared in `permissions`. For example:

```polar theme={null}
has_permission(actor:Actor, permission:String, resource:Resource)...
```

### Roles

`roles` define `Actor`s in relation to a resource. They are declared as an array of strings.

```polar theme={null}
resource Repository {
  roles = ["contributor", "maintainer", "admin"];
}
```

Rules and facts that use role values expect a `String` matching one of the values declared in `roles`. For example:

```polar theme={null}
has_role(actor:Actor, role:String, resource:Resource)...
```

### Relations

Roles classify the relationship between this and others resources.

`relation` declaration must be key-value pairs, whose:

* Key is an unquoted string (i.e. an identifier)
* Value is the type of the related object

For example:

```polar theme={null}
resource Repository {
  relations = { parent: Organization };
}
```

Rules and facts that use relation values expect `String` for the relation name (e.g. `"parent"`), and a value of the related type (e.g. `Organization`). For example:

```polar theme={null}
has_relation(resource: Repository, relation: String, parent: Organization)...
```

## Shorthand Rules

If a resource block declares `permissions`, `roles`, or `relations`, you can write shorthand rules:

```polar theme={null}
resource Repository {
  permissions = ["read", "push"];
  roles = ["contributor", "maintainer"];
  relations = { parent: Organization };

  # Shorthand rules

  # An actor has the "read" permission if they have the "contributor" role.
  "read" if "contributor";  
  # An actor has the "push" permission if they have the "maintainer" role.
  "push" if "maintainer";

  # An actor has the "contributor" role if they have the "maintainer" role.
  "contributor" if "maintainer";

  # An actor has the "maintainer" role if they have the "internal_admin" role
  # on the "parent" Organization.
  "maintainer" if "internal_admin" on "parent";
}
```

A shorthand rule has the basic form:

```polar theme={null}
<role or permission> if <expression>;
```

The left-hand side of the `if` statement is the result that is granted if the right-hand side evaluates to `true`.

Shorthand rules expand into full rules when loaded.

### Left-Hand Side Expressions

The left-hand side can be:

* A role (`"contributor"`).
* A permission (`"read"`).
* The `role` or `permission` keywords (*any* role or permission).

Each of these expands to a rule head that defines what is being granted. For example, in the shorthand rule `"read" if "contributor";`, the left-hand side `"read"` expands to:

```polar theme={null}
has_permission(actor: Actor, "read", resource: Repository) if ...
```

Because this shorthand rule is defined in the `Repository` resource block, the resource type in the expanded rule is `Repository`.

### Right-Hand Side Expressions

The right-hand side of the `if` statement is an expression that specifies the conditions under which the left-hand side is true.

For most expression types (`roles`, `permissions`, or `relations`), the shorthand rule will only succeed if additional supporting statements—facts or other rules—are present in the policy. These statements must follow the schema of the expanded predicate for that expression (referred to below as `$rhs_pred`)
Examples of valid right-hand sides include:

* A **role** (`"contributor"`). This grants specific permissions to a role (`"read" if "contributor"`).
* A **permission** (`"read"`). This groups common permissions to reduce repetition (`"read.issues" if "read"`).
* A role or permission **on a related resource** (`"reader" on "parent"`). This grants roles or permissions across resource types—assigning a role or permission on one resource to a role on a related resource. The granted role or permission must be declared on the related resource type, and the relation must be declared on the current resource type.
* **Rule call** syntax (`is_public(resource)`). This calls a rule with arguments to check an attribute or condition. The syntax is a rule name followed by a list of arguments. Arguments can be primitive values (strings `"open"` or numbers `0`) or the keyword `resource`, which refers to the resource declared in the enclosing resource block.

Right-hand side expressions can be combined with `and` and `or`.

#### Statements Supporting Right-Hand Side Expressions

Right-hand side expressions other than rule calls (e.g. roles) require additional statements (i.e. facts or additional rules) to succeed.

### Expansion Semantics

Shorthand rules are expanded to full Polar rules when they are loaded.

#### Without Relation

```polar theme={null}
$lhs if $rhs;
=> $lhs_pred(actor: Actor, $lhs, resource: $Type) if $rhs_pred(actor, $rhs, resource);
```

In the expanded form, `$lhs_pred` and `$rhs_pred` are derived from the shorthand expression types of `$lhs` and `$rhs`:

| Shorthand expression type | Expanded predicate |
| ------------------------- | ------------------ |
| Permission                | `has_permission`   |
| Role                      | `has_role`         |

The `$Type` in the `resource` position is the type declared by the enclosing resource block.
For example, in `resource Repository {...}`, `$Type` is `Repository`.

For this shorthand rule to be usable in authorization checks, your policy must also define supporting statements—facts or rules—that match the schema of the right-hand side predicate.

For example:

```polar theme={null}
resource Repository {
  permissions = ["read"];
  roles = ["contributor"];

  "read" if "contributor"; # Shorthand rule
}

# Expanded rule
#                            "read"                        if                 "contributor"           ;
#                              \/                                                  \/
has_permission(actor: Actor, "read", resource: Repository) if has_role(actor, "contributor", resource);
```

To satisfy this rule, include supporting facts such as:

```polar theme={null}
has_role(User{"alice"}, "contributor", Repository{"anvils"})
```

#### With Relation

```polar theme={null}
$lhs if $rhs on $rel;
=> $lhs_pred(actor: Actor, $lhs, resource: $Type) if
  $rhs_pred(actor, $rhs, related) and has_relation(resource, $rel, related);
```

The values of `$lhs_pred` and `$rhs_pred` follow the same semantics as expansion without relation.

`$rel` must be a declared relation on the current resource type. The `has_relation` rule is required to access the `related` object that `$rhs_pred` references.

For this shorthand rule to be usable in authorization checks, your policy must also define supporting statements that match the schema of the right-hand side predicate.

For example:

```polar theme={null}
resource Repository {
  roles = ["admin"];
  relations = {parent: Organization};

  "admin" if "owner" on "parent";
}

# Expanded rule
#                      "admin"                        if                 "owner"
#                        \/                                                \/
has_role(actor: Actor, "admin", resource: Repository) if has_role(actor, "owner", related) and
#                                             on                        "parent"     ||
#                                                                          \/        ||
has_relation(resource, "parent", related);
```

To satisfy this rule, include supporting facts such as:

```polar theme={null}
has_role(User{"alice"}, "owner", Organization{"acme"});
has_relation(Repository{"anvils"}, "parent", Organization{"acme"});
```

#### Global Block Expansion

A global block expands to rules that reference the `Global` type.

```polar theme={null}
$lhs if global $rhs;
=> $lhs_pred(actor: Actor, $lhs, resource: $Type) if $rhs_pred(actor, $rhs);
```

`$lhs_pred` and `$rhs_pred` depend on the shorthand expression type of `$lhs` and `$rhs`:

| Shorthand expression type | Expanded predicate |
| ------------------------- | ------------------ |
| Permission                | `has_permission`   |
| Role                      | `has_role`         |

* To satisfy this rule, add supporting facts matching the right-hand side schema.
* The schema of the right-hand side's expanded predicate differs from non-`global` expansions. `global` right-hand side predicates do not expect a `resource` value.

For example:

```polar theme={null}
resource Organization {
  roles = ["internal_admin"];
  permissions = ["read"];

  "internal_admin" if global "admin";
  "read" if "internal_admin";
}


# Expanded rule
#                        "internal_admin"                            if          global "admin" ;
#                              \/                                                         \/
has_role(actor: Actor, "internal_admin", organization: Organization) if has_role(actor, "admin");
```

Supporting facts:

```polar theme={null}
has_role(User{"alice"}, "admin");
```

## Referencing Resources

Whether declared as an actor`or`resource`, refer to a resource by its type name (e.g., `ResourceName\`) followed by a string identifier in curly braces:

```polar theme={null}
ResourceName{"ident"}
```

This format is called object literal syntax.

## Polymorphism

Polar applies polymorphism within resource blocks:

The abstract type `Actor` works with any type declared in an `actor` block when used in `has_role` or `has_permission`.

`Actor`  is a subtype of `Resource`. Any variable of type `Resource` can also be an `Actor`.\
Because all actors are also resources, we use the term "resource blocks" to cover both.

For details, see [`extends`](/reference/polar/extends) documentation.

## `actor` vs. `resource`

`Actor` is a subtype of `Resource`, meaning any `Actor` can also be used where a `Resource` is expected.\
**- Actor**: something that can be assigned roles or permissions (e.g., `User`, `ServiceAccount`).\
**- Resource**: something you grant permissions to (e.g., `Repository`, `Document`).

Choose based on shorthand rule expansion:

* If it needs to appear as the first argument of `has_role` or `has_permission`, make it an `actor`.
* Otherwise, make it a `resource`.
