aboutsummaryrefslogtreecommitdiffstats
path: root/docs/trust.md
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-02 12:03:02 +0100
committertv <tv@krebsco.de>2026-11-02 12:03:02 +0100
commit25076058f102c8275c8fa2ba76efb33a46207687 (patch)
tree6ae44b2acfa6f1fb64ce3d2b7ed9f4c2492359d4 /docs/trust.md
parentb6e44154902fd3507852932b0aed9885ceb85fbf (diff)
add documentation
Diffstat (limited to 'docs/trust.md')
-rw-r--r--docs/trust.md114
1 files changed, 114 insertions, 0 deletions
diff --git a/docs/trust.md b/docs/trust.md
new file mode 100644
index 0000000..521a175
--- /dev/null
+++ b/docs/trust.md
@@ -0,0 +1,114 @@
+# Trust model
+
+Who can do what to a swarm, and what stands in the way. In short: the swarm key
+decides who is a member, and members are trusted with everything.
+
+## The boundaries
+
+**The network.** Every transport authenticates the sender of every message, each by
+its own key: Mycelium by the public key of the sending daemon, libp2p by the peer ID
+of the connection, Tor by a challenge handshake on each connection, in which both sides
+prove their node key ([`transports.md`](transports.md)). So a node always knows which address sent it something, though not
+who wrote what that message carries (changes are relayed). On top, a node proves its
+node ID at each address with a signature by its node key (WHO and ME, [`peers.md`](peers.md)), so a
+node is known by its node ID whichever transport and address it uses. A private Mycelium
+network (`--mycelium-network-key-file`, `--mycelium-network-name`) additionally keeps
+other Mycelium nodes from reaching ours at all; on libp2p and Tor, anyone who knows an
+address can connect, and the swarm key is what keeps them out.
+
+**The swarm key.** With `--swarm-key-file`, a node proves the key in the handshake
+before anything else it sends is acted on; until then it is a *stranger*. Without a
+swarm key, every node that can reach a member can join: a joining node doesn't need to
+know the swarm ID, and the swarm ID is no secret anyway. The key file should be readable
+by its owner only; a node warns at startup if others may read it.
+
+**Public infrastructure.** Nodes use none unless told to: Mycelium peers are those in
+`--mycelium-peers`, and libp2p reaches only seeds, members and the relays of the swarm.
+With `--libp2p-public`, a node joins the IPFS DHT and may use public relays: they see
+whom it talks to and how much (the traffic itself is encrypted end to end), and the DHT
+makes its peer ID and addresses public.
+
+**The node key.** `--node-key-file` holds the node's own key, from which its node ID
+(`continuum:<hex>`) derives: who the node is, whatever transport reaches it. It is a
+secret like the swarm key: readable by its owner only (a node warns otherwise; a key
+it creates is).
+
+**The HTTP API.** Every endpoint but the API description needs a user from
+`--htpasswd`. It listens on `127.0.0.1:3000` by default (`--bind-addr`) and speaks
+plain HTTP: to expose it, put a TLS proxy in front. All users may read and write user
+data and use the admin endpoints (remakes, forgetting peers, exports, log filters).
+There are no read-only users: whoever may open the dashboard may also edit and delete
+the document's data from it, and its writes reach the whole swarm.
+Only the users in `--protocol-writers` may write protocol data through the store; epoch
+metadata and the swarm ID are never writable. The `/debug` endpoints exist only with
+`--debug-api`.
+
+**The configuration.** Whoever can write a node's configuration file or its options can
+run commands as the node's user: a `cmd:` (or `command`) value runs at startup, and a
+`file:` value reads any file the node can ([`configuration.md`](configuration.md), "Importing values").
+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:
+
+* **User data**: any member can write or delete any path.
+* **Who wrote what** (`GET /admin/changes`): each change names its node and API user
+ as the writing node says; nothing signs that, so a member can name another. The
+ names of the users who write are in the document, and so on every node.
+* **The member registry**: each node writes its own entry, but nothing stops a member
+ from writing others'. The registry decides the topology and, through the alive
+ stamps, the electorate of a remake.
+* **Forget records**: any member can make the swarm forget a peer (until it says HELLO
+ again).
+* **Remakes**: any member can propose one, vote, and, as coordinator, decide. Votes
+ are not signed: the votes register says who voted, but any member could write any
+ entry. Every node switches to a committed epoch without counting the votes again.
+* **Epochs it advertises**: a rejoining node follows the epoch ready members
+ advertise, corroborated by two of them once it was ready (one if only one is active,
+ and one before it was ever ready), and downloads the epoch's snapshot from them,
+ checked against its hash.
+* **What it says about itself**: its keepalives and handshake replies say whether it is
+ ready, whether it would sync with the recipient, and how long it last heard from it
+ (which counts towards the recipient's stability tier). Nodes believe that: a member
+ claiming to be ready can become a joining node's catch-up source (though one with an
+ empty document can't make it ready: empty heads prove nothing), and one misreporting
+ absences can move a node between tiers.
+
+So a member that misbehaves, by a bug or on purpose, can rewrite or delete data,
+manipulate the registry and the electorate, forge votes, commit a remake without a
+majority, and make the swarm forget peers. Nothing but the swarm key protects against
+that; keep it to nodes you trust as much as your data.
+
+## What depends on clocks
+
+Nodes don't agree on time; each judges by its own clock: voting periods, when a remake
+expires and may be aborted by others, the replay window, alive stamps (and so the
+electorate). Keep the clocks within a grace period (four keepalives) of each other,
+e.g. with NTP. A node whose clock is further off can, together with an operator's
+abort, make a remake contested ([`remakes.md`](remakes.md), Limits). A node compares its clock with its
+peers' and warns when its own is off (`--clock-skew-warn`; [`measurements.md`](measurements.md), Clocks).
+
+## What a stranger can do
+
+Send messages. Before it proves the swarm key, a node ignores everything from it but
+the handshake, and doesn't sync with it. A stranger can still cost a node the work of
+reading and dropping its messages.
+
+## What protects against mistakes
+
+Not against a hostile member, but against honest ones getting in each other's way:
+
+* Majority voting with one vote per member and epoch: two remakes can't both commit
+ ([`remakes.md`](remakes.md)).
+* A snapshot every node builds itself and checks against the committed epoch, and
+ downloads checked against their hashes.
+* Protocol data writable through the API only by `--protocol-writers`, and logged.
+
+## Not yet
+
+Revoking a single member, or limiting what a member may do, needs per-node keys: a
+member list in the document, with keys that sign what each node writes about itself
+(its registry entry, its votes). See [`review-rejections.md`](review-rejections.md), "Author binding for remake
+votes and decisions".