Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Self-update

spt-core keeps itself current without ever interrupting your agents, and without trusting anything unsigned.

The invariant

No endpoint process terminates or suspends during a self-update. The daemon’s broker (holding PTYs, child processes, sockets) stays up; the brain (all logic) swaps under it. A hosted session’s process id and byte stream are identical before and after.

The trust chain

  • Every release ships SignedRelease metadata: an Ed25519 signature over the release’s artifact digests.
  • Every binary embeds the two-key trusted set — an active primary and a never-used offline recovery key. Verification requires a valid signature from a trusted key and a matching artifact digest; an unverified binary never reaches the apply step.
  • Losing the primary key is a non-event: the next release is signed with the recovery key (already trusted by every deployed binary) and rotates in a fresh primary.
  • Adapters sign their own content. A file_pull adapter update is verified against the adapter author’s key from its manifest; a delegated update is trusted only when the manifest attests the delegated updater verifies its own content (self_verifies). spt-core’s release keys never vouch for adapter bytes.

How updates move

Peer-propagated: one node fetches a release; paired nodes offer/fetch staged releases from each other, each verifying independently before staging. Updating is consent-gated by default — a notification surfaces at your most-recently-active endpoint, and spt update apply is the explicit ack (it re-verifies the staged release before touching the live daemon). Full-auto is an explicit opt-in.

After self-updating, spt-core ripple-updates registered adapters through each manifest’s declared [update] avenue.

Composite adapter updates — a delegated post-step (since v0.16.0)

An adapter can run a second, adapter-owned step after its primary update avenue resolves, under the same spt adapter update. Declaring an optional [update.post] sub-table (command required; an attestation-only self_verifies flag) lets one lever both pull the adapter’s .spt (e.g. from gh_release) and run an in-harness sync (e.g. a plugin updater). The post-step:

  • runs unconditionally — even when the primary avenue was a no-op (its own idempotent check decides what changes);
  • receives a published JSON line on stdin describing the just-resolved update (adapter_applied, version, previous_version, adapter_dir, …; additive keys only — ignore unknown);
  • decides the post-update notice via stdout — custom text supersedes the static [update].message, the reserved sentinel !!update-message!! fires the static message, empty prints nothing;
  • is failure-isolated — if it fails, spt-core warns loudly and falls back to the today behavior (an applied update fires [update].message); a committed pull is never rolled back.

The exact stdin keys, sentinel, and notice precedence are in the manifest [update.post] reference.

Commands

spt update · the consent notification flow (spt notif) — CLI reference.