# Workspaces and roles

A workspace holds a company's work and people, and each member's role decides what they and their clankers can do.

A workspace holds a company's products and environments, its teams, projects and tickets, its test
runs and secrets, and the people who work on them. Every other object belongs to exactly one
workspace. API paths name it by its slug or its ID, such as `/v1/workspaces/acme`.

## Slugs

A workspace slug is 2 to 48 lowercase letters, digits and hyphens, with no hyphen at the start or
end, such as `acme`. Owners and admins can change it under **Settings › Workspace**. API paths take
the workspace ID too, which never changes, so a script that stores the ID keeps working after a
rename. The `clanker link` command stores the ID for the same reason.

## Roles

Each member has one role. Clankers act with their person's role, and account API keys with the role
they were given.

| Role   | Can                                                                                                                                                                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Owner  | Everything an admin can, plus give or take the owner role and manage owner account API keys                                                                                                         |
| Admin  | Manage the workspace, its people, invites, teams, ticket statuses, workspace tags, vault keys and production secrets                                                                                |
| Member | Do the work: create and change products, environments, deployments, tickets and projects; change their teams' views, tags and clanker instructions; publish test runs; write non-production secrets |
| Viewer | Read everything they can see, and join open teams                                                                                                                                                   |

Each concept page lists the exact rules for its objects, such as who may change a team's tags or
restore a production secret.

- Admins cannot change an owner's role, make anyone an owner, or remove an owner.
- The last owner cannot be demoted or removed, and nobody can remove themselves.
- A viewer's clanker can only read, because a viewer can grant only the `read` scope.

## Members and invites

Owners and admins invite people from **Settings › Members** with **Invite member**. An invite asks
one email address to join with a role and, optionally, teams. Its emailed link expires after 7
days; resending sends a fresh link and the old one stops working. The person accepts with the same
email address the invite was sent to.

**Allowed domains** on **Settings › Workspace** list email domains, such as `acme.dev`. When they
are set, invites must use one of them, and anyone who signs in with an address on one of them joins
the workspace as a member automatically. With no allowed domains, invites may use any address.

