Flow
Cutting roles down without surprises
1Mapping as data
Old role, new role, and up, same or down for each.
2Check it
Compare each row with a ranking before writing any SQL.
3Save old roles
Copy them to a side column in the same run.
4Accept old names
Ship code that still understands the old roles.
5Migrate and compare
Run the script and compare counts for each old and new pair.
6Clean up
Drop the old names and turn on the rule that blocks unknown roles.
The comment said the executives become managers. The line right under it made them admins.
That was in a role cleanup on one of the apps I work on. The app had a pile of roles: admin, a couple of executive roles, manager, engineer, plain user and viewer. The commit cut them down to three: admin, manager and member. I read it expecting a rename. It wasn't. It changed what people are allowed to do, and the script that does it is the one file with no test.
Where the role shows up
A role is just a word stored in a table, but lots of code reads it. In this commit, the checks for inviting people and managing teams got shorter lists of who counts as a leader. The team-role check stopped accepting viewer. The code that sends roles to the login provider was trimmed too. A new action lets leaders change someone's role. And a SQL script rewrites the stored roles in one go, prints a count, and commits.
Three answers for the executives
The script's header says executives become managers. The actual update makes them admins. The new code that ranks roles treats any leftover executive as a plain member. That's three answers, and only the update touches the data.
Viewers becoming members matches the header, but it's still a step up. Somebody should agree to that on purpose.
Why nobody would see it
Admins and managers pass the same invite and team checks, so the extra promotion changes nothing you can see there. The login provider treats them the same too. The count at the end of the script only prints numbers, so there's nothing to catch the mistake except the comment, which is the part that's wrong.
In the changed code, the new role-change action is the one place admin and manager differ. As I read it, it only checks that you outrank the role you're handing out. It doesn't check who you're changing, or that the role is a real one. The page hides that control from regular members, but I haven't tested the server side.
The login provider
Resent invites now go out as the provider's roles, so a resent manager invite goes out as the provider's admin. When the provider reports back, the app reads the role from the event, and I'm assuming it saves it. If nothing fixes that later, an invited manager comes back as an admin. I haven't followed that path all the way.
Which ships first
If the script runs before the new code ships, viewers get member access early. If the code ships first, executives lose invite and team access until the script runs. Any row the script misses just stays wrong, because the rule that would block bad roles is commented out.
A mapping that has to admit a promotion
Write the mapping down as data: old role, new role, and whether it goes up, stays the same, or goes down. Check that against a ranking before generating any SQL:
if (rank[to] > rank[from] && dir !== "up") throw new Error(`${from} -> ${to} is a promotion`);
Save the old role in a side column during the same run. Let the code accept old names for a while, migrate, then remove them.
Nothing in the commit tells me if that script has been pointed at real data yet.