Roles and permissions
A person's authority comes from their role in a workspace. A workspace token's authority comes from its scopes. Teams have no roles of their own: a workspace's members may work in every team of that workspace. Reading how a team's work turned out is narrower; see Team outcomes.
Roles
| Role | Rank | Permissions |
|---|---|---|
owner | 2 | read, plan, configure, manage-secrets, manage-runners, manage-token-trusts, administer |
admin | 1 | read, plan, configure, manage-secrets, manage-runners, manage-token-trusts, administer |
member | 0 | read, plan |
The web app shows the roles as Owner, Admin and Member. The person who creates
a workspace is its owner. A person who accepts an invite joins with the role
the invite gives, admin or member. A workspace always has at least one
owner.
A closed workspace grants nothing to anyone.
Permissions
| Permission | Allows | Granted to |
|---|---|---|
read | See a workspace and its resources, and export it as Terraform. | Every role. Every token. |
plan | Check expressions, at POST /api/expressions/check. Open, change and delete replay sets, mark the set that guards a station's changes, start and stop replays, propose and withdraw replay candidates, start and stop searches, pick a search's candidate, and start replay checks, on a team whose outcomes the caller may read. | Every person. Tokens with plan or configure. |
configure | Create, change and delete teams, lines, integrations, hooks, skills and harness profiles; change the workspace. | Owners, admins. Tokens with configure. |
manage-secrets | Create, change and delete secrets. | Owners, admins. Tokens with secrets. |
manage-runners | Create, change and delete runner pools, runner trusts and workspace runners. | Owners, admins. Tokens with runners. |
manage-token-trusts | Create, change and delete workspace token trusts. | Owners, admins. Tokens with trusts. |
administer | Issue, change and revoke workspace tokens; read configuration changes; close the workspace; invite people, list, resend and revoke invites, and add members to teams; connect GitHub; connect the team to an integration over OAuth. | Owners, admins. Never a token. |
open-workspaces | Create a workspace. | Every signed-in person. Never a token. |
A request for something the caller cannot see returns 404. A request to
change something the caller can see but may not change returns 403:
| Permission missing | Title |
|---|---|
configure, manage-secrets, manage-runners, manage-token-trusts | Not allowed to change the <kind> |
administer | Not allowed to administer the <kind> |
open-workspaces | Not allowed to open a workspace |
plan | Not allowed to plan |
See Resource API for the error format.
Token scopes
A workspace token carries one or more scopes. Each scope grants itself and the scopes listed beside it.
| Scope | Also grants | Permissions |
|---|---|---|
read | read | |
plan | read | read, plan |
configure | plan, read | read, plan, configure |
secrets | read | read, manage-secrets |
runners | read | read, manage-runners |
trusts | read | read, manage-token-trusts |
A token's scopes must include read, plan or configure, and name each
scope once; see Scopes for the
messages. A token acts only in its own workspace. See
spotlight_workspace_token_trust for tokens a
trust mints.
Team outcomes
How a team's work turned out can be read only by:
- people on the team;
- the workspace's owners and admins;
- workspace tokens of the workspace with the
readscope.
Anyone else is answered 404, as for something that does not exist.
| Outcome | Where |
|---|---|
| Station outcomes | "Latest runs on this config", "Recent runs" and "Version" on a work station's "Overview" tab, and "Runs by config" on the station's view on Insights. See Station outcomes. |
| Judge | The judge's agreement with people under "Judge" on a work station's "Overview" tab and under "How far to trust the judge" on the station's view on Insights, a run's judge score and people's grades, and grading a run. See Judge and alerts, Agreement and Grades. |
| Grade items | Inbox items asking to grade a run. They reach no one else. |
| Station alert items | Inbox items saying a station crossed one of its alert thresholds. They reach no one else. |
| Insights | Every tab of a team's Insights page, the Insights API, and the Replayed candidates API. |
| Replays | A work station's "Replays" section, its replay sets, replays and replay runs, the Replays API, and the team's replay candidates. Changing them also needs plan. A replay run, with its config and event stream, is readable only through the team it replayed for, even after its station is removed. See Replays. |
| Searches and replay checks | A work station's "Searches" section, its searches, the pull requests picked candidates open, and its replay checks: the Searches API and the Replay checks API. Estimating a search needs only read. Starting and stopping a search, picking a candidate, marking a guarding set and starting a check also need plan. See Searches. |
Members
GET /api/workspaces/{slug}/members lists everyone in the workspace, with
their role, their teams and the roles the caller may give them. Every member
of the workspace may read it. The web app's Members page (see
Web app) is shown only to owners
and admins; a member who opens it is sent to the workspace's own route.
Changing roles
Roles are changed on the Members page, in the "Members" list of any team's
"General" settings page, or with
PATCH /api/workspaces/{slug}/members/{userId}. The role changed is the
person's role in the workspace, and holds in every team.
- Only an owner or an admin may set roles.
- An owner may change anyone's role, including their own.
- An admin may change only members, and may not give the
ownerrole. - The last owner may not be given another role.
For an owner or admin, setting a person's role to the one they already hold changes nothing and is not refused. A refused change returns one of these:
| Status | Message | Cause |
|---|---|---|
403 | This person is not a member of this workspace. | The person is not a member of the workspace. |
403 | Only an owner or an admin can set roles. | The caller is not an owner or admin. |
403 | You can only set roles for people below you. | An admin changing an owner or another admin. |
403 | You cannot change your own role. | An admin changing their own role. |
403 | You cannot give a role above your own. | An admin giving the owner role. |
409 | The workspace needs at least one owner. Please make someone else an owner first. | The last owner given another role. |
The web app offers a role menu only where more than one role can be given.
Invites
An invite asks one email address to join the workspace with a role, and optionally names teams of the workspace to join.
| Action | Endpoint | Who may |
|---|---|---|
| Invite | POST /api/workspaces/{slug}/invites | Owners and admins. |
| List pending invites | GET /api/workspaces/{slug}/invites | Owners and admins. |
| Send an invite again | POST /api/workspaces/{slug}/invites/{inviteId}/resend | Owners and admins. |
| Revoke an invite | DELETE /api/workspaces/{slug}/invites/{inviteId} | Owners and admins. |
| Read what an invite link offers | GET /api/invites/{token} | Anyone with the link, signed in or not. |
| Accept an invite | POST /api/invites/{token}/accept | The person signed in with the invited address. |
| Add a member to a team | POST /api/teams/{teamId}/members | Owners and admins. |
Every action but reading an invite link needs a person signed in; a workspace
token is answered 401. A caller who is not an owner or admin of the workspace
is answered 404 by the actions only they may take, as for a workspace that
does not exist.
- An invite gives the
adminormemberrole. Nobody is invited as anowner; owners and admins may both invite asadmin. - One request invites 1 to 50 addresses, all with the same role and teams. Addresses are compared without regard to case, and a repeated address is invited once.
- An address that belongs to a member of the workspace is sent nothing.
- An address with an open or expired invite is sent it again, with a new link, the role and teams of this request, and a fresh 14 days. An address whose invite was revoked or accepted gets a new invite.
- Sending an invite again replaces its link; the old link stops working. Only an open or expired invite can be sent again.
- Revoking an invite stops its link working. Revoking a revoked invite changes nothing. An accepted invite cannot be revoked.
- An invite lasts 14 days from when it was last sent.
- Accepting needs the person to be signed in with the invited address, compared without regard to case, and the invite to be open.
- Accepting adds the person to the workspace with the invite's role, and to each team it names that still belongs to the workspace. A person already in the workspace keeps their role and is added to the teams.
- The pending invites list holds only open invites, newest first.
- Adding a member to a team needs the person to be in the workspace already.
Each address in an invite request gets one outcome:
| Outcome | Web app | Meaning |
|---|---|---|
invited | "Invited" | A new invite was emailed. |
sent-again | "Sent again" | An open or expired invite was emailed again. |
already-a-member | "Already a member" | The address belongs to a member. Nothing was sent. |
not-sent | "Not sent. Please resend it from Pending invites." | The invite was written but the email could not be sent. |
The email's subject reads <inviter> invited you to join <workspace> on Spotlight,
names the teams the invite joins, and links to /invites/<token> at the
Spotlight address. When the
control plane has no mail server set (SMTP_URL), the message is written to
its log instead of sent.
| State | Meaning |
|---|---|
open | Sent, not yet accepted, revoked or expired. |
accepted | Accepted. |
revoked | Taken back. |
expired | Not accepted within 14 days of being last sent. |
Errors and messages lists the refusals. See Invite people and change their roles and Join a workspace from an invitation.
Actions only people can take
These need a person signed in to Spotlight. A workspace token is refused:
| Action | Needs |
|---|---|
Anything under administer | An owner or admin. |
| Creating a workspace | Any signed-in person. |
| Approving, editing or dismissing a tool call or harness permission | The assignee of the task that asks. A call that asks because of a person's own tool rule is put to that person, and only they can approve it. |
Answering the inbox, saying something to a run and stopping a run are also reserved to the task's assignee.
GitHub connection
Connecting a GitHub App installation to a workspace needs both:
| Condition | Checked by |
|---|---|
| The person is an owner or admin of the workspace. | Their workspace role. |
| The person administers the installation. | GitHub, with the person's GitHub sign-in. For an organisation's installation, they are an active admin of the organisation. For a user's installation, they are that user. |
| Status | Message | Cause |
|---|---|---|
403 | Only a workspace owner or admin can connect GitHub. | Not an owner or admin. |
403 | You are not an admin of this GitHub installation. | Not the installation's administrator. |
403 | GitHub could not confirm this installation is yours. Please sign in again. | GitHub would not say. |
409 | GitHub installation <id> is connected to another workspace. Please disconnect it there first. | Connected to another workspace. |
One installation connects one workspace. See Installation callback and Connect GitHub to a workspace.
Integration connections
An integration that links over OAuth holds a team connection, and, when its
connection.holder is requester, a connection for each person who makes
one. See Holder.
| Action | Who may |
|---|---|
| Connect or reconnect the team | An owner or admin of the workspace. |
| Connect, reconnect or disconnect their own account | Any person on the team, for an integration whose holder is requester. |
| See who on the team has connected, with the account the host named | An owner or admin of the workspace. Nobody sees another person's token. |
| Disconnect another person | Nobody. |
| Set what to ask of each tool's calls made with their own connection | Any person on the team, for themselves only, for an integration whose holder is requester. |
| Approve a call that asks because of a person's own rule | Only that person. The task is put to them. Whoever may answer the task can dismiss the call. |
A tool of a requester integration acts only with the connection of the
person who started the task, and only while they are on the team. Of the
team's rule for a tool and that person's, the stricter wins. See
Person rules
and
Connect an integration that signs in with OAuth.