Skip to main content

aex_core/
identity.rs

1use async_trait::async_trait;
2use serde::{Deserialize, Serialize};
3
4use crate::{AgentId, Result, Signature};
5
6/// The pluggable identity provider interface.
7///
8/// An `IdentityProvider` represents a holder of ONE agent's signing key
9/// plus its view onto the wider registry of peer public keys. The same
10/// trait is implemented by:
11///
12/// - `SpizeNativeProvider` — Ed25519 + Spize's central Identity Registry.
13/// - `EtereCitizenProvider` — did:ethr wallet + EtereCitizen on-chain
14///   registry and reputation.
15/// - `DidWebProvider` — did:web resolution via HTTPS.
16///
17/// The control plane dispatches to the right provider based on the scheme
18/// of the incoming agent_id.
19#[async_trait]
20pub trait IdentityProvider: Send + Sync {
21    /// The agent this provider represents (i.e., the identity that
22    /// `sign()` will produce signatures for).
23    fn agent_id(&self) -> &AgentId;
24
25    /// Sign an arbitrary byte string with the agent's private key.
26    ///
27    /// Errors if the key is unavailable (file missing, HSM offline, user
28    /// unlocked required).
29    async fn sign(&self, message: &[u8]) -> Result<Signature>;
30
31    /// Verify that `signature` was produced by `peer_id` over `message`.
32    ///
33    /// Implementations are responsible for:
34    /// 1. Resolving `peer_id` to a public key (via their registry of choice)
35    /// 2. Verifying the signature cryptographically
36    /// 3. Checking revocation status (e.g., CRL lookup)
37    async fn verify_peer(
38        &self,
39        peer_id: &AgentId,
40        message: &[u8],
41        signature: &Signature,
42    ) -> Result<()>;
43
44    /// Optional: fetch trust metadata about a peer (reputation, verification
45    /// level, capabilities). Returns `None` if this provider does not support
46    /// trust metadata — callers must handle that gracefully.
47    ///
48    /// Policies that depend on reputation must use `has_reputation()` style
49    /// guards rather than requiring metadata presence unconditionally.
50    async fn trust_metadata(&self, _peer_id: &AgentId) -> Option<TrustMetadata> {
51        None
52    }
53}
54
55/// Opaque trust metadata about a peer, returned by providers that support it
56/// (primarily `EtereCitizenProvider`).
57#[derive(Debug, Clone, Default, Serialize, Deserialize)]
58pub struct TrustMetadata {
59    /// Creator verification level, typically 0-3 (0 = unverified, 3 = KYC).
60    pub verification_level: Option<u8>,
61    /// Reputation score. Scale is provider-defined; EtereCitizen uses
62    /// weighted composite in the [0.0, 5.0] range.
63    pub reputation_score: Option<f32>,
64    /// Number of reviews backing the reputation score.
65    pub review_count: Option<u32>,
66    /// Declared capabilities (e.g. "code-generation", "research").
67    pub capabilities: Vec<String>,
68    /// Flags provided by the registry (e.g. "NEW_AGENT", "NO_REVIEWS").
69    pub flags: Vec<String>,
70}