# Development Guide This document provides comprehensive information about the design, architecture, and development of the CalDAV Calendar Synchronizer. ## Architecture Overview The application is built with a modular architecture using Rust's strong type system and async capabilities. ### Core Components #### 1. **Configuration System** (`src/config.rs`) - **Purpose**: Manage configuration from files, environment variables, and CLI arguments - **Features**: - TOML-based configuration files - Environment variable support - Command-line argument overrides - Configuration validation - **Key Types**: `Config`, `ServerConfig`, `CalendarConfig`, `SyncConfig` #### 2. **CalDAV Client** (`src/caldav_client.rs`) - **Purpose**: Handle CalDAV protocol operations with Zoho and Nextcloud - **Features**: - HTTP client with authentication - Calendar discovery via PROPFIND - Event retrieval via REPORT requests - Event creation via PUT requests - **Key Types**: `CalDavClient`, `CalendarInfo`, `CalDavEventInfo` #### 3. **Event Model** (`src/event.rs`) - **Purpose**: Represent calendar events and handle parsing - **Features**: - iCalendar data parsing - Timezone-aware datetime handling - Event filtering and validation - **Key Types**: `Event`, `EventBuilder`, `EventFilter` #### 4. **Timezone Handler** (`src/timezone.rs`) - **Purpose**: Manage timezone conversions and datetime operations - **Features**: - Convert between different timezones - Parse timezone information from iCalendar data - Handle DST transitions - **Key Types**: `TimezoneHandler`, `TimeZoneInfo` #### 5. **Calendar Filter** (`src/calendar_filter.rs`) - **Purpose**: Filter calendars and events based on user criteria - **Features**: - Calendar name filtering - Regex pattern matching - Event date range filtering - **Key Types**: `CalendarFilter`, `FilterRule`, `EventFilter` #### 6. **Sync Engine** (`src/sync.rs`) - **Purpose**: Coordinate the synchronization process - **Features**: - Pull events from Zoho - Push events to Nextcloud - Conflict resolution - Progress tracking - **Key Types**: `SyncEngine`, `SyncResult`, `SyncStats` #### 7. **Error Handling** (`src/error.rs`) - **Purpose**: Comprehensive error management - **Features**: - Custom error types - Error context and chaining - User-friendly error messages - **Key Types**: `CalDavError`, `CalDavResult` ## Design Decisions ### 1. **Selective Calendar Import** The application allows users to select specific Zoho calendars to import from, consolidating all events into a single Nextcloud calendar. This design choice: - **Reduces complexity** compared to bidirectional sync - **Provides clear data flow** (Zoho → Nextcloud) - **Minimizes sync conflicts** - **Matches user requirements** exactly ### 2. **Timezone Handling** All events are converted to UTC internally for consistency, while preserving original timezone information: ```rust pub struct Event { pub id: String, pub summary: String, pub start: DateTime, pub end: DateTime, pub original_timezone: Option, pub source_calendar: String, } ``` ### 3. **Configuration Hierarchy** Configuration is loaded in priority order: 1. **Command line arguments** (highest priority) 2. **User config file** (`config/config.toml`) 3. **Default config file** (`config/default.toml`) 4. **Environment variables** 5. **Hardcoded defaults** (lowest priority) ### 4. **Error Handling Strategy** Uses `thiserror` for custom error types and `anyhow` for error propagation: ```rust #[derive(Error, Debug)] pub enum CalDavError { #[error("HTTP error: {0}")] Http(#[from] reqwest::Error), #[error("Configuration error: {0}")] Config(String), #[error("Calendar not found: {0}")] CalendarNotFound(String), // ... more error variants } ``` ## Data Flow ### 1. **Application Startup** ``` 1. Load CLI arguments 2. Load configuration files 3. Apply environment variables 4. Validate configuration 5. Initialize logging 6. Create CalDAV clients ``` ### 2. **Calendar Discovery** ``` 1. Connect to Zoho CalDAV server 2. Authenticate with app password 3. Send PROPFIND request to discover calendars 4. Parse calendar list and metadata 5. Apply user filters to select calendars ``` ### 3. **Event Synchronization** ``` 1. Query selected Zoho calendars for events (next week) 2. Parse iCalendar data into Event objects 3. Convert timestamps to UTC with timezone preservation 4. Apply event filters (duration, status, patterns) 5. Connect to Nextcloud CalDAV server 6. Create target calendar if needed 7. Upload events to Nextcloud calendar 8. Report sync statistics ``` ## Key Algorithms ### 1. **Calendar Filtering** ```rust impl CalendarFilter { pub fn should_import_calendar(&self, calendar_name: &str) -> bool { // Check exact matches if self.selected_names.contains(&calendar_name.to_string()) { return true; } // Check regex patterns for pattern in &self.regex_patterns { if pattern.is_match(calendar_name) { return true; } } false } } ``` ### 2. **Timezone Conversion** ```rust impl TimezoneHandler { pub fn convert_to_utc(&self, dt: DateTime, timezone: &str) -> CalDavResult> { let tz = self.get_timezone(timezone)?; let local_dt = dt.with_timezone(&tz); Ok(local_dt.with_timezone(&Utc)) } } ``` ### 3. **Event Processing** ```rust impl SyncEngine { pub async fn sync_calendar(&mut self, calendar: &CalendarInfo) -> CalDavResult { // 1. Fetch events from Zoho let zoho_events = self.fetch_zoho_events(calendar).await?; // 2. Filter and process events let processed_events = self.process_events(zoho_events)?; // 3. Upload to Nextcloud let upload_results = self.upload_to_nextcloud(processed_events).await?; // 4. Return sync statistics Ok(SyncResult::from_upload_results(upload_results)) } } ``` ## Configuration Schema ### Complete Configuration Structure ```toml # Zoho Configuration (Source) [zoho] server_url = "https://caldav.zoho.com/caldav" username = "your-zoho-email@domain.com" password = "your-zoho-app-password" selected_calendars = ["Work Calendar", "Personal Calendar"] # Nextcloud Configuration (Target) [nextcloud] server_url = "https://your-nextcloud-domain.com" username = "your-nextcloud-username" password = "your-nextcloud-app-password" target_calendar = "Imported-Zoho-Events" create_if_missing = true # General Settings [server] timeout = 30 [calendar] color = "#3174ad" timezone = "UTC" [sync] interval = 300 sync_on_startup = true weeks_ahead = 1 dry_run = false # Optional Filtering [filters] min_duration_minutes = 5 max_duration_hours = 24 exclude_patterns = ["Cancelled:", "BLOCKED"] include_status = ["confirmed", "tentative"] exclude_status = ["cancelled"] ``` ## Dependencies and External Libraries ### Core Dependencies ```toml [dependencies] tokio = { version = "1.0", features = ["full"] } # Async runtime reqwest = { version = "0.11", features = ["json", "xml"] } # HTTP client serde = { version = "1.0", features = ["derive"] } # Serialization chrono = { version = "0.4", features = ["serde"] } # Date/time chrono-tz = "0.8" # Timezone support quick-xml = "0.28" # XML parsing thiserror = "1.0" # Error handling anyhow = "1.0" # Error propagation config = "0.13" # Configuration clap = { version = "4.0", features = ["derive"] } # CLI tracing = "0.1" # Logging tracing-subscriber = "0.3" # Log formatting toml = "0.8" # TOML parsing ``` ### Optional Dependencies for Future Features ```toml # For enhanced XML handling serde_xml_rs = "0.6" # For better HTTP client customization http = "0.2" # For async file operations tokio-util = "0.7" # For better error formatting color-eyre = "0.6" ``` ## Testing Strategy ### 1. **Unit Tests** - Individual module functionality - Configuration parsing and validation - Event parsing and timezone conversion - Error handling paths ### 2. **Integration Tests** - End-to-end CalDAV operations - Configuration loading from files - CLI argument processing - HTTP client behavior ### 3. **Mock Testing** - Mock CalDAV server responses - Test error conditions without real servers - Validate retry logic and timeout handling ## Performance Considerations ### 1. **Async Operations** All network operations are async to prevent blocking: ```rust pub async fn fetch_events(&self, calendar: &CalendarInfo) -> CalDavResult> { let response = self.client .request(reqwest::Method::REPORT, &calendar.url) .body(report_body) .send() .await?; // Process response... } ``` ### 2. **Memory Management** - Stream processing for large calendar responses - Efficient string handling with `Cow` where appropriate - Clear lifecycle management for HTTP connections ### 3. **Configuration Caching** - Cache parsed timezone information - Reuse HTTP connections where possible - Validate configuration once at startup ## Security Considerations ### 1. **Authentication** - Support for app-specific passwords only - Never log authentication credentials - Secure storage of sensitive configuration ### 2. **Network Security** - Enforce HTTPS by default - SSL certificate validation - Custom CA certificate support ### 3. **Data Privacy** - Minimal data collection (only required event fields) - Optional debug logging with sensitive data filtering - Clear data retention policies ## Future Enhancements ### 1. **Enhanced Filtering** - Advanced regex patterns - Calendar color-based filtering - Attendee-based filtering ### 2. **Bidirectional Sync** - Two-way synchronization with conflict resolution - Event modification tracking - Deletion synchronization ### 3. **Performance Optimizations** - Parallel calendar processing - Incremental sync with change detection - Local caching and offline mode ### 4. **User Experience** - Interactive configuration wizard - Web-based status dashboard - Real-time sync notifications ## Build and Development ### 1. **Development Setup** ```bash # Clone repository git clone ssh://git@gitea.soliverez.com.ar/alvaro/caldavpuller.git cd caldavpuller # Install Rust toolchain rustup update stable rustup component add rustfmt clippy # Build in development mode cargo build # Run tests cargo test # Check formatting cargo fmt --check # Run linter cargo clippy -- -D warnings ``` ### 2. **Release Build** ```bash # Build optimized release cargo build --release # Create distribution archive tar -czf caldav-sync-${VERSION}-${TARGET}.tar.gz \ -C target/release caldav-sync \ -C ../config example.toml \ -C .. README.md LICENSE ``` ### 3. **Testing with Mock Servers** For testing without real CalDAV servers, use the mock server setup: ```bash # Start mock CalDAV server cargo run --bin mock-server # Run integration tests against mock server cargo test --test integration_tests ``` This architecture provides a solid foundation for the CalDAV synchronization tool while maintaining flexibility for future enhancements.