klieo_ops/
source_identity_registry.rs1use crate::key_registry::{load_ed25519_yaml, KeyRegistryError, StaticEd25519KeyRegistry};
10use crate::types::AgentId;
11use ed25519_dalek::VerifyingKey;
12use std::collections::HashMap;
13use std::path::Path;
14use thiserror::Error;
15
16#[derive(Debug, Error)]
18#[non_exhaustive]
19pub enum SourceIdentityRegistryError {
20 #[error(transparent)]
22 Load(#[from] KeyRegistryError),
23}
24
25pub trait SourceIdentityRegistry: Send + Sync {
27 fn lookup(&self, agent: &AgentId) -> Option<VerifyingKey>;
30}
31
32pub struct StaticSourceIdentityRegistry {
40 inner: StaticEd25519KeyRegistry<AgentId>,
41}
42
43impl StaticSourceIdentityRegistry {
44 #[must_use]
46 pub fn from_map(keys: HashMap<AgentId, VerifyingKey>) -> Self {
47 Self {
48 inner: StaticEd25519KeyRegistry::from_map(keys),
49 }
50 }
51
52 pub fn from_yaml(path: impl AsRef<Path>) -> Result<Self, SourceIdentityRegistryError> {
54 let keys = load_ed25519_yaml(path, AgentId)?;
55 Ok(Self {
56 inner: StaticEd25519KeyRegistry::from_map(keys),
57 })
58 }
59}
60
61impl SourceIdentityRegistry for StaticSourceIdentityRegistry {
62 fn lookup(&self, agent: &AgentId) -> Option<VerifyingKey> {
63 use crate::key_registry::Ed25519KeyRegistry as _;
64 self.inner.lookup(agent)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use ed25519_dalek::SigningKey;
72
73 #[test]
74 fn round_trip_via_yaml() {
75 let sk = SigningKey::from_bytes(&[5u8; 32]);
76 let pk = sk.verifying_key();
77 use base64::Engine as _;
78 let b64 = base64::engine::general_purpose::STANDARD.encode(pk.to_bytes());
79 let yaml = format!("claims-triage: \"{b64}\"\n");
80 let path = std::env::temp_dir().join("klieo-test-source-identity.yaml");
81 std::fs::write(&path, yaml).unwrap();
82 let reg = StaticSourceIdentityRegistry::from_yaml(&path).expect("load");
83 let resolved = reg.lookup(&AgentId("claims-triage".into())).expect("found");
84 assert_eq!(resolved.to_bytes(), pk.to_bytes());
85 }
86
87 #[test]
88 fn missing_agent_returns_none() {
89 let reg = StaticSourceIdentityRegistry::from_map(HashMap::new());
90 assert!(reg.lookup(&AgentId("ghost".into())).is_none());
91 }
92}