| Operation                          | API                                           |
| ---------------------------------- | --------------------------------------------- |
| List members                       | [List members](https://docs.clankership.com/api/members/list.md)             |
| Change a role                      | [Change a member's role](https://docs.clankership.com/api/members/update.md) |
| Remove a member                    | [Remove a member](https://docs.clankership.com/api/members/remove.md)        |
| Invite people                      | [Create invites](https://docs.clankership.com/api/invites/create.md)         |
| Change, resend or revoke an invite | [Invites](https://docs.clankership.com/api/invites.md)                       |

## Account API keys

An account API key belongs to the workspace instead of a person, so CI keeps working when people
come and go. It acts with the role it was given. Owners and admins create them under
**Settings › Security › Account API keys**, or with
[Create an account API key](https://docs.clankership.com/api/account-api-keys/create.md); only owners create or manage keys with
the owner role. The key's value is shown once.

```bash
curl https://api.clankership.com/v1/workspaces/acme/account-api-keys \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Release CI", "role": "member" }'
```

```json
{
  "id": "Ak2WqH9sDf5T",
  "name": "Release CI",
  "role": "member",
  "secret": "ctk_4mT8vQ2xR7nL9pW3kS6dH1jF5bY0cZaE"
}
```

An account API key can do what a person in its role can, except what belongs to a person: it
cannot change a profile, create or list user API keys, create workspaces, register clankers, send
messages to clankers or comment on tickets. See [Authentication](https://docs.clankership.com/api/authentication.md).

## Events

Every change records an event naming the person, the clanker and its person, or the account API key
that made it. Members read them on the workspace's **Events** page: the workspace's own events, and
those about the teams, projects and tickets they can open, so a private team's events reach only
its members. Owners, admins and account API keys read every event.
[List events](https://docs.clankership.com/api/events/list.md) returns the 50 most recent the caller can read, newest first.

<!-- surfaces -->

## On every surface

Generated from Clanker Ship's surface registry. A dash means the surface leaves the operation out.

| Operation                                          | Website              | API                                                                                                                                  | MCP                                                   | CLI                                                     |
| -------------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------- |
| Read a workspace                                   | Settings › Workspace | [GET /v1/workspaces/{slug}](https://docs.clankership.com/api/workspaces/get.md)                                                                                     | [`get_workspace`](https://docs.clankership.com/mcp/tools/get_workspace.md)           | [`clanker workspace get`](https://docs.clankership.com/cli/workspace/get.md)           |
| Change a workspace's name, slug or allowed domains | Settings › Workspace | [PATCH /v1/workspaces/{slug}](https://docs.clankership.com/api/workspaces/update.md), [GET /v1/workspaces/{slug}/slug-availability](https://docs.clankership.com/api/workspaces/check-new-slug.md) | [`update_workspace`](https://docs.clankership.com/mcp/tools/update_workspace.md)     | [`clanker workspace update`](https://docs.clankership.com/cli/workspace/update.md)     |
| List members                                       | People               | [GET /v1/workspaces/{slug}/members](https://docs.clankership.com/api/members/list.md), [GET /v1/workspaces/{slug}/people](https://docs.clankership.com/api/members/list-with-role.md)              | [`list_members`](https://docs.clankership.com/mcp/tools/list_members.md)             | [`clanker member list`](https://docs.clankership.com/cli/member/list.md)               |
| Change a member's role                             | Settings › Members   | [PATCH /v1/workspaces/{slug}/members/{userId}](https://docs.clankership.com/api/members/update.md)                                                                  | [`update_member`](https://docs.clankership.com/mcp/tools/update_member.md)           | [`clanker member update`](https://docs.clankership.com/cli/member/update.md)           |
| Remove a member                                    | Settings › Members   | [DELETE /v1/workspaces/{slug}/members/{userId}](https://docs.clankership.com/api/members/remove.md)                                                                 | [`remove_member`](https://docs.clankership.com/mcp/tools/remove_member.md)           | [`clanker member remove`](https://docs.clankership.com/cli/member/remove.md)           |
| List invites                                       | Settings › Members   | [GET /v1/workspaces/{slug}/invites](https://docs.clankership.com/api/invites/list.md)                                                                               | [`list_invites`](https://docs.clankership.com/mcp/tools/list_invites.md)             | [`clanker invite list`](https://docs.clankership.com/cli/invite/list.md)               |
| Invite people                                      | Settings › Members   | [POST /v1/workspaces/{slug}/invites](https://docs.clankership.com/api/invites/create.md)                                                                            | [`create_invites`](https://docs.clankership.com/mcp/tools/create_invites.md)         | [`clanker invite create`](https://docs.clankership.com/cli/invite/create.md)           |
| Change an invite's role                            | Settings › Members   | [PATCH /v1/workspaces/{slug}/invites/{inviteId}](https://docs.clankership.com/api/invites/update.md)                                                                | [`update_invite`](https://docs.clankership.com/mcp/tools/update_invite.md)           | [`clanker invite update`](https://docs.clankership.com/cli/invite/update.md)           |
| Resend an invite                                   | Settings › Members   | [POST /v1/workspaces/{slug}/invites/{inviteId}/resend](https://docs.clankership.com/api/invites/resend.md)                                                          | [`resend_invite`](https://docs.clankership.com/mcp/tools/resend_invite.md)           | [`clanker invite resend`](https://docs.clankership.com/cli/invite/resend.md)           |
| Revoke an invite                                   | Settings › Members   | [POST /v1/workspaces/{slug}/invites/{inviteId}/revoke](https://docs.clankership.com/api/invites/revoke.md)                                                          | [`revoke_invite`](https://docs.clankership.com/mcp/tools/revoke_invite.md)           | [`clanker invite revoke`](https://docs.clankership.com/cli/invite/revoke.md)           |
| List your API keys                                 | Settings › Security  | [GET /v1/api-keys](https://docs.clankership.com/api/api-keys/list.md)                                                                                               | [`list_api_keys`](https://docs.clankership.com/mcp/tools/list_api_keys.md)           | [`clanker api-key list`](https://docs.clankership.com/cli/api-key/list.md)             |
| Create an API key                                  | Settings › Security  | [POST /v1/api-keys](https://docs.clankership.com/api/api-keys/create.md)                                                                                            | —                                                     | [`clanker api-key create`](https://docs.clankership.com/cli/api-key/create.md)         |
| Revoke an API key                                  | Settings › Security  | [POST /v1/api-keys/{apiKeyId}/revoke](https://docs.clankership.com/api/api-keys/revoke.md)                                                                          | [`revoke_api_key`](https://docs.clankership.com/mcp/tools/revoke_api_key.md)         | [`clanker api-key revoke`](https://docs.clankership.com/cli/api-key/revoke.md)         |
| List account API keys                              | Settings › Security  | [GET /v1/workspaces/{slug}/account-api-keys](https://docs.clankership.com/api/account-api-keys/list.md)                                                             | [`list_account_keys`](https://docs.clankership.com/mcp/tools/list_account_keys.md)   | [`clanker account-key list`](https://docs.clankership.com/cli/account-key/list.md)     |
| Create an account API key                          | Settings › Security  | [POST /v1/workspaces/{slug}/account-api-keys](https://docs.clankership.com/api/account-api-keys/create.md)                                                          | —                                                     | [`clanker account-key create`](https://docs.clankership.com/cli/account-key/create.md) |
| Rename an account API key or change its role       | Settings › Security  | [PATCH /v1/workspaces/{slug}/account-api-keys/{id}](https://docs.clankership.com/api/account-api-keys/update.md)                                                    | [`update_account_key`](https://docs.clankership.com/mcp/tools/update_account_key.md) | [`clanker account-key update`](https://docs.clankership.com/cli/account-key/update.md) |
| Revoke an account API key                          | Settings › Security  | [POST /v1/workspaces/{slug}/account-api-keys/{id}/revoke](https://docs.clankership.com/api/account-api-keys/revoke.md)                                              | [`revoke_account_key`](https://docs.clankership.com/mcp/tools/revoke_account_key.md) | [`clanker account-key revoke`](https://docs.clankership.com/cli/account-key/revoke.md) |
| List your CLI sign-ins                             | Settings › Security  | [GET /v1/me/cli-sessions](https://docs.clankership.com/api/cli-sessions/list.md)                                                                                    | [`list_cli_sessions`](https://docs.clankership.com/mcp/tools/list_cli_sessions.md)   | [`clanker auth sessions`](https://docs.clankership.com/cli/auth/sessions.md)           |
| Revoke a CLI sign-in                               | Settings › Security  | [POST /v1/me/cli-sessions/{session}/revoke](https://docs.clankership.com/api/cli-sessions/revoke.md)                                                                | [`revoke_cli_session`](https://docs.clankership.com/mcp/tools/revoke_cli_session.md) | [`clanker auth revoke`](https://docs.clankership.com/cli/auth/revoke.md)               |

<!-- /surfaces -->
