Leave Localhost logoLeave LocalhostDocs
Recipes

Add a New Permission

Add an app permission key that gates a product action on a member's role, and optionally on a billing capability.

Use an app permission when access depends on a member's role in the workspace. If access depends on what the workspace has paid for, add a capability instead (or as well). The full conceptual guide is Roles and Permissions; this is the short path.

1. Add the catalog entry

In packages/backend/convex/permissions/policy.ts, add one entry to permissionCatalog:

"report.export": {
  roles: ["owner", "admin"],
  betterAuth: { report: ["export"] },
  capabilities: ["feature.pro"], // optional billing gate
  resourcePolicy: "organizationMustBeActive", // optional context check
},

roles decides who may take the action. betterAuth declares the statement Better Auth uses to represent that grant. The catalog derives the Better Auth role objects, app-permission key list, and Convex validator; do not edit any of those generated projections separately.

If the statement uses a new Better Auth resource or action, first add that resource/action to organizationStatements in the same policy module. Add a capability only when access depends on an organization entitlement, and add a resource policy only when access depends on a target or organization state.

2. Enforce it in Convex

import { requireAppPermission } from "./permissions";

const actor = await requireAppPermission(ctx, { permission: "report.export" });

This single call verifies authentication, membership, role, capabilities, and any resource policy — there is no per-call copy-paste.

3. Reflect it in the UI (visibility only)

const canExport = useAppPermission("report.export");

Hiding UI is convenience; the backend check is the boundary.

4. Test it

Add or extend cases near packages/backend/convex/permissions/appPermissions.test.ts. The role-by-permission parity test must continue to pass: each catalog grant must match the generated Better Auth role's authorization result.

On this page