From 3d7230d952aa4a71a1aeb64fee9841d16b70ed91 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:21 +0100 Subject: access: signatures required "signatures": "required": a change counts only once a signature by its committer vouches for it, and waits until then; every node then signs every change it makes. Auth plan M6. --- src/state/host.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/state/host.rs') diff --git a/src/state/host.rs b/src/state/host.rs index e401509..fb2e2e9 100644 --- a/src/state/host.rs +++ b/src/state/host.rs @@ -24,8 +24,13 @@ impl AppState { /// document. (Lock order doc -> peer, as in sync generation.) fn swap_document(&self, replica: &mut Replica, epoch: Epoch, doc: Document) -> Document { let old = std::mem::replace(&mut replica.doc, doc); - // The old document's signatures are of its changes. + // The old document's signatures are of its changes; this node's replayed into + // the new one, signed at once. replica.signatures = Default::default(); + if let Some(key) = &self.node_key { + let replica = &mut *replica; + replica.signatures.sign_own_latest(&replica.doc, key); + } replica.epoch = epoch; replica.epoch_seq += 1; // Publishes the epoch with the heads (`Replica::stamps`), under the same lock, @@ -340,6 +345,11 @@ impl Host for AppState { // take the document's lock first (`mutate_doc`). let (old, resumed) = state.take_stale(old); let out = f(&mut replica.doc, &old); + // What it replayed, vouched for at once. + if let Some(key) = &state.node_key { + let replica = &mut *replica; + replica.signatures.sign_own_latest(&replica.doc, key); + } replica.writable = true; replica.refresh_heads(); if resumed { @@ -403,15 +413,18 @@ impl Host for AppState { tokio::task::spawn_blocking(move || { let result = { let mut replica = state.doc.blocking_write(); - let result = if crate::access::policy::of(&replica.doc).enforced() { + let policy = crate::access::policy::of(&replica.doc); + let result = if policy.enforced() { // Judged first (`access::screen`). let (epoch, epoch_seq) = (replica.epoch, replica.epoch_seq); + let replica = &mut *replica; crate::access::screen::apply_bytes( &mut replica.doc, epoch, epoch_seq, change.raw_bytes(), &state.screening, + policy.required().then_some(&mut replica.signatures), &mut crate::document::PatchLog::inactive(), ) .map(|_| ()) -- cgit v1.3.1