Organizations, roles and permissions
Organizations are the companies and teams your users belong to. They are off until you turn them on in the dashboard (Organizations, Settings); with them off, the Backend API and the dashboard still manage them, but sessions have no active organization.
The active organization
Section titled “The active organization”A session has one active organization, or none (the user’s personal account). The session token carries it in
its o claim: the organization’s id, its slug (when slugs are on), the user’s role in it and that role’s custom
permissions. Your frontend changes it with setActive({ organization }); the next token carries the new one.
When the instance requires a membership (on by default once organizations are on), every session needs an active
organization: a session without one is pending with the task choose_organization, a user cannot switch to the
personal account, and they cannot leave or delete their last organization
(personal_accounts_not_allowed).
Roles and permissions
Section titled “Roles and permissions”Each instance starts with two roles: org:admin, with every system permission, and org:member, who can see the
organization’s members. The system permissions are fixed:
| Permission | Allows |
|---|---|
org:sys_profile:manage |
Changing the organization’s name, slug and settings |
org:sys_profile:delete |
Deleting the organization |
org:sys_memberships:read |
Seeing its members |
org:sys_memberships:manage |
Inviting, removing and changing members |
Add your own roles and custom permissions (org:<feature>:<action>, such as org:invoices:read) on the
dashboard’s Roles & permissions page or with the Backend API. A role’s custom permissions travel in the session
token (up to 1 KB of them); system permissions never do.
An organization always keeps a member who can manage its members and delete it; the role new organizations’ creators
get (the creator role, org:admin by default) must have those permissions too
(organization_minimum_permissions_needed).
Checking access
Section titled “Checking access”Every SDK answers has({ role }) and has({ permission }) the same way, from the session token alone: full keys
(org:admin, org:invoices:read), false without an active organization, and always false for a system permission,
which is never in the token. Every condition given must hold; has({}) is false.
// Your server (@zautha/backend, @zautha/nextjs)if (!auth.has({ permission: "org:invoices:read" })) return new Response(null, { status: 403 });Your frontend’s <Show when={{ permission: "org:invoices:read" }}> only hides UI; check the same permission on your
server. A role or permission change reaches the token at its next renewal, within a minute.
Invitations
Section titled “Invitations”An administrator invites people by email from your app (the components), the dashboard or the Backend API, up to 10
at a time. The invitation email links to the hosted login’s /invitation page, which signs the invited address in or
up and makes them a member. With the Backend API you can send no email (notify: false) and deliver the link
yourself: only the response that creates an invitation carries its url. An invitation expires after 30 days by
default (1 to 365).
Self-service
Section titled “Self-service”Users can create organizations, unless the instance turns it off, up to the instance’s per-user limit (100 by
default). Members manage an organization as their role allows; whether they may delete it is the organization’s
admin_delete_enabled. An organization’s member limit (max_allowed_memberships) counts members and pending
invitations.
On the Free plan a production instance can have a limited number of organizations; see Pricing. Every change sends an organization webhook.