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