diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/access.md | 47 | ||||
| -rw-r--r-- | docs/api.md | 2 | ||||
| -rw-r--r-- | docs/openapi.yaml | 34 | ||||
| -rw-r--r-- | docs/trust.md | 5 |
4 files changed, 86 insertions, 2 deletions
diff --git a/docs/access.md b/docs/access.md index 961fc72..df8ad53 100644 --- a/docs/access.md +++ b/docs/access.md @@ -164,3 +164,50 @@ the last user who may manage users: each node can only judge what it holds, and such writes on two nodes at once would leave nobody once they merge anyway. Then, while nobody may manage users, the users in a node's `--protocol-writers` may do everything there again, to set it right. + +## Changes judged on every node + +What a user may do is checked where it writes, by the node it writes through. A swarm +can also have every node judge every change it receives before applying it, so a node +whose operator lets anyone write (or that claims another's users) gets nothing past +the others: the policy, at `_continuum/access/policy`, written by a user who may write +protocol data. + +```sh +curl -X PUT localhost:3000/store/_continuum/access/policy \ + -H 'Content-Type: application/json' -d '{"version": 1, "signatures": "optional"}' +``` + +A change is judged by what it touches, by the node that committed it, and by the user +it names, as the document stood when it was written (at its dependencies): a +revocation since refuses nothing it allowed then, and every node judges alike. + +* A member's entry (`_continuum/members/<id>`) and its votes are written by that member + only; removing an entry, also by a user who may write there. +* Epochs and the swarm ID (`_continuum/epochs`, `_continuum/swarm`) by an epoch's first + change only (the genesis change, a remake's snapshot). +* A remake's decision by the coordinator its proposal names; the rest of a record by + any member. +* A user's tokens revoked by that user too (logging out). +* Everything else, protocol data or not, by a user the registry lets write there. +* A node that isn't a member may only register itself. + +In a swarm without a registry, whatever a user would need, any member may. A refused +change stays out, and so does whatever builds on it; the node logs it (`Refused a +change`) and lists the last thousand (`GET /admin/refused`). A change whose +dependencies haven't come yet waits for them. + +What it doesn't do yet: + +* **Prove who wrote it.** A change is its claimed node's and user's: a member could + claim another member, or a user its node doesn't have. Changes are signed + ([`api.md`](api.md), Signed changes), but the policy doesn't require it yet. +* **Judge a joining node's first sync.** An empty document has no policy: what it gets + from the node it joins through is taken as it is, as that node judged it. +* **Agree at once.** The policy applies as each node gets it: a change received between + the policy's arrival on one node and on another may be refused by one and kept by + the other. + +A node that doesn't know the policy (another version, or a setting it lacks) takes no +writes through the API (`409`) and receives without judging, until it is upgraded. + diff --git a/docs/api.md b/docs/api.md index 89da7ba..c2b9cb4 100644 --- a/docs/api.md +++ b/docs/api.md @@ -238,7 +238,7 @@ are each node's own (`--htpasswd`, or its proxy's): `alice` on two nodes is one only where their operators make it so, which nothing checks. `GET /admin/changes` lists them, newest first, with the paths each touched and whether a signature by its node vouches -for it (`verified`, Signed changes); `GET /admin/changes/settings` those that +for it (`verified`, Signed changes), and `GET /admin/refused` those this node refused under the swarm's policy ([`access.md`](access.md), Changes judged on every node); `GET /admin/changes/settings` those that touched what is at `settings`. Every node holds every change, so user names are known to the whole swarm, and so is who wrote what, until a remake drops the history ([`remakes.md`](remakes.md)). diff --git a/docs/openapi.yaml b/docs/openapi.yaml index d067f4f..742a013 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -626,6 +626,40 @@ paths: '503': description: Node is not ready. + /admin/refused: + get: + tags: [Admin] + summary: Changes refused under the swarm's policy + description: | + The changes this node refused under the swarm's policy + (`_continuum/access/policy`, `access.md`), newest first, the last thousand at + most since it started or switched epochs: each with its hash, when its writer + made it (its clock), the node and user it names, what it touched, and why. + responses: + '200': + description: The refused changes. + content: + application/json: + schema: + type: array + items: + type: object + required: [hash, at, paths, why] + properties: + hash: + type: string + at: + type: integer + node: + type: string + user: + type: string + paths: + type: array + items: + type: string + why: + type: string /admin/changes/{key}: get: tags: [Admin] diff --git a/docs/trust.md b/docs/trust.md index 70369e2..5444b8b 100644 --- a/docs/trust.md +++ b/docs/trust.md @@ -57,7 +57,10 @@ Protect the configuration like the swarm key. ## What members are trusted with Everything in the document. A member syncs changes to and from its peers, and every -node acts on what the document says: +node acts on what the document says. Unless the swarm has a policy +([`access.md`](access.md), Changes judged on every node): then every node judges every +change it receives by rules by path, and those below are refused where a change breaks +them, as far as the node and user a change claims are who wrote it: * **User data**: any member can write or delete any path. * **Who wrote what** (`GET /admin/changes`): each change names its node and API user |
