Skip to main content

aap_protocol/
provenance.rs

1//! AAP Provenance — immutable origin record for agent-produced artifacts.
2
3use 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/// Provenance records the immutable origin of an agent-produced artifact.
11#[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    /// Create and sign provenance for a produced artifact.
30    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    /// Verify the signature against the agent's public key.
58    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}