# apt-ostree D-Bus Interface

## Executive Summary

apt-ostree implements the same D-Bus interface as rpm-ostree, providing 100% compatibility while adapting the underlying functionality to the APT/DEB ecosystem. The D-Bus interface enables secure, reliable communication between unprivileged clients and the privileged daemon.

## D-Bus Architecture

### Service Overview

**Service Name**: `org.aptostree.dev`

**Purpose**: Provide system management interface for apt-ostree operations

**Architecture**:
```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   CLI Client    │    │   GUI Client    │    │   API Client    │
│  (apt-ostree)   │    │  (GNOME/KDE)    │    │  (Python/Go)   │
└─────────┬───────┘    └─────────┬───────┘    └─────────┬───────┘
          │                      │                      │
          └──────────────────────┼──────────────────────┘
                                 │
                    ┌─────────────▼─────────────┐
                    │      D-Bus Interface      │
                    │   (org.aptostree.dev)     │
                    └─────────────┬─────────────┘
                                  │
                    ┌─────────────▼─────────────┐
                    │   apt-ostreed Daemon      │
                    │   (Privileged Service)    │
                    └───────────────────────────┘
```

### Design Principles

1. **100% Compatibility**: Identical interface to rpm-ostree
2. **Standard Interface**: Use standard D-Bus conventions and patterns
3. **Type Safety**: Strong typing for all method parameters and return values
4. **Error Handling**: Comprehensive error reporting and propagation
5. **Progress Reporting**: Real-time progress updates via signals
6. **Transaction Management**: Transaction-based operations with rollback support
7. **OSTree Detection**: Environment validation before operations

## Interface Definition

### Main Objects

#### `/org/aptostree/dev/Sysroot`

**Purpose**: System root management and deployment operations

**Interface**: `org.aptostree.dev.Sysroot`

#### `/org/aptostree/dev/OS`

**Purpose**: Operating system operations and package management

**Interface**: `org.aptostree.dev.OS`

### Interface XML Definition

```xml
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="org.aptostree.dev.Sysroot">
    <method name="GetDeployments">
      <arg name="deployments" type="a(sa{sv})" direction="out"/>
    </method>
    
    <method name="GetBootedDeployment">
      <arg name="deployment" type="(sa{sv})" direction="out"/>
    </method>
    
    <method name="GetPendingDeployment">
      <arg name="deployment" type="(sa{sv})" direction="out"/>
    </method>
    
    <method name="GetDeploymentState">
      <arg name="deployment" type="s" direction="in"/>
      <arg name="state" type="s" direction="out"/>
    </method>
  </interface>
  
  <interface name="org.aptostree.dev.OS">
    <method name="install_packages">
      <arg name="packages" type="as" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="remove_packages">
      <arg name="packages" type="as" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="upgrade_system">
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="rollback">
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="deploy">
      <arg name="ref" type="s" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="rebase">
      <arg name="ref" type="s" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="kargs">
      <arg name="operation" type="s" direction="in"/>
      <arg name="args" type="as" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="cleanup">
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="transaction_address" type="s" direction="out"/>
    </method>
    
    <method name="show_status">
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="status" type="s" direction="out"/>
    </method>
    
    <method name="list_packages">
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="packages" type="as" direction="out"/>
    </method>
    
    <method name="search_packages">
      <arg name="query" type="s" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
      <arg name="results" type="as" direction="out"/>
    </method>
    
    <method name="show_package_info">
      <arg name="package" type="s" direction="in"/>
      <arg name="info" type="s" direction="out"/>
    </method>
    
    <signal name="TransactionChanged">
      <arg name="transaction_address" type="s"/>
      <arg name="state" type="s"/>
      <arg name="message" type="s"/>
      <arg name="percentage" type="i"/>
    </signal>
    
    <signal name="TransactionCompleted">
      <arg name="transaction_address" type="s"/>
      <arg name="success" type="b"/>
      <arg name="result" type="s"/>
    </signal>
    
    <signal name="StatusChanged">
      <arg name="status" type="s"/>
    </signal>
  </interface>
</node>
```

