v2026.6.12
Release date: June 30, 2026
✨ New Features
Granular per-user permissions
Each organization member can have a unique set of permissions configured individually — independent of their assigned role or group.
The resolution hierarchy is exclusive (no merging between layers):
- Custom user permissions — if set, take full priority
- Assigned permission group — used when there are no custom permissions
- Role template — final fallback
Golden rule: the
ownerrole always uses the full template and can never be restricted by custom permissions or groups.
What is it for?
- Grant or restrict specific modules for a user without changing their role
- Define whether an agent sees all customers/pipelines or only the ones they handle
- Create access combinations not covered by default roles
How to configure?
- Go to Settings → Members
- Find the desired member and click Permissions
- In the Individual permission tab, enable the desired modules and actions
- Check or uncheck special flags like "See all customers" or "See all conversations"
- Save — permissions take effect immediately
Customer and CRM visibility control
The canAccessAll flag on the Customers and CRM modules determines the user's scope of view:
| Flag | Sidebar behavior | Filter behavior |
|---|---|---|
canAccessAll: true | Shows "Those I serve" and "All" | Open access |
canAccessAll: false | Shows only "Those I serve" | Automatically filtered by own ID |
Roles with full view by default: owner, admin, manager, financial.
Roles with restricted view by default: agent, agent_limited, sales, medical_doctor, medical_assistant.
Direct navigation to single submenu
When a menu item has submenus but only one of them is available to the user (due to permissions), clicking navigates directly to that page — without opening an expandable panel.
Before: clicking "Customers" expanded the menu, even with a single submenu.
Now: clicking "Customers" goes directly to the only available option.
🔄 Changes
Role checks replaced by effective permissions
All frontend and backend points that directly compared role === 'admin' || role === 'owner' were migrated to use effective permissions:
- Frontend:
isOwnerOrAdmin,isOwnerand module-specific flags (customersPermissions.canAccessAll,chatsPermissions.canAssignToOthers) — derived from theusePermissionshook - Backend:
req.isAdmin,req.isOwnerandreq.is_superadmin— populated in the auth middleware without additional database queries
Access flags in the auth middleware
The applyMembershipAuthContextToRequest middleware now sets req.isOwner and req.isAdmin based on the member's role, directly in the authentication layer. Controllers and handlers no longer make redundant database queries to check the requesting user's role.
Backend route protection by module
requireModuleAccess middleware applied to routes for: settings, integrations, billing, Stripe, subscription, permission groups, service teams and UTM.
Frontend route protection by module
ModuleGuard component wrapping React Router route groups for: financial, reports, members, permission groups, service teams, bulk messages, flows, prompts, billing, channels, medical, documents, POS, UTM and settings.
🐛 Bug Fixes
Custom permissions ignored canAccessAll: false
When a user had custom permissions defined but the canAccessAll field in the customers module was not checked, the system used the default value true — incorrectly showing all customers. Fixed: the absence of the flag in custom permissions is now treated as false (restrictive by default).
🎯 Benefits
- ✅ Module-level access control without creating specific roles
- ✅ Owner never loses full access, even with custom permissions configured
- ✅ Sidebar and filters automatically adapt to the user's view scope
- ✅ Smoother navigation: no unnecessary menu expansion for single-item menus
- ✅ Backend without extra queries: access checks resolved at the authentication layer