From 64c3c47d9bbc8ca2e6352bdcf79a91b1d1669289 Mon Sep 17 00:00:00 2001 From: tv Date: Sun, 8 Nov 2026 21:55:00 +0000 Subject: screen: judged after the policy is gone, too Review 3, R4: whether a batch was judged followed the receiving document's policy now (and whether the batch writes one). After the policy was removed, or replaced by a version the node doesn't know, changes written under it and received late went in unjudged, while nodes that had them earlier judged them; REFUSALS gave up likewise. Screening now remembers that the document held a policy, known or not (Screening::policed), and judges what it receives while it does, each change by the policy at its dependencies; REFUSALS judges then too (not under a policy the node doesn't know, as before). Not across a restart, which access.md says. --- src/swarm/refusals.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/swarm') diff --git a/src/swarm/refusals.rs b/src/swarm/refusals.rs index af4252c..30c3971 100644 --- a/src/swarm/refusals.rs +++ b/src/swarm/refusals.rs @@ -53,15 +53,25 @@ pub(crate) async fn tell( /// rules have it now; if they refuse one, we took it unjudged, and drop it. pub(crate) async fn received(state: &AppState, peer: &str, message: RefusalsMessage) { let doc = std::sync::Arc::clone(&state.doc); + let screening = std::sync::Arc::clone(&state.screening); let changes: Vec = message.changes.into_iter().take(MAX_LISTED).collect(); let judged = tokio::task::spawn_blocking(move || { + use crate::locks::MutexExt; let replica = doc.blocking_read(); if replica.epoch != message.epoch { return None; } + // Without a policy, ever (`Screening::policed`), nothing to judge by; with one + // this node doesn't know now, it can't judge as they do: receiving without + // judging until upgraded. A policy gone since still judges what was written under + // it, each change at its dependencies. let policy = crate::access::policy::of(&replica.doc); - if !policy.enforced() || matches!(policy, crate::access::policy::Policy::Unknown(_)) { - // We can't judge as they do: receiving without judging until upgraded. + if matches!(policy, crate::access::policy::Policy::Unknown(_)) + || !screening + .lock_or_recover() + .of(replica.epoch_seq) + .policed(&replica.doc) + { return None; } let mut refused = None; -- cgit v1.3.1