## Method Details

### Sysroot Methods

#### GetDeployments

**Purpose**: Get list of available deployments

**Parameters**: None

**Returns**: Array of deployment information

**Example**:
```rust
// Client call
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/Sysroot",
    Some("org.aptostree.dev.Sysroot"),
    "GetDeployments",
    &(),
)?;

// Parse result
let deployments: Vec<(String, HashMap<String, Variant>)> = result.body()?;
```

#### GetBootedDeployment

**Purpose**: Get information about the currently booted deployment

**Parameters**: None

**Returns**: Deployment information for booted deployment

**Example**:
```rust
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/Sysroot",
    Some("org.aptostree.dev.Sysroot"),
    "GetBootedDeployment",
    &(),
)?;
```

#### GetPendingDeployment

**Purpose**: Get information about the pending deployment

**Parameters**: None

**Returns**: Deployment information for pending deployment

### OS Methods

#### install_packages

**Purpose**: Install packages with atomic commits

**Parameters**:
- `packages`: Array of package names
- `options`: Dictionary of installation options

**Options**:
- `reboot`: Boolean - Automatically reboot after installation
- `allow-inactive`: Boolean - Allow installing on inactive deployment
- `idempotent`: Boolean - Don't error if packages already installed

**Returns**: Transaction address for tracking operation

**Example**:
```rust
// Prepare packages array
let packages = vec!["vim".to_string(), "git".to_string()];

// Prepare options
let mut options = HashMap::new();
options.insert("reboot".to_string(), Variant::from(false));

// Call method
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "install_packages",
    &(packages, options),
)?;

// Get transaction address
let transaction_address: String = result.body()?;
```

#### remove_packages

**Purpose**: Remove packages with rollback support

**Parameters**:
- `packages`: Array of package names
- `options`: Dictionary of removal options

**Options**:
- `reboot`: Boolean - Automatically reboot after removal
- `idempotent`: Boolean - Don't error if packages not installed

**Returns**: Transaction address for tracking operation

#### upgrade_system

**Purpose**: Upgrade system with automatic policies

**Parameters**:
- `options`: Dictionary of upgrade options

**Options**:
- `reboot`: Boolean - Automatically reboot after upgrade
- `download-only`: Boolean - Download updates without installing
- `allow-downgrade`: Boolean - Allow downgrading packages
- `unchanged-exit-77`: Boolean - Exit with 77 if no changes

**Returns**: Transaction address for tracking operation

**Example**:
```rust
// Prepare options
let mut options = HashMap::new();
options.insert("reboot".to_string(), Variant::from(true));
options.insert("download-only".to_string(), Variant::from(false));

// Call method
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "upgrade_system",
    &(options,),
)?;

// Get transaction address
let transaction_address: String = result.body()?;
```

#### rollback

**Purpose**: Rollback to previous deployment

**Parameters**:
- `options`: Dictionary of rollback options

**Options**:
- `reboot`: Boolean - Automatically reboot after rollback
- `not-as-default`: Boolean - Don't set as default boot option

**Returns**: Transaction address for tracking operation

#### deploy

**Purpose**: Deploy specific version or commit

**Parameters**:
- `ref`: Deployment reference (version or commit hash)
- `options`: Dictionary of deployment options

**Options**:
- `reboot`: Boolean - Automatically reboot after deployment
- `not-as-default`: Boolean - Don't set as default boot option
- `os`: String - Specify operating system name

**Returns**: Transaction address for tracking operation

#### rebase

**Purpose**: Switch to different base image

**Parameters**:
- `ref`: Base image reference
- `options`: Dictionary of rebase options

**Options**:
- `reboot`: Boolean - Automatically reboot after rebase
- `os`: String - Specify operating system name

**Returns**: Transaction address for tracking operation

#### kargs

**Purpose**: Manage kernel arguments

