Users

Access is granted to users you define per domain, each holding a token. A queue's access block then lists, per operation, which users may do it and whether the public may too. No accounts service, no roles to administer: just a folder of user files and a few lists.

taskhoster-users/
  alice.json                user "alice"
  worker1.json              user "worker1"
Users are defined in the taskhoster-users directory of a domain.

Shape

A user is a single JSON file in a domain's taskhoster-users/ folder, named for the user. It holds just two fields:

{
  "taskhoster-name": "alice",
  "taskhoster-token": "0123456789abcdef0123456789abcdef"
}
The user Alice, defined in alice.json
FieldTypeWhat it is
taskhoster-nametextThe user's name; repeats the filename (without .json).
taskhoster-token32-char hexThe access token. You author it yourself; it is not issued by the server, and only its plaintext lives in the file (which the client syncs up like any definition).

The access block

A queue's taskhoster-access block covers the three things one can do to a queue. Each is an object of { "taskhoster-public": bool, "taskhoster-users": [ … ] }:

OperationCovers
taskhoster-postPosting an item: POST /<queue>.
taskhoster-fetchReading status and monitoring: GET /<queue>/items/<id> and the /monitor socket.
taskhoster-workClaiming, progress and result: /claim, the items/<id>/progress and /result endpoints, and the /work socket.

An operation is allowed if the request presents the token of a user in its taskhoster-users list, OR taskhoster-public is true. Both can be on at once: a public operation that also lists users is open to everyone and records the name of any user who authenticated. A missing or empty access block grants nothing; the queue is fully closed. A denied request returns a plain 404, indistinguishable from a queue that isn't there, so a probe learns nothing.

The name of the user who authenticated a post is recorded on the item as postedBy, and appears in its status. A public (anonymous) post leaves postedBy null.

Presenting a token

On an HTTP request, a caller sends its user's token as a bearer credential:

Authorization: Bearer <token>

On a WebSocket (/monitor or /work), browsers can't set request headers, so it goes in the query string instead:

wss://task.example.com/resize/work?token=<token>

The server checks the presented token against the files of the users a queue's operation lists, nothing more. The management API is separate: it is authenticated with the single master token (from /etc/taskhoster/token), and is what the sync client uses. A user token never works against it, and the master token is never needed by producers or workers.