Publication and deliveries
What the Stado-native release pipeline publishes, how deliveries run and pass, and how a delivery installs software on a fleet host, the resident Stado included.
Publication writes the archive, immutable qualification receipt, signature,
and signed manifest last. The signing key is read from the configured Skarbiec
item field private_key; only the item name and trusted key ID are
configuration. For the default configuration the item is
stado-release-signing, never a secret value in a manifest or command line.
Post-publication deliveries are queue jobs consuming the canonical archive URI
and digest. Required package or product channels gate completion; optional
deliveries are adapters whose failure is retained without changing canonical
release success. GitHub may be one such optional adapter, but no GitHub-hosted
step is part of the source, qualification, publication, promotion, or
reconciliation contract. The repository's existing deploy.yml invokes the
same Stado CLI convergence after publication; it is not a second release
contract.
Deliveries are queued together unless one names others in its optional
after list. Such a delivery is queued only once every delivery it names has
passed in the same run, so a schema migration can precede the application that
reads it:
{"name": "vercel-production", "platform": "web-source",
"argv": ["stado", "web", "vercel", "deploy"], "required": true,
"after": ["supabase-production"]}
after may name only deliveries declared earlier in the manifest; anything
else is refused when the manifest is validated. When a named delivery did not
pass, the dependent one is recorded failed with
not queued: delivery <name> did not pass, and a resumed run queues it once
that delivery passes.
A dependent job already submitted keeps its job ID and output location if a
predecessor later loses valid proof. Its actual queued/running state and failure
remain visible; a live job is not replaced by a fictitious unqueued record.
It cannot pass while that predecessor's proof is invalid.
A delivery passes on its receipt, not on its queue job's state. When the job
ends completed, the coordinator reads the job's delivery-receipt.json and
checks it against the delivery's immutable request: it must exist and decode,
and its run, job, delivery name, product, version, platform, archive URI and
digest, manifest URI and digest, schema version, required and secret
references must equal the request's; its argv must be the declared one (a
Stado delivery whose argv starts with stado records the worker's own absolute
executable path in that first place, and only that place may differ); its
step must be passed, its exit code must be the operating system's success
code, and completed_at must parse as RFC 3339. Anything else records the delivery failed with the
cause, for example job <id> left no delivery-receipt.json,
the delivery-receipt.json of job <id> does not decode: <error> or
the delivery-receipt.json of job <id> does not prove delivery <name>: its job is <written>, the request declares <id>.
A delivery already recorded passed is checked again on every pass before the
deliveries after it are admitted, and fails with
the delivery-receipt.json of job <id> hashes to <digest>, but the run accepted <digest>
when its receipt changed since it was accepted. stado release redeliver
checks its job's receipt the same way and ends the redelivery failed with the
same cause. stado release status and Desktop's Releases pane show that cause
on the delivery.
The first accepted receipt digest is retained across later read, decoding,
dependency or integrity failures. Failed bytes never replace that accepted
digest, so a repeated pass cannot approve altered evidence merely because an
earlier pass already observed it. A receipt read failure names the job and the
actual storage cause on the delivery. A queued or running observation removes
any stale passed state before dependent admission while the overall run remains
pending for its live jobs.
Repeating a completed redelivery with the same retry token re-reads its immutable
request and receipt before reporting success. The request must still match its
accepted digest and release/source identity; the receipt must satisfy the same
validator and its previously accepted digest. Missing, unreadable or changed
proof refuses that replay with the exact object path and cause. A replay does
not replace historical proof or submit another job to conceal the failure.
A new redelivery likewise verifies the original passed job's current receipt
against the published artifact and the original accepted digest before writing
its new request or transaction. A stored passed label with absent, malformed or
changed proof is not admission to another delivery.
A delivery that installs software on a fleet host declares that host in its
optional target field and is pinned to run ON it, where
stado release local install (the verb every product's delivery argv names,
run with the host's installed Stado) verifies the delivered archive against the
contract digest (WISENT_RELEASE_ARCHIVE, WISENT_RELEASE_SHA256) and extracts
the named member. For the Stado product it first moves the already-downloaded,
verified archive into
$HOME/.stado/releases/stado/<version>/<platform>/stado-reader-convergence.tar.gz.
It installs changed root bytes under $HOME/.stado/bin by rename with a dated
backup. When those installed bytes already equal the verified payload, a
required-delivery retry leaves the root untouched while repairing the
attestation copy and release-version handshake, then reruns the
image-idempotent global reader pass: processes already mapped to the installed
inode are not kicked, while stale global reader images are reconciled. In
either case private updates execute through the explicit installed
$HOME/.stado/bin/stado, never through the delivery process image that an
earlier rename may have retired.
Before replacing the resident Stado executable, the incoming binary
reconciles com.wisent.stado from its own service catalog, then parses the
native unit's actual argument vector with its own CLI parser. An old flag
that the new parser rejects refuses installation with the unit path, host,
candidate, argv and parser error; the old executable remains in place.
After replacement, installation waits for the resident unit to serve its
declared port. If it exits first, the refusal includes its last launchd exit
and stderr line, and the retained <program>.previous bytes and installed
release coordinate are restored and activated. A process accepted by launchd
but not serving is not a successful delivery.
The real install journey in tests/install/resident/resident_unit.mjs requires a
dedicated host/account with the predecessor's native unit still carrying an
argument rejected by the incoming candidate. Set STADO_BIN,
STADO_TEST_SOURCE, STADO_TEST_SOURCE_COMMIT and
STADO_TEST_DEDICATED_HOST, then run node tests/install/resident/resident_unit.mjs
on that host. It retains the exact source revision, candidate digest,
commands, statuses and output under .build/install-resident-unit/, and
checks the native refusal before installation and the persisted product
receipt and serving process after it. Do not run it against an operator's
live account.
The same command gives every registry-declared Stado reader whose executable
lives under $HOME/.stado/services/ that exact archive through the existing
idempotent service update --from-archive --refresh-image path.
The macOS image-reconciliation pass enumerates every loaded label and domain,
its declared executable and running command, then verifies the kernel image.
A label launchd holds without running it has no image: the inventory reports
it with an empty pid, whether launchctl list wrote - for it or a domain
table wrote 0, and the pass leaves it alone to pick up the installed binary
when launchd next starts it. Only a live pid reaches the image read, so an
idle unit that declares the installed binary never fails a delivery.
It does not collect script-variable requirements, process ages or PATH-version
diagnostics for this operation. Those remain available in the full service
inventory; no labels are excluded from the installation's ownership check.
Routine release version converge owns the same reader completion contract.
Root release activates and restarts only units that execute the global install;
it never compares or kicks an unchanged private executable as though it were
the new global file. If the global root is already byte-attested while a
private reader is old or a prior private update failed, convergence reuses the
retained archive. When that copy is absent or corrupt it fetches and verifies
the exact declared archive without extracting, reinstalling, or restarting the
root. Already-current private trees and process images remain running; stale
ones are installed, refreshed, and proved, and any private failure keeps the
whole convergence failed. The queue agent alone retains its release-handshake
deferral.
If root delivery fails, that invocation does not attempt the private-reader pass.
A target that declares no services has no private-reader leg to run, and that
leg is recorded as skipped — a third delivery status beside completed and
failed. Reader trees are per service: a host that declares none carries no
tree to install, refresh or prove, so there is nothing for the pass to do and
nothing in that to call a failure. skipped is what separates "there was
nothing to do" from "the thing was not done", and only the second may fail a
run; a delivery that installed exactly what it was asked to is never marked
failed for finding no services on a host that declares none.
When one private update exits non-zero after emitting JSON, its complete
decoded or captured stdout and stderr remain in the existing
stado-readers.detail field. The enclosing converge report does not reduce
that evidence to the child's last line.
This partial-state resume contract requires the target's global receiver to be built from a release containing the retained-archive arguments. A numeric version banner alone does not establish that source identity. A receiver built without the contract rejects the hidden archive and digest arguments, so convergence remains failed and cannot report the private readers complete. Deliver a release containing this fix through the normal root path first; there is no compatibility shim.
Installation is a local file operation: no delivery needs ssh, Remote Login, or any other login service, and a failed delivery is re-enqueued on resume — a recorded failure never lets a run complete past a required delivery. A resumed submit retries exactly the failed legs and deliveries; published platforms are verified, never rebuilt.
promotion.reconcile:true is reserved for registry-hosted runtime products and
requires a runtime contract. Package, web, mobile, source, and archive products
use reconcile:false, omit runtime fields, and complete through their required
delivery receipts.
Source: this website