diff --git a/CHANGELOG.md b/CHANGELOG.md index d8cbecb..d88f92e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +### Changed + +- **Built with agent-action-capsule 0.10.0, checkpointed-local-log 0.5.0 and evidencebook 0.0.15.** One + agent-action-capsule line and one checkpointed-local-log line are in the build (it carried two of each), + with capsule-emit 0.0.12, capsule-emit-artifact 0.0.3 and evidence-request 0.5.0. The node still answers + `evidence-interop/0` and `/1` only: a request naming `/2`, which evidence-request 0.5.0 also lists, is + still `request_malformed`, and an answer to one is not believed. `evidence-request` appears twice in the build (0.5.0, and 0.4.1 + through agent-action-capsule 0.10.0, which uses only its time, status and controller-binding modules). capsule-emit 0.0.12 + sends witness registration through its own HTTP client, which refuses a witness response whose `entry_hash_scheme` is not + `legacy`. The web UI uses `@action-state-group/agent-action-capsule` 0.14.0. + ## 0.1.17 ### Changed diff --git a/crates/evidence-plugin/Cargo.lock b/crates/evidence-plugin/Cargo.lock index dbace59..9b28bf9 100644 --- a/crates/evidence-plugin/Cargo.lock +++ b/crates/evidence-plugin/Cargo.lock @@ -10,31 +10,14 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "agent-action-capsule" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40e21e140db3bb0773e7b00d50bc2efa5983765eb888ea97de71f85a74da944c" +checksum = "490f58497264cf106a47a4a5b394093f4f4d4d99b29c86ed1cf9ed2355ae5e47" dependencies = [ "base64 0.22.1", "checkpointed-local-log", "ed25519-dalek", - "evidence-request", - "hex", - "p256", - "serde", - "serde_json", - "sha2 0.10.9", -] - -[[package]] -name = "agent-action-capsule" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f5a684ca3c9daf693cbb77b9cab8b4124e4746614dfdd9efc675256b09a1830" -dependencies = [ - "base64 0.22.1", - "checkpointed-local-log", - "ed25519-dalek", - "evidence-request", + "evidence-request 0.4.1", "hex", "p256", "serde", @@ -251,11 +234,11 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "capsule-emit" -version = "0.0.11" +version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d71d8b6f23b4aaaf2e9835fc4d2557658923df87a8bfae6b98118dfa58333f" +checksum = "36e743dfdd2c85c70a22ef52e894fe458070a50c2b703383d14ded624baa9bc8" dependencies = [ - "agent-action-capsule 0.8.0", + "agent-action-capsule", "anyhow", "base64 0.22.1", "capsule-emit-artifact", @@ -276,11 +259,11 @@ dependencies = [ [[package]] name = "capsule-emit-artifact" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428349dc897094a230f7a2c9b2c0e32f5052123cfe2b535ec5b6396e397fe72b" +checksum = "38e92cadb1165c74f72663eb4fb660096508f774d80fb3639c07c9bf5d4d9ef1" dependencies = [ - "agent-action-capsule 0.8.0", + "agent-action-capsule", "base64 0.22.1", "hex", "rusqlite", @@ -336,9 +319,9 @@ dependencies = [ [[package]] name = "checkpointed-local-log" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1946d9506c829e225df887be5e559278f9b3db9dcca4c91e01261824a5373fb8" +checksum = "3ec489715bc08d10eb0b0a995217951ed1f9db3c2db76d30923300a81ca8b063" dependencies = [ "base64 0.22.1", "coset", @@ -721,7 +704,7 @@ dependencies = [ name = "evidence-plugin" version = "0.1.17" dependencies = [ - "agent-action-capsule 0.9.0", + "agent-action-capsule", "anyhow", "axum", "base64 0.22.1", @@ -733,7 +716,7 @@ dependencies = [ "ciborium", "coset", "ed25519-dalek", - "evidence-request", + "evidence-request 0.5.0", "evidencebook", "getrandom 0.2.17", "hex", @@ -770,6 +753,23 @@ name = "evidence-request" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9946dd4944a44519f90ee9f01bac2b654d76f6dbaa78c93281e05fb2ed64a2f" +dependencies = [ + "base64 0.22.1", + "ciborium", + "ed25519-dalek", + "hex", + "k256", + "serde", + "serde_json", + "sha2 0.10.9", + "thiserror 1.0.69", +] + +[[package]] +name = "evidence-request" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d847257335aaf687d7a6b3b9ee54848127926d024ae7f552d9f83711efcc13b2" dependencies = [ "base64 0.22.1", "checkpointed-local-log", @@ -777,7 +777,6 @@ dependencies = [ "coset", "ed25519-dalek", "hex", - "k256", "serde", "serde_json", "sha2 0.10.9", @@ -786,18 +785,18 @@ dependencies = [ [[package]] name = "evidencebook" -version = "0.0.12" +version = "0.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46cb4ced5c50fa1bcb3a99927c93b3ca1711bfcce138d73e472fab6ee571acbd" +checksum = "5b9382bda3c547a7142d55ffd615b66dae900cd4cfd4515fd08ee127cd1aacf0" dependencies = [ - "agent-action-capsule 0.8.0", + "agent-action-capsule", "base64 0.22.1", "boon", "capsule-emit-artifact", "checkpointed-local-log", "ciborium", "ed25519-dalek", - "evidence-request", + "evidence-request 0.5.0", "hex", "hmac", "icu_casemap", diff --git a/crates/evidence-plugin/Cargo.toml b/crates/evidence-plugin/Cargo.toml index 026fcd7..7f5287c 100644 --- a/crates/evidence-plugin/Cargo.toml +++ b/crates/evidence-plugin/Cargo.toml @@ -153,13 +153,13 @@ reqwest = { version = "0.12", default-features = false, features = ["json", "rus # `arbitrary_precision` for the whole binary (see `strict_json`). 0.0.11 is on # checkpointed-local-log 0.4.0 and agent-action-capsule 0.8.0, the one CLL line # the shelf needs (evidencebook#254 §7.4), with capsule-emit-artifact 0.0.2. -capsule-emit-lib = { package = "capsule-emit", version = "0.0.11" } -cll = { package = "checkpointed-local-log", version = "0.4.0", features = ["sqlite"] } +capsule-emit-lib = { package = "capsule-emit", version = "0.0.12" } +cll = { package = "checkpointed-local-log", version = "0.5.0", features = ["sqlite"] } # The chain's records: capsule-emit's artifact store (SQLite backend), the # layer its `Ledger` keeps each line in beside the CLL log, both on the node's -# shelf, `ledger/shelf.db` (`chain_store`). The version capsule-emit 0.0.11 +# shelf, `ledger/shelf.db` (`chain_store`). The version capsule-emit 0.0.12 # and the shelf both use, so they pass records through one crate. -capsule-emit-artifact = { version = "0.0.2", features = ["sqlite"] } +capsule-emit-artifact = { version = "0.0.3", features = ["sqlite"] } # The shelf's host table beside CLL's and the artifact store's tables (the # chain's checkpoint history, `chain_store::ChainLog`) and the readers' # connections: the rusqlite both of those build, with its bundled SQLite. @@ -172,7 +172,7 @@ rusqlite = { version = "0.40", features = ["bundled"] } # check of Checkpointed Local Log material (`cll`) and witness receipts # (`receipt`). The artifact is built by evidencebook (below). # Pinned exactly: a new release may change what verifies. -evidence-request = { version = "=0.4.1", features = ["cll", "receipt", "acceptance"] } +evidence-request = { version = "=0.5.0", features = ["cll", "receipt", "acceptance"] } # The "asked of you" log (`evidence_answer::log_received`) is evidencebook's # `received` (evidencebook#35), and a ledger line is read into its # `served_summary` facts (`evidence_log::leaf_facts`), whose model Service @@ -186,7 +186,7 @@ evidence-request = { version = "=0.4.1", features = ["cll", "receipt", "acceptan # The node's shelf (`shelf`, evidencebook#254 §7): the chain is one host log # on it. 0.0.12 is the first release with it, on checkpointed-local-log 0.4.0. # Pinned exactly: the shelf's file is a cross-language contract. -evidencebook = { version = "=0.0.12", features = ["deal", "shelf"] } +evidencebook = { version = "=0.0.15", features = ["deal", "shelf"] } # Admission's price rule (#105) is decided by capsule-engine's guard with its # asg/inference terms pack (capsule-engine#265, `rust/capsule-engine`), the # evaluator Muse's Go guard shares vectors with, so the plugin runs no second @@ -196,9 +196,9 @@ evidencebook = { version = "=0.0.12", features = ["deal", "shelf"] } capsule-engine = { git = "https://github.com/action-state-group/capsule-engine", rev = "c7701385b87b68c631803e5d0adeee4d617ff5d4" } # Class 1 verification of a received half (capsule-emit main moved it here), # and, with `inference-history`, the Service History's derivation and checks -# (`service_history`, evidencebook#322). capsule-emit still builds on 0.8.0, so -# two lines of this crate are in the tree until it moves; 0.9.0 only adds. -agent-action-capsule = { version = "0.9.0", features = ["strict", "inference-history"] } +# (`service_history`, evidencebook#322). capsule-emit 0.0.12 builds on 0.10.0 too, so +# one line of this crate is in the tree. +agent-action-capsule = { version = "0.10.0", features = ["strict", "inference-history"] } # The witness's own record of this log (`witness_status`): one blocking GET, # no redirects, a capped body. Already in the tree through capsule-emit. ureq = { version = "2", features = ["json"] } diff --git a/crates/evidence-plugin/src/chain_store.rs b/crates/evidence-plugin/src/chain_store.rs index a7c935e..69c15c5 100644 --- a/crates/evidence-plugin/src/chain_store.rs +++ b/crates/evidence-plugin/src/chain_store.rs @@ -440,6 +440,15 @@ impl WitnessStateStore for ChainLog { self.log.pending_witnesses(now, limit) } + fn pending_witnesses_for( + &self, + witness_id: &str, + now: Timestamp, + limit: usize, + ) -> cll::log::Result> { + self.log.pending_witnesses_for(witness_id, now, limit) + } + fn get_witness( &self, witness_id: &str, diff --git a/crates/evidence-plugin/src/evidence_answer.rs b/crates/evidence-plugin/src/evidence_answer.rs index 54f2664..86e69e0 100644 --- a/crates/evidence-plugin/src/evidence_answer.rs +++ b/crates/evidence-plugin/src/evidence_answer.rs @@ -336,8 +336,10 @@ fn answer_inner(request_bytes: &[u8], responder: &Responder<'_>, asker: &mut Ask _ => return refuse(Reason::RequestMalformed, kind), }; // A profile this node does not implement (profile §3.3 step 4). + // evidence-request 0.5.0 also lists `evidence-interop/2`, which this node + // does not answer, so the list here is its own. let Some(profile) = evidence_artifact::requested_profile(&map) - .filter(|p| evidence_request::envelope::PROFILES.contains(p)) + .filter(|p| evidence_artifact::ANSWERED_PROFILES.contains(p)) else { return refuse(Reason::RequestMalformed, kind); }; diff --git a/crates/evidence-plugin/src/evidence_artifact.rs b/crates/evidence-plugin/src/evidence_artifact.rs index 298444a..a867e31 100644 --- a/crates/evidence-plugin/src/evidence_artifact.rs +++ b/crates/evidence-plugin/src/evidence_artifact.rs @@ -223,6 +223,9 @@ fn signed_envelope( derive: Some(&derive), derivations: None, requester: None, + // The plugin answers no standard_history derivation; None is the + // behavior it had before the field existed (DerivationUnsupported). + standard_card: None, }, b.signing_key, b.issued_at, @@ -438,10 +441,16 @@ struct Stated { cp: DecodedCheckpointCose, } +/// The profile identifiers this node answers and checks (`evidence-interop/0` +/// and `/1`). evidence-request 0.5.0 implements `/2` as well, which this node +/// does not: a request naming it is refused, and an answer to one is not +/// believed. +pub(crate) const ANSWERED_PROFILES: [&str; 2] = [envelope::PROFILE, envelope::PROFILE_V1]; + /// The profile identifier a request names: its `profile` member, or /// `evidence-interop/0` when it has none (profile §3.3 step 2). `None` when /// the member is not text. This node answers and checks `evidence-interop/0` -/// and `evidence-interop/1` ([`envelope::PROFILES`]), each with its own +/// and `evidence-interop/1` ([`ANSWERED_PROFILES`]), each with its own /// refusal reasons (IP v1 §6.3). pub fn requested_profile(request: &Map) -> Option<&str> { match request.get("profile") { @@ -477,7 +486,9 @@ pub fn check( Ok(Value::Object(map)) => requested_profile(&map).map(str::to_string), _ => None, }; - let Some(asked) = asked.filter(|p| p == &env.profile) else { + let Some(asked) = + asked.filter(|p| p == &env.profile && ANSWERED_PROFILES.contains(&p.as_str())) + else { return fail("the answer is not under the profile the request named"); }; env.verify_for_profile(&asked, key, sent) @@ -1432,6 +1443,7 @@ mod tests { for profile in [ json!("evidence-interop/0"), json!("evidence-interop/1"), + json!("evidence-interop/2"), json!(7), ] { let mut asked: Value = serde_json::from_slice(&sent).unwrap(); diff --git a/web-ui/package.json b/web-ui/package.json index 9a3c93a..2a5be70 100644 --- a/web-ui/package.json +++ b/web-ui/package.json @@ -17,7 +17,7 @@ "test": "vitest run" }, "dependencies": { - "@action-state-group/agent-action-capsule": "0.10.0", + "@action-state-group/agent-action-capsule": "0.14.0", "@action-state-group/capsule-viewer": "0.14.0", "@action-state-group/cll": "0.3.0", "@noble/curves": "1.9.7", diff --git a/web-ui/pnpm-lock.yaml b/web-ui/pnpm-lock.yaml index 13188a9..158970a 100644 --- a/web-ui/pnpm-lock.yaml +++ b/web-ui/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@action-state-group/agent-action-capsule': - specifier: 0.10.0 - version: 0.10.0(@action-state-group/cll@0.3.0(@types/node@26.4.1)) + specifier: 0.14.0 + version: 0.14.0(@action-state-group/cll@0.3.0(@types/node@26.4.1)) '@action-state-group/capsule-viewer': specifier: 0.14.0 version: 0.14.0(@types/node@26.4.1) @@ -120,8 +120,8 @@ importers: packages: - '@action-state-group/agent-action-capsule@0.10.0': - resolution: {integrity: sha512-H0hlCj2aZEPQIGoloI2/ObVzs+xFSvu00ZKHTTTbFMOr14h5hwILH3fYMKfM2VkdFBT14LYhVFGOtvsKRT9WEw==} + '@action-state-group/agent-action-capsule@0.13.1': + resolution: {integrity: sha512-3W2t+6eCmGFTwTBjfV6AvD5YkvxTZ9y/jCW6BBc27f5tyEBh6CCQFVEdzQ5+QKr95PktnVpXabl3PJFes+6W0w==} engines: {node: '>=20'} peerDependencies: '@action-state-group/cll': 0.3.0 @@ -129,8 +129,8 @@ packages: '@action-state-group/cll': optional: true - '@action-state-group/agent-action-capsule@0.13.1': - resolution: {integrity: sha512-3W2t+6eCmGFTwTBjfV6AvD5YkvxTZ9y/jCW6BBc27f5tyEBh6CCQFVEdzQ5+QKr95PktnVpXabl3PJFes+6W0w==} + '@action-state-group/agent-action-capsule@0.14.0': + resolution: {integrity: sha512-QLdgnu8gRGsEGBMui+c2CB3LP/sGI6nsUpR5d5qbV81T93kUfUjQJnI6LoZN6NGQObLpO7xKk1ztlwt53Wxm0Q==} engines: {node: '>=20'} peerDependencies: '@action-state-group/cll': 0.3.0 @@ -1883,11 +1883,11 @@ packages: snapshots: - '@action-state-group/agent-action-capsule@0.10.0(@action-state-group/cll@0.3.0(@types/node@26.4.1))': + '@action-state-group/agent-action-capsule@0.13.1(@action-state-group/cll@0.3.0(@types/node@26.4.1))': optionalDependencies: '@action-state-group/cll': 0.3.0(@types/node@26.4.1) - '@action-state-group/agent-action-capsule@0.13.1(@action-state-group/cll@0.3.0(@types/node@26.4.1))': + '@action-state-group/agent-action-capsule@0.14.0(@action-state-group/cll@0.3.0(@types/node@26.4.1))': optionalDependencies: '@action-state-group/cll': 0.3.0(@types/node@26.4.1)