aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/store.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 04:46:19 +0000
committertv <tv@krebsco.de>2026-11-09 05:48:17 +0100
commit98a9180e39742725a61fb1966e342d7d212beee9 (patch)
treecc4b8b5b8a1f022a00e5b46e2f849a3edc72301d /src/api/store.rs
parent97a69e09021244e994602ac5038b4bd7bc16ba78 (diff)
access: what a node holds alone by `_continuum/local/<node ID>/<name>`
Setting a node's log filter took `write` on `_continuum`, all of the protocol data: whoever could change one node's logging could change the swarm's members, remakes and users too. Now what a node holds alone has paths of its own for capabilities, under `_continuum/local/<node ID>/`: `log` (`/admin/log`), `config` (`/admin/config`) and `debug` (`/debug`, always `write`), `read` to look and `write` to act (`api::access::needed`, which takes the node's ID). So `_continuum/local/<node ID>` is everything on one node, `_continuum/local/*/log` the log filter on every node, and holders of `_continuum` keep it all. Nothing is stored there: the store refuses writes under `_continuum/local`, and the rules refuse a change touching it, as for epoch metadata. The quarantine stays with `_continuum`: its entries are everyone's writes, which a node-local capability mustn't show.
Diffstat (limited to 'src/api/store.rs')
-rw-r--r--src/api/store.rs11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/api/store.rs b/src/api/store.rs
index e43d129..00ced48 100644
--- a/src/api/store.rs
+++ b/src/api/store.rs
@@ -662,7 +662,8 @@ fn parse_key_path(key: &str) -> Result<Vec<String>, StatusCode> {
/// what every node acts on, so a write there acts on the whole swarm, and each is
/// logged. Epoch metadata (and `_continuum` as a whole, which contains it) is never
/// writable: the protocol reads it at the snapshot change, so an edit only misleads
-/// whoever reads it later; nor is the swarm ID. A path inside a list or text is
+/// whoever reads it later; nor is the swarm ID, nor `_continuum/local`, which names
+/// what a node holds alone for capabilities and is never stored. A path inside a list or text is
/// judged where the rules judge the write (`inspect::placed`): at the list.
async fn parse_write_path(
state: &AppState,
@@ -674,8 +675,12 @@ async fn parse_write_path(
let path = parse_key_path(key)?;
let placed = crate::document::inspect::placed(&state.doc.read().await.doc, &path);
let protocol = meta::is_protocol(&path);
- // `_continuum` itself, epoch metadata and the swarm ID: nobody.
- let fixed = protocol && (path.len() < 2 || path[1] == meta::EPOCHS || path[1] == meta::SWARM);
+ // `_continuum` itself, epoch metadata, the swarm ID and what is never stored: nobody.
+ let fixed = protocol
+ && (path.len() < 2
+ || path[1] == meta::EPOCHS
+ || path[1] == meta::SWARM
+ || path[1] == meta::LOCAL);
let allowed = match access {
Access::Everything => !protocol || state.protocol_writers.contains(&user.0),
Access::Caps(caps) => caps.allows(crate::access::Right::Write, &placed),