Team Onboarding
Olyron CRM is multi-tenant: everyone who works in your workspace is a member of your organization (a tenant) with a specific role. This guide covers how members are added, what each role can do, and how admins change roles or deactivate people from the Team Management screen.
#How membership works
Every workspace in Olyron CRM is a tenant. Membership is stored one row per person per workspace in the tenant_users table, which links a Supabase auth user to a tenant, carries their role, and tracks a status. A person can belong to more than one workspace and switch between them.
When you first create your organization during onboarding, the atomic create_tenant_with_user database function inserts you into tenant_users with role org_owner and status active. That founding owner is the seat every other member is added from.
tenant_iduuid- The workspace this membership belongs to. Every row is scoped to one tenant.
user_iduuid- The Supabase auth user. Inviting someone creates the auth user if they do not already have an account, then attaches this membership row.
roleuser_role enum- One of org_owner, agency_admin, lead_manager, advisor, staff, or read_only. Defaults to advisor.
statususer_status enum- One of active, invited, or inactive. Only active members can sign in and act in the workspace.
joined_at / invited_at / invited_bytimestamptz / uuid- Audit timestamps and the user who added them. joined_at is set when a member becomes active.
#Roles and what they can do
Olyron CRM ships six roles. Two of them (org_owner and agency_admin) are administrators who can manage the team and organization settings; the rest are operational roles with progressively narrower access. Capabilities are defined in src/lib/rbac/capabilities.ts.
| Role | Level | Typical use | Can manage team? |
|---|---|---|---|
| org_owner | 5 | Founder / final authority; only role that can delete the organization | Yes |
| agency_admin | 4 | Operations lead with full admin capabilities | Yes |
| lead_manager | — | Owns lead routing, SLAs, targets, and the lead-manager dashboard | No |
| advisor | 3 | Front-line advisor working their own book and reports | No |
| staff | 2 | Support staff with self-scoped report access | No |
| read_only | 1 | View-only self reports | No |
Capability highlights
- org_owner and agency_admin hold every CRM capability, including leads.assign, leads.override, reports.view_all, reports.export, and all settings.* (round_robin, business_hours, sla, targets, email_ab) plus sla.override.
- lead_manager holds the same operational set as admins for lead work (assign, override, all settings.*, sla.override, lead_manager.dashboard) but is not a team administrator.
- advisor can view and export only their own reports (reports.view_self, reports.export).
- staff and read_only are limited to reports.view_self.
lead_manager role was added after the original hierarchy in src/lib/tenant.ts (read_only < staff < advisor < agency_admin < org_owner). It has rich capabilities via the RBAC map but is not ranked by hasMinimumRole, so guard code that relies on a minimum numeric level treats it as level 0. Prefer capability checks over level comparisons when gating lead-manager features.#Adding and onboarding a member
Team Management lives at /dashboard/settings/team. The invite form and the member actions are only shown to administrators (org_owner or agency_admin); everyone else sees a read-only roster.
- 1Open Team ManagementAs an org_owner or agency_admin, go to Settings, then Team (/dashboard/settings/team). You'll see the Invite Team Member form above the member roster.
- 2Enter the email and choose a roleType the teammate's email and pick a role from the dropdown. Advisor, Staff, and Read Only are always available; Lead Manager appears for admins; Agency Admin is offered only to an org_owner. Org Owner cannot be assigned from the invite form.
- 3Send the inviteSubmit the form. The server creates or finds their auth user, writes a tenant_users row with status invited, and sends a transactional invite email through Resend. Success is reported only after Resend accepts the message. Pending invites appear on the roster with a Resend action.
- 4They accept the linkThe invitee clicks Accept invite, which signs them in and flips their membership to active so they can open the workspace. Expired links can be resent from the roster.
#Changing roles and removing members
From the member roster, administrators can change any teammate's role inline or deactivate them. Both actions write directly to the tenant_users row and take effect immediately.
Change a role
- Use the role dropdown next to a member to switch them between Advisor, Staff, and Read Only at any admin level.
- org_owner and agency_admin can additionally assign Lead Manager.
- Only an org_owner can assign Agency Admin or Org Owner.
- You cannot change your own role from this screen — the role control is hidden for the currently signed-in user to prevent self-lockout.
Remove a member
The Remove action does not delete the row; it sets the member's status to inactive. Inactive members are filtered out of the roster and can no longer resolve tenant access, because membership resolution requires status = 'active'. Invite their email again to restore them — they come back as invited until they accept the new link.
#Organization-level admin actions
Beyond the team roster, a few organization-wide actions are gated by role at the API layer. These are enforced server-side in /api/organization regardless of what the UI shows.
| Action | Endpoint | Required role |
|---|---|---|
| View organization + your role | GET /api/organization | Any active member |
| Update name, slug, branding, settings | PUT /api/organization | org_owner or agency_admin |
| Delete the organization | DELETE /api/organization?confirm=DELETE | org_owner only |
# Only the org_owner can do this, and the confirm token is mandatory.
curl -X DELETE "https://<your-workspace>/api/organization?confirm=DELETE" \
-H "Cookie: <authenticated session>"
# Missing or wrong confirm value returns HTTP 400:
# { "error": "Deletion must be confirmed with ?confirm=DELETE" }#Members in more than one workspace
Because membership is per-tenant, one person can belong to several workspaces — for example an agency admin who also advises inside a partner org. Olyron tracks the active workspace with the active_tenant_id cookie (or an x-tenant-id request header).
- When resolving which workspace a request runs in, Olyron honors the preferred tenant from the cookie or header if you are an active member there.
- If no preferred workspace is set, it falls back to your most recently joined active membership (highest joined_at).
- Your role is resolved per workspace, so the same person can be an org_owner in one tenant and an advisor in another.