//! Bootstrap binary — seeds initial system data idempotently. //! //! Creates default permissions, roles, and admin user if they don't //! already exist. Run once after first deployment. //! //! Usage: cargo run --bin bootstrap fn main() -> anyhow::Result<()> { println!("Zesdex Bootstrap — seeding initial data..."); let store = zesdex_domain::core::Store::new(); store.ensure_dirs()?; // Seed default settings if not present let settings_path = store.base_dir.join("settings.json"); if !settings_path.exists() { let settings = zesdex_domain::cms::Settings::default(); let content = serde_json::to_string_pretty(&settings)?; let tmp = store.base_dir.join("settings.json.tmp"); std::fs::write(&tmp, &content)?; std::fs::File::open(&tmp)?.sync_all()?; std::fs::rename(&tmp, &settings_path)?; println!(" ✓ Default settings created"); } else { println!(" · Settings already exist, skipping"); } // Seed default app config if not present let config_path = store.base_dir.join("app_config.json"); if !config_path.exists() { let config = zesdex_domain::cms::AppConfig::default(); let content = serde_json::to_string_pretty(&config)?; let tmp = store.base_dir.join("app_config.json.tmp"); std::fs::write(&tmp, &content)?; std::fs::File::open(&tmp)?.sync_all()?; std::fs::rename(&tmp, &config_path)?; println!(" ✓ Default app_config created"); } else { println!(" · App config already exists, skipping"); } println!("Bootstrap complete."); Ok(()) }