Instead of listing permissions user by user, you define a small set of roles and say what each role can do. A viewer can read, an editor can read and change, an admin can also manage billing and users. When someone joins, you assign a role and the permissions follow.
In AI-built apps the classic failure is checking the role only in the interface. The admin button is hidden for normal users, but the API route behind it never checks the role, so anyone can call it directly. Another is storing the role in something the user controls, such as a field in their own profile that the client can update, or trusting a role claim that was never verified on the server.
Enforce roles where the data lives: in server code or database policies, on every route and query, not in the screen. Keep the list of roles short, default new users to the lowest one, and make role changes something only an admin action can do. Test each role against every sensitive endpoint, not just the pages you can see.
if (session.user.role !== "admin") {
return new Response("Forbidden", { status: 403 });
}