Bridge.Permissions answers one question: does this player hold this permission node? A node is granted if a server ACE allows it, or if the player has a Discord role you mapped to that node. No config files, no per-script admin lists.
The thing to understand up front: you wire it with labels, not raw Discord role IDs scattered through your code. A label like 'admin' is a friendly name. You define what role ID(s) the label means in one place, and what permission node(s) it grants in another. The real Discord role snowflake lives in exactly one call.
The two-step flow
1
Map labels → Discord role IDs
Bridge.Discord.RegisterRoles({ label = 'roleId' }) — tells the bridge that the label admin means Discord role 1234…. A label can map to several role IDs (any of them grants it).2
Map labels → permission nodes
Bridge.Permissions.RegisterNodes({ label = { 'node', ... } }) — tells the bridge that the same label admin grants the nodes myscript.admin, myscript.manage, etc.3
Check a node
Bridge.Permissions.Has(src, 'myscript.admin') — the bridge resolves the node back to the label(s) that grant it, then checks whether the player holds that label’s Discord role.Step 1 — register your roles
Map each label to its Discord role snowflake. You can pass a table, or a path to aroles.json shipped in your resource. A label may map to one ID or a list.
Step 2 — map roles to nodes
Map the same labels to the permission node strings your script checks. A node string is yours to name (myscript.admin, garage.impound, …).
myscript.* for a label grants myscript.admin, myscript.manage, and any other myscript.* node; * grants everything.
Step 3 — check a node
Has is the resolution that ties the two maps together:
- If a server ACE allows the node (
IsPlayerAceAllowed), grant it immediately. ACEs are honored first. - Otherwise, find every label whose nodes include that node (wildcards considered), and check whether the player holds any of those labels’ Discord roles.
- Otherwise, deny. Fail-closed.
Discord setup
The Discord side is what makes role-granted nodes work. The bridge talks to the Discord REST API directly with a server-only bot token — there is no separate bot process. It caches each player’s guild profile (roles, avatar, username, …) on join. Enable it with two non-replicated convars. Useset, never setr, so the token never reaches clients:
Has still works via IsPlayerAceAllowed.
End-to-end example
A garage script that gates impound on staff, granting it to anyone with theadmin or mod Discord role (or a matching ACE).
admin Discord role, the mod role, or a server ACE granting garage.impound passes. Everyone else is denied — the handler never runs.
Bridge.Net.On accepts a permission field that calls Has for you before the handler executes — the cleanest place to gate a client→server action. See Networking.