# 🔍 **rpm-ostree vs rpm-ostreed: CLI-Daemon Separation Analysis**

## 📋 **Overview**

This document provides a comprehensive analysis of the separation between `rpm-ostree` (the CLI client) and `rpm-ostreed` (the system daemon) based on examination of the rpm-ostree source code. Understanding this separation is crucial for implementing a similar architecture in apt-ostree.

## 🏗️ **Architecture Overview**

### **Component Separation**
```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   rpm-ostree    │    │   DBus Layer    │    │   rpm-ostreed   │
│   (CLI Client)  │◄──►│   (Communication)│◄──►│   (System Daemon)│
│                 │    │                 │    │                 │
│ • Command Line  │    │ • Client Proxy  │    │ • OSTree Ops    │
│ • User Interface│    │ • Signal Handler│    │ • Package Mgmt  │
│ • Progress Display│   │ • Error Handling│    │ • Transactions  │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

### **Key Design Principles**
1. **Separation of Concerns**: CLI handles user interaction, daemon handles system operations
2. **Privilege Isolation**: Daemon runs with elevated privileges, CLI runs as user
3. **Transaction Management**: Daemon manages long-running operations, CLI monitors progress
4. **Fallback Support**: CLI can operate without daemon for read-only operations
5. **Security by Design**: Daemon handles all privileged operations via PolicyKit

## 🔍 **Detailed Separation Analysis**

### **1. rpm-ostree (CLI Client) Responsibilities**

#### **Command Line Interface**
```cpp
// From libmain.cxx - Command registration and dispatch
static RpmOstreeCommand commands[] = {
  { "compose", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD | RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT,
    "Commands to compose a tree", rpmostree_builtin_compose },
  { "status", (RpmOstreeBuiltinFlags)0, "Get the version of the booted system",
    rpmostree_builtin_status },
  { "upgrade", RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS, "Perform a system upgrade",
    rpmostree_builtin_upgrade },
  { "install", RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE, "Overlay additional packages",
    rpmostree_builtin_install },
  { "uninstall", RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE, "Remove overlayed packages",
    rpmostree_builtin_uninstall },
  { "search", RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE, "Search for packages",
    rpmostree_builtin_search },
  { "rollback", (RpmOstreeBuiltinFlags)0, "Revert to the previously booted tree",
    rpmostree_builtin_rollback },
  { "deploy", RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS, "Deploy a specific commit",
    rpmostree_builtin_deploy },
  { "rebase", RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS, "Switch to a different tree",
    rpmostree_builtin_rebase },
  { "kargs", (RpmOstreeBuiltinFlags)0, "Query or modify kernel arguments",
    rpmostree_builtin_kargs },
  { "initramfs", (RpmOstreeBuiltinFlags)0, "Enable or disable local initramfs regeneration",
    rpmostree_builtin_initramfs },
  { "override", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Manage base package overrides",
    rpmostree_builtin_override },
  { "reset", RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS, "Remove all mutations",
    rpmostree_builtin_reset },
  { "refresh-md", (RpmOstreeBuiltinFlags)0, "Generate rpm repo metadata",
    rpmostree_builtin_refresh_md },
  { "reload", (RpmOstreeBuiltinFlags)0, "Reload configuration",
    rpmostree_builtin_reload },
  { "cancel", (RpmOstreeBuiltinFlags)0, "Cancel an active transaction",
    rpmostree_builtin_cancel },
  { "cleanup", RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE, "Clear cached/pending data",
    rpmostree_builtin_cleanup },
  { "apply-live", (RpmOstreeBuiltinFlags)0, "Apply pending deployment changes to booted deployment",
    rpmostree_builtin_apply_live },
  { "finalize-deployment", (RpmOstreeBuiltinFlags)0, "Finalize staged deployment",
    rpmostree_builtin_finalize_deployment },
  { "initramfs-etc", (RpmOstreeBuiltinFlags)0, "Add files to the initramfs",
    rpmostree_builtin_initramfs_etc },
  { "db", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Commands to query the RPM database",
    rpmostree_builtin_db },
  { "usroverlay", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Apply transient overlay",
    rpmostree_builtin_usroverlay },
  { "ex", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Execute command in deployment",
    rpmostree_builtin_ex },
  { "rebuild", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Rebuild deployment",
    rpmostree_builtin_rebuild },
  { "start-daemon", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Start the daemon",
    rpmostree_builtin_start_daemon },
  { "testutils", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, "Test utilities",
    rpmostree_builtin_testutils },
};
```

**Responsibilities**:
- **Command parsing** and argument validation
- **Option handling** and help display
- **Command dispatch** to appropriate builtin functions
- **User interface** and output formatting
- **Command flag management** and validation

#### **DBus Client Communication**
```cpp
// From rpmostree-clientlib.cxx - Client-side DBus handling
static gboolean
app_load_sysroot_impl (const char *sysroot, GCancellable *cancellable, 
                       GDBusConnection **out_conn, GError **error)
{
  // Start daemon if not running
  ROSCXX_TRY (client_start_daemon (), error);
  
  // Connect to system bus
  g_autoptr (GDBusConnection) connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, 
                                                          cancellable, error);
  
  // Register as client
  uid_t uid = getuid ();
  gboolean should_register;
  if (uid == 0)
    should_register = TRUE;
  else
    {
      g_autofree char *session_id = NULL;
      if (sd_pid_get_session (getpid (), &session_id) >= 0)
        should_register = sd_session_is_active (session_id) == 1;
      else
        should_register = FALSE;
    }
  
  if (should_register)
    {
      g_autoptr (GVariant) options = g_variant_new ("(s@a{sv})", "cli", 
                                                    g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0));
      rpmostree_sysroot_call_register_client (sysroot_proxy, options, NULL, NULL);
    }
}
```

**Responsibilities**:
- **DBus connection** establishment and management
- **Client registration** with daemon
- **Method invocation** on daemon interfaces
- **Signal handling** for progress updates
- **Error handling** and retry logic
- **Daemon startup** if not running

#### **Progress Monitoring and Display**
```cpp
// From rpmostree-clientlib.cxx - Progress and error display
static void
transaction_progress_signal_handler (GDBusConnection *connection, const char *sender_name,
                                    const char *object_path, const char *interface_name,
                                    const char *signal_name, GVariant *parameters,
                                    gpointer user_data)
{
  auto tp = static_cast<TransactionProgress *> (user_data);

  if (g_strcmp0 (signal_name, "Message") == 0) {
    const char *message;
    g_variant_get (parameters, "(&s)", &message);
    
    if (!tp->progress) {
      tp->progress = TRUE;
      rpmostreecxx::console_progress_begin_task (message);
    } else {
      rpmostreecxx::console_progress_set_message (message);
    }
  } else if (g_strcmp0 (signal_name, "PercentProgress") == 0) {
    guint percentage;
    const char *message;
    g_variant_get (parameters, "(u&s)", &percentage, &message);
    
    if (!tp->progress) {
      tp->progress = TRUE;
      rpmostreecxx::console_progress_begin_percent (message);
    }
    rpmostreecxx::console_progress_update (percentage);
  } else if (g_strcmp0 (signal_name, "DownloadProgress") == 0) {
    auto line = rpmostreecxx::client_render_download_progress (*parameters);
    if (!tp->progress) {
      tp->progress = TRUE;
      rpmostreecxx::console_progress_begin_task (line.c_str ());
    } else {
      rpmostreecxx::console_progress_set_message (line.c_str ());
    }
  }
}
```

**Responsibilities**:
- **Progress display** during long operations
- **Status reporting** and user feedback
- **Output formatting** (text, JSON, etc.)
- **Error message** presentation
- **Download progress** visualization
- **Task progress** tracking

#### **Fallback Operations**
```cpp
// From rpmostree-builtin-status.cxx - Fallback when daemon unavailable
static gboolean
rpmostree_builtin_status (int argc, char **argv, RpmOstreeCommandInvocation *invocation,
                         GCancellable *cancellable, GError **error)
{
  // Try daemon first, fallback to direct OSTree if needed
  g_autoptr (GDBusConnection) connection = NULL;
  if (rpmostree_client_connection_new (invocation, cancellable, &connection, error)) {
    // Use daemon for status
    return get_status_via_daemon (connection, invocation, cancellable, error);
  } else {
    // Fallback to direct OSTree operations
    return get_status_direct (invocation, cancellable, error);
  }
}

