Permissions belong in queries, not only menus
Why Plantronic's planner and team rules had to constrain data access below the interface.
- Published
- Updated
- Reading time
- 3 min read
A hidden menu item is not authorization.
During July 2025, Plantronic’s planner roles, team relationships, employee filters, task views, and public database views grew together. That combination forced a useful design question: where does permission actually live?
The interface must reflect what a person may do. But if the underlying query returns every task and the template merely hides some rows or buttons, the policy is cosmetic. Another screen, export, LiveView event, or API can expose the same data.
Scope data before presenting it
The safer pattern starts with a scoped query. Given an authenticated person and a purpose, return only the tasks, employees, teams, or planning rows that person is allowed to inspect.
The UI then renders an already-authorized result. Buttons can still communicate capabilities, but they are not the enforcement point. Mutations apply the policy again because visibility and permission to change are not identical.
This also improves correctness outside security. Team-scoped employee search returns relevant choices. Planner views carry less unrelated data. Tests can assert exact result sets instead of searching rendered markup for an absent link.
Roles are rarely enough
A global role such as “planner” is convenient, but real access often depends on relations. A person may plan for one team, observe another, and have no reason to see a third. A primary-planner relation can be more meaningful than another boolean column on the user.
Relations make policy slightly more work to express. They also make it explainable: this user can see this task because the task belongs to a team they plan for. That explanation is useful in code review, tests, support, and audits.
Public database views need the same attention. A view can become an integration contract that bypasses application-level checks. Its columns and row scope should be treated as deliberate exposure, not a convenient shortcut around the application.
Authorization is a property of every path
Plantronic had screens, searches, reports, imports, and external views. No single controller plug could secure all of them by itself. The durable approach was to keep policy near domain queries and operations, then exercise it through each delivery path.
A scoped query is less visible than a disabled menu item, but it is the part that blocks access.
Whenever I review authorization now, I ask two separate questions: does the interface clearly show what this person can do, and can any code path retrieve or change more than that? Good software needs both answers. Only the second one is the security boundary.