Sigil 0.18.0

release

The release that gives Sigil a verifiable supply chain. sigil env builds a project's whole toolchain from a lockfile, fetches prebuilt outputs from a signed registry instead of compiling them, and refuses anything whose bytes don't match what was signed. Alongside it, two build-integrity fixes you can see from the outside: builds that failed while reporting success now exit non-zero, and the same source built twice now produces the same binary. This is a minor bump because (sigil env) changed meaning. It's the environment engine now, and the old dotenv helpers moved to (sigil dotenv). Projects importing (sigil env) for dotenv need that one-line change; everything else builds without modification.

Download 0.18.0Get started

Environments from a lockfile

sigil env builds and enters a pinned toolchain. A project records its environment in env.lock, which pins every output by the hash of its contents rather than by a version number, so entering that environment on another machine gets the same bytes or fails loudly. sigil env shell drops you into it and passes back the exit status of whatever you ran, so it composes in scripts.

A signed registry, and substitutes instead of compiling

Sigil can fetch a prebuilt output rather than building it. Outputs live in a content-addressed registry, published as ordinary static files, so you can mirror the whole thing with rclone and serve it yourself. The client verifies a signature over the exact bytes it was served, then the archive's hash, then the hash of the unpacked tree, before anything reaches the store. A tampered byte, a wrong path, a replayed old index, or a stale key all refuse rather than degrade.

Trust starts from a single public key compiled into the client. That key signs a registry document listing the operational keys, each scoped to a role, so a compromised publishing key can be revoked without reissuing the client. Retired keys keep verifying documents they signed before retirement and refuse anything newer.

Channels

sigil channel publish writes a signed catalogue and snapshot describing a set of packages, in one transaction. It verifies the staged result before touching anything mutable and rolls back every root if a write fails. Publishing the same content twice is a no-op rather than a new revision.

Builds that fail now say so

A build task that raised an error could print ✓ Build complete! and exit 0, having produced nothing. A build that doesn't run to completion now refuses to exit 0 and says which stage was interrupted. This was reachable from several places, including a failed libsigil.a archive step and a package whose manifest fails validation, and every one of them reported success.

If you script around sigil build and have been checking output text because the exit code was unreliable, you can go back to checking the exit code.

The same source builds the same binary

Two consecutive builds of unchanged source could produce different binaries. Two builders wrote the same libsigil.a, and the cache fingerprinted the inputs rather than the bytes on disk, so the second build served an archive the first had overwritten. Archives are now fingerprinted by content, and a cross-environment gate builds the same commit on two distributions and compares bytes.

Known limitations

Error propagation itself isn't repaired. In a native release build, a short-lived guard during startup overwrites the top-level error handler, so from then on an error that no inner guard catches is swallowed and execution continues. That's why a failing build could report success, and why a few unrelated commands could too.

0.18.0 contains this at the sites we know about, using checks that verify a result directly instead of waiting for an exception to arrive. It doesn't fix the cause, which needs a redesign of how the handler stack is reclaimed. Every cheap patch we tried breaks something else, so we'd rather ship the containment and do the repair properly. The good news is that it's finally understood rather than merely observed.

The build latch catches builds that didn't finish. It doesn't catch a build that finished and produced the wrong artifact, and sigil check staying quiet on a syntax error is a known instance still open.

What's next for sigil env

The machinery here is complete and verified, and there's nothing to point it at yet. No substitute registry is deployed and no core package channel is published, so sigil env today builds what you pin rather than fetching it.

That's the intended shape of this release rather than a shortfall. Building the registry and the channel needs a client that can already consume them, a signing chain that can already be trusted, and formats settled enough to publish against. 0.18.0 brings all three online. Next is standing up the registry itself and publishing the core packages into it, and that work can now proceed against a client in the field instead of alongside one still being designed.