# 🔌 **apt-ostree DBus API Reference**

## 🎯 **Overview**

This document provides a complete reference for the apt-ostree DBus API, including all interfaces, methods, signals, and data types. The API enables communication between the CLI client and the aptostreed daemon, following the same patterns as rpm-ostree.

## 🏗️ **DBus Architecture**

### **Service Information**
- **Service Name**: `org.projectatomic.aptostree1`
- **Object Path**: `/org/projectatomic/aptostree1`
- **Interface**: `org.projectatomic.aptostree1`
- **Bus Type**: System bus (privileged operations)

### **Connection Details**
```bash
# Connect to DBus service
busctl --system call org.projectatomic.aptostree1 \
    /org/projectatomic/aptostree1 \
    org.freedesktop.DBus.Properties \
    Get org.projectatomic.aptostree1 Version

# List available methods
busctl --system introspect org.projectatomic.aptostree1 \
    /org/projectatomic/aptostree1 \
    org.projectatomic.aptostree1
```

## 📋 **Core Interfaces**

### **Main Interface: `org.projectatomic.aptostree1`**

#### **Properties**
```xml
<!-- org.projectatomic.aptostree1.xml -->
<interface name="org.projectatomic.aptostree1">
    <property name="Version" type="s" access="read"/>
    <property name="Status" type="s" access="read"/>
    <property name="ActiveTransaction" type="s" access="read"/>
    <property name="LastOperation" type="s" access="read"/>
    <property name="LastOperationTime" type="t" access="read"/>
</interface>
```

#### **Methods**
```xml
<!-- System Status Methods -->
<method name="GetStatus">
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="status" type="a{sv}" direction="out"/>
</method>

<method name="GetDeployments">
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="deployments" type="a{sv}" direction="out"/>
</method>

<method name="GetSystemInfo">
    <arg name="info" type="a{sv}" direction="out"/>
</method>

<!-- Package Management Methods -->
<method name="InstallPackages">
    <arg name="transaction_id" type="s" direction="in"/>
    <arg name="packages" type="as" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="UninstallPackages">
    <arg name="transaction_id" type="s" direction="in"/>
    <arg name="packages" type="as" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="UpgradeSystem">
    <arg name="transaction_id" type="s" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<!-- Transaction Management Methods -->
<method name="CreateTransaction">
    <arg name="transaction_type" type="s" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="transaction_id" type="s" direction="out"/>
</method>

<method name="CommitTransaction">
    <arg name="transaction_id" type="s" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="CancelTransaction">
    <arg name="transaction_id" type="s" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<!-- Package Override Methods -->
<method name="OverridePackage">
    <arg name="package" type="s" direction="in"/>
    <arg name="version" type="s" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="ResetPackageOverride">
    <arg name="package" type="s" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="ListPackageOverrides">
    <arg name="overrides" type="a{sv}" direction="out"/>
</method>

<!-- User Overlay Methods -->
<method name="ApplyUserOverlay">
    <arg name="name" type="s" direction="in"/>
    <arg name="source" type="s" direction="in"/>
    <arg name="target" type="s" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="RemoveUserOverlay">
    <arg name="name" type="s" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="ListUserOverlays">
    <arg name="overlays" type="a{sv}" direction="out"/>
</method>

<!-- Live Update Methods -->
<method name="ApplyLiveUpdate">
    <arg name="deployment" type="s" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="GetLiveUpdateStatus">
    <arg name="status" type="a{sv}" direction="out"/>
</method>

<!-- Boot Management Methods -->
<method name="RegenerateInitramfs">
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="SetKernelArgs">
    <arg name="args" type="as" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
</method>

<method name="GetKernelArgs">
    <arg name="args" type="as" direction="out"/>
</method>
</interface>
```

