oxigdal_security/lineage/
mod.rs1pub mod graph;
4pub mod metadata;
5pub mod query;
6
7use chrono::{DateTime, Utc};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use uuid::Uuid;
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
14pub struct LineageNode {
15 pub id: String,
17 pub node_type: NodeType,
19 pub entity_id: String,
21 pub metadata: HashMap<String, String>,
23 pub created_at: DateTime<Utc>,
25}
26
27impl LineageNode {
28 pub fn new(node_type: NodeType, entity_id: String) -> Self {
30 Self {
31 id: Uuid::new_v4().to_string(),
32 node_type,
33 entity_id,
34 metadata: HashMap::new(),
35 created_at: Utc::now(),
36 }
37 }
38
39 pub fn with_metadata(mut self, key: String, value: String) -> Self {
41 self.metadata.insert(key, value);
42 self
43 }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
48pub enum NodeType {
49 Dataset,
51 Operation,
53 Agent,
55 Model,
57 Parameters,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
63pub struct LineageEdge {
64 pub id: String,
66 pub source_id: String,
68 pub target_id: String,
70 pub edge_type: EdgeType,
72 pub metadata: HashMap<String, String>,
74 pub created_at: DateTime<Utc>,
76}
77
78impl LineageEdge {
79 pub fn new(source_id: String, target_id: String, edge_type: EdgeType) -> Self {
81 Self {
82 id: Uuid::new_v4().to_string(),
83 source_id,
84 target_id,
85 edge_type,
86 metadata: HashMap::new(),
87 created_at: Utc::now(),
88 }
89 }
90
91 pub fn with_metadata(mut self, key: String, value: String) -> Self {
93 self.metadata.insert(key, value);
94 self
95 }
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
100pub enum EdgeType {
101 DerivedFrom,
103 Used,
105 GeneratedBy,
107 AttributedTo,
109 AssociatedWith,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct LineageEvent {
116 pub id: String,
118 pub event_type: String,
120 pub timestamp: DateTime<Utc>,
122 pub inputs: Vec<String>,
124 pub outputs: Vec<String>,
126 pub operation: Option<String>,
128 pub agent: Option<String>,
130 pub metadata: HashMap<String, String>,
132}
133
134impl LineageEvent {
135 pub fn new(event_type: String) -> Self {
137 Self {
138 id: Uuid::new_v4().to_string(),
139 event_type,
140 timestamp: Utc::now(),
141 inputs: Vec::new(),
142 outputs: Vec::new(),
143 operation: None,
144 agent: None,
145 metadata: HashMap::new(),
146 }
147 }
148
149 pub fn with_input(mut self, input_id: String) -> Self {
151 self.inputs.push(input_id);
152 self
153 }
154
155 pub fn with_output(mut self, output_id: String) -> Self {
157 self.outputs.push(output_id);
158 self
159 }
160
161 pub fn with_operation(mut self, operation_id: String) -> Self {
163 self.operation = Some(operation_id);
164 self
165 }
166
167 pub fn with_agent(mut self, agent_id: String) -> Self {
169 self.agent = Some(agent_id);
170 self
171 }
172
173 pub fn with_metadata(mut self, key: String, value: String) -> Self {
175 self.metadata.insert(key, value);
176 self
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn test_lineage_node_creation() {
186 let node = LineageNode::new(NodeType::Dataset, "dataset-123".to_string())
187 .with_metadata("format".to_string(), "GeoTIFF".to_string());
188
189 assert_eq!(node.node_type, NodeType::Dataset);
190 assert_eq!(node.entity_id, "dataset-123");
191 assert_eq!(node.metadata.get("format"), Some(&"GeoTIFF".to_string()));
192 }
193
194 #[test]
195 fn test_lineage_edge_creation() {
196 let edge = LineageEdge::new(
197 "node-1".to_string(),
198 "node-2".to_string(),
199 EdgeType::DerivedFrom,
200 )
201 .with_metadata("operation".to_string(), "reproject".to_string());
202
203 assert_eq!(edge.source_id, "node-1");
204 assert_eq!(edge.target_id, "node-2");
205 assert_eq!(edge.edge_type, EdgeType::DerivedFrom);
206 }
207
208 #[test]
209 fn test_lineage_event() {
210 let event = LineageEvent::new("transform".to_string())
211 .with_input("input-1".to_string())
212 .with_output("output-1".to_string())
213 .with_operation("op-1".to_string())
214 .with_agent("user-123".to_string());
215
216 assert_eq!(event.event_type, "transform");
217 assert_eq!(event.inputs.len(), 1);
218 assert_eq!(event.outputs.len(), 1);
219 assert_eq!(event.operation, Some("op-1".to_string()));
220 assert_eq!(event.agent, Some("user-123".to_string()));
221 }
222}