Kk-carrier docs

Reliable application upgrades, run by an independent installer.

K is for software you distribute yourself to machines nobody operates: desktop agents, background services installed by curl | sh, CLIs that update themselves. A failed upgrade there means the product silently stops and nobody can log in to fix it.

One request, one transaction, one receipt. The thing doing the upgrading never lives inside the thing being upgraded.

If a package manager, container image or fleet orchestrator already owns your installation, that manager owns upgrades too. Your adapter identifies that ownership so K can defer; you probably do not need K.

Why upgrading is non-trivial

The machine is remote and nobody operates it. An upgrade has to be triggered from far away, stop the running service, start the new one, and keep working while the service is down, because the service is the only thing anyone can reach. If the new version does not start, the old one has to come back on its own; nobody can log in to put it back. Replacing the file proves nothing about whether the service came back.

So the upgrader cannot live inside the application, and every step has to be journaled: an installer that dies halfway, or a machine that reboots mid-upgrade, must be settled by the next installer that runs, not by a person.

What K promises

K stages verified bytes in a second slot, stops the service, starts and probes the candidate, then commits or restores the previous executable. A durable journal lets a later installer recover interrupted work. An upgrade ends in exactly one of three states:

Promoted

The candidate answered the probe with the right version, a new pid and a new start id. Experiment became stable.

Rolled back

The candidate failed before the point of no return. Stable was never touched and is running again.

Unresolved

Bounded recovery could not settle it. Evidence and a verified way to retry are preserved; nothing is reported as success.

K refuses to guess. It never clears a live owner's lock, overwrites an incomplete stable slot, terminates a process by a recorded pid, or reconstructs missing history. It rolls back executables, not application data. Hashes check integrity; your distribution channel establishes trust.

What the installer adds

K is the transaction. The installer around it, built from K and your adapter, is what install.sh, your application's self upgrade and a remote request all launch. It outlives the application it replaces, runs when the application cannot start, and decides everything K does not: fresh installs, adopting an installation that predates K, repairing one K cannot settle, and what to say and ask in each case, attended or not.

That behavior is written down as the installer contract: one model for every entry, every machine and every outcome. It is advisory and still settling; the first implementation is raft-computer-installer.

What you ship

The bootstrap verifies the installer; the installer verifies the product. Paths are illustrative, not a K schema.

You supply the release source and the service lifecycle operations; K supplies the transaction machinery. Releases can come from a static manifest on any CDN or from a release platform such as K's sibling project Hands. The runner uses Node 24, external or bundled into a single executable.

Status

Two-slot transaction, journal, lock, receiptsDone. Generated crash matrix, seeded simulation, Lean model of every phase and crash interleaving (host honesty assumed).
External runner, supervisor, bounded recoveryDone. Linux and macOS process tests.
Verified download, resume, gzipDone.
Command controller boundaryDone; demo controller only.
Single-executable runnerVerified by hand; build flag provided, no CI.
WindowsCore is platform-seamed; harness port incomplete, CI informational.
Repair beyond K's transactionBoundary documented; implementation belongs to the product installer.
Product-ready install.sh templateNot yet.
Publisher signingNot provided; hash and size only.
Restart after rebootNot provided; product OS hook.
Receipt garbage collectionNot provided.

Documentation

How an upgrade works
The processes involved, one upgrade start to finish, what breaks, how to read the result. Read this first.
Installer contract
What the installer around K should do for every entry, machine and outcome. Advisory.
Runnable example
A service, a controller and a runner you can drive from a terminal.
Integration
Build, launch, observe, recover, package and distribute your own installer.
Design
K's normative contract: execution model, transaction, supervision, controller obligations, repair boundary.
Reference
Protocol, exit codes, budgets, on-disk layout.
Test plan, harness, formal model
What is tested, how, and what the Lean proofs cover.
Prior art
Rustup, Tailscale and Datadog, and what K took from each.

Incubating. TypeScript on Node 24. Apache-2.0. Contributions welcome.