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
| Type | Purpose | Collaboration | Created By |
|---|---|---|---|
personal | Single-user workspace, auto-created on first sign-in | No -- member creation and invitations are blocked | System (bootstrapping) |
family | Shared workspace for household members | Yes | User (future) |
company | Team workspace for professional use | Yes | User (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
ensurePersonalOrganizationinpackages/auth/src/server.ts. The type is embedded in themetadatafield asJSON.stringify({ type: "personal" })and also set via the Better Auth plugin'sadditionalFields.typedefault. - Family and company organizations will be created through the Better Auth organization client API (exposed via
authClientfrom@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.