A repository that takes the current user as an argument and adds WHERE owner_id = current_user.id to every query makes IDOR impossible at the data layer. A misconfigured route can’t expose another user’s row because the WHERE clause is enforced regardless of what the route checked.
BaseRepository.get_by_id(id, current_user) raises 404 if owner_id != current_user.id.
Routes cannot bypass: the repo signature requires current_user.
Tests assert cross-user GET returns 404, not 403 (to avoid leaking existence).
Route -> Repo.get_by_id(id, current_user)
WHERE owner_id = current_user.id
(no return if mismatch)
Enforce IDOR at the repo, not at the route. The route can’t forget what the repo enforces by signature.