Skip to main content

Access rules

Override channel and channel group permissions for specific roles or members.

What are access rules?

An access rule is a permission override that applies to a specific combination of:

  • A subject: a role or community member
  • A target: a channel or channel group
  • An overlay: a set of permission overrides

When you create an access rule, you specify which permissions to allow, deny, or leave unchanged. Root applies this overlay whenever the subject accesses the target.

One access rule connects exactly one subject to one target. To affect multiple subjects or targets, create multiple access rules.

The overlay tri-state

Each permission in an overlay has three possible states:

ValueEffect
trueExplicitly allow this permission
falseExplicitly deny this permission
undefinedNo change; keep the current value

This tri-state model lets you grant specific permissions, restrict others, and leave the rest unchanged:

const overlay: ChannelOverlayPermission = {
channelView: true, // Explicitly allow
channelCreateMessage: true, // Explicitly allow
channelCreateFile: false, // Explicitly deny
// All other permissions: undefined (no change)
};

The channelView permission controls visibility as well as access. Setting channelView: true makes a hidden channel visible to the subject; setting channelView: false hides a channel the subject would otherwise see.

How access rules work

When your code creates or modifies access rules, you need to understand how Root combines them with base permissions. This helps you:

  • Design overlays that achieve the behavior you want
  • Predict how multiple access rules will interact
  • Debug permission errors by tracing where a permission was granted or denied

Root calculates effective permissions through four stages.

Step 1: Initialize from base permissions

Root creates the starting permission set by merging your manifest permissions with permissions from your assigned roles using OR logic: if any source grants a permission, it's allowed. A role cannot remove a permission your manifest declares, and your manifest cannot remove a permission a role grants.

For example, if your manifest declares CreateMessage and CreateFile, and the @EVERYONE role grants ViewFile:

PermissionManifest@EVERYONE roleResult
CreateMessagetruefalsetrue
CreateFiletruefalsetrue
ViewFilefalsetruetrue
All othersfalsefalsefalse

Any true in a row means the result is true. The role's lack of CreateFile doesn't matter because the manifest grants it.

This is how your code differs from human members: humans get base permissions from roles only, while your code gets permissions from both its manifest and its roles.

Step 2: Find applicable access rules

Root looks up access rules for the target channel or channel group. For channels, which rules apply depends on the channel's inheritance setting:

  • Inherits from group: The channel uses access rules defined on its parent channel group. Any access rules on the channel itself are ignored.
  • Independent permissions: The channel uses only access rules defined directly on it. The parent group's access rules don't apply.

This is either/or—there's no cascading where both group and channel rules combine.

Step 3: Apply role-based overlays

Root collects every access rule that targets a role your code has, then merges their overlays per permission:

  • Any role allows it (true): the permission is allowed, even if other roles deny it.
  • No role allows it, but at least one denies it (false): the permission is denied.
  • All roles leave it undefined: the current value from Step 1 stays unchanged.

Step 4: Apply member-specific overlay

If an access rule targets your code directly (by member ID rather than role), Root applies its overlay last. For each permission in the overlay:

  • true: the permission is allowed, regardless of what Steps 1–3 produced.
  • false: the permission is denied, regardless of what Steps 1–3 produced.
  • undefined: no change; the value from Step 3 stays.

The final permission set determines what your code can do on that channel.

Examples

Inheritance controls which rules apply

This example demonstrates Step 2: how a channel's inheritance setting determines which access rules Root applies.

Suppose your manifest requests CreateFile for your code. The community's "Media" channel group contains two channels with different inheritance settings:

  • The access rule on "Media" targets the @EVERYONE role: { channelCreateFile: false }.
  • #chat inherits from the group, so the group's access rules apply.
  • #uploads uses independent permissions, so the group's access rules don't apply.

#chat (inherits from group):

StepCreateFile
Base permissiontrue
@EVERYONE role overlay (from "Media")false
Resultdenied

Only one role overlay applies here. If multiple roles had overlays, Root would merge them with OR logic (see Step 3).

#uploads (independent permissions):

StepCreateFile
Base permissiontrue
No overlay applies
Resultallowed

The group's overlay only reaches #chat because it inherits from the group. #uploads uses independent permissions, so the group overlay doesn't apply.

Member overlays override role overlays

This example demonstrates Steps 3 and 4: when a role overlay and a member overlay conflict on the same channel, the member overlay wins.

Suppose your manifest requests CreateMessage for your code. The community's #announcements channel has two access rules that conflict:

  • The role-based rule denies CreateMessage for @EVERYONE (Step 3).
  • The member-specific rule allows CreateMessage for your code (Step 4).
StepCreateMessage
Base permissiontrue
@EVERYONE role overlayfalse
Member overlay (your code)true
Resultallowed

The role overlay denies CreateMessage, but the member overlay runs last and overrides it.

When to use access rules

Use access rules when your code needs different permissions in different places:

  • Create private spaces: Grant channelView and channelCreateMessage to specific members on a channel, giving them access to a space that's hidden from others.
  • Lock a channel during incidents: Deny channelCreateMessage to the @EVERYONE role when your code detects spam or abuse, then remove the access rule when it's safe.

If your code needs the same permissions everywhere, configure roles instead. Access rules are for targeted overrides on specific channels or channel groups.

Troubleshooting

When your code gets an unexpected permission error:

  1. Check base permissions: Does your manifest declare the required permission? Does any assigned role grant it?
  2. Check visibility: Can your code see the channel? Call ChannelClient.list() and verify the channel appears in the response.
  3. Check access rules: Call AccessRuleClient.listByChannelOrChannelGroup() to see what overlays apply to the target.
  4. Check inheritance: Is the channel inheriting from its group or using independent permissions? The wrong access rules might be applying.
  5. Check for member overrides: A member-specific access rule always wins over role-based rules.