From c82a62186a8e0a46fd41e08345a2fa3e54ddffe2 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:09 +0100 Subject: access: authorization at the API Every request is judged by the registry the node holds: store reads pruned to what the user may read, writes refused where it may not, admin endpoints by protocol capabilities. Without a registry, as before (--protocol-writers for protocol data). Auth plan M1. --- docs/access.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'docs/access.md') diff --git a/docs/access.md b/docs/access.md index 8cb1ef9..042e0d5 100644 --- a/docs/access.md +++ b/docs/access.md @@ -40,3 +40,53 @@ Its genesis node records the first users, with the swarm ID, in its first change 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. -- cgit v1.3.1