koprogo_api/domain/entities/
gdpr_art30.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5/// Registre des activités de traitement — GDPR Art. 30 §1
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ProcessingActivity {
8    pub id: Uuid,
9    pub activity_name: String,
10    pub controller_name: String,
11    pub purpose: String,
12    pub legal_basis: String,
13    pub data_categories: Vec<String>,
14    pub data_subjects: Vec<String>,
15    pub recipients: Vec<String>,
16    pub retention_period: String,
17    pub security_measures: String,
18    pub created_at: DateTime<Utc>,
19    pub updated_at: DateTime<Utc>,
20}
21
22/// Accord sous-traitant (DPA) — GDPR Art. 28 + Art. 30 §2
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ProcessorAgreement {
25    pub id: Uuid,
26    pub processor_name: String,
27    pub service_description: String,
28    pub dpa_signed_at: Option<DateTime<Utc>>,
29    pub dpa_url: Option<String>,
30    pub transfer_mechanism: Option<String>,
31    pub data_categories: Vec<String>,
32    pub certifications: Option<Vec<String>>,
33    pub created_at: DateTime<Utc>,
34    pub updated_at: DateTime<Utc>,
35}
36
37impl ProcessorAgreement {
38    pub fn has_signed_dpa(&self) -> bool {
39        self.dpa_signed_at.is_some()
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    fn make_agreement(signed: bool) -> ProcessorAgreement {
48        let now = Utc::now();
49        ProcessorAgreement {
50            id: Uuid::new_v4(),
51            processor_name: "AWS".to_string(),
52            service_description: "Cloud hosting".to_string(),
53            dpa_signed_at: if signed { Some(now) } else { None },
54            dpa_url: Some("https://aws.amazon.com/dpa".to_string()),
55            transfer_mechanism: Some("SCCs".to_string()),
56            data_categories: vec!["personal_data".to_string()],
57            certifications: Some(vec!["ISO27001".to_string()]),
58            created_at: now,
59            updated_at: now,
60        }
61    }
62
63    #[test]
64    fn test_has_signed_dpa_true() {
65        assert!(make_agreement(true).has_signed_dpa());
66    }
67
68    #[test]
69    fn test_has_signed_dpa_false() {
70        assert!(!make_agreement(false).has_signed_dpa());
71    }
72
73    #[test]
74    fn test_processing_activity_fields() {
75        let now = Utc::now();
76        let act = ProcessingActivity {
77            id: Uuid::new_v4(),
78            activity_name: "User management".to_string(),
79            controller_name: "KoproGo ASBL".to_string(),
80            purpose: "Contract performance".to_string(),
81            legal_basis: "Art. 6(1)(b) GDPR".to_string(),
82            data_categories: vec!["contact".to_string(), "financial".to_string()],
83            data_subjects: vec!["owners".to_string()],
84            recipients: vec!["syndic".to_string()],
85            retention_period: "7 years".to_string(),
86            security_measures: "Encryption at rest, TLS".to_string(),
87            created_at: now,
88            updated_at: now,
89        };
90        assert_eq!(act.data_categories.len(), 2);
91        assert_eq!(act.legal_basis, "Art. 6(1)(b) GDPR");
92    }
93}