Groups
Groups complement roles by adding a many-to-many layer: a user has exactly one role, but can belong to any number of groups. Permissions can reference groups with the group: prefix, making them ideal for team-scoped and field-level access.
auth:
strategies:
- type: emailAndPassword
groups:
- name: marketing
- name: finance
description: Finance team with access to financial data
- name: project-alpha
description: Cross-functional team
maxMembers: 50
Teams are configured through groups — define a group per team (engineering, marketing, …) and reference it in permissions.
Defining Groups
auth.groups is an array of group definitions.
| Property | Description |
|---|---|
name |
Required. Group identifier. Lowercase, alphanumeric, hyphens; must start with a letter. Must be unique and must not collide with a role name. |
description |
Human-readable description of the group's purpose. |
maxMembers |
Maximum number of members (integer ≥ 1). Unlimited when omitted. |
Naming rules — group names match ^[a-z][a-z0-9-]*$ (the same convention as role names):
| Name | Valid? | Reason |
|---|---|---|
marketing |
✅ | lowercase letters |
dev-team |
✅ | hyphen allowed |
project-alpha |
✅ | hyphen allowed |
Marketing |
❌ | uppercase not allowed |
123team |
❌ | must start with a letter |
Roles and groups share one namespace. A group named admin is rejected because it collides with the built-in role. Keep group names distinct from every built-in and custom role name. Validation also rejects duplicate group names.
Membership
A user can be a member of multiple groups simultaneously. Membership is managed at runtime (assigned by admins or by automations) — the schema declares which groups exist, not who belongs to them. When maxMembers is set, attempts to add a member beyond the cap are rejected.
Group-Based Permissions
Reference a group in a table's permissions block by prefixing its name with group:. Group entries sit alongside role names in the same permission arrays:
tables:
- id: 1
name: Campaigns
fields:
- { id: 1, name: title, type: single-line-text, required: true }
- { id: 2, name: budget, type: number }
permissions:
read: [member, 'group:marketing']
update: ['group:marketing']
# field-level: only finance can read the budget column
fields:
budget:
read: ['group:finance']
| Entry form | Meaning |
|---|---|
member |
Grant to everyone with the member role. |
group:marketing |
Grant to every member of the marketing group. |
admin |
Grant to the admin role. |
Permission resolution is most-permissive-wins: a user's effective permissions are the union of those granted by their role and by every group they belong to. If a user's role grants read and their marketing group grants update, they get both.
Groups shine for field-level permissions — e.g. exposing a salary or budget column only to a group:finance while the rest of the table is broadly readable. See Table Permissions for the complete field-level model.
Related Pages
- Roles & RBAC — the single-role layer groups build on.
- Table Permissions — full
group:permission and field-level model. - Automations — assign users to groups in response to events.