ROKRescue Operator Knowledge

How it works

How ROK keeps agencies' data separate

Where ROK checks each request — the agency in your session token, row-level security rules in the database, workflow triggers and server functions — and why a hidden button isn't the security.

Many agencies share one ROK system, so the question that matters is where the line between them is drawn. The short answer: in the database, on every request. By the end of this page you'll know what happens between a click in the console and a row coming back, which checks run where, and which protections are about the screen rather than the data.

Where ROK checks a requestEvery request is checked in the database. The screens only decide which buttons to show.Console or apppublishable key onlySession tokencarries the active agencyDatabase APIreads and writes rowssigns ineach requestchecked per rowRow-Level Securityagency + permissionwritesWorkflow triggerse.g. publishing rulesreads return onlythe rows that passChange savedonly if every rule passesRefusedwith the reasoninvites, billing, syncServer functionssecret key · re-check firstHidden buttona courtesy, not a controlServer functions bypass the row rules, so each one establishes who is calling before it acts.
The database decides what each request can read or change. The screen only decides what to show.

The apps hold no secrets

The console in your browser and the operator app both talk straight to the database's API. Neither has a ROK application server of its own in between, and neither contains a secret key. They carry a publishable key — an identifier for the project that grants nothing by itself — plus the signed session of the person using them. Everything else depends on who that session belongs to.

Your session carries your active agency

When you sign in, and whenever your session is refreshed, a database hook stamps your session token with your active agency. Before it does, it checks that you're an active member of that agency and that the agency itself is active; if not, it falls back to another agency you actively belong to, or to none. Switching agencies updates your profile — the database refuses an agency you're not an active member of — and refreshes the token.

A session with no active agency fails closed: every rule that compares a row's agency with the session's matches nothing.

Row-level security decides each row

Row-level security is switched on for the tables that hold agency data. Each has rules — policies — that the database applies to every read and write, row by row:

  • Is this row in your active agency? Almost every policy compares the row's agency with the one in your session.
  • Do you hold the permission? Beyond reading published content, a policy asks whether you hold the relevant permission in that agency, through your groups — creating content needs Create content, editing needs Edit content, and so on. See how access works.

A read returns only the rows that pass; a write that fails is refused. Operators can read only published content; drafts are readable only by staff of the same agency. Uploaded files follow the same rule: they're stored under a folder named for your agency, and storage checks that folder against your active agency (the files of published ROK Library items aside, which can be read so they can be imported).

Every one of these checks looks up your account, your membership and your agency's status as each request runs, not just when the token was issued — the agency named in the token counts only while you're still an active member of it. So suspending someone, removing them or suspending the agency takes away their access on their next request, published content and files included, rather than at their next token refresh. The operator app's sync also checks on every attempt, and stops sending an agency's content to a member suspended there, or to anyone once the agency itself is suspended.

Triggers enforce the workflow

Some rules are about whether a change is allowed, not who can see a row. Those live in database triggers that run on the write itself, whichever screen or app sent it:

  • the publishing workflow — publishing needs Publish, submitting needs Submit for review, withdrawing needs Unpublish — and two-person sign-off;
  • plan caps on members, content and storage — see how plans and limits work;
  • the ceiling on group changes: you can only hand out groups whose permissions you already hold.

Server functions re-check the caller

A few jobs can't be expressed as a row rule — sending invitations, managing the subscription, building an operator's offline sync, rendering print binders, exporting your agency's data. These run in ROK's server functions, which hold the secret key and therefore bypass row-level security. So each one works out who is calling before it acts. The functions that act for a signed-in person verify the session and check the relevant permission again, in the agency concerned — Manage users for invitations, Manage billing for the subscription. The sync function works out your agency on the server from your active membership, and filters everything it sends by it.

Hiding a button is not the security

The console hides controls you can't use, so the screen stays honest. That is presentation. If you reached a hidden control another way, the database would still apply the same rules. When an action is refused despite a visible button, the reason is a missing permission or an unmet condition — not a broken screen.

The two-factor requirement under Security is enforced in both places. The console will not show its screens until a required second factor is entered, and the database checks how the session signed in: a permission only counts from a session that passed two-factor authentication when your policy covers staff, or whenever the person has enrolled an authenticator. ROK's own platform administrators get no cross-agency access at all without it. A stolen password used directly against the API therefore carries no more than an operator's read access. Idle sign-out is different — the console signs an idle tab out; it is not a database rule.

Accounts belong to people, not agencies. One agency cannot add an existing account to itself — the person is invited and must accept — and an agency cannot set the password of, or remove the authenticator from, someone who also belongs to another agency.

What this means in practice

  • A screen's own filtering doesn't widen what the database returns. Whatever a screen asks for, it gets back only the rows the rules allow your session.
  • "Where did it go?" is usually the active agency. Everything you see belongs to the agency in your session — check the switcher in the header. See agencies, members and what's separate.
  • Two things are shared on purpose, read-only: the ROK Library's published content and the active ROK recognition catalog.
  • ROK support visits are recorded and limited. ROK staff who are not members of your agency enter it only on a support visit: they must give a reason, it is view only unless they chose to make changes, it can never publish, delete content, notify your operators, change who has access or touch billing, and it ends after four hours. Each visit's start and end, with the reason, appear in your audit log as Entered tenant (platform admin) and Left tenant (platform admin).

See also

Last reviewed