use serde::{Deserialize, Serialize}; /// Server response to `POST /api/upload`. Shape is stable across all clients. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AckResponse { pub case_id: String, pub recorded_at: String, pub status: AckStatus, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum AckStatus { /// Recording accepted and persisted. Received, /// Case no longer exists server-side; client should delete its local copy. Gone, } #[cfg(test)] mod tests { use super::*; #[test] fn status_serializes_lowercase() { assert_eq!( serde_json::to_string(&AckStatus::Received).unwrap(), "\"received\"" ); assert_eq!(serde_json::to_string(&AckStatus::Gone).unwrap(), "\"gone\""); } #[test] fn status_deserializes_lowercase() { let got: AckStatus = serde_json::from_str("\"received\"").unwrap(); assert_eq!(got, AckStatus::Received); let got: AckStatus = serde_json::from_str("\"gone\"").unwrap(); assert_eq!(got, AckStatus::Gone); } #[test] fn response_roundtrip() { let original = AckResponse { case_id: "550e8400-e29b-41d4-a716-446655440000".into(), recorded_at: "2026-04-15T10:32:00Z".into(), status: AckStatus::Received, }; let json = serde_json::to_string(&original).unwrap(); let decoded: AckResponse = serde_json::from_str(&json).unwrap(); assert_eq!(decoded.case_id, original.case_id); assert_eq!(decoded.recorded_at, original.recorded_at); assert_eq!(decoded.status, original.status); } }