use std::ops::ControlFlow;
use auths_id::keri::types::Prefix;
use auths_verifier::types::IdentityDID;
pub use auths_verifier::org_bundle::{
AIR_GAPPED_ORG_BUNDLE_SCHEMA_VERSION, AirGappedOrgBundle, BundledKel,
};
use crate::context::AuthsContext;
use crate::domains::org::audit::list_offboarding_records;
use crate::domains::org::delegation::list_members;
use crate::domains::org::error::OrgError;
fn collect_bundled_kel(ctx: &AuthsContext, prefix: &Prefix) -> Result<BundledKel, OrgError> {
let mut events = Vec::new();
ctx.registry
.visit_events(prefix, 0, &mut |event| {
events.push(event.clone());
ControlFlow::Continue(())
})
.map_err(OrgError::Storage)?;
let mut attachments = Vec::with_capacity(events.len());
for event in &events {
let seq = event.sequence().value();
let attachment = ctx
.registry
.get_attachment(prefix, seq)
.map_err(OrgError::Storage)?;
attachments.push(attachment.map(hex::encode).unwrap_or_default());
}
Ok(BundledKel {
prefix: prefix.clone(),
events,
attachments,
})
}
pub fn build_org_bundle(
ctx: &AuthsContext,
org_prefix: &Prefix,
) -> Result<AirGappedOrgBundle, OrgError> {
let org_did = IdentityDID::from_prefix(org_prefix.as_str())
.map_err(|e| OrgError::InvalidDid(e.to_string()))?;
let org_kel = collect_bundled_kel(ctx, org_prefix)?;
let built_at_org_seq = org_kel
.events
.last()
.map(|e| e.sequence().value())
.unwrap_or(0);
let mut member_kels = Vec::new();
for member in list_members(ctx, org_prefix)? {
let member_prefix = Prefix::new_unchecked(member.member_prefix.clone());
member_kels.push(collect_bundled_kel(ctx, &member_prefix)?);
}
let offboarding_records = list_offboarding_records(ctx, org_prefix)?;
Ok(AirGappedOrgBundle {
schema_version: AIR_GAPPED_ORG_BUNDLE_SCHEMA_VERSION,
org_did: org_did.clone(),
org_prefix: org_prefix.clone(),
built_at_org_seq,
built_at: ctx.clock.now().to_rfc3339(),
org_kel,
member_kels,
offboarding_records,
pinned_roots: vec![org_did],
})
}