ironflow_api/entities/
artifact.rs1use chrono::{DateTime, Utc};
4use ironflow_store::models::Artifact;
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7
8#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct ArtifactResponse {
34 pub id: Uuid,
36 pub step_id: Uuid,
38 pub name: String,
40 pub content_type: String,
42 pub size_bytes: u64,
44 pub sha256: String,
46 pub created_at: DateTime<Utc>,
48}
49
50impl From<Artifact> for ArtifactResponse {
51 fn from(artifact: Artifact) -> Self {
52 Self {
53 id: artifact.id,
54 step_id: artifact.step_id,
55 name: artifact.name,
56 content_type: artifact.content_type,
57 size_bytes: artifact.size_bytes,
58 sha256: artifact.sha256,
59 created_at: artifact.created_at,
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 fn sample() -> Artifact {
69 Artifact {
70 id: Uuid::now_v7(),
71 run_id: Uuid::now_v7(),
72 step_id: Uuid::now_v7(),
73 name: "report.html".to_string(),
74 storage_key: "artifacts/secret/path/uuid".to_string(),
75 content_type: "text/html".to_string(),
76 size_bytes: 142,
77 sha256: "0".repeat(64),
78 created_at: Utc::now(),
79 updated_at: Utc::now(),
80 }
81 }
82
83 #[test]
84 fn conversion_keeps_the_caller_facing_fields() {
85 let artifact = sample();
86 let response = ArtifactResponse::from(artifact.clone());
87
88 assert_eq!(response.id, artifact.id);
89 assert_eq!(response.step_id, artifact.step_id);
90 assert_eq!(response.name, artifact.name);
91 assert_eq!(response.size_bytes, artifact.size_bytes);
92 assert_eq!(response.sha256, artifact.sha256);
93 }
94
95 #[test]
96 fn serialization_never_leaks_the_storage_key() {
97 let json = serde_json::to_string(&ArtifactResponse::from(sample())).expect("serialize");
98
99 assert!(!json.contains("storage_key"));
100 assert!(!json.contains("secret/path"));
101 }
102
103 #[test]
104 fn serialization_omits_the_run_id_carried_by_the_route() {
105 let json = serde_json::to_string(&ArtifactResponse::from(sample())).expect("serialize");
106 assert!(!json.contains("run_id"));
107 }
108}