Stop Guessing Why Odoo Denies Access
A new module for OCA server-tools that makes Odoo's security system fully transparent — for developers and administrators.
Odoo's permission system is powerful. It's also one of the hardest parts of the platform to debug. Two overlapping layers — model-level ACLs and record-level rules — interact in ways that are nearly invisible. This module makes them visible.
The Problem Every Odoo Developer Knows
A user reports they can't open a record. You check their groups — they look correct. You check the access rights for the model — they look correct. You check the record rules — something is off, but you're not sure which rule is blocking access or why.
The usual approach: trial and error in the developer console, adding debug logging, or temporarily granting wider access to narrow things down. It works, but it's slow — and in production, it's risky.
Joel is not the customer on this record. The active record rule restricts visibility to orders where the partner matches the logged-in user. Blocked at the record rule layer — model ACL alone would have allowed it.
Joel is the customer on this order. The record rule evaluates to true for this specific record. Read access is granted, but write/create/delete remain blocked by a separate ACL group restriction.
These two outcomes — same user, same model, different records — are exactly what the Security Visualizer is designed to explain clearly, without reading through Python domain expressions by hand.
What the Module Does
base.group_system. It only reads and explains — it never modifies security configuration.The Access Matrix — A Practical Example
The matrix view gives you a cross-reference of users and models. Here's a simplified version of what it looks like in practice:
| User | Model | Read | Write | Create | Delete |
|---|---|---|---|---|---|
| Joel (Portal) | sale.order | ✓ Yes | ✗ No | ✗ No | ✗ No |
| Sarah (Sales) | sale.order | ✓ Yes | ✓ Yes | ✓ Yes | ✗ No |
| Joel (Portal) | account.move | ✗ No | ✗ No | ✗ No | ✗ No |
| Sarah (Sales) | account.move | ✓ Yes | — | — | ✗ No |
This is the kind of view that would normally require navigating through Settings → Technical → Security → Access Rights, cross-referencing multiple tables manually. The matrix collapses that into one screen.
Technical Details
For those who want to understand what's actually under the hood:
security_visualizer/ ├── models/ │ └── security_visualizer.py # Core logic: ACL + rule evaluation ├── static/src/ │ ├── js/ │ │ ├── rule_explainer.js # OWL component — analyzer view │ │ └── access_matrix.js # OWL component — matrix view │ └── xml/ │ └── templates.xml ├── views/ │ └── security_visualizer_views.xml ├── tests/ # 15 unit tests │ ├── test_acl.py │ ├── test_rules.py │ ├── test_simulation.py │ └── test_matrix.py └── security/ └── ir.model.access.csv # Restricted to base.group_system
The frontend is built with Odoo's native OWL framework, reusing built-in components — AutoComplete, TagsList, useService("orm") — with only about 126 lines of custom CSS to handle layout features that Odoo's design system doesn't cover (sticky headers, collapsible sections). No custom colors: everything is standard Bootstrap utility classes.
Dependencies: base + web only. No third-party packages, no external APIs. Works on any standard Odoo 16.0 deployment.
The OCA Review Process
The PR has been open since February 2026 and is actively under review by OCA maintainers. This is how open source works — serious modules get serious scrutiny, and that's a good thing.
Reviewer feedback so far has been constructive and substantive. The main themes:
What reviewers appreciated: The core concept (explainability over shortcutting), the restriction to system administrators, and the fact that the module is purely read-only and safe for production environments.
Feedback also led to concrete improvements already merged into the PR: native OWL component reuse, adherence to Odoo's design system, filter state preservation between tabs, and cleaner CRUD operation handling. The review process has made the module better.
Why This Matters for Odoo Teams
Odoo's security model is genuinely complex. ir.model.access operates at the model level — a blunt instrument that applies to all records of a type. ir.rule operates at the record level — a fine-grained filter using domain expressions that evaluate differently for each record and each user.
When both layers are in play, diagnosing access issues means reasoning about both simultaneously. That's hard to do mentally, especially in multi-company deployments where rules can vary by company context.
The Security Visualizer doesn't replace understanding — it amplifies it. You still need to know how Odoo's security system works. But now you have a tool that shows you exactly what it's doing for a specific user, on a specific model, for a specific record, in real time.
PR #3516 — Currently Under OCA Review
The module targets Odoo 16.0 and is submitted to the OCA server-tools repository. Community interest has also been expressed in 18.0 and 19.0 support. You can follow the discussion and contribute feedback at:
github.com/OCA/server-tools/pull/3516
Have Access Issues in Your Odoo?
If you're debugging security problems or need a production-ready implementation, reach out directly.
Stop Guessing Why Odoo Denies Access
A new module for OCA server-tools that makes Odoo's security system fully transparent — for developers and administrators.
Odoo's permission system is powerful. It's also one of the hardest parts of the platform to debug. Two overlapping layers — model-level ACLs and record-level rules — interact in ways that are nearly invisible. This module makes them visible.
The Problem Every Odoo Developer Knows
A user reports they can't open a record. You check their groups — they look correct. You check the access rights for the model — they look correct. You check the record rules — something is off, but you're not sure which rule is blocking access or why.
The usual approach: trial and error in the developer console, adding debug logging, or temporarily granting wider access to narrow things down. It works, but it's slow — and in production, it's risky.
Joel is not the customer on this record. The active record rule restricts visibility to orders where the partner matches the logged-in user. Blocked at the record rule layer — model ACL alone would have allowed it.
Joel is the customer on this order. The record rule evaluates to true for this specific record. Read access is granted, but write/create/delete remain blocked by a separate ACL group restriction.
These two outcomes — same user, same model, different records — are exactly what the Security Visualizer is designed to explain clearly, without reading through Python domain expressions by hand.
What the Module Does
base.group_system. It only reads and explains — it never modifies security configuration.The Access Matrix — A Practical Example
The matrix view gives you a cross-reference of users and models. Here's a simplified version of what it looks like in practice:
| User | Model | Read | Write | Create | Delete |
|---|---|---|---|---|---|
| Joel (Portal) | sale.order | ✓ Yes | ✗ No | ✗ No | ✗ No |
| Sarah (Sales) | sale.order | ✓ Yes | ✓ Yes | ✓ Yes | ✗ No |
| Joel (Portal) | account.move | ✗ No | ✗ No | ✗ No | ✗ No |
| Sarah (Sales) | account.move | ✓ Yes | — | — | ✗ No |
This is the kind of view that would normally require navigating through Settings → Technical → Security → Access Rights, cross-referencing multiple tables manually. The matrix collapses that into one screen.
Technical Details
For those who want to understand what's actually under the hood:
security_visualizer/ ├── models/ │ └── security_visualizer.py # Core logic: ACL + rule evaluation ├── static/src/ │ ├── js/ │ │ ├── rule_explainer.js # OWL component — analyzer view │ │ └── access_matrix.js # OWL component — matrix view │ └── xml/ │ └── templates.xml ├── views/ │ └── security_visualizer_views.xml ├── tests/ # 15 unit tests │ ├── test_acl.py │ ├── test_rules.py │ ├── test_simulation.py │ └── test_matrix.py └── security/ └── ir.model.access.csv # Restricted to base.group_system
The frontend is built with Odoo's native OWL framework, reusing built-in components — AutoComplete, TagsList, useService("orm") — with only about 126 lines of custom CSS to handle layout features that Odoo's design system doesn't cover (sticky headers, collapsible sections). No custom colors: everything is standard Bootstrap utility classes.
Dependencies: base + web only. No third-party packages, no external APIs. Works on any standard Odoo 16.0 deployment.
The OCA Review Process
The PR has been open since February 2026 and is actively under review by OCA maintainers. This is how open source works — serious modules get serious scrutiny, and that's a good thing.
Reviewer feedback so far has been constructive and substantive. The main themes:
What reviewers appreciated: The core concept (explainability over shortcutting), the restriction to system administrators, and the fact that the module is purely read-only and safe for production environments.
Feedback also led to concrete improvements already merged into the PR: native OWL component reuse, adherence to Odoo's design system, filter state preservation between tabs, and cleaner CRUD operation handling. The review process has made the module better.
Why This Matters for Odoo Teams
Odoo's security model is genuinely complex. ir.model.access operates at the model level — a blunt instrument that applies to all records of a type. ir.rule operates at the record level — a fine-grained filter using domain expressions that evaluate differently for each record and each user.
When both layers are in play, diagnosing access issues means reasoning about both simultaneously. That's hard to do mentally, especially in multi-company deployments where rules can vary by company context.
The Security Visualizer doesn't replace understanding — it amplifies it. You still need to know how Odoo's security system works. But now you have a tool that shows you exactly what it's doing for a specific user, on a specific model, for a specific record, in real time.
PR #3516 — Currently Under OCA Review
The module targets Odoo 16.0 and is submitted to the OCA server-tools repository. Community interest has also been expressed in 18.0 and 19.0 support. You can follow the discussion and contribute feedback at:
github.com/OCA/server-tools/pull/3516
Have Access Issues in Your Odoo?
If you're debugging security problems or need a production-ready implementation, reach out directly.