Subsystem

HTTP API: users

The 4 operations tagged users, each with its parameters, its body and what it answers.

List the accounts on this instance

GET /v1/users

Who is on this instance, oldest first.

Paged like every other listing here (SR#2384). It used to take a ceiling of 200 rows from the domain, supply no limit of its own, and answer with a literal has_more: false — so past two hundred accounts it dropped rows and stated there were no more, with a null total that could not contradict it. The docstring said has_more was always false for the same reason a task's links are, and that reason does not survive a ceiling: a task's links are bounded by what somebody typed, where this was bounded by a number we chose.

answers_to names a person and returns the agents answerable to them (SR#2387), directly or through another. It exists because paging this listing would otherwise break the one thing that reads it whole: subroutine user deactivate says "this also stops N agent(s)" before it acts, and a confirmation that under-reports is worse than the truncation this route was fixed for. A caller wanting one account by name wants GET /v1/users/{username} (SR#2386) rather than this listing and a filter in their own code.

total is opt-in, which is §8.4's rule; the old envelope answered null and meant nothing by it.

Parameters

Responses

Create an account

POST /v1/users

Add a person, or a machine identity, to this instance.

Needs instance:user_create. The new account belongs to no workspace yet — joining it to one is a separate act with a separate permission, because deciding that somebody exists and deciding where they may work are different decisions and often different people.

Request body: Create as application/json, required.

Responses

Read one account

GET /v1/users/{username}

Read the account with this name — SR#2386.

The API was behind its own domain here. domain.users.by_username has always existed and both POST and PATCH resolve through it; nothing published a way to read one account, so a caller wanting si fetched the whole directory and filtered it themselves. That is a client re-implementing a lookup the server owns, and it is why paging the listing could not be done on its own (SR#2384).

Readable by anyone authenticated, for the same reason the listing is: an identifier is unique and public where content is neither, and this view carries no email address and no content at all.

Case-insensitive, because by_username resolves through the normalised column — Simon and simon being two accounts would be a trap rather than a feature.

Parameters

Responses

Mark somebody as having left, hand an agent over, or say where you are

PATCH /v1/users/{username}

Mark somebody as having left or brought back, or hand an agent to somebody else.

Both in one call, and the order is deliberate: handing the agents over happens before the deactivation, so somebody clearing up after a leaver in a single request keeps what they meant to keep.

Needs instance:user_create — the same grant as making an account, because deciding somebody works here and deciding they no longer do are the same decision twice.

Except timezone, which needs no permission and is refused for anybody but yourself. The check is are you this person, not something anybody can be granted: §6.5's user level records where somebody keeps their diary, and a permission to write it would be a permission to be wrong on their behalf.

Deactivating stops every agent answerable to that person, at their next call, wherever they are running. Ask for the list first with GET /v1/users?answers_to=<username>: the CLI names them before it does it, and a caller here should too. That used to say to read GET /v1/users and pick the rows out by responsible_user_id — which was a whole directory fetched to answer one question, and it stopped being possible the moment that listing was paged (SR#2384, SR#2387). It also only ever found the agents answerable directly; the filter walks the chain, which is what "answerable to that person" means one sentence above.

The last person who can administer the instance is refused, because an instance nobody can administer cannot be repaired from inside and would have stopped every agent on it.

Parameters

Request body: Update as application/json, required.

Responses