Skip to content

Roles & Permissions ​

Shelf has four organization roles. Every member of a workspace holds at least one; the few who hold several are judged by the most privileged (see Precedence below).

RoleIn plain language
OwnerCreated (or was handed) the workspace. Everything an Administrator can do, plus billing, add-ons, SSO/SCIM settings and transferring ownership. Exactly one per workspace.
AdministratorRuns the workspace: catalogue, settings, team, every booking and every custody assignment. Only the Owner can grant, change or revoke it.
Self serviceBooks equipment and takes custody for themselves. Sees and changes their own bookings; sees others' bookings or custody only when the workspace allows it.
BaseRequests bookings for themselves. Cannot take custody. Sees others' bookings or custody only when the workspace allows it.

How a decision is made ​

Two questions, two resolvers, both in @shelf/permissions:

QuestionAnswered by
May this role do action on entity?the permission matrix: userHasPermission (client), requirePermission / requireMobilePermission (server). A member holding several roles gets the union of their grants; Owner and Administrator are allowed everything.
How far does this role reach? Whose bookings, whose custody, which audits, which limits, who hears about what?the role policy table ROLE_POLICIES, read through resolveRoleAccess to a RoleAccess object. It reads the member's single highest-rank role and folds in the workspace's visibility toggles.

Where to get it:

  • Web loaders and actions: const { access } = await requirePermission(…).
  • Mobile API: const { access } = await getMobileUserContext(userId, organizationId).
  • Web components: useRoleAccess() for reach, useOrganizationRoles() + userHasPermission for the matrix.
  • Companion: useRoleAccess() (apps/companion/hooks/use-role-access.ts) from the roles and toggles /api/mobile/me returns.
  • Owner-only actions: isWorkspaceOwner(roles) / access.ownsWorkspace.
  • Prisma audiences: roles: { hasSome: rolesWhere((p) => p.notifications.orgBookingBroadcasts) }.

Never compare role names in app code. The lint rule local-rules/no-direct-role-checks refuses it in the webapp and the companion: a comparison decides for the roles it names and guesses for the rest.

Workspace visibility toggles ​

Settings → Bookings has four switches: Self service can see bookings, Base can see bookings, Self service can see custody, Base can see custody. Each widens what one role may see. None widens what it may change.

Effective access ​

Rendered from the characterization fixture (apps/webapp/app/utils/permissions/__snapshots__/effective-access.json). Do not edit by hand: run pnpm --filter @shelf/webapp docs:roles.

Precedence (a member holding several roles is judged by the highest): Owner > Administrator > Self service > Base.

Reach ​

OwnerAdministratorSelf serviceBase
Sees every booking (toggles off / on)yes / yesyes / yesno / yesno / yes
Sees every custodian (toggles off / on)yes / yesyes / yesno / yesno / yes
Removes booking items inDRAFT, RESERVED, ONGOING, OVERDUEDRAFT, RESERVED, ONGOING, OVERDUEDRAFT, RESERVEDDRAFT
Default asset indexADVANCEDADVANCEDSIMPLESIMPLE

Permission matrix ​

EntityOwnerAdministratorSelf serviceBase
assetcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleread, custodyread
assetIndexSettingscreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolereadread
assetModelcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneread
assetReminderscreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
auditcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleread, updateread, update
auditNotecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, readcreate, read
bookingcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, archive, cancel, extend, manage-assets, manage-kitscreate, read, update, delete, export, manage-assets, manage-kits
bookingNotecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, readcreate, read
categorycreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
command-palette-searchcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolereadread
custodycreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
customFieldcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
dashboardcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
emailSettingscreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
generalSettingscreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
kitcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleread, custodyread
locationcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
locationNotecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
nonRegisteredMembercreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
notecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
qrcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolereadread
reportscreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
scancreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
subscriptioncreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
tagcreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
teamMembercreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
teamMemberNotecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
teamMemberProfilecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone
updatecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolereadread
user-datacreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleread, updateread, update
workingHourscreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolereadread
workspacecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-rolecreate, read, update, delete, checkout, checkin, export, import, archive, cancel, extend, manage-assets, custody, manage-kits, change-roleNoneNone

Adding a role ​

  1. Add the value to the OrganizationRoles enum in packages/database/prisma/schema.prisma and write the migration (ALTER TYPE … ADD VALUE, alone in its file).
  2. Add it to ORGANIZATION_ROLES in packages/permissions/src/roles.ts; the parity check forces both sides to match.
  3. Add its row to Role2PermissionMap (matrix.ts), ROLE_POLICIES (policies.ts) and ROLE_LABELS (roles.ts). All three are total records: the build fails until each has an entry.
  4. If an SSO group can confer it, add an SsoDetails column and its entry in SSO_GROUP_ROLE (apps/webapp/app/utils/sso-group-roles.ts).
  5. Regenerate the fixture and this page, and review every changed row.

Released under the AGPL-3.0 License.