Integration and distribution
Compile K and a trusted product adapter into an independent Rust installer. The application can use any language.
Publish three deliverables
A small platform bootstrap verifies and launches the installer; the installer contains K plus product policy; the product is the executable installed into the two slots. Installer and product versions are independent. Publish immutable artifacts and authenticated metadata for both. A SHA-256 check verifies bytes against metadata, not publisher identity.
Construct the runner
Depend on the published k-carrier = "=0.3.1" and commit Cargo.lock for application builds. Use a pinned Git revision only to test unpublished changes. Start with examples/native-installer.rs, which CI compiles and executes:
use k_carrier::{host::CommandHost, runner::Runner,
source::StaticManifestSource, storage::FileStore};
use std::sync::Arc;
fn runner() -> k_carrier::Result<Runner> {
let store = FileStore::new("/absolute/product/upgrades");
let host = CommandHost::new(
vec!["/absolute/product/controller".into()], store.root.clone(), 30_000)?;
Runner::new(store, Arc::new(host),
Arc::new(StaticManifestSource::new("https://downloads.example.com/releases")?))
}
These are publisher-controlled paths and URLs. Set Runner::hooks to implement Hooks::{managed_elsewhere,compatibility,notify,progress}, policy for Auto, Confirm or NotifyOnly, and surfaces for declared lifecycle readback. Supply a custom artifact::ReleaseSource for another distribution policy. No distribution platform is required.
Establish a baseline
storage::bootstrap_stable(&state_dir, version, &artifact) adopts already authenticated, usable bytes under the shared lock. It does not download, authenticate, start or probe them. It refuses partial or conflicting state and never downgrades an initialized stable slot. Product setup handles first installation and enrollment.
Implement the host boundary
host::Host exposes fence, quiesce, stop, start, probe and resume. CommandHost sends the v1 JSON protocol to a separately packaged controller. Stop must establish termination; probe must report version, pid and startId from one ready live incarnation. Test against the actual service manager. Products supply data-migration compatibility and workload continuity.
Supervise completion
serve::serve_runner reads bounded stdin before invoking the runner factory and writes one response. Exit the worker using its returned code. A direct call alone does not supervise recovery.
supervisor::supervise_release downloads and verifies a worker; supervise_bytes stages trusted bytes already held by the installer. Both return LaunchResult, enforce execution/recovery budgets and require a receipt matching the operation and process exit code. Keep retained recovery files on unresolved results. resume_runner re-verifies them before offline recovery.
Package the installer
Native binaries
cargo build --locked --release --example native-installer --bin k-example-controller
cargo doc --locked --no-depsShip native executables for each supported OS and architecture, including the controller and any external libraries they require. Test the release build on the target platform; cross-compilation alone is insufficient. Sign and notarize artifacts where appropriate. The bootstrap must not implement a second transaction algorithm.
Keep supervisor, worker, controller and persistent state outside the resident slots. A child process may remain in the application's systemd cgroup or Windows job: publishers must arrange an independent lifetime. On Windows copy running application images outside the slots and clear inherited protocol handles with host::isolate_standard_handles before spawning children. Built-in worker/supervisor paths apply this guard themselves.
Repair beyond K
Attempt bounded recovery first. A failed upgrade is not permission to erase state. If product policy authorizes repair, prove safe handoff and use quarantine::quarantine_state under the same lock; retain displaced evidence and leave application data alone. Unreadable state requires both allow_unreadable and a successful handoff callback. A missing operation receipt with an existing journal also requires handoff. Every supplied callback runs under K's lock, even for a settled receipt. Reinstall verified bytes, bootstrap and probe. Record repair separately from upgrade: it does not promise rollback. Never bypass a live lock or kill a process by an unverified recorded pid.
Publishing the crate
The publish-crate.yml workflow runs on a version tag matching Cargo.toml. It requires the reusable three-platform CI and Lean job, verifies the packaged source with cargo publish --dry-run --locked, then authenticates with crates.io Trusted Publishing. Configure botiverse/k-carrier and that workflow in the crate's publisher settings. No registry token is committed. A successful dry run does not prove registry-side publisher configuration or perform a release.