aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 18:15:28 +0000
committertv <tv@krebsco.de>2026-11-08 19:29:04 +0100
commit4ce3bde36bb8283d82b914f0f73e30d89c935113 (patch)
tree5269a3bc63af5621e41393bf16a6511e4f415960
parentf315b94c024fea5ac228da15e24a2f3f717ddac2 (diff)
remake: a strict remake makes the registry, policy and bans anew
Review 2, N12: a strict remake kept only the values at the signed places its manifest names, and copied what holds them as it was. A member that replaced _continuum/users by a scalar before the turn left the strict epoch without a registry, where any member may do anything. The holders of the registry, `_continuum/access` and the bans are now made anew as maps, with only what the manifest keeps copied into them; and a manifest keeping no user is refused (at proposal, vote and build alike), as a strict swarm without one would trust every member.
-rw-r--r--src/access/strict.rs9
-rw-r--r--src/remake/kind.rs16
2 files changed, 25 insertions, 0 deletions
diff --git a/src/access/strict.rs b/src/access/strict.rs
index f5051a8..0fa6577 100644
--- a/src/access/strict.rs
+++ b/src/access/strict.rs
@@ -140,6 +140,15 @@ pub(crate) fn read(text: &str) -> Result<Manifest, String> {
if manifest.policy.get("values").and_then(JsonValue::as_str) != Some("signed") {
return Err("its policy isn't strict (\"values\": \"signed\")".to_owned());
}
+ // A strict swarm without a registry would let every member do anything.
+ let users = crate::access::registry::users_dir();
+ if !manifest
+ .keep
+ .iter()
+ .any(|kept| kept.path.len() == users.len() + 1 && kept.path.starts_with(&users))
+ {
+ return Err("it keeps no user".to_owned());
+ }
Ok(manifest)
}
diff --git a/src/remake/kind.rs b/src/remake/kind.rs
index a429828..f32f847 100644
--- a/src/remake/kind.rs
+++ b/src/remake/kind.rs
@@ -277,6 +277,22 @@ impl RemakeKind for Strict {
target: &mut Transaction<'_>,
) -> Result<(), StoreError> {
let manifest = Self::manifest(content)?;
+ // What holds the registry, the policy and the bans made anew, maps, with only
+ // what the manifest keeps in them: whatever a member made of them before (a
+ // scalar in place of the registry, say) is gone too.
+ for holder in [meta::USERS, meta::ACCESS, meta::BANNED] {
+ let at = meta::path(&[holder]);
+ match store::delete_path(target, &at, false) {
+ Ok(()) | Err(StoreError::NotFound) => {}
+ Err(error) => return Err(error),
+ }
+ store::write_path(target, &at, &JsonValue::Object(Default::default()))?;
+ }
+ for (path, value) in crate::access::strict::held(old_at_base) {
+ if meta::is_protocol(&path) && manifest.keeps(&path, &value) {
+ store::copy_path(old_at_base, target, &path)?;
+ }
+ }
Self::keep_named(old_at_base, &manifest, target, meta::is_protocol)?;
store::write_path(
target,