// Direct OSTree operations for fallback
static gboolean
get_status_direct (RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
  // Direct OSTree sysroot access
  g_autoptr (OstreeSysroot) sysroot = ostree_sysroot_new_default ();
  if (!ostree_sysroot_load (sysroot, cancellable, error))
    return FALSE;
  
  // Get deployment information directly
  g_autoptr (GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
  if (!deployments)
    return FALSE;
  
  // Display deployment information
  for (guint i = 0; i < deployments->len; i++) {
    auto deployment = static_cast<OstreeDeployment *> (deployments->pdata[i]);
    print_deployment (deployment, opt_verbose, opt_only_booted, textarea_width);
  }
  
  return TRUE;
}
```

**Responsibilities**:
- **Fallback logic** when daemon unavailable
- **Direct OSTree operations** for read-only tasks
- **Graceful degradation** of functionality
- **User notification** of limited capabilities
- **Local system access** for basic operations

### **2. rpm-ostreed (Daemon) Responsibilities**

#### **System State Management**
```cpp
// From rpmostreed-daemon.cxx - Daemon state management
struct _RpmostreedDaemon {
  GObject parent_instance;

  GHashTable *bus_clients;                     // Active client tracking
  gboolean running;                            // Daemon running state
  gboolean rebooting;                          // System reboot state
  GDBusProxy *bus_proxy;                       // System bus proxy
  GSource *idle_exit_source;                   // Auto-exit timer
  guint rerender_status_id;                    // Status rerender timer
  RpmostreedSysroot *sysroot;                  // OSTree sysroot management
  gchar *sysroot_path;                         // System root path

  // Configuration settings
  guint idle_exit_timeout;                     // Auto-exit timeout
  RpmostreedAutomaticUpdatePolicy auto_update_policy;  // Update policy
  gboolean lock_layering;                      // Package layering lock
  gboolean disable_recommends;                 // Recommends handling

  // DBus infrastructure
  GDBusConnection *connection;                 // DBus connection
  GDBusObjectManagerServer *object_manager;    // Object management

  // Async runtime
  std::optional<rust::Box<rpmostreecxx::TokioHandle>> tokio_handle;
};
```

**Responsibilities**:
- **Global state** management and persistence
- **Configuration** loading and validation
- **Client lifecycle** management
- **System monitoring** and health checks
- **Auto-exit** management for resource efficiency
- **Update policy** enforcement

#### **OSTree Operations**
```cpp
// From rpmostreed-sysroot.cxx - OSTree system management
struct _RpmostreedSysroot {
  RPMOSTreeSysrootSkeleton parent_instance;

  OstreeSysroot *ot_sysroot;                   // OSTree sysroot object
  OstreeRepo *repo;                            // OSTree repository
  struct stat repo_last_stat;                   // Repository stat cache
  RpmostreedTransaction *transaction;           // Active transaction
  guint close_transaction_timeout_id;           // Transaction timeout

  PolkitAuthority *authority;                   // PolicyKit authority
  gboolean on_session_bus;                      // Session bus flag

  GHashTable *os_interfaces;                    // OS interface objects
  GHashTable *osexperimental_interfaces;        // Experimental interfaces

  GFileMonitor *monitor;                        // Filesystem monitoring
  guint sig_changed;                            // Change signal handler
};

// OSTree operations implementation
static gboolean
rpmostreed_sysroot_handle_deploy (RPMOSTreeSysroot *skeleton, GDBusMethodInvocation *invocation,
                                   const char *osname, const char *refspec, GVariant *options)
{
  // Check authorization
  if (!rpmostreed_sysroot_check_authorization (self, invocation, 
                                               "org.projectatomic.rpmostree1.deploy")) {
    return FALSE;
  }
  
  // Create deployment transaction
  g_autoptr (RpmostreedTransaction) transaction = rpmostreed_transaction_new (
    self, invocation, "deploy", refspec, options);
  
  if (!transaction)
    return FALSE;
  
  // Execute deployment
  rpmostreed_transaction_execute (transaction);
  return TRUE;
}
```

**Responsibilities**:
- **OSTree repository** management and operations
- **Deployment** creation, modification, and removal
- **Filesystem** operations and staging
- **Boot configuration** management
- **System updates** and rollbacks
- **Repository monitoring** and change detection

#### **Transaction Management**
```cpp
// From rpmostreed-transaction.cxx - Transaction lifecycle
struct _RpmostreedTransactionPrivate {
  GDBusMethodInvocation *invocation;            // DBus method context
  gboolean executed;                            // Transaction completion state
  GCancellable *cancellable;                    // Cancellation support
  
  // System state during transaction
  char *sysroot_path;                           // Sysroot path
  OstreeSysroot *sysroot;                       // OSTree sysroot
  gboolean sysroot_locked;                      // Sysroot lock state
  
  // Client tracking
  char *client_description;                     // Client description
  char *agent_id;                               // Client agent ID
  char *sd_unit;                                // Systemd unit
  
  // Progress tracking
  gint64 last_progress_journal;                 // Progress journal timestamp
  gboolean redirect_output;                     // Output redirection flag
  
  // Peer connections
  GDBusServer *server;                          // DBus server
  GHashTable *peer_connections;                 // Client connections
  
  // Completion state
  GVariant *finished_params;                    // Completion parameters
  guint watch_id;                               // Watch identifier
};

// Transaction execution
static void
rpmostreed_transaction_execute (RpmostreedTransaction *self)
{
  RpmostreedTransactionPrivate *priv = rpmostreed_transaction_get_private (self);
  
  // Lock sysroot
  if (!ostree_sysroot_lock (priv->sysroot, priv->cancellable, NULL)) {
    rpmostreed_transaction_fail (self, "Failed to lock sysroot");
    return;
  }
  priv->sysroot_locked = TRUE;
  
  // Execute operations
  for (guint i = 0; i < priv->operations->len; i++) {
    auto operation = static_cast<RpmostreedOperation *> (priv->operations->pdata[i]);
    
    // Emit progress
    rpmostreed_transaction_emit_percent_progress (self, 
      (i * 100) / priv->operations->len, "Executing operation");
    
    // Execute operation
    if (!rpmostreed_operation_execute (operation, self)) {
      rpmostreed_transaction_fail (self, "Operation execution failed");
      return;
    }
  }
  
  // Commit transaction
  rpmostreed_transaction_commit (self);
}
```

**Responsibilities**:
- **Transaction lifecycle** management
- **Atomic operation** execution
- **Progress tracking** and reporting
- **Rollback** and error recovery
- **Client communication** during operations
- **Resource locking** and cleanup

#### **Security and Privilege Management**
```cpp
// From rpmostreed-sysroot.cxx - Security integration
static gboolean
rpmostreed_sysroot_check_authorization (RpmostreedSysroot *self, 
                                         GDBusMethodInvocation *invocation,
                                         const char *action)
{
  // Get client credentials
  g_autoptr (GCredentials) credentials = g_dbus_method_invocation_get_credentials (invocation);
  if (!credentials)
    return FALSE;
  
  // Check PolicyKit authorization
  g_autoptr (GError) local_error = NULL;
  g_autoptr (PolkitAuthorizationResult) result = polkit_authority_check_authorization_sync (
    self->authority, credentials, action, NULL, 
    POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &local_error);
  
  if (!result) {
    g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
                                           "Failed to check authorization: %s", 
                                           local_error ? local_error->message : "unknown error");
    return FALSE;
  }
  
  if (!polkit_authorization_result_get_is_authorized (result)) {
    g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED,
                                           "Not authorized for action: %s", action);
    return FALSE;
  }
  
  return TRUE;
}
```

**Responsibilities**:
- **PolicyKit integration** and authorization
- **Privilege escalation** management
- **Access control** and security policies
- **Audit logging** and security events
- **Client credential** validation
- **Operation permission** checking

## 🔄 **Communication Patterns**

### **1. DBus Interface Structure**
```
org.projectatomic.rpmostree1
├── /org/projectatomic/rpmostree1/Sysroot
│   ├── Properties
│   │   ├── Booted (s)
│   │   ├── Path (s)
│   │   ├── ActiveTransaction (o)
│   │   └── Locked (b)
│   ├── Methods
│   │   ├── GetOS (s) → o
│   │   ├── RegisterClient (sa{sv}) → ()
│   │   ├── UnregisterClient (s) → ()
│   │   ├── Reload () → ()
│   │   └── ReloadConfig () → ()
│   └── Signals
│       └── Changed ()
└── /org/projectatomic/rpmostree1/OS/{osname}
    ├── Properties
    │   ├── Version (s)
    │   ├── Origin (s)
    │   ├── Packages (a(sss))
    │   └── RequestedPackages (as)
    ├── Methods
    │   ├── PkgChange (sa{sv}) → o
    │   ├── Deploy (s) → o
    │   ├── Rebase (s) → o
    │   ├── Upgrade (sa{sv}) → o
    │   ├── Rollback () → o
    │   ├── Cleanup () → o
    │   ├── SetKargs (asasas) → ()
    │   └── GetKargs () → as
    └── Signals
        └── Changed ()
