Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
69 changes: 34 additions & 35 deletions crates/evidence-plugin/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions crates/evidence-plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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"] }
Expand Down
9 changes: 9 additions & 0 deletions crates/evidence-plugin/src/chain_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<WitnessState>> {
self.log.pending_witnesses_for(witness_id, now, limit)
}

fn get_witness(
&self,
witness_id: &str,
Expand Down
4 changes: 3 additions & 1 deletion crates/evidence-plugin/src/evidence_answer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down
16 changes: 14 additions & 2 deletions crates/evidence-plugin/src/evidence_artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<String, Value>) -> Option<&str> {
match request.get("profile") {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion web-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
16 changes: 8 additions & 8 deletions web-ui/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading