Overview
BunShip uses an organization-based multi-tenancy model. Every resource in the system — projects, webhooks, API keys, subscriptions, audit logs — belongs to an organization. Users access resources through their organization membership, and each membership carries a role that determines what the user can do.Data Model
Three database tables form the foundation of the multi-tenant system:- Organizations
- Memberships
- Invitations
deletedAt. All queries filter out soft-deleted organizations automatically.Creating an Organization
When a user creates an organization, they automatically become the owner:- Validate the name and slug (slug must be unique)
- Insert the organization record
- Create a membership with
role: "owner"for the creating user - Return the organization with the user’s membership
Configuration Limits
These are set in
featuresConfig.organizations and can be adjusted:
Team Management
Inviting Members
Users with themembers:invite permission can invite new team members by email:
1
Send invitation
An admin or owner sends an invitation specifying the email and desired role. The API generates a secure token, hashes it, and stores the invitation record.
2
Email delivered
BunShip sends a transactional email with an invitation link containing the plaintext token.
3
Accept invitation
The invitee clicks the link and calls the accept endpoint. If they already have an account, they are added to the organization. If not, they register first, then accept.
4
Membership created
A membership record is created with the role specified in the invitation. The invitation’s
acceptedAt timestamp is set.Roles
Every membership carries one of four roles. Roles determine what permissions the user has within the organization. See Permissions for the complete permission matrix.Updating Roles
Users with themembers:update permission can change another member’s role:
Removing Members
Users with themembers:remove permission can remove team members:
Organization-Scoped Data
All resources in BunShip are scoped to an organization through a foreign key:Organization Middleware
TheorganizationMiddleware runs on every organization-scoped route. It performs two database lookups in sequence:
- Load the organization by the
:orgIdURL parameter, filtering out soft-deleted records - Load the user’s membership to confirm they belong to this organization
organization and membership from the context without additional database queries.
Organization Settings
Each organization has a JSONsettings column that stores optional configuration:

