open-standards/smart-byte/smart-byte-rs/crates/smart-byte-edv/tests/zcap_chain.rs
Transaction Science 94681289e6 ingest wave A2: 3 crates · op-dispute-evidence + smart-byte-edv + eoc-agent
OpenPay (1 crate, ~2287 LOC, 15 tests)
  op-dispute-evidence  Chargeback lifecycle + evidence packaging across Visa
                       VCR (10.x/11.x/12.x/13.x), Mastercard Mastercom
                       (4837/4853/1240/1442), Amex SafeKey + DRR, Discover DRR,
                       PayPal. CE3.0 compelling-evidence qualifier (120-365d
                       window, ≥2 qualifiers, ≥2 linking matches, 10.4-only).
                       Phase state machine + ReasonCodeCatalog + sealed
                       EvidencePackageBuilder + win-rate scoring.

Smart Byte (1 crate, ~2479 LOC, 44 tests)
  smart-byte-edv       Encrypted Data Vaults (DIF v0.10).
                       JWE ECDH-ES P-256 + HKDF-SHA256-Concat-KDF + AES-256-GCM,
                       multi-recipient; HMAC-SHA-256 encrypted index with
                       AND-equality queries; full ZCAP-LD chain validation;
                       chunked AES-256-GCM streaming with per-chunk AAD;
                       Vault trait + InMemoryVault + one-way pull replication.

EOC (1 crate, ~2065 LOC, 29 tests)
  eoc-agent            Agentic loops with per-step joule accounting.
                       ReAct, Reflexion (PASS/FAIL judge + episodic memory),
                       Tree of Thoughts (BFS/DFS + self-scoring), LATS
                       (MCTS-UCT select/expand/simulate/backprop),
                       Plan-and-Execute, CodeAct (fenced-block + pluggable
                       runtime). Budget enforcement (tokens/joules/tool-calls),
                       trace spans, JouleCounter integration.

Three other batch-5 deferrals (op-ewallets-asia, smart-byte-zk, eoc-rag)
will land in wave A3.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-24 11:42:26 -04:00

127 lines
3.8 KiB
Rust

//! ZCAP-LD capability chain validation: prove delegation narrows
//! permissions, that an unauthorised invocation is rejected, and that an
//! expired root invalidates every descendant.
use chrono::{Duration, Utc};
use smart_byte_edv::error::EdvError;
use smart_byte_edv::zcap::{Capability, Invocation, verify_chain};
#[test]
fn three_link_chain_authorises_intended_action() {
// alice (controller) -> bob (auditor) -> carol (read-only delegate).
let root = Capability::root(
"urn:cap:root",
"https://vault/example/docs/urn:doc:1",
"did:example:alice",
"did:example:bob",
vec!["read".into(), "write".into(), "delete".into()],
);
let mid = root
.delegate(
"urn:cap:mid",
"did:example:bob",
"did:example:carol",
vec!["read".into(), "write".into()],
)
.expect("delegate mid");
let leaf = mid
.delegate(
"urn:cap:leaf",
"did:example:carol",
"did:example:dan",
vec!["read".into()],
)
.expect("delegate leaf");
let inv = Invocation::new(&leaf, "read");
verify_chain(
&[root.clone(), mid.clone(), leaf.clone()],
"did:example:alice",
&inv,
)
.expect("read should be allowed");
// dan does not get write — leaf was narrowed to "read".
let bad = Invocation::new(&leaf, "write");
let res = verify_chain(&[root, mid, leaf], "did:example:alice", &bad);
assert!(matches!(res, Err(EdvError::Unauthorized(_, _))));
}
#[test]
fn delegation_cannot_widen_actions() {
let root = Capability::root(
"urn:cap:root",
"https://vault/example",
"did:example:alice",
"did:example:bob",
vec!["read".into()],
);
let res = root.delegate(
"urn:cap:child",
"did:example:bob",
"did:example:mallory",
vec!["read".into(), "delete".into()],
);
assert!(matches!(res, Err(EdvError::Capability(_))));
}
#[test]
fn broken_chain_link_is_rejected() {
let root = Capability::root(
"urn:cap:root",
"https://vault/example",
"did:example:alice",
"did:example:bob",
vec!["read".into()],
);
let mut child = root
.delegate(
"urn:cap:child",
"did:example:bob",
"did:example:carol",
vec!["read".into()],
)
.expect("delegate");
// Snap the chain by pointing to a non-existent parent.
child.parent_capability = Some("urn:cap:does-not-exist".into());
let inv = Invocation::new(&child, "read");
let res = verify_chain(&[root, child], "did:example:alice", &inv);
assert!(matches!(res, Err(EdvError::Capability(_))));
}
#[test]
fn expired_root_invalidates_chain() {
let mut root = Capability::root(
"urn:cap:root",
"https://vault/example",
"did:example:alice",
"did:example:bob",
vec!["read".into()],
);
root.expires = Some(Utc::now() - Duration::minutes(1));
let child = root
.delegate(
"urn:cap:child",
"did:example:bob",
"did:example:carol",
vec!["read".into()],
)
.expect("delegate");
let inv = Invocation::new(&child, "read");
let res = verify_chain(&[root, child], "did:example:alice", &inv);
assert!(matches!(res, Err(EdvError::Capability(_))));
}
#[test]
fn wrong_root_controller_rejected() {
let root = Capability::root(
"urn:cap:root",
"https://vault/example",
"did:example:alice",
"did:example:bob",
vec!["read".into()],
);
let inv = Invocation::new(&root, "read");
let res = verify_chain(&[root], "did:example:mallory", &inv);
assert!(matches!(res, Err(EdvError::Capability(_))));
}