Seat types vs. group permissions
Honeyframe's access model has two independent axes. Most user confusion comes from collapsing them in your head — keep them separate.
Seat types: licensing
Every user has exactly one seat type:
| Seat type | What they can reach |
|---|---|
admin | Everything, including Admin surfaces |
builder | Datasets, recipes, flows, dashboards — full authoring |
analyst | Dashboards (view + author), datasets (read), no flow editing |
viewer | Read-only access to whatever they're permissioned for |
Seat types determine which product surfaces a user is allowed to enter at all. An analyst literally cannot reach the flow editor — the navbar item doesn't render for them, and the route would 404.
Seat types are about what the org pays for. Each seat consumes a license. You buy seats per type; running out means new users go onto a waitlist or get downgraded.
Group permissions: security
Independently, every user belongs to zero or more groups, and groups carry permission grants that say "this group can dashboard.edit dashboard 42".
A group permission row looks like:
group_id=42, permission_type='dashboard.edit', target_id='7'
Reading: "members of group 42 may edit dashboard 7."
The set of permissions a user has is the union of grants across every group they belong to.
Why two axes
Because the question "what can Alice do?" has two parts that genuinely don't co-vary:
- Licensing ("does Alice's seat allow her into the dashboard editor at all?") — about money
- Security ("can Alice edit this specific dashboard?") — about authorization
A user could be a builder seat (technically capable of editing dashboards) but have no group memberships granting edit rights to any dashboard. They'd see the editor but every dashboard they opened would render read-only.
A user could be a viewer seat (technically not allowed to enter the editor) but be in a group that has dashboard.edit on dashboard 42. The grant doesn't matter — the seat type stops them at the front door.
The resolver enforces both: a request needs both the seat type allowing the surface and a permission grant covering the specific object.
Common mappings
In practice, real orgs assign seats and groups in correlated patterns:
| Role | Typical seat | Typical groups |
|---|---|---|
| Data engineer | builder | Dataset Authors, Flow Operators |
| Analyst | analyst | Dashboard Authors, Finance Leadership |
| Executive | viewer | Finance Leadership, Board Reports |
| External auditor | viewer | Audit Read-Only |
| Admin | admin | org.admin (group with the org-admin permission) |
The patterns are correlated but not enforced by the platform. You can have a viewer seat in Dataset Authors if you want — they'll just hit the seat-type wall before ever reaching a permission check.
Migrating from a single-role model
Older Honeyframe deployments used a single role string per user (admin, editor, viewer, ...). The migration to seat-types-plus-groups is gradual:
- Existing users keep their
rolefor backwards compatibility (the resolver has a legacy shim that treatsrole='admin'as superuser) - New users should be assigned a seat type plus group memberships
- Migrate existing users by inferring a seat type from their role (e.g. legacy
editor→builder) and creating groups that mirror their previous capabilities
See the Permissions Reference for the resolver behavior including the legacy shim.
See also
- Users & Groups — the operational model
- Permissions Reference — the actual permission strings and the resolver
- Bulk import users from CSV — assigns seats and groups together