use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RepositoryConfig { pub version: u32, pub id: String, pub created_at: String, pub chunking: ChunkingConfig, pub compression: String, #[serde(skip_serializing_if = "Option::is_none")] pub encryption: Option, pub pack_target_size: u64, #[serde(default)] pub parity: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ParityConfigSpec { pub algorithm: String, pub data_count: usize, pub parity_count: usize, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChunkingConfig { pub algorithm: String, pub min_size: u32, pub avg_size: u32, pub max_size: u32, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct EncryptionConfig { pub algorithm: String, pub kdf: String, pub kdf_params: KdfParams, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct KdfParams { pub memory: u32, pub iterations: u32, pub parallelism: u32, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct KeyFile { pub id: String, pub created_at: String, pub kdf: String, pub kdf_salt: String, pub kdf_params: KdfParams, pub encrypted_key: String, pub nonce: String, pub auth_tag: String, } impl Default for ChunkingConfig { fn default() -> Self { Self { algorithm: "fastcdc".to_string(), min_size: 65536, // 64 KB avg_size: 262144, // 256 KB max_size: 1048576, // 1 MB } } } impl Default for KdfParams { fn default() -> Self { Self { memory: 262144, // 256 MB iterations: 3, parallelism: 4, } } } impl Default for EncryptionConfig { fn default() -> Self { Self { algorithm: "aes-256-gcm".to_string(), kdf: "argon2id".to_string(), kdf_params: KdfParams::default(), } } } impl RepositoryConfig { pub fn new(encryption: Option) -> Self { Self { version: 1, id: format!("repo-{}", uuid::Uuid::new_v4()), created_at: chrono::Utc::now().to_rfc3339(), chunking: ChunkingConfig::default(), compression: "gzip".to_string(), encryption, pack_target_size: 8 * 1024 * 1024, // 8 MB parity: Some(ParityConfigSpec { algorithm: "reed-solomon".to_string(), data_count: 20, parity_count: 1, }), } } }