Odoo has a multi-layered security system. User groups define roles. Access Control Lists (ACLs) determine which models each group can read, write, create, and delete. Record rules filter which individual records within a model are visible.
Groups
Defined in XML: res.groups. Typical: User, Manager, Administrator. Groups can inherit other groups (implied_ids). A manager automatically has all user permissions. Groups are linked to menus and views, so users only see what's relevant.
ACL (ir.model.access.csv)
One row per model and group. Four columns: perm_read, perm_write, perm_create, perm_unlink. Without an ACL row, the model is invisible to that group. This is the most common cause of "Access Denied" errors: missing ACL configuration.
Record Rules
Filter records based on conditions. "Salespeople see only their own leads" is implemented with a record rule: [('user_id','=',user.id)] on the crm.lead model, linked to the sales group. More granular control than ACLs which are all-or-nothing per model.
Superuser
The administrator account (uid 2) bypasses all security rules. Use it for configuration, not daily work. Create separate accounts for all users, including yourself.
Common mistakes
Giving everyone admin permissions "to make it work". That's a security risk and makes it impossible to track who did what. Forgetting record rules on sensitive models (HR, payroll, contracts). Not testing with a user in each group after configuration.
Design security early in the project. Adding it afterwards, when data already exists and users are used to seeing everything, is always harder.