A permission model with two independent axes
data_scope controls what a role can see. edit_scope separately controls what it can change. Both are enforced server-side and re-checked on every route.
A branch manager sees their branch. A sales officer sees their own customers. The owner sees everything. The client UI mirrors those rules, but it never decides them.