Design
The normative contract for K's execution model, transaction, supervision and controller boundary. It states obligations; it does not explain them. Read how an upgrade works first for the narrative and vocabulary, and the reference for wire formats, exit codes, budgets and file layout.
Execution and trust
The processes are drawn and named in the guide. The obligations on that layout:
- The runner and its runtime live outside the application slots and service unit. Stopping the application must leave the worker alive. A child process can still belong to a systemd cgroup or Windows job; the publisher must arrange isolation.
- The supervisor retains recovery code until settlement. Installation state persists. An OS hook or operator must restart installation after reboot.
- The adapter is fixed at build time. Requests select an action and a target version, never code, commands or download URLs.
- The publisher authenticates distribution metadata and caller authority. K checks artifact SHA-256 and size; these checks do not establish publisher identity. See packaging.
Components
Paths are relative to core/src/.
| Component | Responsibility |
|---|---|
launcher/ | Acquire, verify, execute and clean runner code; supervise recovery |
protocol/ | Validate the bounded request/response contract |
runner/ | Serve stdin/stdout, execute requests and map outcomes to exit codes |
createRunner.ts | Assemble source, host, policy and transaction state |
lifecycle/ | Stop/start/probe the application, including command-based control |
artifact/, txn/, converge/ | Verified acquisition, durable transactions and readiness predicates |
createRunnercreateRunner(options)constructs the transaction interface.serveRunnerserveRunner(factory)serves it in the runner process.launchRunnerlaunchRunner({release, request, scratchDir, interpreter?})verifies and supervises a worker, writes one final response and returns its exit code.superviseRunner- Returns the same result as data, including any retained
recoveryFile. resumeRunnerresumeRunner(recoveryFile)verifies that retained runner and performs operation-bound recovery without distribution access.
Transaction and recovery
Each installation has one lock, stable and experiment executable slots, and a journal. Application data belongs outside the slots. The walkthrough is in the guide, one upgrade start to finish and when something goes wrong; the obligations:
- The phases are, in order,
idle,staged,handing-over,running-experiment,readback, thenpromotedorrolled-back. Intent is journaled before effects. - Recovery takes the same lock and uses existing slot bytes without release lookup. Before durable promote intent it restores stable; after it, it replays commit idempotently.
- Every started operation has an owner that waits for a durable terminal result or explicitly reports unresolved recovery. An installer invocation settles unfinished work before admitting a new upgrade; recovering an interrupted operation does not retry its requested upgrade.
A running candidate alone does not authorize commit. Corrupt or unknown state, and another live lock owner, prevent conflicting operations. Filesystem durability and controller behavior determine the real platform guarantees.
The supervisor
- runs outside the application service unit;
- retains the verified runner while the operation is active;
- enforces execution and recovery budgets (values);
- starts a recovery worker after an abnormal exit;
- stops supervising after completion or an explicit unresolved result.
Recovery attempts and total elapsed time are bounded. Exhaustion preserves state and provides a recovery command rather than reporting success.
Takeover and binding
- Observe exit first
- Before starting a successor, the supervisor must observe the prior worker exit. The recovery worker then takes the lock and fences outstanding controller effects before replaying lifecycle actions. An expired deadline alone is insufficient; an unconfirmed exit forbids takeover.
- Bind to the original id
- Recovery must bind to the original operation id under K's transaction lock. If another operation has since run, recovery inspects or replays the original result without modifying the newer operation. Recovery reuses the existing journal and receipts; supervision does not create another transaction log.
- Clean up after settlement
- Persist the outcome, release owned resources, then remove disposable code. Never delete slots, a live owner's lock, or recovery logs to make an interrupted operation appear complete. If recovery remains unresolved, preserve the evidence and a verified means to invoke it again.
- Budget every host call
- Every engine host call has a positive budget. Uncertain effects retain the worker's lock until it exits. Bundled workers exit after flushing their response; custom in-process callers must also exit on
HostCallUncertainrather than reuse that worker.
Repair boundary
K's refusals forbid silent bypass: no part of K clears a live owner's lock, overwrites an incomplete stable slot, reconstructs missing history, or terminates a process by recorded pid.
They do not forbid a product installer from repairing a machine K cannot, provided the repair stays outside K's transaction and keeps these obligations:
- Settle first
- Run recovery to its terminal or unresolved result before repairing. Repair is never the response to a rolled-back or failed upgrade; it is the response to records that cannot be settled or read.
- Never under a live lock
- Liveness is decided by the lock protocol, not by age.
- Quarantine, do not delete
- Slots, journal, lock, receipts and recovery logs move aside intact in one atomic rename, under K's lock, including records K itself cannot read (
quarantineStatewithallowUnreadable). Data outside the slots is left alone. - Attribution and receipt
- Repair runs as its own request or on a broken machine, never on a machine that can be upgraded, and its receipt records what it displaced, what it installed and who ran it.
- Re-enter K
- Repair ends with
bootstrapStableon the installed bytes and a live probe. Until then no upgrade may be admitted. - No rollback claim
- Repair is reported as a repair, never as a promoted upgrade.
K supplies bootstrapStable, quarantineState and the lock protocol; the installer decides when to repair.
Host control contract
createRunner requires a HostAdapter. Its operations and the controller's obligations:
| Operation | Controller obligation |
|---|---|
fence | Drain or fence previous controller effects; required when effects can outlive the worker |
quiesce | Stop admission and durably park promised workloads; repeated calls safe |
stop | Stop the specified slot's service and confirm termination |
start | Start the selected artifact idempotently, without creating duplicate residents |
healthProbe | Return version, pid and startId from one ready live instance |
resume | Restore parked work on either candidate or rolled-back stable |
- The controller must work while the old application is down.
startreturning does not establish readiness; the probe does.- K probes once before handover and records that incarnation's
startIdwith the handing-over intent. Readback evidence carrying the samestartIdis refused and rolls back: the old service was not replaced. startmust not execute the artifact in place inside the slot on Windows; promotion renames slot directories and a running executable locks its directory. Copy or hard-link to a runtime path outside the slots.- A stateless service satisfies
quiesceandresumeby acknowledging. The obligations apply to workloads the product promises to preserve. - Adapters with no effects surviving their worker may omit
fence. All other adapters must supply it and test it against their real service manager.createCommandHostalways deliversfence; a command controller that queues nothing acknowledges it. - If OS lifecycle surfaces are declared, K also requires them to reference the promoted artifact before retiring their previous manager. Undeclared surfaces are not observed.
createCommandHost runs an external controller via argv without a shell, records the controller pid durably before each call, and drains recorded controllers before fence during recovery. Wire format, bounds and pid handling are in the reference. The recorded pid is never used to kill an arbitrary process. fence acknowledgement is a product contract, not something K infers from process exit. Fire-and-forget stop cannot establish termination.
Product responsibilities
The adapter defines release lookup, installation ownership, consent and compatibility policy. K restores executables; products provide data-migration compatibility, backup and restore, and any promised workload continuity. What the installer around K should do for each entry and outcome is the advisory installer contract.