I'll have to think about this. has_access knows GlobalStaff > Instructor > Staff and thus if checking for Staff, it should also check Instructor and GlobalStaff ... If it gets the actual Role object, it will still need to break the encapsulation in order to implement this override or we'll need to move the escalation logic down into roles.py (which may make the most sense but further burdens roles.py with behavioral knowledge which you objected to above).