```

### **2. Signal Flow Patterns**
```
Daemon Event → DBus Signal → Client Handler → User Display
```

**Signal Types**:
- **`Message`**: Text messages and status updates
- **`TaskBegin`/`TaskEnd`**: Task start/completion notifications
- **`PercentProgress`**: Progress percentage updates
- **`DownloadProgress`**: Download progress details
- **`Finished`**: Transaction completion notification
- **`Changed`**: System state change notifications

### **3. Method Invocation Patterns**
```
Client Request → DBus Method → Daemon Handler → Operation Execution → Response
```

**Method Flow**:
1. **Client invokes** DBus method on daemon interface
2. **Daemon receives** method call and validates parameters
3. **Authorization check** performed via PolicyKit
4. **Operation executed** with progress reporting
5. **Response sent** back to client with results
6. **Signals emitted** for progress and completion

## 📊 **Responsibility Matrix**

| Responsibility | CLI (rpm-ostree) | Daemon (rpm-ostreed) | Notes |
|----------------|-------------------|----------------------|-------|
| **Command Parsing** | ✅ Primary | ❌ None | CLI handles all user input |
| **Argument Validation** | ✅ Primary | ❌ None | CLI validates before sending |
| **DBus Communication** | ✅ Client | ✅ Server | Both sides of communication |
| **OSTree Operations** | ❌ None | ✅ Primary | Daemon handles all OSTree errors |
| **Package Management** | ❌ None | ✅ Primary | Daemon handles RPM/OSTree |
| **Transaction Management** | ❌ None | ✅ Primary | Daemon manages lifecycle |
| **Progress Reporting** | ✅ Display | ✅ Generation | Daemon generates, CLI displays |
| **Error Handling** | ✅ User-facing | ✅ System-level | Different error contexts |
| **Security** | ❌ None | ✅ Primary | Daemon handles authorization |
| **Configuration** | ✅ Reading | ✅ Reading/Writing | Daemon can modify system |
| **Fallback Operations** | ✅ Primary | ❌ None | CLI handles when daemon unavailable |
| **System State** | ❌ None | ✅ Primary | Daemon monitors and manages |
| **Resource Locking** | ❌ None | ✅ Primary | Daemon locks sysroot |
| **Rollback Operations** | ❌ None | ✅ Primary | Daemon manages rollback |

## 🚀 **apt-ostree Implementation Strategy**

### **1. CLI Client (`apt-ostree`)**

#### **Core Responsibilities**
```rust
// src/main.rs - CLI entry point
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = env::args().collect();
    
    match args.get(1).map(|s| s.as_str()) {
        Some("status") => show_system_status().await?,
        Some("install") => install_packages(&args[2..]).await?,
        Some("upgrade") => upgrade_system().await?,
        Some("rollback") => rollback_system().await?,
        Some("--help") | Some("-h") => show_usage(),
        Some("--version") | Some("-V") => show_version(),
        _ => {
            eprintln!("Unknown command. Use --help for usage information.");
            std::process::exit(1);
        }
    }
    
    Ok(())
}

