Release gates
Five gates over what Vike Trader ships — the container image, the shipped units, the fxcm-linked artifact, the public mirror, and the dispatcher's boot behaviour.
A release leaves the repository as bytes nobody re-reads: an image, a set of unit files, a handful
of binaries, a published source tree. Five gates in crates/vike-ops/tests/ hold the properties of
those artifacts that no compiler can see — each chosen because its violation stays invisible until
the artifact is run in production.
The container image
crates/vike-ops/tests/container_image_gate.rs opens with the fact that shapes it: no runner has
a container runtime. Measured 2026-08-24 on the box the release workflow is pinned to, none of the
four common runtimes is installed and the docker socket does not exist, while a control probe finds
the ordinary shell tools — "so that is a fact about the runner and not about a broken check."
Coverage is split by what is provable without one. The entrypoint is executable shell, so it is
run: the_entrypoints_own_selftest_passes drives the real script through the stamp, the
verification, the wholesale swap and every refusal. The Dockerfile is text, so the rest are text
rules. the_entrypoint_execs_the_daemon is called "the single most dangerous line". Without exec the
shell stays PID 1, and a shell does not forward SIGTERM to its children: docker stop waits out its
timeout then SIGKILLs, so cancel_orders_on_shutdown never runs and "the resting book is ABANDONED
at the venue" — the defect crates/vike-ops/tests/graceful_stop_pin.rs exists to keep fixed,
reached through the container instead of the unit file. Alongside it: the base image is pinned by
digest, no packages are installed, both released binaries are present, the stop timeout outlasts the
daemon's own shutdown deadline, and no_baked_environment_variable_is_a_removed_setting —
vike_config::REMOVED_ENV names variables whose presence is a hard startup refusal, and one baked
as an ENV line would make every container of that image refuse to start.
What the image gate cannot prove
That the image builds, that the base's glibc satisfies the binaries, or that the entrypoint works
under a real PID 1. crates/vike-ops/tests/container_image_gate.rs says so itself, in its What it
deliberately does NOT prove section: none of it is reachable without a container runtime, so the
release script that stages and builds the image carries the runtime check instead — "the only place
the glibc-too-old failure can be observed at all."
That check runs --version on every version-capable link — six of them, all symlinks into one
dispatcher — inside the freshly built image before anything is published.
crates/vike/src/lib.rs's Route::Version records the same rule from the dispatcher's side: "the
image smoke runs --version through every link, the dispatcher's included." One link is not
enough — a released image once answered vike-tradehub --version with that tool's usage error, a
break a single-link smoke catches only for the link it runs.
The shipped units
crates/vike-ops/tests/deploy_layout_gate.rs holds one rule — every shipped daemon unit describes
one project folder, and the same one throughout — and names two defects that shipped before it
existed. The first was a layout that no longer existed anywhere, so a fresh deploy rebuilt an
abandoned three-location shape. The second was worse: EnvironmentFile= pointed at the credential
store. Nothing was exposed, but the route shipped, and it inverts a guarantee four gates rest on —
the live, control, reconcile and Telegram flags are read off the real process environment precisely
because the store never reaches there.
The write grant is the instructive rule, because its first version caused what it looked like it
prevented. It demanded exactly one ReadWritePaths= naming exactly one path, on the argument that a
second path is a second location. It is not: every path was already required to be under the unit's
own root, so a second path inside one folder is a narrower grant. The rule forced the one daemon
that legitimately writes in two places to grant the only single path covering both — the root —
which on a shared folder covered a live daemon's binaries, its notional ceiling, its credential
store and its armed kill switch. Containment is checked instead: no granted path may reach
ExecStart='s binary or any ExecStartPre= binary — not the executable and not a directory holding
it, since write permission there is enough to unlink and replace the file — nor the settings
directory the unit names. The gate states its own limit: intent is all a text gate can read.
The fxcm-linked artifact
crates/vike-ops/tests/release_fxcm_artifact_gate.rs governs a second daemon binary built from the
same tagged commit with --features fxcm. Its rule is one line: a release may grow an
fxcm-linked artifact; it may not change the one everybody deploys. A feature build writes to the
same output path the default build just produced, so getting it wrong silently replaces the binary
the deploy installs — with one that dies at exec, before main. The extra asset rides in the
checksum manifest but is never installed, checked over a derived subject rather than a hand list,
because "an absence check never opens the file nobody remembered to add, and reports a pass for it."
Third, an asset named -fxcm must actually be linked: with no SDK the identical command produces a
stub that builds green, so the script reads the ELF's dynamic section rather than trusting an exit
code, and the gate runs it against a fake cargo — the only way to prove the guard is wired into
the build.
A return from a test body is a pass
This gate's behavioural half once opened with an early return on a missing toolchain, so a runner
without a C compiler reported it green over a release script none of it had executed. Since
2026-08-28 the cases differ: off an ELF platform they are #[ignore]d with the reason attached, and
a missing tool on Linux fails, because a box that can build the workspace already has all three.
The public mirror and the dispatcher
crates/vike-ops/tests/publish_mirror_gate.rs guards the script deciding what leaves the private
repository, on two properties. ALLOW is an allowlist — a catch-all turns the script into
"publish everything except…", which fails in the wrong direction, silently, and once. And the
forbidden-token scan refuses rather than warns: "redaction alone is a habit; redaction plus a
refusal is a gate." Neither is checkable by reading the script, so the gate runs it over the real
tree and inspects the result.
crates/vike-ops/tests/multicall_gate.rs requires the multicall dispatcher to do nothing before
handing over, and one tool to run per process. It performs the process's single environment sweep,
then hands control to a tool that boots for itself — if the dispatcher also booted, one process
would walk for settings twice, and the second walk is blind to the settings-directory override. That
is the defect that once put a live daemon on no policy, no config and no credentials, every venue
silently on paper, no error anywhere. The boot-ownership gate cannot catch it: it keys on crate
directories containing a boot call, so "the dispatcher boots and the tool it calls boots" reads as
two crates each booting once. The one-tool rule follows from process-global state — a second tool
would inherit the first's logging and handlers in a process that may be signing orders — so the
dispatcher panics, and the gate proves the panic is real.
Related: Supply chain · Drift gates · Safety gates
Supply chain
What CI may download and run on the boxes that sign real orders, how much unsafe code the workspace holds, and the single transport stack cargo-deny enforces.
Drift gates
The committed-generated-artifact family — why two build outputs are committed rather than produced, how each is re-derived and compared, and why the comparison styles differ.