#### **Signals**
```xml
<!-- Progress and Status Signals -->
<signal name="TransactionProgress">
    <arg name="transaction_id" type="s"/>
    <arg name="progress" type="u"/>
    <arg name="message" type="s"/>
</signal>

<signal name="TransactionCompleted">
    <arg name="transaction_id" type="s"/>
    <arg name="success" type="b"/>
    <arg name="message" type="s"/>
</signal>

<signal name="SystemStatusChanged">
    <arg name="status" type="s"/>
    <arg name="details" type="a{sv}"/>
</signal>

<signal name="PackageStatusChanged">
    <arg name="package" type="s"/>
    <arg name="status" type="s"/>
    <arg name="details" type="a{sv}"/>
</signal>
```

## 🔧 **Transaction Management Interface**

### **Transaction Types**
```rust
// Transaction type definitions
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TransactionType {
    PackageInstall,
    PackageUninstall,
    SystemUpgrade,
    PackageOverride,
    UserOverlay,
    LiveUpdate,
    BootManagement,
    Custom(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransactionOptions {
    pub timeout: Option<u64>,
    pub force: bool,
    pub dry_run: bool,
    pub reboot_after: bool,
    pub user_id: Option<u32>,
    pub session_id: Option<String>,
}
```

### **Transaction States**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TransactionState {
    Created,
    Running,
    Completed,
    Failed,
    Cancelled,
    RollingBack,
    RolledBack,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransactionInfo {
    pub id: String,
    pub transaction_type: TransactionType,
    pub state: TransactionState,
    pub created_at: u64,
    pub started_at: Option<u64>,
    pub completed_at: Option<u64>,
    pub progress: u32,
    pub message: String,
    pub options: TransactionOptions,
    pub result: Option<TransactionResult>,
}
```

## 📦 **Package Management Interface**

### **Package Information**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PackageInfo {
    pub name: String,
    pub version: String,
    pub architecture: String,
    pub description: Option<String>,
    pub depends: Vec<String>,
    pub recommends: Vec<String>,
    pub suggests: Vec<String>,
    pub conflicts: Vec<String>,
    pub installed_size: u64,
    pub maintainer: Option<String>,
    pub section: Option<String>,
    pub priority: Option<String>,
    pub source: Option<String>,
    pub installed: bool,
    pub status: PackageStatus,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PackageStatus {
    NotInstalled,
    Installed,
    Upgradable,
    Broken,
    Hold,
    PendingInstall,
    PendingRemove,
    PendingUpgrade,
}
```

### **Package Operations**
```rust
// Package installation options
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstallOptions {
    pub version: Option<String>,
    pub force: bool,
    pub allow_downgrade: bool,
    pub allow_remove_essential: bool,
    pub allow_unauthenticated: bool,
    pub install_recommends: bool,
    pub install_suggests: bool,
    pub user_id: Option<u32>,
    pub session_id: Option<String>,
}

// Package search and query options
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryOptions {
    pub installed_only: bool,
    pub upgradable_only: bool,
    pub search_pattern: Option<String>,
    pub architecture: Option<String>,
    pub section: Option<String>,
    pub priority: Option<String>,
}
```

## 🌳 **OSTree Management Interface**

### **Deployment Information**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentInfo {
    pub id: String,
    pub osname: String,
    pub ref: String,
    pub checksum: String,
    pub version: String,
    pub timestamp: u64,
    pub booted: bool,
    pub staged: bool,
    pub pending: bool,
    pub rollback: bool,
    pub origin: String,
    pub packages: Vec<PackageInfo>,
    pub kernel_args: Vec<String>,
    pub initramfs: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OSTreeStatus {
    pub deployments: Vec<DeploymentInfo>,
    pub booted_deployment: Option<String>,
    pub staged_deployment: Option<String>,
    pub pending_deployment: Option<String>,
    pub repository_status: RepositoryStatus,
    pub system_status: SystemStatus,
}
```

### **Repository Operations**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepositoryStatus {
    pub path: String,
    pub mode: String,
    pub compression: String,
    pub refs: Vec<String>,
    pub commits: u64,
    pub objects: u64,
    pub size: u64,
    pub free_space: u64,
    pub healthy: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitInfo {
    pub checksum: String,
    pub subject: String,
    pub body: Option<String>,
    pub author: String,
    pub timestamp: u64,
    pub parent: Option<String>,
    pub tree: String,
    pub metadata: HashMap<String, String>,
}
```