**Parameters**:
- `operation`: Operation type ("append", "delete", "replace", "show")
- `args`: Array of kernel arguments
- `options`: Dictionary of kernel argument options

**Options**:
- `reboot`: Boolean - Automatically reboot after changes

**Returns**: Transaction address for tracking operation

#### cleanup

**Purpose**: Clean up old deployments

**Parameters**:
- `options`: Dictionary of cleanup options

**Options**:
- `base`: Boolean - Clean up base images
- `repomd`: Boolean - Clean up repository metadata
- `rollback`: Boolean - Clean up rollback deployments

**Returns**: Transaction address for tracking operation

#### show_status

**Purpose**: Show system status and deployment information

**Parameters**:
- `options`: Dictionary of status options

**Options**:
- `json`: Boolean - Output in JSON format
- `booted`: Boolean - Show only booted deployment
- `pending`: Boolean - Show only pending deployment

**Returns**: Status string (JSON or text format)

**Example**:
```rust
// Prepare options
let mut options = HashMap::new();
options.insert("json".to_string(), Variant::from(false));

// Call method
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "show_status",
    &(options,),
)?;

// Get status
let status: String = result.body()?;
println!("Status: {}", status);
```

#### list_packages

**Purpose**: List installed packages

**Parameters**:
- `options`: Dictionary of list options

**Options**:
- `json`: Boolean - Output in JSON format

**Returns**: Array of package names

#### search_packages

**Purpose**: Search for packages

**Parameters**:
- `query`: Search query string
- `options`: Dictionary of search options

**Options**:
- `json`: Boolean - Output in JSON format
- `limit`: Integer - Limit number of results

**Returns**: Array of matching package names

**Example**:
```rust
// Prepare options
let mut options = HashMap::new();
options.insert("json".to_string(), Variant::from(false));
options.insert("limit".to_string(), Variant::from(10));

// Call method
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "search_packages",
    &("firefox", options),
)?;

// Get results
let results: Vec<String> = result.body()?;
for package in results {
    println!("Found package: {}", package);
}
```

#### show_package_info

**Purpose**: Show detailed package information

**Parameters**:
- `package`: Package name

**Returns**: JSON-formatted package information

**Example**:
```rust
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "show_package_info",
    &("vim",),
)?;

let info: String = result.body()?;
println!("Package info: {}", info);
```

## Signals

### TransactionChanged

**Purpose**: Report transaction state changes

**Parameters**:
- `transaction_address`: Transaction identifier
- `state`: Transaction state ("preparing", "downloading", "installing", "finalizing")
- `message`: Human-readable status message
- `percentage`: Progress percentage (0-100)

**Example**:
```rust
// Signal handler
fn handle_transaction_changed(
    msg: &Message,
    _: &Connection,
    _: &Message,
) -> Result<(), Box<dyn std::error::Error>> {
    let (transaction_address, state, message, percentage): (String, String, String, i32) = msg.body()?;
    
    println!("Transaction {}: {} - {} ({}%)", 
             transaction_address, state, message, percentage);
    Ok(())
}

// Subscribe to signal
connection.add_match(
    "type='signal',interface='org.aptostree.dev.OS',member='TransactionChanged'",
)?;

connection.add_signal_handler(
    "org.aptostree.dev.OS",
    "TransactionChanged",
    handle_transaction_changed,
)?;
```

### TransactionCompleted

**Purpose**: Report transaction completion

**Parameters**:
- `transaction_address`: Transaction identifier
- `success`: Boolean indicating success or failure
- `result`: Result message or error description

**Example**:
```rust
fn handle_transaction_completed(
    msg: &Message,
    _: &Connection,
    _: &Message,
) -> Result<(), Box<dyn std::error::Error>> {
    let (transaction_address, success, result): (String, bool, String) = msg.body()?;
    
    if success {
        println!("Transaction {} completed successfully: {}", transaction_address, result);
    } else {
        println!("Transaction {} failed: {}", transaction_address, result);
    }
    Ok(())
}
```

