From 822e6a8268e2bc03463b2f0672fd6d6aad160432 Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 9 Nov 2026 15:37:16 +0000 Subject: signatures: a listed signed path takes `*`, as everything else does Review 4, appendix: whether a write is signed because `_continuum/access/signed` lists its path compared the listed paths by prefix (`signatures::related`), so a `*` there was a literal key, while api.md says the list holds paths as capabilities name them, which take `*` since 1259, and signed values already read the same list as patterns (`envelope::reaches_signed`). A listed `metrics/*/alerts` signed nothing. It compares by `access::agree` now: within or above the pattern, `*` for any one key. --- src/document/signatures.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/document/signatures.rs b/src/document/signatures.rs index da2df03..e5c9e69 100644 --- a/src/document/signatures.rs +++ b/src/document/signatures.rs @@ -60,10 +60,11 @@ impl Sign { } } -/// Whether a write at `path` touches what is at `signed`: within it, or above it -/// (replacing or deleting what holds it). +/// Whether a write at `path` touches what is at `signed`, a pattern as capabilities and +/// signed values take them (`*` for any one key): within it, or above it (replacing or +/// deleting what holds it). fn related(signed: &[String], path: &[String]) -> bool { - path.starts_with(signed) || signed.starts_with(path) + crate::access::agree(signed, path) } /// The paths `doc` lists as signed (`SIGNED_PATHS`); an entry that isn't a list of @@ -587,6 +588,18 @@ mod tests { .unwrap(); } + /// A listed signed path is a pattern: `*` takes any one key, within and above. + #[test] + fn listed_paths_take_a_star() { + let path = |text: &str| -> Vec { text.split('/').map(str::to_owned).collect() }; + let signed = path("metrics/*/alerts"); + assert!(related(&signed, &path("metrics/eu/alerts/x"))); + assert!(related(&signed, &path("metrics/eu"))); + assert!(related(&signed, &path("metrics"))); + assert!(!related(&signed, &path("metrics/eu/rates"))); + assert!(!related(&signed, &path("other"))); + } + /// The latest unsigned change of each of this node's actors is signed, below the /// heads too (an earlier actor's, built on under a later one); another node's, and /// those vouched for, left. -- cgit v1.3.1