Subsystem

HTTP API: workspaces

The 11 operations tagged workspaces, each with its parameters, its body and what it answers.

List workspaces

GET /v1/workspaces

List the workspaces this caller can reach.

Parameters

Responses

Create a workspace

POST /v1/workspaces

Create a workspace, stocked with its vocabulary, owned by you.

Needs instance:workspace_create, which is an instance-tier verb: it happens outside every workspace, so no role can carry it and only a superuser holds it (§7.1). A token still narrows it.

Request body: Create as application/json, required.

Responses

Read one workspace

GET /v1/workspaces/{id_or_slug}

Return one workspace, by id or by short name.

Parameters

Responses

Change a workspace

PATCH /v1/workspaces/{id_or_slug}

Change a workspace. Omitted fields are untouched; nulls clear (docs/design.md §8.3).

Parameters

Request body: Update as application/json, required.

Responses

Move a workspace to the trash

DELETE /v1/workspaces/{id_or_slug}

Soft-delete a workspace. Everything in it leaves the visible world, and returns with it.

Needs workspace:delete, which is the only verb separating the owner and admin roles — so until this route existed the two were the same role with two descriptions.

The workspace itself is returned rather than a 204, so a caller can see deleted_at and knows what to hand back to the restore. The last live workspace is refused: an installation with none cannot file a task and reports itself as interrupted part-way through setup.

Parameters

Responses

Who belongs to this workspace

GET /v1/workspaces/{id_or_slug}/members

List this workspace's members and their roles.

Needs workspace:read: knowing who you are working alongside is part of working somewhere, and it is the question anybody about to add or remove somebody asks first.

Enveloped and unpaginated, like a task's links (§8.4) and for the same reason — a workspace's membership is bounded by how many people somebody put in it.

Parameters

Responses

Add somebody to this workspace

POST /v1/workspaces/{id_or_slug}/members

Give somebody a role in this workspace.

Needs workspace:admin rather than workspace:write: deciding who belongs somewhere is not the same act as doing work there, and a member who can add members can grant themselves anything the roles allow. That check did not exist at all at first — the service took an actor, attributed the event to it, and never asked it anything — and it was found on the morning this endpoint was written.

Parameters

Request body: Join as application/json, required.

Responses

Change what somebody may do in this workspace

PATCH /v1/workspaces/{id_or_slug}/members/{username}

Move an existing member to another role.

A third verb rather than a flag on the POST, because adding somebody and re-grading them are two acts: one decides that they belong here, the other decides what they may do now that they do. Until this existed the only route was to remove them and add them back, which writes two events for one act and leaves nothing in the record saying a role moved.

Needs user:admin, the same verb that gates adding and removing — its own description is managing who belongs to this workspace and what they may do here, and this is the half of that sentence nothing implemented.

Somebody who is not a member is refused by name rather than added, which keeps this and the POST a pair: each turns down the other's case and says which one to run.

The last account able to administer the workspace cannot be moved out of an administering role, for the same reason it cannot be removed — a workspace nobody can administer cannot be repaired from inside, including by granting the role that would repair it.

Parameters

Request body: Regrade as application/json, required.

Responses

Take somebody out of this workspace

DELETE /v1/workspaces/{id_or_slug}/members/{username}

Remove somebody's membership of this workspace.

Here rather than later, for the reason that holds of anything that can be added: somebody joined by mistake can see private projects they should not, and a membership that can only be granted is one whose mistakes are permanent.

The last account able to administer the workspace cannot be removed — a workspace nobody can administer has thrown away the remedy for every later mistake, including that one.

Parameters

Responses

Take a workspace out of the trash

POST /v1/workspaces/{id_or_slug}/restore

Restore a soft-deleted workspace, and everything in it with it.

POST rather than DELETE ?restore=, matching a project's restore, because it is not a deletion of anything. The short name may have been taken while this was in the trash — the unique index ignores deleted rows — and that is refused by name with the rename that clears it, rather than surfacing as a constraint violation.

Parameters

Responses

What is in force in this workspace, and where it came from

GET /v1/workspaces/{id_or_slug}/settings

Every setting this workspace may carry, as it applies here.

Each says what is in force, what it would be if nothing stated it, and whether this workspace states it — so a settings page can tell a choice somebody made here from a default nobody chose. A workspace is the widest scope there is, so nothing here is inherited.

Needs workspace:read.

Parameters

Responses