// Command implementation with daemon fallback
async fn install_packages(packages: &[String]) -> Result<(), Error> {
    // Try daemon first
    if let Ok(client) = AptOstreeClient::new().await {
        let transaction_id = client.create_transaction().await?;
        let success = client.install_packages(&transaction_id, packages.to_vec()).await?;
        
        if success {
            println!("✅ Packages installed successfully!");
        } else {
            println!("❌ Package installation failed");
        }
    } else {
        // Fallback to direct operations (limited functionality)
        println!("⚠️  Daemon unavailable, using limited fallback mode");
        install_packages_direct(packages).await?;
    }
    
    Ok(())
}
```

#### **DBus Client Integration**
```rust
// src/client/dbus.rs - DBus client implementation
pub struct AptOstreeClient {
    connection: zbus::Connection,
    sysroot_proxy: zbus::Proxy<'static>,
}

impl AptOstreeClient {
    pub async fn new() -> Result<Self, Error> {
        let connection = zbus::Connection::system().await?;
        
        let sysroot_proxy = zbus::Proxy::new(
            &connection,
            "org.projectatomic.aptostree1",
            "/org/projectatomic/aptostree1/Sysroot",
            "org.projectatomic.aptostree1.Sysroot",
        ).await?;
        
        Ok(Self { connection, sysroot_proxy })
    }
    