### StatusChanged

**Purpose**: Report system status changes

**Parameters**:
- `status`: New system status

## Transaction Management

### Transaction Lifecycle

1. **Initiation**: Client calls method, receives transaction address
2. **Progress**: Daemon emits TransactionChanged signals
3. **Completion**: Daemon emits TransactionCompleted signal
4. **Cleanup**: Transaction resources are cleaned up

### Transaction States

- **preparing**: Transaction is being prepared
- **downloading**: Packages are being downloaded via APT
- **installing**: Packages are being installed
- **finalizing**: Transaction is being finalized
- **completed**: Transaction completed successfully
- **failed**: Transaction failed

### Transaction Tracking

**Example**:
```rust
// Start transaction
let transaction_address: String = result.body()?;

// Subscribe to transaction signals
connection.add_match(
    "type='signal',interface='org.aptostree.dev.OS',member='TransactionChanged'",
)?;

connection.add_match(
    "type='signal',interface='org.aptostree.dev.OS',member='TransactionCompleted'",
)?;

connection.add_signal_handler(
    "org.aptostree.dev.OS",
    "TransactionChanged",
    handle_transaction_changed,
)?;

connection.add_signal_handler(
    "org.aptostree.dev.OS",
    "TransactionCompleted",
    handle_transaction_completed,
)?;
```

## Error Handling

### Error Types

1. **org.freedesktop.DBus.Error.ServiceUnknown**: Daemon service not available
2. **org.freedesktop.DBus.Error.NoReply**: Daemon not responding
3. **org.freedesktop.DBus.Error.Timeout**: Operation timed out
4. **org.freedesktop.DBus.Error.Failed**: General operation failure
5. **org.freedesktop.DBus.Error.InvalidArgs**: Invalid method arguments
6. **org.aptostree.dev.Error.OstreeEnvironment**: Non-OSTree system

### Error Handling Example

```rust
let result = connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "upgrade_system",
    &(options,),
);

match result {
    Ok(response) => {
        let transaction_address: String = response.body()?;
        println!("Upgrade started: {}", transaction_address);
    }
    Err(Error::MethodError(ref name, ref message, _)) => {
        match name.as_str() {
            "org.freedesktop.DBus.Error.ServiceUnknown" => {
                eprintln!("Daemon is not running. Using direct system calls.");
            }
            "org.aptostree.dev.Error.OstreeEnvironment" => {
                eprintln!("This system is not running on an OSTree deployment.");
            }
            _ => {
                eprintln!("Error: {} - {}", name, message);
            }
        }
    }
    Err(e) => {
        eprintln!("Unexpected error: {}", e);
    }
}
```

## Security

### Authentication

**PolicyKit Integration**:
```xml
<policyconfig>
    <action id="org.aptostree.dev.upgrade">
        <description>Upgrade system</description>
        <message>Authentication is required to upgrade the system</message>
        <defaults>
            <allow_any>auth_admin</allow_any>
            <allow_inactive>auth_admin</allow_inactive>
            <allow_active>auth_admin</allow_active>
        </defaults>
        <annotate key="org.freedesktop.policykit.exec.path">/usr/libexec/apt-ostreed</annotate>
    </action>
    
    <action id="org.aptostree.dev.install">
        <description>Install packages</description>
        <message>Authentication is required to install packages</message>
        <defaults>
            <allow_any>auth_admin</allow_any>
            <allow_inactive>auth_admin</allow_inactive>
            <allow_active>auth_admin</allow_active>
        </defaults>
        <annotate key="org.freedesktop.policykit.exec.path">/usr/libexec/apt-ostreed</annotate>
    </action>
</policyconfig>
```

### Access Control

- **System Bus**: D-Bus system bus for privileged operations
- **Service Activation**: Automatic service activation via systemd
- **User Permissions**: PolicyKit-based user permission management

## OSTree Environment Detection

### Detection Integration

apt-ostree integrates OSTree environment detection into the D-Bus interface:

