Advanced Permission
Replaces role-and-permlevel access control with a no-code engine you configure per DocType — which rows a person sees, which fields inside them, what they can do, and how access propagates — enforced identically across the Desk, the REST API and MCP.
Where native permissions stop
Frappe's own model ends at role → DocType → permlevel. Advanced Permission lets you express the rest of the sentence, in a visual builder:
A Receivable User may read a Sales Invoice only if its customer has an outstanding balance — and even then, blur the cost fields and hide the timeline. Everyone else must request access, which auto-approves for their own department and expires in seven days.
Every decision is made on the server. The bundled client script only makes the screen match what the server already returned — it never grants anything.
What you get
| Row scopes | A visual AND/OR/NOT builder decides which records a door opens — by field, owner, reporting line, department, age, a linked record, or “I can access the linked doc”. |
| Six field levels | Per field: Hidden, Blur, Masked (show first/last N), Read-only, Editable, or Show. Values are removed on the server, so hiding is real. |
| Per-row child tables | Blur cells or drop rows of a child table for the rows a person may not see — restored on save, so nothing is lost. |
| Relationship scopes | Reports-to subtree, department, junction EXISTS, and dynamic-link “has access to the linked doc” at a chosen permission level. |
| Access requests | A restricted user can request more; requests route to approvers, can auto-approve by rule, and expire. |
| Route guards | Blocks the paths that bypass has_permission — file download, print / PDF, and email. |
| Anti-scraping and audit | Per-window read and export caps, plus an access log of who did what. |
| A simulator | “What can this user see, and why?” — the row condition, the counts, and the opening doors for one record. |
Three words worth keeping straight
Access Rule
One per governed DocType. Decides whether the app governs it at all, and how its doors combine.
Door
A single grant inside a rule. Who (roles) × which rows (scope) × what they can do (profile).
Access Profile
A reusable bundle. The actions — read, write and the rest — and the default field access a door grants.
Safe to try
Installing changes nothing
A DocType with no enabled Access Rule is completely un-governed — Frappe's native permissions apply unchanged.
Build, save, simulate
Open the Access Rule Builder at /app/access-builder, add a door, then open the Access Simulator at /app/access-simulator to see exactly what a test user gets before anyone else does.
One tick reverses it
Turning off a rule restores native behaviour immediately. That's the escape hatch, and nothing is lost.
Enforced everywhere, not just on screen
Enforcement hooks the server document lifecycle rather than the browser, so the same decision applies whether a record is reached through the Desk, the REST API, or an MCP connector.
| Lists | Filtered by permission_query_conditions. |
| Single documents | Checked by has_permission. |
| Fields and child rows | Redacted on the read path, before the data leaves the server. |
| File, print and email | Guarded at the request layer — the routes that bypass has_permission in stock Frappe. |
Full documentation is public
Concepts, row scopes, fields and child tables, cascade and link guards, access requests and recipes — plus enforcement and security, the Access Simulator, and a developer reference.