feat: identity lifecycle tests and ADR-011 DWN deprioritization

Added 8 integration tests for identity manager covering create,
sign/verify, list, delete, default management, and Nostr key gen.
Documented DWN deprioritization decision.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-15 05:01:06 +00:00
parent 7139dc43a6
commit eed4bc7211
3 changed files with 141 additions and 2 deletions

View File

@@ -215,6 +215,17 @@ impl IdentityManager {
self.load_signing_key(id).await
}
/// Get the default identity ID, if one is set.
pub async fn get_default_id(&self) -> Result<Option<String>> {
let marker = self.identities_dir.join(DEFAULT_MARKER);
if marker.exists() {
let id = fs::read_to_string(&marker).await?;
Ok(Some(id.trim().to_string()))
} else {
Ok(None)
}
}
/// Sign data with a specific identity.
pub async fn sign(&self, id: &str, data: &[u8]) -> Result<String> {
let signing_key = self.load_signing_key(id).await?;
@@ -415,3 +426,100 @@ impl IdentityManager {
Ok(SigningKey::from_bytes(&arr))
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[tokio::test]
async fn test_create_identity_did_key_format() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let record = mgr.create("Test".to_string(), IdentityPurpose::Personal).await.unwrap();
assert!(record.did.starts_with("did:key:z6Mk"), "DID should be did:key:z6Mk..., got {}", record.did);
assert!(!record.id.is_empty());
assert_eq!(record.name, "Test");
}
#[tokio::test]
async fn test_create_nostr_key_npub_format() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let record = mgr.create("Nostr".to_string(), IdentityPurpose::Personal).await.unwrap();
let npub = mgr.create_nostr_key(&record.id).await.unwrap();
assert!(npub.starts_with("npub1"), "npub should start with npub1, got {}", npub);
}
#[tokio::test]
async fn test_sign_and_verify() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let record = mgr.create("Signer".to_string(), IdentityPurpose::Personal).await.unwrap();
let data = b"hello archipelago";
let sig = mgr.sign(&record.id, data).await.unwrap();
let valid = mgr.verify(&record.did, data, &sig).await.unwrap();
assert!(valid, "Signature should verify");
}
#[tokio::test]
async fn test_sign_verify_wrong_data() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let record = mgr.create("Signer".to_string(), IdentityPurpose::Personal).await.unwrap();
let sig = mgr.sign(&record.id, b"correct").await.unwrap();
let valid = mgr.verify(&record.did, b"wrong", &sig).await.unwrap();
assert!(!valid, "Signature should not verify with wrong data");
}
#[tokio::test]
async fn test_list_identities() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
mgr.create("One".to_string(), IdentityPurpose::Personal).await.unwrap();
mgr.create("Two".to_string(), IdentityPurpose::Business).await.unwrap();
let (list, _) = mgr.list().await.unwrap();
assert_eq!(list.len(), 2);
}
#[tokio::test]
async fn test_delete_identity() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let r1 = mgr.create("First".to_string(), IdentityPurpose::Personal).await.unwrap();
let r2 = mgr.create("Second".to_string(), IdentityPurpose::Business).await.unwrap();
mgr.delete(&r1.id).await.unwrap();
let (list, _) = mgr.list().await.unwrap();
assert_eq!(list.len(), 1);
assert_eq!(list[0].id, r2.id);
}
#[tokio::test]
async fn test_set_and_get_default() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let r1 = mgr.create("First".to_string(), IdentityPurpose::Personal).await.unwrap();
let r2 = mgr.create("Second".to_string(), IdentityPurpose::Business).await.unwrap();
mgr.set_default(&r2.id).await.unwrap();
let default_id = mgr.get_default_id().await.unwrap();
assert_eq!(default_id, Some(r2.id.clone()));
// First is no longer default
assert_ne!(default_id, Some(r1.id));
}
#[tokio::test]
async fn test_delete_default_shifts() {
let dir = tempdir().unwrap();
let mgr = IdentityManager::new(dir.path()).await.unwrap();
let r1 = mgr.create("First".to_string(), IdentityPurpose::Personal).await.unwrap();
mgr.create("Second".to_string(), IdentityPurpose::Business).await.unwrap();
mgr.set_default(&r1.id).await.unwrap();
mgr.delete(&r1.id).await.unwrap();
let (list, default_id) = mgr.list().await.unwrap();
assert_eq!(list.len(), 1);
// Default should have shifted or be cleared
if let Some(def) = default_id {
assert_ne!(def, r1.id, "Default should not point to deleted identity");
}
}
}