auths-id 0.1.2

Multi-device identity and attestation crate for Auths
Documentation
use auths_core::crypto::said::compute_next_commitment;
use auths_verifier::core::{Attestation, Ed25519PublicKey, Ed25519Signature, ResourceId};
use auths_verifier::types::CanonicalDid;
use ring::rand::SystemRandom;
use ring::signature::{Ed25519KeyPair, KeyPair};

use crate::keri::event::{CesrKey, Event, IcpEvent, KeriSequence, Threshold, VersionString};
use crate::keri::finalize_icp_event;
use crate::keri::types::{Prefix, Said};

/// Minimal signed inception event for registry contract tests.
///
/// The SAID is properly computed and the event is signed with a fresh Ed25519
/// keypair so it passes `GitRegistryBackend`'s signature validation.
///
/// Each call produces a different Ed25519 key and thus a different SAID / prefix.
/// Use the returned event's `prefix()` as the first argument to `append_event`.
///
/// Args:
/// * `key_seed`: Ignored — exists only for call-site readability.
///
/// Usage:
/// ```ignore
/// let event = test_inception_event("seed-1");
/// let prefix = event.prefix().to_string();
/// backend.append_event(&prefix, &event).unwrap();
/// ```
pub fn test_inception_event(key_seed: &str) -> Event {
    let _ = key_seed;
    let rng = SystemRandom::new();

    let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
    let keypair = Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap();
    let key_encoded = auths_keri::KeriPublicKey::ed25519(keypair.public_key().as_ref())
        .expect("ed25519 verkey is 32 bytes")
        .to_qb64()
        .expect("cesride verkey encode is infallible");

    let next_pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
    let next_keypair = Ed25519KeyPair::from_pkcs8(next_pkcs8.as_ref()).unwrap();
    let next_commitment = compute_next_commitment(
        &auths_keri::KeriPublicKey::ed25519(next_keypair.public_key().as_ref())
            .expect("ed25519 verkey is 32 bytes"),
    );

    let icp = IcpEvent {
        v: VersionString::placeholder(),
        d: Said::default(),
        i: Prefix::default(),
        s: KeriSequence::new(0),
        kt: Threshold::Simple(1),
        k: vec![CesrKey::new_unchecked(key_encoded)],
        nt: Threshold::Simple(1),
        n: vec![next_commitment],
        bt: Threshold::Simple(0),
        b: vec![],
        c: vec![],
        a: vec![],
    };

    let finalized = finalize_icp_event(icp).expect("fixture event must finalize");
    let _ = keypair; // signatures attach as CESR attachments, not embedded in the event body.
    Event::Icp(finalized)
}

/// Minimal attestation fixture for registry and org member contract tests.
///
/// Args:
/// * `device_did`: The device DID that is the subject of this attestation.
/// * `issuer`: The issuer DID string (e.g. `"did:keri:ETestOrg"`).
///
/// Usage:
/// ```ignore
/// let did = CanonicalDid::new_unchecked("did:key:zTest");
/// let att = test_attestation(&did, "did:keri:ETestOrg");
/// backend.store_attestation(&att).unwrap();
/// ```
pub fn test_attestation(device_did: &CanonicalDid, issuer: &str) -> Attestation {
    #[allow(clippy::disallowed_methods)] // INVARIANT: test-only literal with valid DID format
    let issuer = CanonicalDid::new_unchecked(issuer);
    Attestation {
        version: 1,
        rid: ResourceId::new("test-rid"),
        issuer,
        subject: device_did.clone(),
        device_public_key: Ed25519PublicKey::from_bytes([0u8; 32]).into(),
        identity_signature: Ed25519Signature::empty(),
        device_signature: Ed25519Signature::empty(),
        revoked_at: None,
        expires_at: None,
        timestamp: None,
        note: None,
        payload: None,
        commit_sha: None,
        commit_message: None,
        author: None,
        oidc_binding: None,
        delegated_by: None,
        signer_type: None,
        environment_claim: None,
    }
}