# Users and what they may do Who the users are, and what each may do, is the swarm's: a registry in the document, the same on every node. How a user proves who it is stays each node's: its `--htpasswd`, or a reverse proxy naming the user (`--user-header`, [`trust.md`](trust.md)). ## The registry `_continuum/users/`, one entry per user. It is protocol data: every member holds it, a remake's snapshot carries it into the next epoch, and it holds no secrets (no password hashes: every member reads the document). ```json { "since": 1762400000000, "by": "continuum:3f…", "caps": { "8c41e2…": { "path": [], "rights": ["read", "write"], "by": "continuum:3f…", "since": 1762400000000 } }, "disabled": false } ``` * **Names** are what `--htpasswd` and the proxy give: 1 to 64 of `A-Z a-z 0-9 . _ @ -`. * **Capabilities** (`caps`): each a path, as segments as the store's API takes them, and the rights it gives there and below: `read`, `write`. A capability covers its path segment by segment (`servers/eu` covers `servers/eu/0`, not `servers/europe`). One outside protocol data never covers protocol data: `[]` is all of the swarm's data, `["_continuum"]` protocol data, managing users included (`_continuum/users`). They are kept by a random ID, so two capabilities granted at once both hold, and revoking one removes it alone. Each names who granted it (`by`: a user as `user:`, or the node that recorded it) and when (`since`). * **`disabled`**: the entry stays (who wrote what stays readable), and gives nothing. An entry that doesn't read as above gives less, never more: a capability that doesn't read is left out, and anything but `false` disables. ## A new swarm Its genesis node records the first users, with the swarm ID, in its first change: * those of `--bootstrap-users`, each with everything (`[]` and `["_continuum"]`); * unset: the users of its `--htpasswd` with `[]`, and those of them, or of the proxy's, in `--protocol-writers` with `["_continuum"]` too. A swarm nobody could manage doesn't start: with none of them with `["_continuum"]`, `--genesis` is refused, naming both options. ## At the HTTP API Every request is checked against the registry, as the node serving it holds it: a change to it counts on a node as soon as it has reached it. * **The store** (`/store`, `/stream`): writing a path (`PUT`, `POST`, `DELETE`) takes `write` on it; `?prune=true` deletes maps left empty only up to the highest one the user may write. Reading takes `read`: of a place the user may read only partly, it sees the keys on the way to what it may read, as a directory one may pass through but not list (a capability on `servers/eu` shows `servers` with `eu` alone in it), and nothing else; a list on the way is left out whole, as its items have no paths of their own. Native forms (`text/plain` of a map, a counter as its own type) only of what it may read whole. What a write answers with is what was written. A stream shows what the user could read when it opened. * **Protocol data** is in the store too, under `_continuum`: `read` and `write` on it as on any path. * **Looking at the node** (`/admin/stats`, `GET /peers`, the dashboard): any user with a capability. * **Remakes** (`/admin/remakes`): `read` on `_continuum/remakes` to look, `write` to propose or abort one. **Forgetting a peer** (`DELETE /peers/…`): `write` on `_continuum/forgotten`. * **Everything else an operator does** (`/admin/config`, `/admin/log`, `/admin/document`, `/admin/changes`, `/admin/epochs`, `/admin/quarantine`, `/debug`): `read` on `_continuum` to look, `write` on it to act. A user the node lets in but the registry doesn't have may do nothing (`403`). `[]` and `["_continuum"]` are two capabilities on purpose: protocol data acts on the whole swarm (its members, its remakes, its users), so it is given apart, never by accident with the data. A user who may do both has both. ## An existing swarm A swarm whose document has no registry (one from before it, `_continuum/users` missing) goes on as before: every user a node lets in may read and write the swarm's data and use the admin endpoints, and only those in `--protocol-writers` write protocol data. It gets a registry once a protocol writer writes one, through the store: ```sh curl -u alice --request PUT --header 'Content-Type: application/json' \ --data '{"since": 0, "by": "user:alice", "disabled": false, "caps": {"1": {"path": [], "rights": ["read", "write"]}, "2": {"path": ["_continuum"], "rights": ["read", "write"]}}}' \ http://localhost:3000/store/_continuum/users/alice ``` From that write on, every node serves only the users the registry has, so the first entry must be the writer's own, with `["_continuum"]`, or nobody may change the registry again; add the other users the same way.