Trovella Wiki

Organization Types

The three organization types (personal, family, company) and how they affect permissions and collaboration.

Trovella supports three organization types. The type determines whether collaboration features (invitations, adding members) are available and influences CASL permission rules.

The Three Types

TypePurposeCollaborationCreated By
personalSingle-user workspace, auto-created on first sign-inNo -- member creation and invitations are blockedSystem (bootstrapping)
familyShared workspace for household membersYesUser (future)
companyTeam workspace for professional useYesUser (future)

Schema Definition

The type is stored as a text column on the organization table with a default of "personal":

// packages/db/src/schema/auth.ts
export const organization = pgTable("organization", {
  id: text("id").primaryKey(),
  name: text("name").notNull(),
  slug: text("slug").notNull().unique(),
  logo: text("logo"),
  createdAt: timestamp("created_at").notNull(),
  metadata: text("metadata"),
  type: text("type").default("personal"),
});

A tenant_type enum also exists in packages/db/src/schema/enums.ts for reference, but the auth schema uses a plain text column because Better Auth's organization plugin manages the table definition. The allowed values are "personal", "family", and "company".

How Type Affects Permissions

The CASL ability builder in packages/api/src/abilities/define-ability.ts checks the organization type to restrict collaboration in personal orgs:

// Personal orgs: no collaboration
if (ctx.orgType === "personal") {
  cannot("create", "Member");
  cannot("manage", "Invitation");
}

This means that even an owner of a personal organization cannot invite others or add members. The restriction applies regardless of role. Family and company organizations have no such restriction -- their permissions follow the standard role matrix.

For the full role-permission matrix, see Identity & Access -- Authorization.

How Type Is Set

  • Personal organizations are created by ensurePersonalOrganization in packages/auth/src/server.ts. The type is embedded in the metadata field as JSON.stringify({ type: "personal" }) and also set via the Better Auth plugin's additionalFields.type default.
  • Family and company organizations will be created through the Better Auth organization client API (exposed via authClient from @repo/auth/client). This flow is not yet implemented -- MVP focuses on personal organizations only.

Where Type Is Read

The organization type is read in authorizedProcedure (in packages/api/src/trpc.ts) when building the CASL ability:

const org = await ctx.db.query.organization.findFirst({
  where: eq(organization.id, ctx.organizationId),
  columns: { type: true },
});

const ability = defineAbilityFor({
  userId: ctx.session.user.id,
  role: memberRecord.role,
  orgType: (org?.type ?? "personal") as OrgType,
});

If the type is missing (null), it defaults to "personal" -- the most restrictive option.

MVP Scope

For MVP, only personal organizations exist. Family and company organization creation will be added when the product roadmap calls for multi-user collaboration. The type system is in place now so that the permission model and RLS behavior do not need to change when collaboration is added.

On this page