**Error Handling**:
```rust
// Check OSTree environment before operations
if !ostree_detection.detect_ostree_environment()? {
    return Err(Error::MethodError(
        "org.aptostree.dev.Error.OstreeEnvironment".to_string(),
        "This system is not running on an OSTree deployment.".to_string(),
        None,
    ));
}
```

**Error Messages**:
```
Error: apt-ostree requires an OSTree environment to operate.

This system does not appear to be running on an OSTree deployment.

To use apt-ostree:
1. Ensure you are running on an OSTree-based system
2. Verify that /ostree directory exists
3. Verify that /run/ostree-booted file exists
4. Ensure you have a valid booted deployment
```

## Performance Considerations

### Connection Management

**Connection Pooling**:
```rust
// Reuse connections when possible
lazy_static! {
    static ref CONNECTION: Mutex<Option<Connection>> = Mutex::new(None);
}

fn get_connection() -> Result<Connection, Box<dyn std::error::Error>> {
    let mut conn_guard = CONNECTION.lock().unwrap();
    if conn_guard.is_none() {
        *conn_guard = Some(Connection::new_system_sync()?);
    }
    Ok(conn_guard.as_ref().unwrap().clone())
}
```

### Async Operations

**Non-blocking Calls**:
```rust
connection.call_method(
    Some("org.aptostree.dev"),
    "/org/aptostree/dev/OS",
    Some("org.aptostree.dev.OS"),
    "upgrade_system",
    &(options,),
)?.body::<String>()
    .map(|transaction_address| {
        println!("Upgrade started: {}", transaction_address);
    })
    .map_err(|e| {
        eprintln!("Error: {}", e);
    });
```

## Monitoring and Debugging

### D-Bus Monitoring

**Monitor D-Bus Traffic**:
```bash
# Monitor all D-Bus traffic
dbus-monitor --system

# Monitor specific service
dbus-monitor --system "destination='org.aptostree.dev'"
```

### Debugging Tools

**D-Bus Introspection**:
```bash
# Introspect service
gdbus introspect --system --dest org.aptostree.dev --object-path /org/aptostree/dev/OS
```

**D-Bus Call Testing**:
```bash
# Test method call
gdbus call --system --dest org.aptostree.dev --object-path /org/aptostree/dev/OS --method org.aptostree.dev.OS.show_status
```

## APT Integration

### APT-Specific Methods

**Package Management**:
- `install_packages`: Install packages via APT
- `remove_packages`: Remove packages via APT
- `upgrade_system`: Upgrade system via APT
- `list_packages`: List packages via APT database
- `search_packages`: Search packages via APT
- `show_package_info`: Show package info via APT

**APT Database Integration**:
```rust
// APT database operations in D-Bus methods
pub fn handle_install_packages(
    &self,
    packages: Vec<String>,
    options: HashMap<String, Variant>,
) -> Result<String, Box<dyn std::error::Error>> {
    // Initialize APT database
    let mut apt_manager = AptManager::new()?;
    
    // Install packages
    apt_manager.install_packages(&packages)?;
    
    // Create transaction
    let transaction_id = self.create_transaction("install")?;
    
    Ok(transaction_id)
}
```

## Future Enhancements

### Planned Features

1. **Event Streaming**: Real-time event streaming for status updates
2. **Batch Operations**: Support for batch operations
3. **Advanced Filtering**: Enhanced filtering and querying capabilities
4. **Performance Optimization**: Further performance improvements

### Interface Improvements

1. **Versioning**: Interface versioning for backward compatibility
2. **Extensions**: Extensible interface for custom operations
3. **Validation**: Enhanced parameter validation
4. **Documentation**: Improved interface documentation

### APT Enhancements

1. **Advanced Dependency Resolution**: Enhanced dependency handling
2. **Package Conflict Resolution**: Improved conflict resolution
3. **Repository Management**: Enhanced repository management
4. **Package Verification**: Enhanced package verification 