Saphan StudioDocs
Deployment

Verifying an install

Why the version string is not the check, and the two cheap checks that are.

~/.saphan/bin/saphan version # per-user installs
/opt/saphan/bin/saphan version # machine-wide installs
saphan version # package / installer installs (already on PATH)

saphan version and saphan --version print the same block — version, commit, build channel, build date and Go version — and saphan-agent --version and saphan-gateway version print it in the same shape, so one line in a rollout script reads all of them. Add --json to saphan version for a machine-readable answer.

Every scripted path verifies checksums before anything lands: the installer checks each binary against SHA256SUMS and refuses on mismatch with nothing installed; the macOS installer checks its payload digest before extraction. For what the engine itself re-checks after delivery to a runner — digest and version re-resolved on the machine that will execute — see Runners: what happens during a run.

version proves the stamp, not the behaviour

The commit in saphan version is written into the binary by the linker at the moment of linking. Nothing in that chain binds what the file does to what it says, so the stamp is evidence that a build happened at that commit — not that the running code is that commit's code.

This is not theoretical. An install has been observed producing a binary that reported the correct commit and still behaved as the code from before a fix that commit contained; a second install, from the same unchanged tree, produced a correct one. The root cause was not established. What the incident settles is the predicate, not the mechanism: a version check passed on a defective binary, so a version check cannot be what closes an upgrade.

Verify an install two ways, both cheap:

By content — the bytes you shipped are the bytes now installed:

grep '<os>-<arch>/saphan$' SHA256SUMS # in the distribution tree you installed from
ssh <host> 'sha256sum "$HOME/.saphan/bin/saphan"' # on the machine (shasum -a 256 on macOS)

Equal digests mean the delivery is honest end to end. This is strictly stronger than the stamp, because it pins the content rather than a string inside it.

By behaviour — exercise the thing you upgraded for. Whatever the change was, there is some verb whose outcome differs before and after it; run that one. A proc run costs no model tokens and is the cheapest carrier for such a check:

saphan run --workspace <workspace> --stream <fresh-slug> --backend proc \
 --actor <you> --binary /usr/bin/true --profile execute \
 --workdir <fresh empty dir> --wall-clock 1m

Two rules make such a probe mean something. Use a fresh stream slug and a fresh empty workdir — a reused one carries channel files and prior rows that change the answer for reasons unrelated to the upgrade. And know which inputs make the old behaviour reachable at all: a probe that omits the flag the defect needed will pass on the old binary and the new one alike, for the same reason, and prove nothing. If you cannot state what the probe would print on the old binary, it is not yet a check.

Neither check reads the supervisor

Both checks above go green on an install that will not come back after a restart. That is a third question, with its own reading: saphan service status --workspace <workspace> (add --system for a machine-wide installation) — see saphan service.

On this page