What the built-in roles actually hold
Permission by permission for admin, member and viewer — where the grants come from, the two places the answer is wrong, and the fourth role nobody gets.
Who can see and do what tells you which role to give whom. This article answers the narrower question an access review actually asks: what, exactly, does each built-in role hold? It is longer and less comfortable.
Three roles are created. A fourth is configured and never made
A new organisation is created with exactly three roles: admin (Full organization access), member (Standard member access) and viewer (Read-only access).
Where the grants come from
- The database trigger (the intended source)
- A trigger fires the instant a role row is created — that is, inside the transaction that provisions your organisation. If the role is named
adminit is granted every row in the permissions catalogue, unconditionally, including rows a migration adds next year for a module that does not exist yet. Any other recognised name is granted whatever a policy table lists for it. An unrecognised name is granted nothing, which is how a custom role starts empty. - The application map (the older one)
- A hardcoded map that also runs at organisation creation, listing finite permission sets per role. Its errors are discarded. Everything it grants is added on top of the trigger's work.
The admin case is unaffected by the disagreement, because all of them is a superset of any list. That is the whole reason admin is defined as a wildcard rather than an enumeration: no future migration can lock an organisation's owner out of a new module. The problem is confined to member and viewer.
`admin`
Every permission in the catalogue, present and future. In practice that means everything in this article plus everything in every other module — SIEM, XDR, PAM, AI, billing, licensing, integrations, compliance, the real-time stream and push devices.
admin is also the only role that can mint a delegation, delete a network zone, delete an authentication policy, delete a federation provider, issue a provisioning token, read privileged-session content, or manage cloud discovery credentials.
The practical reading of that: every additional administrator is another account that, if stolen, hands over the whole organisation. Two is the right number for a small firm.
`viewer` — read-only, with two exceptions it should not have
The intended definition is read actions only, and never a read that exposes secret material, money, or a security-administration surface. What it holds:
| Area | Held |
|---|---|
| Identity | users.read, members.read, organizations.read, roles.read |
| Identity administration surfaces | iam:network_zones.read, iam:auth_policies.read, iam:risk.read, iam:swa_apps.read, iam:federation.read |
| Detection and response | Read across SIEM sources, alerts, rules, dashboards and queries; read across XDR endpoints, rules, alerts, incidents and telemetry; siem:risk.read |
| Privileged access | pam:sessions.read and the other PAM read permissions — but not pam:session_content.read, so a viewer cannot obtain a session recording or transcript |
| Elsewhere | Read across AI conversations, licensing, integrations, compliance, the real-time stream and push devices |
| Not intended, and granted anyway | pam:credentials.read and billing:subscriptions.read. Both are named in the policy table as deliberately withheld from viewer, and the application map grants them. See below. |
`member` — the operator role
Everything viewer holds, plus the writes somebody working the queue actually needs.
| Added | So they can |
|---|---|
siem:alerts.write | Triage and update an alert. |
siem:queries.write, siem:dashboards.write | Save an investigative search and build a dashboard. |
xdr:alerts.write, xdr:incidents.write | Work an incident end to end. |
xdr:response_actions.execute | Isolate a machine from the network. This is the one that surprises people — see below. |
compliance:evidence.write | Upload evidence. |
pam:access_requests.write | Raise a privileged-access request. Not approve one. |
ai:conversations.write | Use the assistant. |
push:devices.write | Register their own phone for alerts. |
siem:risk.read, siem:risk.write | Work with risk scoring. |
iam:swa_credentials.write | Save their own password for a vaulted application. |
| Not intended, and granted anyway | api_keys.write, sso.read, integration:webhooks.write, ai:assistants.write. The policy table names all four as admin-only. |
`delegated_admin`, if you create one
The seeded set is consistent and the pattern is the interesting part: read and write, never delete, and never an action that issues a credential.
iam:network_zones.read iam:network_zones.write (not .delete)
iam:auth_policies.read iam:auth_policies.write (not .delete)
iam:risk.read (not .write)
iam:scim.read (not .write)
iam:swa_apps.read iam:swa_apps.write (not .delete)
iam:swa_credentials.write
iam:federation.read iam:federation.write (not .delete)
partner:portfolio.read partner:baselines.read/.writeSomebody who curates your identity configuration can do the day-to-day work without being able to remove a control or hand out a key. Note what is not in that list: users.read, members.read, organizations.read and roles.read. A freshly created delegated_admin cannot list a single person in your organisation until you add those yourself.
Permissions that exist and govern nothing
Four are worth naming, because they appear in the catalogue, can be granted, and change nothing when you grant them.
iam:scim.readandiam:scim.write. The provisioning-token administration you would expect them to govern is gated on thessofamily instead. Granting them has no effect on SCIM.iam:users.readandiam:users.write. One of them is genuinely used, by the endpoint-detection module rather than by identity. Neither governs anything on the identity side, where the bareusers.*family does the work.
Granting them does no harm. Expecting them to do something does — and an access-review document that lists iam:scim.write as the control governing provisioning is describing a control that is not there.
How to check yours, in five minutes
Read the catalogue
GET /api/v1/permissionsreturns every permission the platform defines and needs no permission of its own. Any authenticated user can call it, which is itself worth knowing.Read each role's actual grants
GET /api/v1/roles/{roleID}/permissions, needingroles.read. This is the authoritative answer for your tenant, and the only one.Diff it against this article
Specifically look for
pam:credentials.readandbilling:subscriptions.readonviewer, andapi_keys.write,sso.read,integration:webhooks.writeandai:assistants.writeonmember.Remove what you did not intend
DELETE /api/v1/roles/{roleID}/permissions/{permissionID}, needingroles.write— which requires a fresh second factor, so do it from a session rather than a script. See Step-up authentication.Write down what you removed
A future migration that re-runs the seeding could put them back. Knowing what you removed and why turns that into a five-minute recheck rather than a rediscovery.
The theme of this article, and of The permission model, is the same: names are claims and lists are facts. A role called viewer is read-only because of what is attached to it, not because of what it is called.