Users & Groups
Honeyframe's access control model has two independent axes:
- Seat types govern licensing — every user has exactly one of
admin,builder,analyst, orviewer. Seat types determine which areas of the product a user can reach at all (e.g. analysts can build dashboards but not edit ingestion flows). - Group permissions govern security — what specific objects a user can read, edit, or administer. Groups are orthogonal to seat types: a
viewerin the "Finance Leadership" group may have read access to dashboards abuilderin the "Marketing" group cannot see.
Groups themselves can be local (managed inside Honeyframe) or LDAP-mapped (synced from a directory server via the group's ldap_dn). LDAP-mapped groups carry the same permission grants as local groups; the only difference is membership source.
Permissions attach to groups via permission_type strings (for example dashboard.edit, dataset.read, org.admin) and may optionally be scoped to a specific object using target_id. The platform resolves a permission check by first granting the request if the user is a superadmin, then falling back to a legacy single-role check for backwards compatibility, and finally consulting the user's group memberships and the permissions attached to those groups. Frontend code uses the usePermission() hook and the <ProtectedRoute> component to gate UI surfaces declaratively.
The /api/groups endpoints provide CRUD for groups and their permission grants. The frontend bootstraps its permission cache from /api/groups/me/permissions on login.
Org Setup Wizard (v0.0.38)
For first-time super-admin onboarding, the Org Setup Wizard walks through the canonical setup in five steps without leaving one surface:
- Organization details — name, slug, default timezone.
- License entitlements — pick the license tier; the platform resolves which features the org has access to via the per-org entitlements resolver. Higher tiers unlock plugin enablement, opt-in RLS, and the AI generator.
- First admin — bootstrap the org's first admin user (or import from LDAP if configured). The admin is auto-added to the seeded
Org Adminsgroup. - Default groups — accept the seeded set (
Org Admins,Builders,Analysts,Viewers) or skip; groups can be added later via the Groups page. - Default project — create the org's first project. The wizard provisions it via the same idempotent
/seedendpoint that tenant seed scripts use.
Trigger the wizard from /admin/org-setup (super-admin only). Re-running it on an org that's already set up is safe — every step's underlying API is idempotent.
Per-org entitlements
A new entitlements resolver (v0.0.38) decides which features an org has access to based on its license tier. The organizations table now carries a license_tier column and a feature_flags JSON map; the resolver merges them at request time.
Common gates:
| Feature | Gate |
|---|---|
| Plugin enablement (per-org / per-tenant) | entitlements.plugins.enabled |
| Opt-in RLS for cross-tenant isolation | entitlements.rls.opt_in |
| AI generator (dashboards / agents) | entitlements.ai.generator |
| Embedded analytics (SaaS surface) | entitlements.embed |
Frontend gating uses the same usePermission() hook with an entitlement key prefix (entitlements.*); backend gating uses the require_entitlement() dependency.
Project visibility (v0.0.38)
Project visibility now defaults to allow on user/project create. When a new project is created, every existing org user is auto-stitched into a baseline dataset.read role on the project; when a new user is created, they're auto-stitched into every existing project at the same baseline. Override per-project via Project Settings → Members to restrict.
This default-allow behavior reverses the prior default-deny — the prior model required explicit grants and was a frequent "I created a project, why can't anyone see it?" support hit. Default-allow is the right choice for single-tenant deploys; multi-tenant orgs that need strict isolation should turn on opt-in RLS (see Data Policies → Cross-tenant isolation).