    pub async fn create_transaction(&self) -> Result<String, Error> {
        let transaction_id = self.sysroot_proxy
            .call_method("CreateTransaction", &())
            .await?;
        
        Ok(transaction_id.body::<String>()?)
    }
    
    pub async fn install_packages(&self, transaction_id: &str, packages: Vec<String>) -> Result<bool, Error> {
        let success = self.sysroot_proxy
            .call_method("InstallPackages", &(transaction_id, packages))
            .await?;
        
        Ok(success.body::<bool>()?)
    }
}
```

### **2. Daemon (`apt-ostreed`)**

#### **Core Responsibilities**
```rust
// daemon/src/main.rs - Daemon entry point
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    tracing_subscriber::fmt::init();
    
    // Create daemon instance
    let daemon = Arc::new(AptOstreeDaemon::new()?);
    
    // Set up DBus connection
    let _connection = ConnectionBuilder::system()?
        .name("org.projectatomic.aptostree1")?
        .serve_at("/org/projectatomic/aptostree1/Sysroot", daemon.clone())?
        .serve_at("/org/projectatomic/aptostree1/OS/debian", daemon.clone())?
        .build()
        .await?;
    
    // Keep daemon running
    loop {
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    }
}

// DBus interface implementation
#[dbus_interface(name = "org.projectatomic.aptostree1.Sysroot")]
impl AptOstreeDaemon {
    async fn create_transaction(&self) -> zbus::fdo::Result<String> {
        let transaction = Transaction::new(
            self.get_user_id().await?,
            self.get_session_id().await?,
            "Package installation".to_string(),
            "apt-ostree CLI".to_string(),
        );
        
        let transaction_id = transaction.id.clone();
        self.transactions.write().await.insert(transaction_id.clone(), transaction);
        
        Ok(transaction_id)
    }
    
