Overview
BunShip enforces access control through a role-based permission system. Every organization member has a role, and each role maps to a set of permissions. Middleware checks these permissions before a route handler executes, so unauthorized requests never reach your business logic.Role Hierarchy
Four built-in roles are ordered from most to least privileged:Permission Definitions
Every permission follows the patternresource:action. A wildcard suffix (resource:*) grants all actions for that resource. The global wildcard (*) grants every permission.
Role-Permission Matrix
The mapping from roles to permissions is defined infeaturesConfig.organizations.permissions:
How Permissions Are Checked
BunShip provides two middleware functions for access control:requirePermission() for permission-based checks and requireRole() for role-based checks.
Permission Check
requirePermission() reads the user’s role from their membership, looks up the role’s permission list, and runs it through the hasPermission() function:
Permission Resolution Logic
ThehasPermission() function checks three levels of matching:
["*"]) passes every check, and admin’s "members:*" grants "members:read", "members:invite", "members:update", and "members:remove" in a single entry.
Role Check
For cases where you need to restrict by role name rather than permission, userequireRole():
Using Permission Middleware in Routes
A typical organization-scoped route chains the middleware in order:Adding Custom Roles
To add a new role (for example,billing-admin with access to billing and org settings):
1
Add the role to the features config
2
Update the database enum
Add the new role to the membership and invitation schema enums:
3
Generate and run a migration
requirePermission() and requireRole() functions will pick up the new role automatically because they read from featuresConfig at runtime.
Adding Custom Permissions
To protect a new resource type (for example,reports):
1
Define the permissions
2
Assign permissions to roles
3
Use in routes
Permission is derived from the permissions object keys.API Key Scopes
API keys use a separate scope system from RBAC permissions. Scopes follow aaction:resource format (note the reversed order compared to RBAC permissions):
How Scopes Relate to Permissions
When an API key is used for authentication, the system checks both that the key is valid and that its scopes cover the requested operation. A key with
["read:projects"] can list projects but cannot create or delete them.
API key scopes are deliberately more coarse-grained than RBAC permissions. A
write:projects
scope grants create, update, and delete in one entry, while RBAC separates these into individual
permissions. This keeps key creation simple for integrators.Utility Functions
The@bunship/config package exports several helper functions for working with permissions programmatically:

