RBAC and security model
Roles and capabilities, where authorization is enforced, organization MFA, API keys, MCP OAuth, credential protection, and what is logged.
Summary
- Three roles map to four capabilities. Noru's own membership record is the authority; the role your identity provider reports is mapped into it on sign-in and never consulted at request time.
- Authorization happens at the resource, on every request: pages, API calls, server actions, Cortex tools, and MCP tools each check membership and then capability.
- Machine access is scoped and hashed. API keys are organization-bound, scoped, optionally expiring, shown once, and stored as a one-way hash. MCP OAuth issues short-lived access tokens with rotating refresh tokens whose scopes are capped by the member's role.
Concepts
| Role | org.read | org.write | settings.manage | billing.checkout |
|---|---|---|---|---|
| Admin | yes | yes | yes | yes |
| Editor | yes | yes | no | yes |
| Viewer | yes | no | no | no |
A role is exactly its capability set. org.read covers every page in the sidebar; org.write covers creating, editing, linking, and deleting records, including through Cortex; settings.manage covers the whole Settings page; billing.checkout covers starting a checkout. Roles from the identity provider are mapped on the way in: an organization admin becomes admin, a member becomes editor, anything unknown or missing becomes viewer. See Roles and permissions.
How it works
Enforcement points
| Surface | Checks, in order |
|---|---|
| Every page | Signed in, active organization, membership in Noru's record, onboarding complete, then the organization MFA gate. Failure redirects. |
| REST API and route handlers | The same checks; unauthenticated calls get 401, everything else that fails gets 403. |
| Server actions (every button that writes) | Membership first, then the capability the action needs, then for privacy actions the privacy customer segment. |
| Cortex tools | Tools the role cannot use are removed before the model runs. |
| MCP tools | Scopes are issued per role and re-checked on every call. |
Membership is always verified before the role is resolved, so a removed member fails rather than being treated as a viewer. There is no allowlist in front of the app and no request-level shortcut: each resource makes its own decision.
Organization MFA gate
When an admin turns on Require MFA for all members, every page checks whether the current user has a second factor and routes them to a holding page until they add one. An admin cannot turn the requirement on from an account without MFA, so nobody can lock themselves out. The requirement is per organization and covers signing in to Noru only; it does not enforce MFA in connected systems.
API keys
- Created by admins under Settings → Developer with a name, an optional expiry in days, and one or more scopes.
- Shown once. Only a one-way hash is stored; the visible Key Prefix exists so you can match a key to a client config, and validation is constant-time so prefixes cannot be probed.
- Bound to the organization and acting as the admin who created it. Last Used updates on each call.
- Revocation is immediate and permanent; the row stays, marked Revoked.
MCP OAuth
Interactive AI clients sign in with OAuth rather than a key. The authorization server publishes its metadata at a well-known URL; clients register dynamically or present a client ID metadata document, and use PKCE. The consent screen shows the client's name and host, lets you pick the organization the client acts in and tick the permissions it needs, and disables anything above your role. A remembered approval is reused only when it covers every requested scope, and is re-narrowed to your current role each time.
| Setting | Value |
|---|---|
| Access token | 1 hour |
| Refresh token | 30 days, rotated on every use; reuse of an old token revokes the whole family |
| Refresh | Re-checks the membership the grant rests on, so a removed member cannot keep a token alive |
| Token storage | Tokens are stored as one-way hashes; client secrets are hashed too |
Every scope decision goes through one rule: admins and editors may hold all scopes, viewers only read scopes; offline_access is a protocol scope any role may hold. Unknown scopes are dropped.
| Scope family | Scopes |
|---|---|
| Read | read:frameworks, read:policies, read:controls, read:risks, read:evidence, read:organization, read:users, read:vendors, read:assets, read:personnel, read:datamaps, read:internal-audits |
| Write | write:policies, write:controls, write:compliance, write:risks, write:evidence, write:assets, write:vendors, write:personnel, write:datamaps, write:internal-audits, write:ai-inventory |
Connector credentials
Credentials for data sources are encrypted at rest with authenticated encryption under a key held only by our infrastructure. The same sensitive-field list drives three behaviours: encryption in storage, stripping before a sync is queued so that no secret ever sits in a background job payload, and redaction before a configuration reaches the browser. Secrets are decrypted only at the moment of use. Evidence signing keys are protected under a separate key, so a credential leak could not enable forged attestations. See Permissions and security.
Sessions and activity
Active sessions are tracked with their expiry so a missed sign-out event cannot leave a user signed in indefinitely. A latest-state record per actor (user or API key), organization, and source (web, API, MCP) holds last-seen and last-action times; it is presence, not an event log.
Headers
Every response carries frame, content-type, and referrer protections, HSTS, a permissions policy, and a content security policy limited to Noru and the third-party services the app embeds.
What is logged
Changes to policies, risks, and controls are written to their own logs, visible on the record; integration syncs keep a sync history; vendor events (assignment, submission, review) go to the vendor activity log; and every background job keeps its own log lines. Writes through the REST API and MCP land in the same logs as a click in the app.
Edge cases and failure modes
- Revocation fails closed. Removing a member breaks their pages, actions, and OAuth refresh on the next request. API keys they created survive, because keys belong to the organization.
- Identity-provider role drift is ignored. If the identity provider and Noru disagree, Noru's record wins until the next sync.
- Demotion narrows tokens immediately. A user demoted to viewer loses write tools on the next MCP call without re-authorizing.
- Onboarding. Until onboarding completes, everything but the onboarding flow itself is refused.
- The last admin cannot be removed and cannot demote themselves.
What you can influence
- Member roles and the organization MFA requirement (admins).
- API key scopes and expiry, and revoking keys.
- Which scopes you consent to for an MCP client, within your role's cap, and whether the approval is remembered.
Related guides
Last updated on
AI and Cortex
Where AI is used in Noru, how customer data is handled, how Cortex tools are gated by role, and how AI output is marked so it is never mistaken for a decision.
Notifications and email
Where in-app notifications come from, how they reach the browser, which emails exist, how preferences apply, and what Slack does and does not do.