1use crate::identity::{AgentIdentity, PublicIdentity};
7use crate::identity_support::UserContext;
8use crate::trust::TrustManager;
9use crate::types::TrustTier;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use std::collections::HashMap;
13use std::sync::{Arc, Mutex};
14use std::time::{SystemTime, UNIX_EPOCH};
15
16fn unix_secs_now() -> u64 {
17 SystemTime::now()
18 .duration_since(UNIX_EPOCH)
19 .unwrap_or_default()
20 .as_secs()
21}
22
23fn hex(bytes: &[u8]) -> String {
24 bytes.iter().map(|byte| format!("{byte:02x}")).collect()
25}
26
27fn capability_matches(granted: &str, requested: &str) -> bool {
28 granted == "*"
29 || granted == requested
30 || granted
31 .strip_suffix(":*")
32 .map(|prefix| requested.starts_with(&format!("{prefix}:")))
33 .unwrap_or(false)
34 || requested.starts_with(&format!("{granted}:"))
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct CapabilityGrant {
39 pub grant_id: String,
40 pub capability: String,
41 pub action: String,
42 pub resource: String,
43 pub qualifier: Option<String>,
44 pub granted_to: String,
45 pub granted_by: String,
46 pub resource_ids: Vec<String>,
47 pub conditions: HashMap<String, String>,
48 pub granted_at_secs: u64,
49 pub expires_at_secs: Option<u64>,
50 pub active: bool,
51 pub revoked_at_secs: Option<u64>,
52}
53
54impl CapabilityGrant {
55 pub fn parse_capability(capability: &str) -> Result<(String, String, Option<String>), String> {
56 let parts = capability.split(':').collect::<Vec<_>>();
57 if parts.len() < 2 {
58 return Err(format!("invalid capability '{capability}'"));
59 }
60 Ok((
61 parts[0].to_string(),
62 parts[1].to_string(),
63 parts.get(2).map(|value| (*value).to_string()),
64 ))
65 }
66
67 pub fn create(
68 capability: &str,
69 granted_to: &str,
70 granted_by: &str,
71 resource_ids: Vec<String>,
72 ) -> Result<Self, String> {
73 let (action, resource, qualifier) = Self::parse_capability(capability)?;
74 Ok(Self {
75 grant_id: format!("grant_{:012x}", rand::random::<u64>()),
76 capability: capability.to_string(),
77 action,
78 resource,
79 qualifier,
80 granted_to: granted_to.to_string(),
81 granted_by: granted_by.to_string(),
82 resource_ids,
83 conditions: HashMap::new(),
84 granted_at_secs: unix_secs_now(),
85 expires_at_secs: None,
86 active: true,
87 revoked_at_secs: None,
88 })
89 }
90
91 pub fn is_valid(&self) -> bool {
92 self.active
93 && self
94 .expires_at_secs
95 .map(|expires_at| unix_secs_now() < expires_at)
96 .unwrap_or(true)
97 }
98
99 pub fn matches(&self, requested: &str, resource_id: Option<&str>) -> bool {
100 (self.is_valid()
101 && capability_matches(&self.capability, requested)
102 && self.resource_ids.is_empty())
103 || (self.is_valid()
104 && capability_matches(&self.capability, requested)
105 && resource_id
106 .map(|resource| self.resource_ids.iter().any(|entry| entry == resource))
107 .unwrap_or(false))
108 }
109
110 pub fn revoke(&mut self) {
111 self.active = false;
112 self.revoked_at_secs = Some(unix_secs_now());
113 }
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct CapabilityScope {
118 pub agent_did: String,
119 pub grants: Vec<CapabilityGrant>,
120 pub denied: Vec<String>,
121}
122
123impl CapabilityScope {
124 pub fn new(agent_did: &str) -> Self {
125 Self {
126 agent_did: agent_did.to_string(),
127 grants: Vec::new(),
128 denied: Vec::new(),
129 }
130 }
131
132 pub fn add_grant(&mut self, grant: CapabilityGrant) -> Result<(), String> {
133 if grant.granted_to != self.agent_did {
134 return Err("grant is for a different agent".to_string());
135 }
136 self.grants.push(grant);
137 Ok(())
138 }
139
140 pub fn has_capability(&self, capability: &str, resource_id: Option<&str>) -> bool {
141 !self
142 .denied
143 .iter()
144 .any(|denied| capability_matches(denied, capability))
145 && self
146 .grants
147 .iter()
148 .any(|grant| grant.matches(capability, resource_id))
149 }
150
151 pub fn get_capabilities(&self) -> Vec<String> {
152 let mut capabilities = self
153 .grants
154 .iter()
155 .filter(|grant| grant.is_valid())
156 .map(|grant| grant.capability.clone())
157 .collect::<Vec<_>>();
158 capabilities.sort();
159 capabilities.dedup();
160 capabilities
161 }
162
163 pub fn filter_capabilities(&self, requested: &[String]) -> Vec<String> {
164 requested
165 .iter()
166 .filter(|capability| self.has_capability(capability, None))
167 .cloned()
168 .collect()
169 }
170
171 pub fn deny(&mut self, capability: &str) {
172 if !self.denied.iter().any(|entry| entry == capability) {
173 self.denied.push(capability.to_string());
174 }
175 }
176
177 pub fn revoke_all(&mut self) -> usize {
178 let mut count = 0;
179 for grant in &mut self.grants {
180 if grant.active {
181 grant.revoke();
182 count += 1;
183 }
184 }
185 count
186 }
187}
188
189pub struct CapabilityRegistry {
190 scopes: Mutex<HashMap<String, CapabilityScope>>,
191}
192
193impl CapabilityRegistry {
194 pub fn new() -> Self {
195 Self {
196 scopes: Mutex::new(HashMap::new()),
197 }
198 }
199
200 pub fn scope_for(&self, agent_did: &str) -> CapabilityScope {
201 self.scopes
202 .lock()
203 .unwrap_or_else(|e| e.into_inner())
204 .entry(agent_did.to_string())
205 .or_insert_with(|| CapabilityScope::new(agent_did))
206 .clone()
207 }
208
209 pub fn grant(
210 &self,
211 granted_to: &str,
212 granted_by: &str,
213 capability: &str,
214 resource_ids: Vec<String>,
215 ) -> Result<CapabilityGrant, String> {
216 let grant = CapabilityGrant::create(capability, granted_to, granted_by, resource_ids)?;
217 let mut scopes = self.scopes.lock().unwrap_or_else(|e| e.into_inner());
218 scopes
219 .entry(granted_to.to_string())
220 .or_insert_with(|| CapabilityScope::new(granted_to))
221 .add_grant(grant.clone())?;
222 Ok(grant)
223 }
224
225 pub fn has_capability(
226 &self,
227 agent_did: &str,
228 capability: &str,
229 resource_id: Option<&str>,
230 ) -> bool {
231 self.scopes
232 .lock()
233 .unwrap_or_else(|e| e.into_inner())
234 .get(agent_did)
235 .map(|scope| scope.has_capability(capability, resource_id))
236 .unwrap_or(false)
237 }
238}
239
240impl Default for CapabilityRegistry {
241 fn default() -> Self {
242 Self::new()
243 }
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct HandshakeChallenge {
248 pub challenge_id: String,
249 pub nonce: String,
250 pub issued_at_secs: u64,
251 pub expires_in_seconds: u64,
252}
253
254impl HandshakeChallenge {
255 pub fn generate() -> Self {
256 Self {
257 challenge_id: format!("challenge_{:016x}", rand::random::<u64>()),
258 nonce: hex(&rand::random::<[u8; 32]>()),
259 issued_at_secs: unix_secs_now(),
260 expires_in_seconds: 30,
261 }
262 }
263
264 pub fn is_expired(&self) -> bool {
265 unix_secs_now().saturating_sub(self.issued_at_secs) > self.expires_in_seconds
266 }
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct HandshakeResponse {
271 pub challenge_id: String,
272 pub response_nonce: String,
273 pub agent_did: String,
274 pub capabilities: Vec<String>,
275 pub trust_score: u32,
276 pub signature_hex: String,
277 pub public_key_hex: String,
278 pub user_context: Option<UserContext>,
279 pub timestamp_secs: u64,
280}
281
282#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
283#[serde(rename_all = "snake_case")]
284pub enum HandshakeTrustLevel {
285 VerifiedPartner,
286 Trusted,
287 Standard,
288 Untrusted,
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct HandshakeResult {
293 pub verified: bool,
294 pub peer_did: String,
295 pub peer_name: Option<String>,
296 pub trust_score: u32,
297 pub trust_level: HandshakeTrustLevel,
298 pub capabilities: Vec<String>,
299 pub user_context: Option<UserContext>,
300 pub handshake_started_secs: u64,
301 pub handshake_completed_secs: u64,
302 pub latency_ms: u64,
303 pub rejection_reason: Option<String>,
304}
305
306impl HandshakeResult {
307 pub fn success(
308 peer_did: &str,
309 trust_score: u32,
310 capabilities: Vec<String>,
311 started_at_secs: u64,
312 user_context: Option<UserContext>,
313 ) -> Self {
314 let completed = unix_secs_now();
315 let trust_level = match TrustTier::from_score(trust_score) {
316 TrustTier::VerifiedPartner => HandshakeTrustLevel::VerifiedPartner,
317 TrustTier::Trusted => HandshakeTrustLevel::Trusted,
318 TrustTier::Standard => HandshakeTrustLevel::Standard,
319 TrustTier::Probationary | TrustTier::Untrusted => HandshakeTrustLevel::Untrusted,
320 };
321 Self {
322 verified: true,
323 peer_did: peer_did.to_string(),
324 peer_name: None,
325 trust_score,
326 trust_level,
327 capabilities,
328 user_context,
329 handshake_started_secs: started_at_secs,
330 handshake_completed_secs: completed,
331 latency_ms: completed.saturating_sub(started_at_secs) * 1000,
332 rejection_reason: None,
333 }
334 }
335
336 pub fn failure(peer_did: &str, started_at_secs: u64, reason: &str) -> Self {
337 let completed = unix_secs_now();
338 Self {
339 verified: false,
340 peer_did: peer_did.to_string(),
341 peer_name: None,
342 trust_score: 0,
343 trust_level: HandshakeTrustLevel::Untrusted,
344 capabilities: Vec::new(),
345 user_context: None,
346 handshake_started_secs: started_at_secs,
347 handshake_completed_secs: completed,
348 latency_ms: completed.saturating_sub(started_at_secs) * 1000,
349 rejection_reason: Some(reason.to_string()),
350 }
351 }
352}
353
354pub struct TrustHandshake {
355 agent_did: String,
356 identity: Option<AgentIdentity>,
357 trust_manager: Option<Arc<TrustManager>>,
358 peers: Mutex<HashMap<String, PublicIdentity>>,
359 pending: Mutex<HashMap<String, HandshakeChallenge>>,
360}
361
362impl TrustHandshake {
363 pub fn new(
364 agent_did: &str,
365 identity: Option<AgentIdentity>,
366 trust_manager: Option<Arc<TrustManager>>,
367 ) -> Self {
368 Self {
369 agent_did: agent_did.to_string(),
370 identity,
371 trust_manager,
372 peers: Mutex::new(HashMap::new()),
373 pending: Mutex::new(HashMap::new()),
374 }
375 }
376
377 pub fn register_peer(&self, identity: &AgentIdentity) {
378 self.peers.lock().unwrap_or_else(|e| e.into_inner()).insert(
379 identity.did.clone(),
380 PublicIdentity {
381 did: identity.did.clone(),
382 public_key: identity.public_key.to_bytes().to_vec(),
383 capabilities: identity.capabilities.clone(),
384 },
385 );
386 }
387
388 pub fn issue_challenge(&self, peer_did: &str) -> HandshakeChallenge {
389 let challenge = HandshakeChallenge::generate();
390 self.pending
391 .lock()
392 .unwrap_or_else(|e| e.into_inner())
393 .insert(peer_did.to_string(), challenge.clone());
394 challenge
395 }
396
397 pub fn create_response(
398 &self,
399 peer_identity: &AgentIdentity,
400 challenge: &HandshakeChallenge,
401 trust_score: u32,
402 user_context: Option<UserContext>,
403 ) -> HandshakeResponse {
404 let payload = format!("{}:{}", challenge.challenge_id, challenge.nonce);
405 let signature = peer_identity.sign(payload.as_bytes());
406 HandshakeResponse {
407 challenge_id: challenge.challenge_id.clone(),
408 response_nonce: challenge.nonce.clone(),
409 agent_did: peer_identity.did.clone(),
410 capabilities: peer_identity.capabilities.clone(),
411 trust_score,
412 signature_hex: hex(&signature),
413 public_key_hex: hex(&peer_identity.public_key.to_bytes()),
414 user_context,
415 timestamp_secs: unix_secs_now(),
416 }
417 }
418
419 pub fn verify_response(
420 &self,
421 response: &HandshakeResponse,
422 required_trust_score: u32,
423 required_capabilities: &[String],
424 ) -> HandshakeResult {
425 let started = unix_secs_now();
426 let challenge = self
427 .pending
428 .lock()
429 .unwrap_or_else(|e| e.into_inner())
430 .remove(&response.agent_did);
431 let Some(challenge) = challenge else {
432 return HandshakeResult::failure(&response.agent_did, started, "no pending challenge");
433 };
434 if challenge.is_expired()
435 || challenge.challenge_id != response.challenge_id
436 || challenge.nonce != response.response_nonce
437 {
438 return HandshakeResult::failure(
439 &response.agent_did,
440 started,
441 "challenge mismatch or expiration",
442 );
443 }
444 let Some(identity) = self
445 .peers
446 .lock()
447 .unwrap_or_else(|e| e.into_inner())
448 .get(&response.agent_did)
449 .cloned()
450 else {
451 return HandshakeResult::failure(&response.agent_did, started, "peer not registered");
452 };
453 let payload = format!("{}:{}", challenge.challenge_id, challenge.nonce);
454 let signature = response
455 .signature_hex
456 .as_bytes()
457 .chunks(2)
458 .filter_map(|chunk| std::str::from_utf8(chunk).ok())
459 .filter_map(|chunk| u8::from_str_radix(chunk, 16).ok())
460 .collect::<Vec<_>>();
461 if !identity.verify(payload.as_bytes(), &signature) {
462 return HandshakeResult::failure(
463 &response.agent_did,
464 started,
465 "signature verification failed",
466 );
467 }
468 if response.trust_score < required_trust_score {
469 return HandshakeResult::failure(
470 &response.agent_did,
471 started,
472 "trust score below threshold",
473 );
474 }
475 if !required_capabilities.iter().all(|required| {
476 response
477 .capabilities
478 .iter()
479 .any(|cap| capability_matches(cap, required))
480 }) {
481 return HandshakeResult::failure(
482 &response.agent_did,
483 started,
484 "required capabilities missing",
485 );
486 }
487 HandshakeResult::success(
488 &response.agent_did,
489 response.trust_score,
490 response.capabilities.clone(),
491 started,
492 response.user_context.clone(),
493 )
494 }
495
496 pub fn verify_registered_peer(
497 &self,
498 peer_did: &str,
499 required_trust_score: u32,
500 required_capabilities: &[String],
501 ) -> HandshakeResult {
502 let started = unix_secs_now();
503 let Some(identity) = self
504 .peers
505 .lock()
506 .unwrap_or_else(|e| e.into_inner())
507 .get(peer_did)
508 .cloned()
509 else {
510 return HandshakeResult::failure(peer_did, started, "peer not registered");
511 };
512 let trust_score = self
513 .trust_manager
514 .as_ref()
515 .map(|manager| manager.get_trust_score(peer_did).score)
516 .unwrap_or(500);
517 if trust_score < required_trust_score {
518 return HandshakeResult::failure(peer_did, started, "trust score below threshold");
519 }
520 if !required_capabilities.iter().all(|required| {
521 identity
522 .capabilities
523 .iter()
524 .any(|cap| capability_matches(cap, required))
525 }) {
526 return HandshakeResult::failure(peer_did, started, "required capabilities missing");
527 }
528 HandshakeResult::success(
529 peer_did,
530 trust_score,
531 identity.capabilities.clone(),
532 started,
533 None,
534 )
535 }
536
537 pub fn agent_did(&self) -> &str {
538 &self.agent_did
539 }
540
541 pub fn has_local_identity(&self) -> bool {
542 self.identity.is_some()
543 }
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize)]
547pub struct PeerInfo {
548 pub peer_did: String,
549 pub peer_name: Option<String>,
550 pub protocol: String,
551 pub trust_score: u32,
552 pub trust_verified: bool,
553 pub last_verified_secs: Option<u64>,
554 pub capabilities: Vec<String>,
555 pub endpoint: Option<String>,
556}
557
558pub struct TrustBridge {
559 pub agent_did: String,
560 pub default_trust_threshold: u32,
561 peers: Mutex<HashMap<String, PeerInfo>>,
562 handshake: TrustHandshake,
563}
564
565impl TrustBridge {
566 pub fn new(
567 agent_did: &str,
568 identity: Option<AgentIdentity>,
569 trust_manager: Option<Arc<TrustManager>>,
570 ) -> Self {
571 Self {
572 agent_did: agent_did.to_string(),
573 default_trust_threshold: 700,
574 peers: Mutex::new(HashMap::new()),
575 handshake: TrustHandshake::new(agent_did, identity, trust_manager),
576 }
577 }
578
579 pub fn register_peer(&self, identity: &AgentIdentity, protocol: &str) {
580 self.handshake.register_peer(identity);
581 self.peers.lock().unwrap_or_else(|e| e.into_inner()).insert(
582 identity.did.clone(),
583 PeerInfo {
584 peer_did: identity.did.clone(),
585 peer_name: None,
586 protocol: protocol.to_string(),
587 trust_score: 0,
588 trust_verified: false,
589 last_verified_secs: None,
590 capabilities: identity.capabilities.clone(),
591 endpoint: None,
592 },
593 );
594 }
595
596 pub fn verify_peer(
597 &self,
598 peer_did: &str,
599 protocol: &str,
600 required_trust_score: Option<u32>,
601 required_capabilities: &[String],
602 ) -> HandshakeResult {
603 let result = self.handshake.verify_registered_peer(
604 peer_did,
605 required_trust_score.unwrap_or(self.default_trust_threshold),
606 required_capabilities,
607 );
608 if result.verified {
609 self.peers.lock().unwrap_or_else(|e| e.into_inner()).insert(
610 peer_did.to_string(),
611 PeerInfo {
612 peer_did: peer_did.to_string(),
613 peer_name: result.peer_name.clone(),
614 protocol: protocol.to_string(),
615 trust_score: result.trust_score,
616 trust_verified: true,
617 last_verified_secs: Some(unix_secs_now()),
618 capabilities: result.capabilities.clone(),
619 endpoint: None,
620 },
621 );
622 }
623 result
624 }
625
626 pub fn is_peer_trusted(&self, peer_did: &str, required_score: Option<u32>) -> bool {
627 self.peers
628 .lock()
629 .unwrap_or_else(|e| e.into_inner())
630 .get(peer_did)
631 .map(|peer| {
632 peer.trust_verified
633 && peer.trust_score >= required_score.unwrap_or(self.default_trust_threshold)
634 })
635 .unwrap_or(false)
636 }
637
638 pub fn get_peer(&self, peer_did: &str) -> Option<PeerInfo> {
639 self.peers
640 .lock()
641 .unwrap_or_else(|e| e.into_inner())
642 .get(peer_did)
643 .cloned()
644 }
645
646 pub fn get_trusted_peers(&self, min_score: Option<u32>) -> Vec<PeerInfo> {
647 self.peers
648 .lock()
649 .unwrap_or_else(|e| e.into_inner())
650 .values()
651 .filter(|peer| {
652 peer.trust_verified
653 && peer.trust_score >= min_score.unwrap_or(self.default_trust_threshold)
654 })
655 .cloned()
656 .collect()
657 }
658
659 pub fn revoke_peer_trust(&self, peer_did: &str) -> bool {
660 if let Some(peer) = self
661 .peers
662 .lock()
663 .unwrap_or_else(|e| e.into_inner())
664 .get_mut(peer_did)
665 {
666 peer.trust_verified = false;
667 peer.trust_score = 0;
668 return true;
669 }
670 false
671 }
672}
673
674pub struct ProtocolBridge {
675 pub agent_did: String,
676 pub trust_bridge: TrustBridge,
677 pub supported_protocols: Vec<String>,
678}
679
680impl ProtocolBridge {
681 pub fn new(
682 agent_did: &str,
683 identity: Option<AgentIdentity>,
684 trust_manager: Option<Arc<TrustManager>>,
685 ) -> Self {
686 Self {
687 agent_did: agent_did.to_string(),
688 trust_bridge: TrustBridge::new(agent_did, identity, trust_manager),
689 supported_protocols: vec!["a2a".into(), "mcp".into(), "iatp".into(), "acp".into()],
690 }
691 }
692
693 pub fn translate(&self, message: &Value, from_protocol: &str, to_protocol: &str) -> Value {
694 if from_protocol == "a2a" && to_protocol == "mcp" {
695 let task_type = message
696 .get("task_type")
697 .and_then(Value::as_str)
698 .unwrap_or("execute");
699 let parameters = message
700 .get("parameters")
701 .cloned()
702 .unwrap_or(Value::Object(Default::default()));
703 serde_json::json!({
704 "method": "tools/call",
705 "params": { "name": task_type, "arguments": parameters }
706 })
707 } else if from_protocol == "mcp" && to_protocol == "a2a" {
708 let params = message
709 .get("params")
710 .cloned()
711 .unwrap_or(Value::Object(Default::default()));
712 serde_json::json!({
713 "task_type": params.get("name").and_then(Value::as_str).unwrap_or("execute"),
714 "parameters": params.get("arguments").cloned().unwrap_or(Value::Object(Default::default()))
715 })
716 } else {
717 message.clone()
718 }
719 }
720
721 pub fn add_verification_footer(
722 &self,
723 content: &str,
724 trust_score: u32,
725 agent_did: &str,
726 ) -> String {
727 format!(
728 "{content}\n\n> Verified by AgentMesh (Trust Score: {trust_score}/1000)\n> Agent: {agent_did}\n"
729 )
730 }
731}
732
733#[derive(Debug, Clone, Serialize, Deserialize)]
734pub struct TrustedAgentCard {
735 pub peer_did: String,
736 pub peer_name: Option<String>,
737 pub trust_score: u32,
738 pub capabilities: Vec<String>,
739 pub protocol: String,
740 pub issuer_did: String,
741 pub issued_at_secs: u64,
742 pub metadata: HashMap<String, String>,
743}
744
745impl TrustedAgentCard {
746 pub fn from_handshake_result(
747 issuer_did: &str,
748 protocol: &str,
749 result: &HandshakeResult,
750 ) -> Self {
751 Self {
752 peer_did: result.peer_did.clone(),
753 peer_name: result.peer_name.clone(),
754 trust_score: result.trust_score,
755 capabilities: result.capabilities.clone(),
756 protocol: protocol.to_string(),
757 issuer_did: issuer_did.to_string(),
758 issued_at_secs: unix_secs_now(),
759 metadata: HashMap::new(),
760 }
761 }
762}
763
764pub struct CardRegistry {
765 cards: Mutex<HashMap<String, TrustedAgentCard>>,
766}
767
768impl CardRegistry {
769 pub fn new() -> Self {
770 Self {
771 cards: Mutex::new(HashMap::new()),
772 }
773 }
774
775 pub fn put(&self, card: TrustedAgentCard) {
776 self.cards
777 .lock()
778 .unwrap_or_else(|e| e.into_inner())
779 .insert(card.peer_did.clone(), card);
780 }
781
782 pub fn get(&self, peer_did: &str) -> Option<TrustedAgentCard> {
783 self.cards
784 .lock()
785 .unwrap_or_else(|e| e.into_inner())
786 .get(peer_did)
787 .cloned()
788 }
789}
790
791impl Default for CardRegistry {
792 fn default() -> Self {
793 Self::new()
794 }
795}
796
797#[cfg(test)]
798mod tests {
799 use super::*;
800
801 #[test]
802 fn capability_registry_tracks_grants_and_denies() {
803 let registry = CapabilityRegistry::new();
804 registry
805 .grant(
806 "did:agentmesh:peer",
807 "did:agentmesh:root",
808 "read:data",
809 Vec::new(),
810 )
811 .unwrap();
812 assert!(registry.has_capability("did:agentmesh:peer", "read:data", None));
813 assert!(!registry.has_capability("did:agentmesh:peer", "write:data", None));
814 }
815
816 #[test]
817 fn trust_handshake_verifies_registered_peer() {
818 let peer = AgentIdentity::generate("peer", vec!["data.read".into()]).unwrap();
819 let trust = Arc::new(TrustManager::with_defaults());
820 trust.set_trust(&peer.did, 750);
821 let handshake = TrustHandshake::new("did:agentmesh:self", None, Some(trust));
822 handshake.register_peer(&peer);
823 let result = handshake.verify_registered_peer(&peer.did, 700, &["data.read".into()]);
824 assert!(result.verified);
825 assert_eq!(result.trust_level, HandshakeTrustLevel::Trusted);
826 }
827
828 #[test]
829 fn trust_bridge_records_verified_peer() {
830 let peer = AgentIdentity::generate("peer", vec!["data.read".into()]).unwrap();
831 let trust = Arc::new(TrustManager::with_defaults());
832 trust.set_trust(&peer.did, 900);
833 let bridge = TrustBridge::new("did:agentmesh:self", None, Some(trust));
834 bridge.register_peer(&peer, "mcp");
835 let result = bridge.verify_peer(&peer.did, "mcp", Some(700), &["data.read".into()]);
836 assert!(result.verified);
837 assert!(bridge.is_peer_trusted(&peer.did, Some(700)));
838 assert_eq!(bridge.get_trusted_peers(None).len(), 1);
839 }
840
841 #[test]
842 fn protocol_bridge_translates_between_a2a_and_mcp() {
843 let bridge = ProtocolBridge::new("did:agentmesh:self", None, None);
844 let a2a = serde_json::json!({
845 "task_type": "search.web",
846 "parameters": { "query": "agentmesh" }
847 });
848 let mcp = bridge.translate(&a2a, "a2a", "mcp");
849 assert_eq!(mcp["method"], "tools/call");
850 let a2a_roundtrip = bridge.translate(&mcp, "mcp", "a2a");
851 assert_eq!(a2a_roundtrip["task_type"], "search.web");
852 }
853
854 #[test]
855 fn card_registry_stores_handshake_cards() {
856 let result = HandshakeResult::success(
857 "did:agentmesh:peer",
858 800,
859 vec!["search.web".into()],
860 unix_secs_now(),
861 None,
862 );
863 let card = TrustedAgentCard::from_handshake_result("did:agentmesh:self", "mcp", &result);
864 let registry = CardRegistry::new();
865 registry.put(card);
866 assert_eq!(registry.get("did:agentmesh:peer").unwrap().protocol, "mcp");
867 }
868}