From 5471e5285e94ce7576e6c86f260fea15ed9503d1 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:21 +0100 Subject: signatures: verified changes GET /admin/changes shows whether a signature by its node vouches for each change. Auth plan M5. --- src/api/changes.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/api/changes.rs') diff --git a/src/api/changes.rs b/src/api/changes.rs index 419f5ed..c3a847d 100644 --- a/src/api/changes.rs +++ b/src/api/changes.rs @@ -2,8 +2,9 @@ //! or of what is at a path (as `/store/` names it). Every change names the node that //! committed it (its author) and, for a write through the API, the user who wrote it (in //! its message, `User:`), with when (its writer's clock) and the store paths it touched -//! (`document::replica::Writer`). Every node holds every change, so any node answers -//! for the whole swarm, as far as it has synced. +//! (`document::replica::Writer`), and whether a signature by that node vouches for it +//! (`document::signatures`). Every node holds every change, so any node answers for the +//! whole swarm, as far as it has synced. use axum::{ Json, @@ -39,6 +40,9 @@ pub(crate) struct ChangeReport { /// The user it was written for through the API, if any. #[serde(skip_serializing_if = "Option::is_none")] user: Option, + /// Whether a signature by its node vouches for it, as far as this node has the + /// signatures (`document::signatures`). + verified: bool, /// The store paths it touched (a list's items by index). paths: Vec, } @@ -82,18 +86,19 @@ async fn report( return Err(StatusCode::SERVICE_UNAVAILABLE); } let limit = query.limit.unwrap_or(100).clamp(1, MAX_LIMIT); - Ok(Json( - state - .render( - move |doc| changes(doc, limit, path.as_deref()), - |report| report, - ) - .await, - )) + let doc = std::sync::Arc::clone(&state.doc); + let report = tokio::task::spawn_blocking(move || { + let replica = doc.blocking_read(); + changes(&replica.doc, &replica.signatures, limit, path.as_deref()) + }) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + Ok(Json(report)) } fn changes( doc: &crate::document::Document, + signatures: &crate::document::signatures::Signatures, limit: usize, path: Option<&[String]>, ) -> ChangesReport { @@ -128,6 +133,7 @@ fn changes( .as_deref() .and_then(crate::document::replica::user_of) .map(str::to_owned), + verified: signatures.verified(&meta.actor, meta.seq), paths: paths.iter().map(|path| path.join("/")).collect(), }); } -- cgit v1.3.1