Prood
ApplicationsDashboard

Team Management

Organization members, roles, and invitations in the dashboard.

The dashboard Team page manages organization membership using Better Auth's organization plugin.

Organization model

Each merchant store is a Better Auth organization:

ConceptDescription
OrganizationA merchant store (tenant)
MemberA user belonging to an organization
Roleowner, admin, or member
InvitationPending invite to join an organization

When a merchant registers, Better Auth creates:

  1. A user record
  2. An organization record (the store)
  3. A member record linking the user as owner

Team page

Route: /team

Displays:

  • Current organization name and slug
  • Member list with roles
  • Pending invitations
  • Invite form (email + role)

Member roles

RolePermissions
ownerFull access — manage team, delete org, all admin operations
adminFull admin access — products, orders, integrations, domains
memberRead-only access (future fine-grained permissions)

Inviting members

// Server action
await auth.api.createInvitation({
  body: {
    email: 'colleague@example.com',
    role: 'admin',
    organizationId: activeOrgId,
  },
})

The invited user receives an email (when email provider is configured) or can accept via a direct link.

Organization switching

If a user belongs to multiple organizations, they can switch the active org:

await auth.api.setActiveOrganization({
  body: { organizationId: newOrgId },
})

The session's activeOrganizationId updates, and all subsequent admin API calls scope to the new org.

API scoping

The Commerce API resolves the tenant from the session's active organization:

// apps/api/lib/resolve-caller.ts
const session = await auth.api.getSession({ headers })
const orgId = session.session.activeOrganizationId
// → scopes: ['admin', 'storefront']

All admin endpoints (/v1/admin/*) require the admin scope, which is granted when a valid session with an active organization is present.

Auth tables

Better Auth organization plugin creates:

TablePurpose
organizationStore records (id, name, slug)
memberUser ↔ organization membership with role
invitationPending invitations

These are pushed via pnpm db:auth alongside core auth tables.

On this page