01 · Before and afterThe pattern
// before: subset check only
if (selected.some((s) => !grant.scopes.includes(s))) throw new Error("re-consent");
// after: enforce the UI's invariants server-side, and revoke on a real transition
if (!selected.length || (grant.scopes.includes("read") && !selected.includes("read")))
throw new Error("Keep read access, or disconnect");
const droppedOffline = grant.scopes.includes("offline_access") && !selected.includes("offline_access");
if (droppedOffline) await db.refreshToken.deleteMany({ where: { userId, clientId } });02 · Run it on your appThe check
For every toggle your UI disables, does the server action reject that same change if called directly?
If the honest answer is no or not sure, this is worth a look before it reaches production.