    async fn install_packages(&self, transaction_id: &str, packages: Vec<String>) -> zbus::fdo::Result<bool> {
        // Check authorization
        if !self.security_manager.check_package_operation(self.get_user_id().await?).await? {
            return Err(zbus::fdo::Error::PermissionDenied("Not authorized".into()));
        }
        
        // Create and execute transaction
        let mut transaction = self.get_transaction(transaction_id).await?;
        transaction.add_operation(Operation::InstallPackage { packages });
        
        match transaction.execute(self).await {
            Ok(()) => Ok(true),
            Err(_) => Ok(false),
        }
    }
}
```

### **3. Integration Points**

#### **Progress Reporting**
```rust
// daemon/src/transaction.rs - Progress emission
impl Transaction {
    pub async fn emit_progress(&self, operation: &Operation, progress: u32, message: &str) {
        // Emit DBus signal for progress
        if let Some(daemon) = &self.daemon {
            daemon.emit_signal(
                "org.projectatomic.aptostree1.Transaction",
                "PercentProgress",
                &(message, progress),
            ).ok();
        }
    }
}

// CLI progress handling
impl AptOstreeClient {
    pub async fn monitor_progress(&self, transaction_id: &str) -> Result<(), Error> {
        let mut stream = self.connection
            .receive_signal_with_args(
                "org.projectatomic.aptostree1.Transaction",
                "PercentProgress",
                &[("transaction_id", transaction_id)],
            ).await?;
        
        while let Some(msg) = stream.next().await {
            let (message, progress): (String, u32) = msg.body()?;
            println!("[{}%] {}", progress, message);
        }
        
        Ok(())
    }
}
```

## 🎯 **Key Implementation Principles**

### **1. Clear Separation of Concerns**
- **CLI**: User interface, command parsing, progress display
- **Daemon**: System operations, OSTree management, security

### **2. Graceful Degradation**
- **Primary mode**: Full functionality via daemon
- **Fallback mode**: Limited functionality when daemon unavailable

### **3. Security by Design**
- **Privilege isolation**: Daemon handles privileged operations
- **Authorization**: PolicyKit integration for all system changes
- **Sandboxing**: Package script execution in controlled environment

### **4. Transaction Safety**
- **Atomic operations**: All changes are atomic
- **Rollback support**: Automatic rollback on failure
- **Progress tracking**: Real-time operation monitoring

### **5. Performance Optimization**
- **Caching**: Intelligent caching of deployment and package information
- **Parallel operations**: Concurrent package processing where possible
- **Resource management**: Efficient memory and disk usage

This CLI-daemon separation analysis provides the foundation for implementing a production-ready apt-ostree system that maintains the proven architecture of rpm-ostree while adapting to the Debian/Ubuntu package management paradigm. The clear separation of responsibilities ensures maintainability, security, and scalability.
