Record rules
Record rules (sys.rule) restrict which rows a user sees or modifies, on top of model ACLs (sys.access). Same rules apply to the web UI and JSON-RPC.
When to use
- Users share a model but must not see each other's rows (e.g. salespeople see only their company's orders)
- Multi-company isolation within one database
Use ACLs first for coarse CRUD; add record rules only when row filtering is required.
Model fields
| Field | Purpose |
|---|---|
name | Rule label |
model_id | Target model |
domain_force | JSON domain (see Domain filters) |
perm_read, perm_write, perm_create, perm_unlink | Which operations the rule applies to |
global | Apply to all users (vs group-scoped) |
groups | Many2many to core.group when not global |
Administrators edit rules under Settings → Security → Record rules when security_admin.xml is loaded.
Loading from addons
Place rules in security/*_rules.xml (or inline in security.xml). List the file in manifest.json → data after groups and ACLs.
<record id="rule_sale_order_company" model="sys.rule">
<field name="name">Sales orders: multi-company</field>
<field name="model_id" ref="model_sale_order"/>
<field name="domain_force">[["company_id", "in", "$company_ids"]]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="global" eval="True"/>
</record>Run -u your_module after changes. Rule cache invalidates on update.
Global vs group rules
- Global rules — AND-combined; every user must satisfy them
- Group rules — OR-combined among rules sharing the same groups; then AND with globals
Keep domains testable — overly complex rules are hard to debug.
Multi-company pattern
Typical pattern for business documents:
[["company_id", "in", "$company_ids"]]The active company comes from the company switcher (POST /web/company/switch). This is not multi-tenant SaaS — one PostgreSQL database, shared schema. See Isolation model.
Worked example: CRM own leads
- Create group
crm.group_user(already in CRM addon) - ACL grants read/write on
crm.leadfor that group - Optional record rule:
[["user_id", "=", "$uid"]]for non-managers
Managers use a separate group without the restrictive rule or with global rules that allow all leads in company.
RPC and exports
JSON-RPC search, search_read, and report export all enforce the same record rules as the workspace UI.
See also
- Security & access
- Domain filters
- Manifest & layout — security load order