aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 19:26:29 +0000
committertv <tv@krebsco.de>2026-11-08 20:27:20 +0100
commit83171090a0ff9cb9aeca3c1f91edff769076a5a7 (patch)
tree4a64910e841247649a516d7158acb7f87d65a251 /docs
parentc9c7807bf0f068474ce5c853244bcb392bdfcce3 (diff)
state: limit refused writes per user
A write every node would refuse is rolled back by forking the document at the heads before it, under the write lock, at a cost that grows with the document's history. A user could ask for such writes in a loop. Count each user's refused writes over the last minute. Past --refused-writes-per-minute (default 10), its writes are answered 429 without being tried, until the oldest refusal leaves the minute.
Diffstat (limited to 'docs')
-rw-r--r--docs/access.md5
-rw-r--r--docs/example.toml5
2 files changed, 9 insertions, 1 deletions
diff --git a/docs/access.md b/docs/access.md
index 782724a..9d38bd5 100644
--- a/docs/access.md
+++ b/docs/access.md
@@ -266,7 +266,10 @@ stays as it is, wherever it comes from later (a joining node catching up, say).
A node judges each change it makes the same way before it leaves, its own writes and
those through the API alike: one every node would refuse is rolled back, never
-written, and the request refused (`403`, saying why). So a write the API's checks let
+written, and the request refused (`403`, saying why). A rollback costs a copy of the
+document, so a user with more than ten such writes within a minute
+(`--refused-writes-per-minute`) has its writes answered `429`, untried, until the
+oldest leave the minute. So a write the API's checks let
through (they look at the path asked for, the rules at everything the change does)
can't cut its node off.
diff --git a/docs/example.toml b/docs/example.toml
index 70d65b2..c152b8b 100644
--- a/docs/example.toml
+++ b/docs/example.toml
@@ -105,6 +105,11 @@ htpasswd = "/etc/continuum/htpasswd"
# together at most.
# key-logins-per-user = 100
+# Writes a user may have refused within a minute because every node would refuse them
+# (docs/access.md); past it, its writes are answered 429 untried for a while. Each
+# refusal costs a copy of the document.
+# refused-writes-per-minute = 10
+
# The hash of the swarm's genesis change (hex, as its genesis node logs it and GET
# /admin/epochs shows it): joining with an empty document, the only root this node
# takes. Without, the one its peers name, none while they name different ones