diff options
| author | tv <tv@krebsco.de> | 2026-11-07 22:35:21 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-07 22:35:21 +0100 |
| commit | 3d7230d952aa4a71a1aeb64fee9841d16b70ed91 (patch) | |
| tree | 82c36db267f03afe88b728d130e20955ca29a2da /src/state | |
| parent | f44fbf5b93269bb3573e8a2701e70ab0d7613153 (diff) | |
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.
Diffstat (limited to 'src/state')
| -rw-r--r-- | src/state/host.rs | 17 | ||||
| -rw-r--r-- | src/state/mod.rs | 5 |
2 files changed, 19 insertions, 3 deletions
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(|_| ()) diff --git a/src/state/mod.rs b/src/state/mod.rs index 049c9e6..294b446 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -542,7 +542,10 @@ impl AppState { if after != before && let [hash] = after[..] { - if state.sign_every == SignEvery::Change || sign.wanted(&replica.doc) { + if state.sign_every == SignEvery::Change + || sign.wanted(&replica.doc) + || crate::access::policy::of(&replica.doc).required() + { let replica = &mut *replica; replica.signatures.sign(&replica.doc, hash, key); } else { |
