Concepts

RBAC and approvals

Roles, scopes, and how production publishes get gated.

Showly's access model has three layers: roles on the workspace, scopes on the action, and approvals for production-impacting changes. This page covers how each layer composes.

Roles

A user's role is set at the workspace level. From least to most privilege:

RoleCan do
viewerRead sites, deployments, logs, audit log.
deployerRead + create deployments.
developerRead + manage projects and sites, create deployments, read webhooks/flags, forms.
adminFull access: workspace settings, MCP tokens, billing, members, approvals.
ownerFull access, plus transfer ownership and delete the workspace.

Workspaces can also define custom roles (via role permissions) when the five built-ins don't fit.

A user can have at most one role per workspace. Memberships across workspaces are independent — being owner of one workspace gives you nothing in another.

Scopes

MCP tokens, API tokens, and service tokens carry scopes that are a strict subset of what their issuer can grant. A scope describes a resource:verb pair. The ten MCP scopes are:

project:read
site:read
site:write
preview:read
preview:create
checks:run
publish:request
logs:read
template:read
template:create

Roughly, viewer maps to the read scopes (project:read, site:read, preview:read, logs:read, template:read); developer adds the write scopes used by the agent loop (site:write, preview:create, checks:run, publish:request, template:create); admin and owner carry the full set. Internally, workspace roles also grant broader org-level scopes (for example deployment:write, token:, billing:, member:, approval:) that aren't exposed over MCP — those govern dashboard and API actions, not agent tools.

A token can only do what's in its scope set, regardless of who issued it. Issuing a token with a scope you don't have is rejected.

See the scope reference for the canonical scope-to-tool mapping.

Approvals

Approvals gate production-impacting changes. The most common rule: publishing to production requires N approvals from a set of allowed roles.

Approval-request defaults:

  • requiredApprovals defaults to 1.
  • allowedRoles defaults to an empty list, meaning any role may approve.
  • A reject is final — a rejected request cannot be re-approved.

When an agent calls request_publish over MCP, the resulting publish request is created with requiredApprovals: 1 and allowedRoles: ["owner", "admin"]. This MCP-driven approval workflow requires the approvalWorkflows entitlement (Team plan).

Customize per site or per workspace in Workspace settings → Approval policy.

Separation of duties

A user cannot approve their own request. This is enforced at the data-model level: if you proposed the publish, someone else with an allowed role must approve it.

What gets audited

Every action — agent, human, API — writes an audit row:

  • actor (user id + role at the time, or MCP client id + scopes)
  • action (the scope verb + resource id)
  • outcome (allowed, denied, pending_approval, approved, rejected)
  • when

Audit rows are append-only and exported to your SIEM if you've connected one.

Emergency overrides

Showly does not currently expose an emergency publish bypass through MCP or the public Web flow. Emergency work is handled by accelerating approval on a ready preview, then publishing with fresh MFA. If a future break-glass path is added, it must:

  • still pass an approval (the gate is approvals, not authorization).
  • write a special emergency=true audit row.
  • open a follow-up post-mortem task automatically.