use ed25519_dalek::{Signature, VerifyingKey};
pub trait MeshSigner: Send + Sync {
fn verifying_key(&self) -> VerifyingKey;
fn sign(&self, msg: &[u8]) -> Signature;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{AgentKey, AgentMetadata, Caveats, UserKey};
use ed25519_dalek::{Signer, SigningKey, Verifier};
fn fixture_agent() -> AgentKey {
let user = UserKey::generate();
AgentKey::issue(
&user,
AgentMetadata {
role: "worker".into(),
host: "test-host".into(),
capabilities: vec!["test".into()],
issued_at: "2026-05-28T00:00:00Z".into(),
expires_at: None,
caveats: Caveats::top(),
},
)
}
struct RawSigner {
signing: SigningKey,
}
impl MeshSigner for RawSigner {
fn verifying_key(&self) -> VerifyingKey {
self.signing.verifying_key()
}
fn sign(&self, msg: &[u8]) -> Signature {
self.signing.sign(msg)
}
}
#[test]
fn agent_key_is_a_mesh_signer() {
let agent = fixture_agent();
let signer: &dyn MeshSigner = &agent;
let msg = b"sign-via-trait";
let sig = signer.sign(msg);
assert_eq!(signer.verifying_key().as_bytes(), &agent.public_bytes());
signer
.verifying_key()
.verify(msg, &sig)
.expect("trait signature verifies under trait verifying_key");
}
#[test]
fn agent_key_trait_sign_matches_inherent_sign() {
let agent = fixture_agent();
let msg = b"identical";
let via_trait = MeshSigner::sign(&agent, msg);
let via_inherent = agent.sign(msg);
assert_eq!(via_trait.to_bytes(), via_inherent.to_bytes());
}
#[test]
fn raw_signer_double_signs_and_verifies() {
let signing = SigningKey::from_bytes(&[7u8; 32]);
let expected_vk = signing.verifying_key();
let signer = RawSigner { signing };
let msg = b"raw-signer";
let sig = MeshSigner::sign(&signer, msg);
assert_eq!(signer.verifying_key().as_bytes(), expected_vk.as_bytes());
signer
.verifying_key()
.verify(msg, &sig)
.expect("raw signer signature verifies");
}
#[test]
fn signer_is_object_safe_and_send_sync() {
fn assert_send_sync<T: Send + Sync + ?Sized>() {}
assert_send_sync::<dyn MeshSigner>();
let agent = fixture_agent();
let _boxed: std::sync::Arc<dyn MeshSigner> = std::sync::Arc::new(agent);
}
}