auths-id 0.1.2

Multi-device identity and attestation crate for Auths
Documentation
use auths_verifier::core::Attestation;
use auths_verifier::types::CanonicalDid;
use mockall::mock;

use crate::error::StorageError;
use crate::identity::helpers::ManagedIdentity;
use crate::storage::attestation::AttestationSource;
use crate::storage::identity::IdentityStorage;

mock! {
    /// Mock for [`IdentityStorage`] — use for single-behavior unit tests.
    pub IdentityStorage {}

    impl IdentityStorage for IdentityStorage {
        fn create_identity(
            &self,
            controller_did: &str,
            metadata: Option<serde_json::Value>,
        ) -> Result<(), StorageError>;

        fn load_identity(&self) -> Result<ManagedIdentity, StorageError>;

        fn get_identity_ref(&self) -> Result<String, StorageError>;
    }
}

mock! {
    /// Mock for [`AttestationSource`] — use for single-behavior unit tests.
    pub AttestationSource {}

    impl AttestationSource for AttestationSource {
        fn load_attestations_for_device(
            &self,
            device_did: &CanonicalDid,
        ) -> Result<Vec<Attestation>, StorageError>;

        fn load_all_attestations(&self) -> Result<Vec<Attestation>, StorageError>;

        fn load_all_attestations_paginated(
            &self,
            limit: usize,
            offset: usize,
        ) -> Result<Vec<Attestation>, StorageError>;

        fn discover_device_dids(&self) -> Result<Vec<CanonicalDid>, StorageError>;
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use auths_core::storage::keychain::IdentityDID;

    #[test]
    fn mock_identity_storage_load_returns_configured_value() {
        let mut mock = MockIdentityStorage::new();
        mock.expect_load_identity().returning(|| {
            #[allow(clippy::disallowed_methods)]
            // INVARIANT: test-only literal with valid DID format
            let controller_did = IdentityDID::new_unchecked("did:keri:Etest".to_string());
            Ok(ManagedIdentity {
                controller_did,
                storage_id: "test-repo".to_string(),
                metadata: None,
            })
        });

        let result = mock.load_identity().unwrap();
        assert_eq!(result.controller_did, "did:keri:Etest");
    }

    #[test]
    fn mock_identity_storage_create_succeeds() {
        let mut mock = MockIdentityStorage::new();
        mock.expect_create_identity().returning(|_, _| Ok(()));

        assert!(mock.create_identity("did:keri:Etest", None).is_ok());
    }

    #[test]
    fn mock_attestation_source_returns_empty_list() {
        let mut mock = MockAttestationSource::new();
        mock.expect_load_all_attestations().returning(|| Ok(vec![]));

        let attestations = mock.load_all_attestations().unwrap();
        assert!(attestations.is_empty());
    }
}