From d74538f77cb68c1836f6245b0a36f7f9d683c237 Mon Sep 17 00:00:00 2001 From: tv Date: Sun, 8 Nov 2026 19:10:03 +0000 Subject: screen: what a node receives judged, policy or not Review 2, N7: a node screened received changes only while its own document had a policy it enforces. A joiner's empty document has none, so its first sync, as much history as the node it joins through chose, was applied unjudged, and under signatures required unvouched; the same for any node while the policy's own change arrived with later ones. Sync messages, deltas and downloaded changes are now always screened, each change judged by the policy at its dependencies (1135), so the verdicts are the swarm's. While neither the document nor the changes hold a policy (none touches a "policy" key: inspect::touch_key), only an epoch's root is judged and nothing is placed: bench_screening, after 1188, measured placing everything at about as much again as applying (564 ms + 543 ms for 100 000 changes), judging by the rules at about five times (+2.5 s), which a document with a policy pays anyway. access.md no longer lists the joiner's first sync, nor nodes agreeing only as the policy reaches them (judged at the dependencies, they agree), as left to do; changes::load_delta is for tests now. --- src/document/inspect.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/document/inspect.rs') diff --git a/src/document/inspect.rs b/src/document/inspect.rs index c42de82..f0356de 100644 --- a/src/document/inspect.rs +++ b/src/document/inspect.rs @@ -86,6 +86,17 @@ impl Place { } } +/// Whether any of `changes` does anything at a map key `key`: a cheap look, without +/// placing anything, for whether they may write the policy (`access::screen`). +pub(crate) fn touch_key(changes: &[ExpandedChange], key: &str) -> bool { + changes.iter().any(|change| { + change + .operations + .iter() + .any(|op| matches!(&op.key, Key::Map(name) if name.as_str() == key)) + }) +} + /// Where a write at `path` in `doc` is, as rules see it (`Inspector`): placed by the /// same rule (`Place::child`), so cut after the first list or text on the way, which /// what is inside one touches. Where `doc` holds nothing (or a scalar) on the way, the -- cgit v1.3.1