# How Clanker Ship works

The website, the API and the MCP server run the same services, with the same permission checks behind each.

Clanker Ship has one set of services: the rules for workspaces, planning, clanker messages, test runs
and secrets, and the permission checks that guard them. The website, the HTTP API and the MCP server
are three ways to call those services. An action that a viewer may not take is refused on all three,
with the same message.

## The surfaces

| Surface          | Address                                  | Who uses it                                     | Signs in with                      |
| ---------------- | ---------------------------------------- | ----------------------------------------------- | ---------------------------------- |
| Website          | `https://clankership.com`                | People                                          | Google, or email and password      |
| HTTP API         | `https://api.clankership.com/v1`         | Scripts, CI, integrations and the `clanker` CLI | API keys, or the CLI's own sign-in |
| MCP server       | `https://api.clankership.com/mcp`        | Clankers                                        | A clanker grant, through OAuth     |
| Clanker HTTP API | `https://api.clankership.com/clanker/v1` | The plugin's CLI, and clankers without MCP      | The same clanker grant             |

The website calls the services directly, not through the API. The API and the MCP server run
together on the API host and call the same services for each request. A background worker sends
invite emails and runs scheduled jobs with the same services. Workspace data lives in one database,
and test-run evidence such as videos and traces is kept in object storage.

## Who acts

Every request acts for someone, and the services check that someone's role in the workspace before
they read or change anything.

| Caller             | Credential                          | Acts with                                                                   |
| ------------------ | ----------------------------------- | --------------------------------------------------------------------------- |
| A person           | A website session                   | Their role in the workspace                                                 |
| A user API key     | `ctk_…`                             | Its owner's current role in each workspace                                  |
| A CLI login        | `ctat_…`, from `clanker auth login` | The person who signed in                                                    |
| An account API key | `ctk_…`, belonging to one workspace | The role it was given: owner, admin, member or viewer                       |
| A clanker          | An access token from its grant      | The person who granted it, limited to the grant's `read` and `write` scopes |
| A vault key        | `ctvk_…`                            | Nothing but pulling the production secrets it names                         |

Roles are owner, admin, member and viewer; see
[Workspaces and roles](https://docs.clankership.com/get-started/concepts/workspaces-and-roles.md). A clanker never has more access
than its person: a viewer's clanker only reads.

## One rule set

Because every surface calls the same services:

- **The rules match.** A slug that is taken, an archived product, or a ticket status from another
  team fails the same way on the website, through the API and from a clanker. The API returns it as
  an [error](https://docs.clankership.com/api/errors.md) with a tagged name; the MCP server returns it as a tool error with a code.
- **The operations match.** The API does everything the website does. Each MCP tool has an HTTP
  twin under `/clanker/v1`, so the plugin's CLI and the MCP server cannot drift apart.
- **Workspaces stay apart.** Another workspace's objects are not found: requests for them return
  `404`, never `403`.

## Every change is recorded

Each change writes an event in the same transaction, naming what changed and who changed it: the
person, the clanker and the person it works for, or the account API key. The workspace's
**Events** page lists them, and so does [List events](https://docs.clankership.com/api/events/list.md).

## The loop

Clanker Ship is built around one loop. People decide what to build and accept the proof; clankers do
the work in between.

1. A person or a clanker creates a ticket on a team, such as `WEB-31` Add docs search, and writes
   its Scope: the goal, numbered requirements and how we will know it works. Given any task, the
   plugin's `work-on-ticket` skill finds the task's ticket or creates it, and links it to the
   branch it works on.
2. A person approves the scope and sends the ticket to their clanker with an ask, such as Write the
   plan.
3. The clanker writes the Plan from its status's
   [instructions](https://docs.clankership.com/get-started/concepts/planning/clanker-instructions.md) and stops for a person to
   approve it and its test cases.
4. The clanker builds it, records each step in the Build record, and runs the tests with
   `clanker run`, which publishes a [test run](https://docs.clankership.com/get-started/concepts/test-runs.md) with every test's
   evidence.
5. The clanker writes the Review: the demo, the runs and what changed. A person approves it, and the
   change merges and moves to Ship.
6. The clanker follows the change into production, writes the Ship report, and moves the ticket to
   Done.

Each checklist item says whether a person or a clanker does it, so both know whose move it is, and
shows whether it is not started, in progress or done, so everyone sees what is being worked. When
only a person's items are left, a clanker asks a question, or work comes back, the ticket shows
**Needs human** until a person acts, and its owner is notified.

The clanker links the pull request it opens to the ticket at the end of Build, so reviewers open it
from the ticket page and the clanker knows which pull requests to merge and follow into production.
