use auths_id::keri::types::Prefix;
pub use auths_verifier::org_bundle::AuthorityAtSigning;
use crate::context::AuthsContext;
use crate::domains::org::delegation::{OrgKelSnapshot, list_members};
use crate::domains::org::error::OrgError;
use crate::domains::org::offboarding::{
SignedOffboardingRecord, find_revocation_event, load_offboarding_record,
};
pub fn classify_authority_at_signing(
ctx: &AuthsContext,
org_prefix: &Prefix,
member_prefix: &Prefix,
signed_at: Option<u128>,
) -> Result<AuthorityAtSigning, OrgError> {
let snapshot = OrgKelSnapshot::load(ctx, org_prefix)?;
classify_authority_at_signing_with(&snapshot, member_prefix, signed_at)
}
pub fn classify_authority_at_signing_with(
snapshot: &OrgKelSnapshot,
member_prefix: &Prefix,
signed_at: Option<u128>,
) -> Result<AuthorityAtSigning, OrgError> {
let Some(authority) = snapshot.member_authority(member_prefix) else {
return Ok(AuthorityAtSigning::NeverDelegated);
};
if !authority.revoked {
return Ok(AuthorityAtSigning::AuthorizedBeforeRevocation);
}
let revoked_at = find_revocation_event(snapshot.org_kel(), member_prefix)
.map(|(_, seq)| seq)
.ok_or_else(|| {
OrgError::Signing("revoked member has no revocation event on the org KEL".to_string())
})?;
Ok(match signed_at {
None => AuthorityAtSigning::RejectedRevokedPositionUnknown { revoked_at },
Some(seq) if seq < revoked_at => AuthorityAtSigning::AuthorizedBeforeRevocation,
Some(_) => AuthorityAtSigning::RejectedAfterRevocation { revoked_at },
})
}
pub fn list_offboarding_records(
ctx: &AuthsContext,
org_prefix: &Prefix,
) -> Result<Vec<SignedOffboardingRecord>, OrgError> {
let mut records = Vec::new();
for member in list_members(ctx, org_prefix)?
.into_iter()
.filter(|m| m.revoked)
{
let member_prefix = Prefix::new_unchecked(member.member_prefix.clone());
if let Some(record) = load_offboarding_record(ctx, org_prefix, &member_prefix)? {
records.push(record);
}
}
Ok(records)
}