aitp_session_bundle/
wire.rs1use crate::error::SessionBundleError;
5use crate::types::{SessionBundleEnvelope, SessionTrustBundle};
6use serde_json::Value;
7
8pub fn parse_session_bundle_wire(value: &Value) -> Result<SessionTrustBundle, SessionBundleError> {
18 if value.get("session_bundle").is_some() {
19 let env: SessionBundleEnvelope = serde_json::from_value(value.clone()).map_err(|e| {
20 SessionBundleError::WireFormInvalid(format!(
21 "transport envelope: {e} (RFC-AITP-0010 §3 places `signature` \
22 inside the signed body, never beside the wrapper)"
23 ))
24 })?;
25 Ok(env.session_bundle)
26 } else {
27 serde_json::from_value(value.clone())
28 .map_err(|e| SessionBundleError::WireFormInvalid(format!("bundle body: {e}")))
29 }
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35 use serde_json::json;
36
37 fn valid_body() -> Value {
38 json!({
39 "version": "aitp/0.2",
40 "session_id": "00000000-0000-4000-8000-000000000000",
41 "coordinator": "aid:pubkey:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik",
42 "issued_at": 1_700_000_000,
43 "expires_at": 1_700_010_000,
44 "participants": [],
45 "signature": "A".repeat(86),
46 })
47 }
48
49 #[test]
50 fn wrapped_with_signature_inside_parses() {
51 let wire = json!({ "session_bundle": valid_body() });
52 assert!(parse_session_bundle_wire(&wire).is_ok());
53 }
54
55 #[test]
56 fn bare_body_parses() {
57 assert!(parse_session_bundle_wire(&valid_body()).is_ok());
58 }
59
60 #[test]
61 fn sibling_signature_is_rejected() {
62 let mut body = valid_body();
63 let signature = body.as_object_mut().unwrap().remove("signature").unwrap();
64 let wire = json!({ "session_bundle": body, "signature": signature });
65 assert!(matches!(
66 parse_session_bundle_wire(&wire),
67 Err(SessionBundleError::WireFormInvalid(_))
68 ));
69 }
70
71 #[test]
72 fn unexpected_sibling_key_is_rejected() {
73 let wire = json!({ "session_bundle": valid_body(), "extra": "nope" });
74 assert!(matches!(
75 parse_session_bundle_wire(&wire),
76 Err(SessionBundleError::WireFormInvalid(_))
77 ));
78 }
79
80 #[test]
81 fn bare_body_missing_signature_is_rejected() {
82 let mut body = valid_body();
83 body.as_object_mut().unwrap().remove("signature");
84 assert!(matches!(
85 parse_session_bundle_wire(&body),
86 Err(SessionBundleError::WireFormInvalid(_))
87 ));
88 }
89}