---
title: "Permissions"
---

> This is an experimental feature that is not enabled or enforced yet

Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control.

Permissions do not apply to the user that is flagged as "owner". This user  will always have access to everything.

## General permission structure

Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities.

```python
{
  "entities": …
}
```

Each category can further split into subcategories that describe parts of that category.

```python
{
  "entities": {
    "domains": …,
    "entity_ids": …
  }
}
```

If a category is omitted, the user will not have permission to that category.

When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access.

## Entities

Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids` and `domains`. Granting access to an entity means a user will be able to read the state and control it.

If an entity is specified in both the `entity_ids` and `domains` subcategory, the `entity_ids` result will be used, unless it is `None`. In the following example, the user will have access to all light entities except for `light.kitchen`.

```python
{
  "entities": {
    "domains": {
      "light": True
    },
    "entity_ids": {
      "light.kitchen": False
    }
  }
}
```

## Merging policies

If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology:

1. If any of the values is `True`, the merged value becomes `True`.
2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology.
3. If all values are `None`, the merged value becomes `None`.

Let's look at an example:

```python
{
  "entities": {
    "entity_ids": {
      "light.kitchen": True
    }
  }
}
```

```python
{
  "entities": {
    "entity_ids": True
  }
}
```

Once merged becomes

```python
{
  "entities": {
    "entity_ids": True
  }
}
```
