Skip to main content

agent_toolprint/
envelope.rs

1//! DSSE PAE + envelope helpers.
2
3use base64::{engine::general_purpose::STANDARD, Engine};
4use serde_json::{json, Value};
5
6use crate::error::Error;
7use crate::types::PAYLOAD_TYPE;
8
9pub fn pae_encode(payload_type: &str, body: &[u8]) -> Vec<u8> {
10    let head = format!(
11        "DSSEv1 {} {} {} ",
12        payload_type.len(),
13        payload_type,
14        body.len()
15    );
16    let mut out = Vec::with_capacity(head.len() + body.len());
17    out.extend_from_slice(head.as_bytes());
18    out.extend_from_slice(body);
19    out
20}
21
22pub fn new_envelope(body: &[u8]) -> Value {
23    json!({
24        "payloadType": PAYLOAD_TYPE,
25        "payload": STANDARD.encode(body),
26        "signatures": [],
27    })
28}
29
30pub fn envelope_payload_bytes(env: &Value) -> Result<Vec<u8>, Error> {
31    let s = env
32        .get("payload")
33        .and_then(Value::as_str)
34        .ok_or_else(|| Error::Invalid("envelope.payload missing".into()))?;
35    STANDARD
36        .decode(s)
37        .map_err(|e| Error::Invalid(format!("envelope.payload base64: {e}")))
38}
39
40pub fn envelope_pae_bytes(env: &Value) -> Result<Vec<u8>, Error> {
41    let ptype = env
42        .get("payloadType")
43        .and_then(Value::as_str)
44        .ok_or_else(|| Error::Invalid("envelope.payloadType missing".into()))?;
45    let body = envelope_payload_bytes(env)?;
46    Ok(pae_encode(ptype, &body))
47}