## 🔒 **Security and Authorization Interface**

### **Polkit Integration**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorizationRequest {
    pub action: String,
    pub user_id: u32,
    pub session_id: Option<String>,
    pub details: HashMap<String, String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorizationResult {
    pub authorized: bool,
    pub details: Option<String>,
    pub expires_at: Option<u64>,
    pub challenge: Option<String>,
}

// Authorization actions
pub const ACTIONS: &[&str] = &[
    "org.projectatomic.aptostree.status",
    "org.projectatomic.aptostree.upgrade",
    "org.projectatomic.aptostree.install",
    "org.projectatomic.aptostree.uninstall",
    "org.projectatomic.aptostree.override",
    "org.projectatomic.aptostree.usroverlay",
    "org.projectatomic.aptostree.live-update",
    "org.projectatomic.aptostree.boot-management",
];
```

### **User and Session Management**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserInfo {
    pub user_id: u32,
    pub username: String,
    pub groups: Vec<String>,
    pub home_directory: String,
    pub shell: String,
    pub authorized_actions: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionInfo {
    pub session_id: String,
    pub user_id: u32,
    pub service: String,
    pub type_: String,
    pub state: String,
    pub created_at: u64,
    pub last_activity: u64,
}
```

## 📊 **Monitoring and Metrics Interface**

### **System Metrics**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemMetrics {
    pub cpu_usage: f64,
    pub memory_usage: u64,
    pub memory_total: u64,
    pub disk_usage: u64,
    pub disk_total: u64,
    pub network_rx: u64,
    pub network_tx: u64,
    pub uptime: u64,
    pub load_average: [f64; 3],
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApplicationMetrics {
    pub operations_total: u64,
    pub operations_failed: u64,
    pub active_connections: u32,
    pub package_installations: u64,
    pub package_removals: u64,
    pub system_upgrades: u64,
    pub average_response_time: f64,
    pub cache_hit_rate: f64,
}
```

### **Health Check Interface**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
    pub overall: HealthState,
    pub components: HashMap<String, ComponentHealth>,
    pub last_check: u64,
    pub next_check: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HealthState {
    Healthy,
    Degraded,
    Unhealthy,
    Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentHealth {
    pub state: HealthState,
    pub message: String,
    pub details: Option<String>,
    pub last_check: u64,
    pub error_count: u32,
}
```

## 🔌 **Client Implementation Examples**

### **Rust Client Example**
```rust
use zbus::{Connection, Proxy};
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize)]
pub struct AptOstreeClient {
    connection: Connection,
    proxy: Proxy<'static>,
}

impl AptOstreeClient {
    pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
        let connection = Connection::system().await?;
        let proxy = Proxy::new(
            &connection,
            "org.projectatomic.aptostree1",
            "/org/projectatomic/aptostree1",
            "org.projectatomic.aptostree1",
        ).await?;
        
        Ok(Self { connection, proxy })
    }
    
    pub async fn get_status(&self) -> Result<OSTreeStatus, Box<dyn std::error::Error>> {
        let status: a{sv} = self.proxy.call_method("GetStatus", &()).await?;
        let status: OSTreeStatus = serde_json::from_value(status.into())?;
        Ok(status)
    }
    
    pub async fn install_packages(
        &self,
        transaction_id: &str,
        packages: &[String],
        options: &InstallOptions,
    ) -> Result<bool, Box<dyn std::error::Error>> {
        let result: bool = self.proxy.call_method(
            "InstallPackages",
            &(transaction_id, packages, options),
        ).await?;
        Ok(result)
    }
    
    pub async fn create_transaction(
        &self,
        transaction_type: &str,
        options: &TransactionOptions,
    ) -> Result<String, Box<dyn std::error::Error>> {
        let transaction_id: String = self.proxy.call_method(
            "CreateTransaction",
            &(transaction_type, options),
        ).await?;
        Ok(transaction_id)
    }
}
```

