RoSignal is built so you can verify what touches your game.
You're connecting a live experience with real players to an outside service. Rather than asking you to trust a list of badges, this page describes the parts you can check yourself: the Roblox-side code is published, the installed files are named and explained, and each backend control below matches how the system actually works today. If a statement here is wrong, that's a bug - please report it.
The Roblox code is public
The Studio plugin and every script RoSignal inserts into your place are published for inspection before you install them.
Access is scoped to one game
A game key authenticates one game. The backend stores a SHA-256 hash of it, and every request is checked against that game.
Roblox permissions are incremental
Signing in asks for openid and profile only. Anything more is requested from the feature that needs it.
Secrets stay server-side
Roblox app credentials, the session signing key and the token encryption key exist only on the server. Refresh tokens are encrypted before storage.
Every action is permission checked
Being signed in is not access. Each sensitive call re-resolves your access to that specific game and the capability your role holds.
You decide what connects
Events, traits and rank changes only happen where your own code calls the RoSignal API. The handler file is yours.
In your place
What RoSignal installs in your game
Setup adds four scripts under ServerScriptService. One of them is generated by RoSignal and refreshed on every setup or repair; the other three are yours and are never overwritten once they exist.
ServerScriptService
├── RoSignal (RoSignal) ├── RoSignalHandlers (yours) │ └── RoSignalDemo (yours) └── RoSignalSettings (yours)
- RoSignal
- The generated runtime. It talks to the RoSignal service and contains your game's server-side key, which is why it belongs in ServerScriptService and nowhere else. Setup and Repair replace this file - don't edit it.
- RoSignalHandlers
- Your integration point, deliberately tiny: a Bind, an OnAnnouncement and a Track call showing where your game code hooks in. Created once, then left alone.
- RoSignalDemo
- An optional starter demo that puts the first test on screen so you can see it working. Delete it whenever you've wired RoSignal into your own systems.
- RoSignalSettings
- Your configuration file. Preserved across runtime refreshes and repairs.
Studio plugin
What the plugin can and can't do
The plugin's whole job is pairing your place with your RoSignal game and writing those four scripts. Its source is in the same public repository.
It does
- Check that Studio is allowed to reach rosignal.app.
- Accept a one-time pairing code and exchange it for your setup payload and game key.
- Insert or refresh the runtime script, leaving your own files intact.
- Store the game key and pairing details in Studio's own plugin settings for this place.
- Export place geometry - only when you press the export button.
It does not
- Publish your place. Going live is always your own publish.
- Read or upload the source of your scripts. It never reads a script's source.
- Modify unrelated instances. It only looks up the four scripts by name under ServerScriptService.
- Export geometry in the background. Nothing is collected until you click Export.
The map export walks BasePart instances and sends axis-aligned boxes - position, size and a coarse colour bucket. No part names, no scripts, no player data. View plugin source.
Runtime traffic
What the runtime sends, and what it doesn't
Every request carries the game key in a header and goes to rosignal.app. Be clear-eyed about the reach: the runtime runs with server permissions in your place, so it could do more than it does. What follows is what the published code actually does.
Sent when the related feature is used
- Config requests: a GET carrying the game key and the place version, answered with your config, overrides and rollouts.
- Event aggregates: per-minute counts for the event names your code passes to RoSignal.Track, plus per-player counts and a small sampled set of example events with their properties.
- Map cells: when map capture is on, event counts bucketed into a grid cell (rounded coordinates), never a player's exact position or path.
- Traits: only the key/value pairs your code passes to RoSignal.SetTraits, batched and sent a few seconds later.
- Acknowledgements: ids confirming an announcement, message run or moderation action reached the server.
- Group rank requests: player id and target role, only when your code calls RoSignal.SetRank.
- Delivery identifiers: the game id, job id and place version needed to route and acknowledge work.
Not collected
- No Lua source code. The runtime never reads the source of any script, including your own.
- No DataStores. The runtime makes no DataStoreService calls at all; MemoryStore is used only as a short-lived buffer to merge counts between servers.
- No chat. Nothing in the runtime touches TextChatService, chat events or message contents.
- No sweep of your place. The runtime reads no instances outside what your code hands it, and only looks up RoSignalSettings by name.
- No player personal data from Roblox. RoSignal does not request emails, ages, friends or messages.
Backend
Sign-in, sessions and stored credentials
The other half of the question: how protected is the service your game is talking to?
- Roblox OAuth
- Sign-in happens on Roblox. There is no RoSignal password to leak. The flow uses PKCE (S256) and a random state value, both checked when Roblox sends you back.
- OAuth handoff cookie
- A short-lived cookie (10 minutes, HttpOnly, Secure, SameSite=Lax) carries the verifier and state between starting sign-in and returning from Roblox.
- Session cookie
- HMAC-SHA256 signed by a server-only key and compared in constant time, so altered session data fails verification. HttpOnly keeps page scripts from reading it, Secure keeps it on HTTPS, SameSite=Lax limits cross-site sending, and it lasts 7 days. It is signed rather than encrypted, and holds only your Roblox id, username, display name, avatar and Founding Tester flag - no tokens.
- Roblox tokens
- Access tokens are used in memory and never stored. Refresh tokens are encrypted with AES-256-GCM (fresh IV per value) using a server-held key before they are written to the database, and they rotate each time they're used. The app credentials and encryption key are server environment secrets and are never shipped to a browser.
- CSRF
- Server function calls run behind cross-site request forgery protection, so another site cannot make your browser perform actions in your account.
Keys and tokens
Game keys, pairing codes and invite links
- Game key
- 192 bits of randomness, prefixed
rsk_. The database keeps a SHA-256 hash and a short display prefix, not a recoverable copy - so the stored record cannot be turned back into a working key. The real key does pass through setup and lives in your server-side runtime, because your game has to authenticate with it. Keep it out of LocalScripts, screenshots and public repositories. - Key scope and rotation
- A key authorises exactly one game: requests are matched against the game recorded for that key. Generating a new pairing code revokes the previous key immediately, so re-pairing is how you rotate a leaked key.
- Pairing code
- A random 8-character code, stored only as a SHA-256 hash, valid for 10 minutes and burned on first use by a conditional update that can only succeed once. Generating a new code cancels any code still outstanding, and the pairing endpoint is limited to 10 attempts per minute per address.
- Invite links
- 192 bits of randomness, stored as a SHA-256 hash with a short prefix for display. Invites expire after 7 days, can be revoked, can be locked to a specific Roblox account, and are marked accepted once used.
Authorization
Signed in is not the same as allowed
Authentication establishes which Roblox account you are. Authorization decides what that account may do to a specific game. Every sensitive call resolves your access to that game, then checks whether your role holds the capability the action needs - changing live config, sending messages, editing automations, moderating players, managing group ranks or reading and rotating keys.
| Role | Can do | Notes |
|---|---|---|
| Owner | Everything below | Plus transferring ownership |
| Admin | Everything a Developer can do | Plus managing team members and invites |
| Developer | Live config, segments, messages, automations, moderation actions, group rank changes, game keys | Cannot manage the team |
| Viewer | Read-only: game data, team list, moderation history, groups | Changes nothing |
Owners can hand out Admin, Developer or Viewer; Admins can hand out Developer or Viewer; Developers and Viewers cannot grant access at all. While a game is disconnected, the actions that touch a live game are blocked for everyone, whatever their role.
Least privilege
Roblox permissions are asked for when a feature needs them
First sign-in requests openid and profile - enough to know who you are. Anything beyond that is requested from the page where you turn the feature on, so an account that never uses moderation never grants moderation permissions. Roblox replaces the whole authorization each time, so a new request re-includes what you already granted.
| Roblox permission | Requested when |
|---|---|
| openid, profile | First sign-in. Identifies your Roblox account - nothing else. |
| universe:read | Only when you ask RoSignal to find a private or team-owned experience. Public experiences are found without it. |
| universe-messaging-service:publish | Sending live messages and announcements into running servers. |
| universe.user-restriction:read / :write | Viewing and applying bans from the Moderation page. |
| group:read / group:write | Reading group roles and changing a player's rank. |
| universe.analytics:read | Showing Roblox's own analytics next to your event data. |
Data isolation
How one creator's data stays away from another's
It's worth being precise about where this boundary lives, because it is often overstated.
- Rows are scoped
- Events, configs, messages, players, automations, moderation and team records all carry the account and game they belong to, and queries are filtered by the game your access was resolved for.
- The browser never queries the database
- Every read and write goes through a server function that checks your access first. Row Level Security is enabled on all application tables and no policy grants browser-side roles access to them, so a stolen publishable key reaches nothing.
- Where the check really happens
- Those server-side queries run with a service role, so the effective boundary between accounts is the capability check in the application, backed by game and account scoping on every query - not a per-row database policy. Saying otherwise would overstate it.
- Game endpoints
- The endpoints your Roblox servers call authenticate by hashing the presented key and then only act on the single game that key belongs to, even if the URL names another.
Web application
Browser-level protections
These headers ship with the app itself, so they hold wherever it's hosted.
- HTTPS only
- Strict-Transport-Security tells browsers to refuse plain HTTP to rosignal.app and its subdomains for a year.
- Content Security Policy
- Scripts, styles, images, fonts and network calls are restricted to RoSignal itself plus the few named origins it genuinely uses (Roblox's image CDN, Google Fonts, the payment provider). Plugins and embedded objects are blocked entirely. Inline scripts and styles are still allowed because server-side rendering emits them, which is a real limit on how much this policy can stop.
- Clickjacking
- frame-ancestors 'none' plus X-Frame-Options: DENY, so no other site can frame RoSignal and trick you into clicking inside it.
- Sniffing and referrers
- X-Content-Type-Options: nosniff stops browsers second-guessing content types; Referrer-Policy: strict-origin-when-cross-origin keeps page paths out of outbound referrers.
- Unused browser features
- Permissions-Policy disables camera, microphone and geolocation.
- Caching
- API responses, auth routes and any signed-in request are sent with Cache-Control: no-store, so shared caches never keep them.
- Origin handling
- Sign-in redirect origins are restricted to a fixed list of hostnames (rosignal.app and the preview hosts used for development) rather than whatever a request claims.
Abuse containment
One runaway loop can't become unlimited backend work
Limits are per game and enforced in the database, not just in the app instance handling the request. Defaults below; plans can differ.
- Uploads
- 12 aggregate uploads per game per minute, with an hourly ceiling on top of it. Request bodies over 512 KB are rejected outright.
- Rows and events
- Up to 2,000 counter rows per upload, 500 counter rows per minute, and daily ceilings on per-player and map-cell rows. Any single row's count is clamped.
- Event names
- A cap on distinct event names per game per day, claimed atomically, so a typo in a loop can't create unbounded columns of data.
- Timestamps
- Buckets older than 24 hours or dated in the future are rejected.
- Other endpoints
- Pairing is limited to 10 attempts per minute per address, automation webhooks to 60 calls per minute per token, trait uploads to 50 players per batch.
- When the limiter itself fails
- The code falls back to an in-process limit rather than letting traffic through unchecked. That fallback is best-effort across instances - it is a brake, not a guarantee. RoSignal does not claim DDoS protection.
Failure behaviour
What happens when RoSignal is unreachable
For a live-game tool, safety also means the outside service failing shouldn't take your game with it.
- Calls are guarded
- Every network call in the runtime is wrapped, so a failed request warns rather than erroring upward.
- Track can't throw at you
- RoSignal.Track is wrapped at its entry point: if anything inside goes wrong the event is dropped and your code continues.
- Batching and backoff
- Events are counted in the server and uploaded per minute rather than one request per event. After a failed or rate-limited upload the runtime backs off from 15 seconds up to 5 minutes, resetting on success.
- Studio polling
- In Studio, config polling starts at one second and doubles up to 30 seconds while the service is unavailable, then returns to fast polling.
- Config
- Config is held in memory for the life of the server, so a later fetch failure doesn't blank out values your code is already reading. If the very first fetch fails, the runtime falls back to the defaults you pass to Get.
- Shutdown
- On server close the runtime makes a best-effort final flush within a short deadline. It's best-effort: a hard kill can still lose the last counts.
- Repair
- Repair rewrites the generated runtime from your existing key without touching your handlers, settings or demo.
Accountability
Who did what
Sensitive actions are recorded with the account that caused them and shown in the game's Activity view.
- Config changes, with the old and new value.
- Message and announcement sends, with their outcome and any error.
- Moderation actions, with the target, reason and result.
- Group rank changes.
- Automation runs, with what triggered them and what they did.
- Team changes: invites, role changes and removals.
Changes RoSignal itself makes - the guided setup demo, or an automation firing on a schedule - are recorded as runs and history entries without a person attached, because no person triggered them.
Disclosure
Reporting a security problem
Report privately first, especially anything involving keys, tokens, another creator's data or a way to act on a game you don't have access to. Please don't post it in a public channel or test against someone else's game - connect a place of your own instead.
- Email support@rosignal.app - the fastest route, and the right one for anything sensitive.
- The public repository has a SECURITY.md with the same contact: rosignal-roblox.
- For non-sensitive questions, message thunder_thigh on Discord or find me in the RoSignal server.
RoSignal is run by one developer, so there's no formal response-time commitment - reports are read first and answered as soon as possible, and confirmed fixes are listed in the changelog. RoSignal holds no security certifications and doesn't claim any.
Also useful
