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

# Roles and Permissions

> Four account roles, seven actions, eleven resource types — and why grants, not role escalation, are the tool for narrowing access

Authorization on Noorle is a role plus a set of explicit grants, evaluated per operation. The role is a coarse default; grants are how you say something precise.

## The four roles

| Role           | What the role alone authorizes                      |
| -------------- | --------------------------------------------------- |
| **Owner**      | Every action except resolving an autonomy gate      |
| **Admin**      | Every action except resolving an autonomy gate      |
| **Member**     | Every action except **delete** and gate resolution  |
| **Restricted** | **Nothing.** Access comes only from explicit grants |

That is the entire role model. There is no Developer role, no custom roles, and no groups.

<Note>
  Owner and Admin have the same authority from the role. The distinction between them is organizational, not a difference in what the authorization layer permits.
</Note>

**Restricted is the useful one.** It is not a punishment tier — it is the starting point for a principal you intend to scope precisely, especially a service account. Give it Restricted and exactly the grants it needs, and it can do that and nothing else.

## Actions

Seven, and they are the complete set:

| Action         | Applies to   |
| -------------- | ------------ |
| `list`         | A collection |
| `create`       | A collection |
| `read`         | One item     |
| `write`        | One item     |
| `delete`       | One item     |
| `execute`      | One item     |
| `resolve_gate` | One agent    |

`resolve_gate` is deliberately special. It is the authority to submit the approve-or-deny decision on an autonomy gate — something Noorle otherwise reserves for a human user. **No role implies it, not even Owner.** It can only arrive through an explicit grant, and it can only be granted on an agent.

## Resource types

Eleven: `Account`, `Capability`, `Agent`, `Channel`, `McpGateway`, `User`, `ServiceAccount`, `ApiKey`, `Thread`, `Workflow`, `ConnectedApp`.

Not every action is valid on every type. `Account` allows only `list`, `read`, and `write` — there is no create or delete path for an account through this layer. `Agent` is the only type that allows `resolve_gate`. A grant carrying an action the resource type does not allow is rejected when it is created, not silently ignored later.

## Grants

A grant is a resource plus a permission set. The resource is either a **collection** ("all agents") or a specific **item** ("this agent").

Collection and item grants do not interchange. A grant on the agents collection does not authorize an operation on one specific agent, and an item grant does not authorize a collection listing. If you want both, grant both.

```mermaid theme={null}
graph TD
    Q["May this principal do X to Y?"]
    Q --> R{"Role authorizes it?"}
    R -->|yes| A["Allow"]
    R -->|no| G{"A matching grant?"}
    G -->|yes| A
    G -->|no| D["Deny — 403"]
```

## How a decision is actually made

Handlers do not evaluate authority themselves. Each one builds an identity context at the edge and calls a per-resource management service, which **re-reads role and grants for that operation**. Nothing is frozen for the duration of a request, so a permission change takes effect immediately rather than at the next login.

For a listing, authority resolves to a scope. A scope that matches nothing is a **403**, the same as a point denial — not an empty list, which would leak the fact that nothing matched.

**403 versus 404.** An authority denial is 403. A resource that does not exist under your account is 404. Validation runs only after authority succeeds, so a caller who is denied cannot use error shapes to discover what exists.

## Denials

Separately from grants, an account can carry **deny** entries that block specific tools on specific capabilities. Denies are evaluated *before* policy in the admission door and cannot be overridden by any grant — the rule is: union of allows, minus matching denies, and a deny never grants.

A deny matches if it covers **any** identity the call carries. That includes the delegation chain: a deny naming a human also applies to a sub-agent acting on their behalf.

This is also the one place a decision changes retroactively. If an admin writes a deny while a tool call sits parked waiting for approval, the deny wins when the call resumes — it is re-checked ahead of the recorded human decision.

## API keys and principals

An API key holds no permissions of its own. It identifies a principal, and that principal's role and grants decide everything.

The consequence, worth repeating because it changes how you set things up: **you scope a key by scoping the principal.** Create a service account, set it Restricted, grant it precisely what it needs, then issue its key.

## Connected apps

A third-party app acts with the authority of the principal that authorized it. It cannot exceed that — authorizing an app never elevates anything.

## What is not built

Stated plainly so you do not plan around it:

* **No custom roles.** The four are the four.
* **No groups or teams** as an authorization construct. Grants attach to principals.
* **No per-resource sharing UI.** Access to a specific agent or gateway is expressed as a grant on that principal, not as a share.
* **No per-API-key scope.** Scoping happens on the principal.

## Practical shapes

**A backend integration.** A service account, Restricted, with `execute` on the one agent it invokes. Nothing else in the account is reachable, and its API key cannot be used to explore.

**A contractor.** A user at Restricted with `read` and `execute` grants on the specific agents they need. When the engagement ends, remove the grants — the principal itself can stay for the audit trail.

**A product resolving gates on its users' behalf.** A service principal granted `resolve_gate` on the specific agent, which then attaches an attestation identifying the end user it acted for. That attestation is recorded for audit; it is not a Noorle principal and is not treated as one.

**Day-to-day team members.** Member. They can build and run without being able to delete, which is usually the right default.

## Troubleshooting

| Symptom                                        | Cause                                                                                                          |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| 403 on an operation the role should allow      | The action may be `delete` (Member cannot) or `resolve_gate` (no role implies it)                              |
| 403 on a list that should return something     | A list scope matching nothing is a 403, not an empty result. Check for a collection grant.                     |
| 404 on a resource you can see elsewhere        | It is not in this account. The tenancy floor answers before authority does.                                    |
| A grant exists and is still denied             | Check collection versus item — they do not interchange. Then check for a deny entry, which no grant overrides. |
| Approval was granted and the call still failed | A deny written during the pause is re-checked on resume and overrides it.                                      |

***

That is the Learn tab. The [Run tab](/docs/run/introduction) covers doing all of this.