### **Python Client Example**
```python
import dbus
import json
from typing import Dict, List, Optional

class AptOstreeClient:
    def __init__(self):
        self.bus = dbus.SystemBus()
        self.proxy = self.bus.get_object(
            'org.projectatomic.aptostree1',
            '/org/projectatomic/aptostree1'
        )
        self.interface = dbus.Interface(
            self.proxy,
            'org.projectatomic.aptostree1'
        )
    
    def get_status(self) -> Dict:
        """Get system status"""
        result = self.interface.GetStatus({})
        return json.loads(result)
    
    def install_packages(
        self,
        transaction_id: str,
        packages: List[str],
        options: Dict
    ) -> bool:
        """Install packages"""
        result = self.interface.InstallPackages(
            transaction_id,
            packages,
            options
        )
        return bool(result)
    
    def create_transaction(
        self,
        transaction_type: str,
        options: Dict
    ) -> str:
        """Create a new transaction"""
        transaction_id = self.interface.CreateTransaction(
            transaction_type,
            options
        )
        return str(transaction_id)
    
    def get_deployments(self) -> List[Dict]:
        """Get list of deployments"""
        result = self.interface.GetDeployments({})
        return json.loads(result)

# Usage example
if __name__ == "__main__":
    client = AptOstreeClient()
    
    # Get system status
    status = client.get_status()
    print(f"System status: {status}")
    
    # Create transaction and install package
    transaction_id = client.create_transaction("PackageInstall", {})
    success = client.install_packages(transaction_id, ["vim"], {})
    print(f"Installation successful: {success}")
```

### **Shell Script Example**
```bash
#!/bin/bash

# apt-ostree DBus client script

DBUS_SERVICE="org.projectatomic.aptostree1"
DBUS_OBJECT="/org/projectatomic/aptostree1"
DBUS_INTERFACE="org.projectatomic.aptostree1"

# Function to call DBus method
call_dbus_method() {
    local method="$1"
    shift
    busctl --system call "$DBUS_SERVICE" "$DBUS_OBJECT" "$DBUS_INTERFACE" "$method" "$@"
}

# Function to get property
get_property() {
    local property="$1"
    busctl --system get-property "$DBUS_SERVICE" "$DBUS_OBJECT" "$DBUS_INTERFACE" "$property"
}

# Get system status
get_status() {
    echo "Getting system status..."
    call_dbus_method "GetStatus" '{}'
}

# Get deployments
get_deployments() {
    echo "Getting deployments..."
    call_dbus_method "GetDeployments" '{}'
}

# Install packages
install_packages() {
    local packages="$1"
    local transaction_id
    
    echo "Creating transaction..."
    transaction_id=$(call_dbus_method "CreateTransaction" 's' "PackageInstall" '{}')
    transaction_id=$(echo "$transaction_id" | sed 's/"//g')
    
    echo "Installing packages: $packages"
    call_dbus_method "InstallPackages" 's' "$transaction_id" 'as' "$packages" '{}'
    
    echo "Committing transaction..."
    call_dbus_method "CommitTransaction" 's' "$transaction_id"
}

# Main script
case "$1" in
    "status")
        get_status
        ;;
    "deployments")
        get_deployments
        ;;
    "install")
        if [ -z "$2" ]; then
            echo "Usage: $0 install <package1> [package2] ..."
            exit 1
        fi
        shift
        install_packages "$@"
        ;;
    *)
        echo "Usage: $0 {status|deployments|install}"
        exit 1
        ;;
esac
```

## 📝 **Error Handling**

