aap_protocol/
provenance.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use crate::crypto::{KeyPair, sha256_of, signable, verify_signature};
8use crate::errors::Result;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct Provenance {
13 pub aap_version: String,
14 pub artifact_id: String,
15 pub agent_id: String,
16 pub action: String,
17 pub input_hash: String,
18 pub output_hash: String,
19 pub authorization_id: String,
20 pub timestamp: DateTime<Utc>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub target: Option<String>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub parent_artifact_id: Option<String>,
25 pub signature: String,
26}
27
28impl Provenance {
29 pub fn new(
31 agent_id: &str,
32 action: &str,
33 input_data: &[u8],
34 output_data: &[u8],
35 authorization_id: &str,
36 agent_kp: &KeyPair,
37 ) -> Result<Self> {
38 let mut prov = Self {
39 aap_version: "0.1".into(),
40 artifact_id: Uuid::new_v4().to_string(),
41 agent_id: agent_id.into(),
42 action: action.into(),
43 input_hash: sha256_of(input_data),
44 output_hash: sha256_of(output_data),
45 authorization_id: authorization_id.into(),
46 timestamp: Utc::now(),
47 target: None,
48 parent_artifact_id: None,
49 signature: String::new(),
50 };
51 let v = serde_json::to_value(&prov)?;
52 let data = signable(&v)?;
53 prov.signature = agent_kp.sign(&data);
54 Ok(prov)
55 }
56
57 pub fn verify(&self, agent_public_key_b64: &str) -> Result<()> {
59 let v = serde_json::to_value(self)?;
60 let data = signable(&v)?;
61 verify_signature(agent_public_key_b64, &data, &self.signature)
62 }
63}