zinit 0.3.7

Process supervisor with dependency management
Documentation
//! # zinit - Process Supervisor with Dependency Management
//!
//! Zinit is a lightweight process supervisor with sophisticated dependency management.
//! It's designed to be simpler than systemd while providing the core features needed
//! for service management in containers, VMs, and bare-metal systems.
//!
//! ## Overview
//!
//! Zinit manages services through:
//! - **State Machine**: 7-state service lifecycle (Inactive, Blocked, Starting, Running, Stopping, Exited, Failed)
//! - **Dependency Graph**: Supports `after`, `requires`, `wants`, and `conflicts` dependencies
//! - **Service Classes**: `user` (bulk-controllable) and `system` (protected) services
//! - **JSON-RPC 2.0 API**: Unix socket IPC with 44 RPC methods
//! - **Health Checks**: TCP, HTTP, and exec-based health monitoring
//! - **Process Groups**: Proper signal handling for shell-wrapped processes
//! - **Hot Restart**: State persistence and process adoption on restart
//!
//! ## Architecture
//!
//! The crate is organized into modules:
//!
//! - [`sdk`] - Shared types, configuration, RPC protocol, and client libraries
//! - [`server`] - (with `server` feature) Main supervisor daemon
//! - [`client`] - (with `client` feature) CLI interface
//!
//! ## Features
//!
//! - `sdk` - Shared types and protocol (always included in lib)
//! - `client` - CLI client interface
//! - `tui` - Terminal UI for interactive client
//! - `repl` - Interactive REPL shell
//! - `async` - Async client support with tokio
//! - `server` - Supervisor daemon with full feature set
//! - `pid1` - PID 1 init process (Linux only)
//! - `full` - Everything: client + server + pid1 + tui + repl
//!
//! ## Quick Start
//!
//! ### Blocking Client
//!
//! ```no_run
//! use zinit::{ZinitClient, ServiceConfig, ServiceDef};
//!
//! // Connect to supervisor
//! let mut client = ZinitClient::connect_default().expect("Failed to connect");
//!
//! // List all services
//! let services = client.list().expect("Failed to list");
//! println!("Services: {:?}", services);
//!
//! // Get service status
//! let status = client.status("my-service").expect("Service not found");
//! println!("Status: {:?}", status.state);
//! ```
//!
//! ### Async Client
//!
//! ```no_run
//! # #[cfg(feature = "async")]
//! # async fn example() {
//! use zinit::AsyncZinitClient;
//!
//! let client = AsyncZinitClient::new(
//!     &std::path::PathBuf::from("/var/run/zinit.sock")
//! ).expect("Failed to create client");
//!
//! let status = client.status("my-service").await.expect("Status failed");
//! println!("PID: {}", status.pid);
//! # }
//! ```
//!
//! ### Creating Services
//!
//! ```no_run
//! use zinit::{ZinitClient, ServiceConfig, ServiceDef, ServiceClass, RestartPolicy};
//! use std::collections::HashMap;
//!
//! let mut client = ZinitClient::connect_default().expect("Failed to connect");
//!
//! // Create a service config
//! let mut config = ServiceConfig {
//!     service: ServiceDef {
//!         name: "my-app".to_string(),
//!         exec: "/usr/bin/my-app --daemon".to_string(),
//!         dir: Some("/opt/my-app".to_string()),
//!         env: HashMap::new(),
//!         status: "start".to_string(),
//!         class: ServiceClass::User,
//!         critical: false,
//!         oneshot: false,
//!     },
//!     ..Default::default()
//! };
//!
//! // Add the service
//! let result = client.add(&config, true).expect("Add failed");
//! println!("Created service: {}", result.name);
//! ```
//!
//! ### Managing Dependencies
//!
//! ```toml
//! # In /etc/zinit/services/app.toml
//! [service]
//! name = "app"
//! exec = "/usr/bin/app"
//!
//! [dependencies]
//! requires = ["database"]
//! after = ["logger"]
//! wants = ["cache"]
//! conflicts = ["dev-mode"]
//!
//! [lifecycle]
//! restart = "on-failure"
//! start_timeout_ms = 30000
//! stop_timeout_ms = 10000
//! ```
//!
//! ## RPC Methods
//!
//! The supervisor exposes 44 RPC methods over JSON-RPC 2.0:
//!
//! ### System
//! - `system.ping` - Check if supervisor is alive
//! - `system.shutdown` - Gracefully shutdown
//! - `system.reboot` - Reboot system (PID 1 only)
//! - `system.prepare_restart` - Save state for hot restart
//!
//! ### Services
//! - `service.list` - List service names
//! - `service.list_full` - List services with state
//! - `service.status` - Get service status
//! - `service.stats` - Get resource usage (PID, memory, CPU)
//! - `service.start` / `service.stop` / `service.restart`
//! - `service.create` / `service.delete` - Manage services
//! - `service.tree` - Show dependency tree
//! - `service.why` - Explain why service is blocked
//! - `service.start_all` / `service.stop_all` - Bulk operations (user-class only)
//!
//! ### Logging
//! - `logs.get` - Get log lines
//! - `logs.tail` - Get structured logs
//! - `logs.filter` - Filter logs by service/stream/time
//!
//! ### Xinet (Socket Activation)
//! - `xinet.create` / `xinet.delete` - Manage proxies
//! - `xinet.list` / `xinet.status` - Query proxies
//!
//! See [`sdk::protocol`] for complete RPC types and [`docs/OPENRPC_IMPLEMENTATION.md`](https://github.com/geomind_code/zinit/blob/main/docs/OPENRPC_IMPLEMENTATION.md) for detailed API documentation.
//!
//! ## Configuration Format
//!
//! Services are configured in TOML format:
//!
//! ```toml
//! [service]
//! name = "my-service"
//! exec = "/usr/bin/my-service --daemon"
//! dir = "/opt/my-service"
//! class = "user"        # or "system"
//! critical = false      # Fail boot if critical (PID 1 only)
//! oneshot = false       # Exit without restart
//!
//! [dependencies]
//! after = ["database"]
//! requires = ["logger"]
//! wants = ["cache"]
//! conflicts = ["competitor"]
//!
//! [lifecycle]
//! restart = "on-failure"  # always, on-failure, never
//! restart_delay_ms = 1000
//! start_timeout_ms = 30000
//! stop_timeout_ms = 10000
//! stop_signal = "SIGTERM"
//! max_restarts = 10
//!
//! [health]
//! type = "tcp"
//! target = "localhost:8080"
//! interval_ms = 10000
//! timeout_ms = 5000
//! retries = 3
//!
//! [logging]
//! buffer_lines = 1000
//! file = "/var/log/my-service.log"
//! ```
//!
//! ## Operating Modes
//!
//! ### Standalone Server
//! ```bash
//! zinit-server --config-dir /etc/zinit/services
//! ```
//!
//! ### Container Mode
//! ```bash
//! zinit init -c --config-dir /etc/zinit/services
//! ```
//!
//! ### VM/Bare-metal (as PID 1)
//! ```bash
//! zinit init --config-dir /etc/zinit/services --system-dir /etc/zinit/system
//! ```
//!
//! ## Platform Support
//!
//! - **Linux**: Full support including PID 1 mode with systemd-style boot
//! - **macOS/Darwin**: Client and server support (no PID 1 mode)
//! - **Windows**: Client support (via WSL recommended)
//!
//! Path handling is platform-aware:
//! - Linux: `/run/zinit.sock`, `/etc/zinit/services`
//! - macOS/Windows: `$HOME/hero/var/zinit.sock`, `$HOME/hero/cfg/zinit`
//!
//! See [`sdk::socket`] for path configuration details.
//!
//! ## Examples
//!
//! See the `examples/` directory for complete working examples:
//! - `list_services.rs` - Enumerate services
//! - `monitor_service.rs` - Watch service state changes
//! - `dependency_graph.rs` - Visualize dependencies
//! - `create_service.rs` - Dynamically create services
//!
//! ## Error Handling
//!
//! Most operations return `Result<T, Box<dyn std::error::Error>>` for convenience.
//! For detailed error information, use the underlying error types:
//!
//! - [`sdk::protocol::RpcError`] - RPC protocol errors
//! - [`sdk::validate::ValidationError`] - Configuration validation errors
//!
//! ## Concurrency
//!
//! - Clients are single-threaded (synchronous)
//! - Server uses tokio async runtime with `RwLock<ServiceGraph>` for safe concurrent access
//! - IPC is over Unix domain sockets with newline-delimited JSON
//!
//! ## See Also
//!
//! - [`sdk`] module documentation
//! - [`server`] module documentation (with `server` feature)
//! - [`client`] module documentation (with `client` feature)
//! - `docs/` directory for ADRs and specifications
//! - `docs/OPENRPC_IMPLEMENTATION.md` for complete API reference

// SDK module - always available
pub mod sdk;

// Re-export commonly used types from SDK at crate root
pub use sdk::{
    DependencyDef,
    FailureReason,
    LifecycleDef,
    LoggingDef,
    OkResponse,
    RestartPolicy,
    ServiceClass,
    // Config types
    ServiceConfig,
    ServiceDef,
    // State types
    ServiceState,
    ServiceStats,
    // Response types
    ServiceStatus,
    State,
    Status,
    WhyBlocked,
    // Client
    ZinitClient,
    // Modules
    protocol,
    socket,
    validate,
    xinet,
};

// Async client (when async feature enabled)
#[cfg(feature = "async")]
pub use sdk::AsyncZinitClient;

// Server module (when server feature enabled)
#[cfg(feature = "server")]
pub mod server;

// Client module (when client feature enabled)
#[cfg(feature = "client")]
pub mod client;