### **Error Types**
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AptOstreeError {
    // System errors
    SystemError(String),
    PermissionDenied(String),
    ResourceNotFound(String),
    ResourceBusy(String),
    
    // Package errors
    PackageNotFound(String),
    PackageConflict(String),
    DependencyError(String),
    InstallationFailed(String),
    
    // OSTree errors
    OSTreeError(String),
    RepositoryError(String),
    DeploymentError(String),
    CommitError(String),
    
    // Transaction errors
    TransactionNotFound(String),
    TransactionFailed(String),
    TransactionTimeout(String),
    
    // Security errors
    AuthorizationFailed(String),
    InvalidCredentials(String),
    PolicyViolation(String),
    
    // Network errors
    NetworkError(String),
    TimeoutError(String),
    ConnectionError(String),
}

impl std::fmt::Display for AptOstreeError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AptOstreeError::SystemError(msg) => write!(f, "System error: {}", msg),
            AptOstreeError::PermissionDenied(msg) => write!(f, "Permission denied: {}", msg),
            AptOstreeError::PackageNotFound(pkg) => write!(f, "Package not found: {}", pkg),
            AptOstreeError::OSTreeError(msg) => write!(f, "OSTree error: {}", msg),
            AptOstreeError::TransactionFailed(msg) => write!(f, "Transaction failed: {}", msg),
            AptOstreeError::AuthorizationFailed(msg) => write!(f, "Authorization failed: {}", msg),
            _ => write!(f, "Unknown error: {:?}", self),
        }
    }
}
```

### **Error Response Format**
```xml
<!-- Error response structure -->
<method name="InstallPackages">
    <arg name="transaction_id" type="s" direction="in"/>
    <arg name="packages" type="as" direction="in"/>
    <arg name="options" type="a{sv}" direction="in"/>
    <arg name="result" type="b" direction="out"/>
    <annotation name="org.freedesktop.DBus.GLib.Error" value="AptOstreeError"/>
</method>
```

## 🔄 **Event Handling**

### **Signal Handling**
```rust
use zbus::{Connection, SignalReceiver};
use futures_util::StreamExt;

pub async fn handle_signals(connection: Connection) -> Result<(), Box<dyn std::error::Error>> {
    let receiver = SignalReceiver::new(connection, "org.projectatomic.aptostree1").await?;
    
    while let Some(signal) = receiver.next().await {
        match signal.member_name().as_str() {
            "TransactionProgress" => {
                let (transaction_id, progress, message) = signal.body().deserialize()?;
                println!("Transaction {}: {}% - {}", transaction_id, progress, message);
            }
            "TransactionCompleted" => {
                let (transaction_id, success, message) = signal.body().deserialize()?;
                println!("Transaction {} completed: {} - {}", 
                    transaction_id, if success { "SUCCESS" } else { "FAILED" }, message);
            }
            "SystemStatusChanged" => {
                let (status, details) = signal.body().deserialize()?;
                println!("System status changed: {} - {:?}", status, details);
            }
            _ => {
                println!("Unknown signal: {:?}", signal);
            }
        }
    }
    
    Ok(())
}
```

## 🎯 **Next Steps**

### **Immediate Actions**
1. **Implement core DBus interface** in the daemon
2. **Create client libraries** for Rust, Python, and shell
3. **Set up signal handling** for real-time updates
4. **Implement error handling** and response formatting

### **Short-term Goals**
1. **Complete all interface methods** with proper implementations
2. **Add comprehensive error handling** and validation
3. **Implement security and authorization** checks
4. **Add monitoring and metrics** endpoints

### **Long-term Vision**
1. **Performance optimization** and connection pooling
2. **Advanced event handling** and filtering
3. **Multi-language client** support
4. **Integration with** system monitoring tools

---

*This DBus API reference provides comprehensive coverage of all interfaces and methods for apt-ostree. For detailed implementation information, refer to the architecture documents in the `docs/apt-ostree-daemon-plan/architecture/` directory.*
