use crate::error::SessionBundleError;
use crate::types::{SessionBundleEnvelope, SessionTrustBundle};
use serde_json::Value;
pub fn parse_session_bundle_wire(value: &Value) -> Result<SessionTrustBundle, SessionBundleError> {
if value.get("session_bundle").is_some() {
let env: SessionBundleEnvelope = serde_json::from_value(value.clone()).map_err(|e| {
SessionBundleError::WireFormInvalid(format!(
"transport envelope: {e} (RFC-AITP-0010 §3 places `signature` \
inside the signed body, never beside the wrapper)"
))
})?;
Ok(env.session_bundle)
} else {
serde_json::from_value(value.clone())
.map_err(|e| SessionBundleError::WireFormInvalid(format!("bundle body: {e}")))
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
fn valid_body() -> Value {
json!({
"version": "aitp/0.2",
"session_id": "00000000-0000-4000-8000-000000000000",
"coordinator": "aid:pubkey:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik",
"issued_at": 1_700_000_000,
"expires_at": 1_700_010_000,
"participants": [],
"signature": "A".repeat(86),
})
}
#[test]
fn wrapped_with_signature_inside_parses() {
let wire = json!({ "session_bundle": valid_body() });
assert!(parse_session_bundle_wire(&wire).is_ok());
}
#[test]
fn bare_body_parses() {
assert!(parse_session_bundle_wire(&valid_body()).is_ok());
}
#[test]
fn sibling_signature_is_rejected() {
let mut body = valid_body();
let signature = body.as_object_mut().unwrap().remove("signature").unwrap();
let wire = json!({ "session_bundle": body, "signature": signature });
assert!(matches!(
parse_session_bundle_wire(&wire),
Err(SessionBundleError::WireFormInvalid(_))
));
}
#[test]
fn unexpected_sibling_key_is_rejected() {
let wire = json!({ "session_bundle": valid_body(), "extra": "nope" });
assert!(matches!(
parse_session_bundle_wire(&wire),
Err(SessionBundleError::WireFormInvalid(_))
));
}
#[test]
fn bare_body_missing_signature_is_rejected() {
let mut body = valid_body();
body.as_object_mut().unwrap().remove("signature");
assert!(matches!(
parse_session_bundle_wire(&body),
Err(SessionBundleError::WireFormInvalid(_))
));
}
}