Staff and roles

Staff are the people in the Roblox roles you nominate, whether or not any of them ever sign in to Rostack. Roles decide what those people may do here. Both hang off Roblox rank, which is why a demotion made in Roblox is felt here within the hour.

Who counts as staff

Staff is not "people with a Rostack account". It is the people in the Roblox roles you nominated. Everybody at one of those ranks gets an employment record here on the next sweep, and it exists whether or not they have ever opened Rostack.

That is why identity is always the Roblox user id. A staff record is stored under it and every comparison is made on it, while the linked Rostack account beside it is a separate field that is empty far more often than it is filled. Somebody signing in later attaches their account to the record that was already there; it does not create a second one.

Staff are unlimited

Staff are never counted and never charged for. Rostack is mirroring a list you already maintain inside Roblox rather than selling seats, so nominate the ranks that describe your team rather than the ones you could afford to.

Nominating the ranks

You pick the ranks while creating the workspace, at the step that asks which of your Roblox roles are staff, and you can change that choice afterwards on the Roles page. At least one rank has to be tracked: an empty list would retire every record the sweep created, on its next run.

Your own rank is always included and cannot be removed. Its checkbox is fixed, and the server adds the owner rank back to whatever was submitted rather than trusting the form, because the sweep tracks exactly these ranks and a set without the owner's rank would have the next run retire the owner from their own workspace. When it is forced back in, the audit entry says so.

Before saving, the Roles page will preview the change: who gains authority, who loses it, and how many people each rank holds. The preview resolves through the same code as the save, so it is not a second implementation that could drift from the first and be confidently wrong. Above a few thousand staff it says that it stopped counting, rather than rounding its answer up to certainty.

How the roster keeps up

Roblox publishes no webhooks and no group audit log, so the only way to learn that somebody was promoted, demoted or removed is to look again and compare. Rostack does that every hour, from the public member list, which needs no credential: a workspace that has never connected an Open Cloud key is still reconciled.

Somebody who has entered a tracked rank and has no record gets one. Somebody whose rank has left the tracked set, or who has left the group entirely, is retired. Only records the sweep created itself are retired that way: a person added by hand survives a rank they no longer hold, and the owner is never auto-created and never auto-retired.

Retiring is not deleting

The document is the evidence that this person was staff here, and it is what warnings, sessions and payouts refer back to. It is retired in place, so the history stays attributable and re-tracking the same person rejoins their old record instead of starting a blank one. A retired record resolves to no permissions at all, and that empty list is written in the same moment as the status, so there is no window in which somebody retired still holds a live grant.

Coming back is deliberately narrow. The sweep reinstates somebody only when it was the sweep that retired them, and only for the reason it retires for. A record an administrator ended by hand stays ended: a rank being added back to the tracked set is not a decision about that person.

The sweep can also write less than you might expect. It may set rank, role name, the time it synced and the display fields, and nothing else. Roblox has no opinion about who is suspended, what anyone was granted, or who owns the workspace, so a sync can never reinstate a suspended seat or rewrite a grant.

What a role is

A role is a set of permissions, a list of Roblox ranks it covers, and a list of people named individually. Everybody at a mapped rank inherits the role, and somebody named individually holds it regardless of rank, which is how one person is given something without giving it to their whole rank. People are named by Roblox id here too, so a role can name somebody who has never signed in.

On top of the roles, one person can be given individual additions and individual removals. Their effective grant is the union of every role that reaches them, plus their additions, minus their removals.

how one person's permissions are resolved

1  not active     ->  nothing at all, before anything else is considered
2  owner          ->  every permission, minus their own removals
3  everyone else  ->  roles matching their rank
                      + roles naming them
                      + their individual additions
                      - their individual removals

The order is the security model. Suspension is checked first, or it would only be advice. Removals are applied last, so a removal always wins over whatever granted it. The resolved list is then stored on the staff record and is the only thing an access check reads, which is why editing a role recomputes everybody that edit could have moved instead of being resolved again on every request.

Roles are saved as one whole set rather than one at a time. Two people saving different halves could otherwise interleave and produce a grant neither of them chose, and the checks below have to see the complete next state to judge it.

The guard rails

Somebody who can edit roles could otherwise write themselves a better one. Four rules stop that, and each refuses with a reason rather than silently dropping part of the change.

You cannot grant a permission you do not hold. Without this, anybody with roles.manage could mint an accomplice holding payouts.approve and escalate sideways in a single save.

You cannot map a role to a rank at or above your own. Your own rank counts: mapping it is a self-grant with an extra step, and mapping a rank above you hands authority to people who outrank you. The owner is exempt, because every rank is at or below theirs and that exemption is what keeps them able to configure their own workspace. Naming yourself in a role is refused for the same reason, and the owner is not exempt from that one.

One role cannot hold both payouts.run and payouts.approve. A payout run waits for approval precisely so that the person who prepares it is not the person who releases it, and a role holding both ends would make that step theatre. Split them across two roles.

A suspended record resolves to no permissions at all. So does a retired one. Suspension beats every other rule, and it is re-resolved in both directions: suspending recomputes the stored list, and so does reinstating.

Changing one person's access follows the same shape. You cannot change your own, you cannot change the owner's, and you cannot change the access of somebody at or above your own Roblox rank.

Rank is a grant

Because a role can be mapped to a rank, moving somebody into that rank hands them whatever it is mapped to. Rank is therefore not only a ceiling on what Rostack will let somebody hold, it is also a way of granting it. A rank change is checked as the permission change it really is, and a rank that carries permissions can only be assigned by a person, never by an API key: automation moves people between ranks that carry no authority, while handing out authority is a decision with a name on it.

The consequence runs both ways. Demote an administrator in Roblox and the next sweep mirrors the new rank and re-resolves what it grants, so their access here goes with it inside the hour. Demote them out of the tracked ranks altogether and the record is retired, which is no permissions at all. Anything privileged also re-reads the live rank from Roblox before acting rather than trusting the stored copy, so a stale number cannot outlive the demotion.

A promotion nobody here made is drift. A rank change counts as explained only if Rostack itself assigned exactly that rank to exactly that person inside the window: assigning 50 and then finding 120 is still drift, and several unexplained rank changes at once is what a compromised account looks like from in here.