Repository navigation
Releases: eggstack/eggup
Release list
0.2.0
Eggup 0.2.0
The lockstep 0.2.0 publication of every Eggup crate. Integrity evidence remains
SHA-256 checksum only — no crate in this release makes an authenticity or
signature claim, and no crate selects a release or authorizes a destination.
Why 0.2.0 and not 0.1.4
eggup-acquisition's next release had to be source-breaking: AcquisitionError::Io(String)
became Io { operation, source } with a live source() chain, and because
std::io::Error implements neither Clone nor PartialEq/Eq the enum now
derives Debug only. A source-breaking seam cannot ship as 0.1.4, and the
workspace is version-lockstep (version.workspace = true in all eight crates),
so the seam's version carried every crate forward with it.
Per-package publication source commits
All seven published from one commit — b612608, which is this tag:
| Package | Published from | Registry checksum |
|---|---|---|
eggup-core 0.2.0 |
b612608 (this tag) |
2c86a0eb…eb23b8 |
eggup-archive 0.2.0 |
b612608 (this tag) |
ce35edd5…ff57ad |
eggup-acquisition 0.2.0 |
b612608 (this tag) |
2ef74b4d…299fc3 |
eggup-curl 0.2.0 |
b612608 (this tag) |
15cf536f…90d3f7 |
eggup-eggfetch 0.2.0 |
b612608 (this tag) |
9fc8f648…658721 |
eggup-service 0.2.0 |
b612608 (this tag) |
31dd2e22…fe1b4a |
eggup-eggpack 0.2.0 |
b612608 (this tag) |
33dc1da4…14f1f6 |
The publication order was eggup-core → eggup-archive → eggup-acquisition
→ eggup-curl → eggup-eggfetch → eggup-service → eggup-eggpack,
because a crate is packaged only after every in-workspace dependency it names is
on the registry.
No existing tag was moved. The published 0.1.x versions are not withdrawn:
eggup-curl remains published through 0.1.2 and the other six through
0.1.3.
Three source breaks to plan for
eggup-acquisition:AcquisitionError::Io(String)is now
AcquisitionError::Io { operation, source }, and the enum derivesDebug
only —Clone,PartialEq, andEqare removed. A consumer that matched
Io(_)must match the struct form; a consumer that cloned or compared whole
error values must match on the variant and its fields instead.
eggup-curlandeggup-eggfetchinherit this break transitively through
theireggup-acquisition ^0.2requirement, andeggup-eggpackinherits it
through its exact=0.2.0pin.eggup-service:ServiceError::Manager(detail)is now
ServiceError::Manager { kind, detail, os_code }, carrying a
ManagerFailureKind. Match the struct form and branch onkind, not on the
message text.eggup-service:LifecycleUpdateReceiptgained the public field
engine_policy. The struct has noDefaultimpl, so a consumer that
constructs it with a struct literal must add the field and stops
compiling until it does. A consumer that only reads the receipt's fields is
unaffected.
What the 0.2.0 line closes
eggup-service 0.1.3misreported a successful stdin write as a failure.
The bounded executor consumed the stdin writer's verdict withtry_recv,
which removes the message, so the writer'sOk(())was discarded and the
later receive observed an empty, disconnected channel. Acrontab -install
reportedmanager(Spawn, …)after a write that in fact succeeded. This is
the first publication that carries the fix.eggup-core 0.1.3had no bounded stdin and an unbounded candidate
deadline.run_boundedevaluated its documented wall-clock deadline only
while the direct child was still alive, so a descendant that inherited the
output pipe could pin the call indefinitely, and the timeout path left both
reader threads unjoined.eggup-core 0.2.0addsCommandSpec::stdin_data
andMAX_STDIN_BYTES, makes the deadline an unconditional maximum bound on
the whole bounded execution, and classifies a stdin failure by the instant the
writer observed it.eggup-archive'scleanup()success path was unreachable. The shared
implementation emptied the owned tree and then unconditionally returned
Err(CleanupFailed). All four entry points now share one truthful contract,
andOk(())is reachable.eggup-eggpackno longer runs a second SHA-256 implementation. It
delegates toeggup_core::hash_file, and its directsha2runtime
dependency is gone.
eggup-service also gained one behaviour change worth reading about: the cron
managed block body must now embed the absolute executable path of the spec, so
a desired_block that omits spec.executable() receives
ServiceError::InvalidInput from inspect, install, and uninstall.
Verification
Every crate was proven from outside this repository: a fresh fixture crate with
no path, git, or patch source, depending on =0.2.0, whose generated lockfile
resolves only from crates.io. The eggup-service fixture resolves
eggup-core 0.2.0 transitively, and the eggup-eggpack fixture resolves all
three of its exact pins at 0.2.0.
0.1.3
Eggup 0.1.3
Correctness and compatibility publication for the acquisition, archive, and core
subsystems. Integrity evidence remains SHA-256 checksum only — no crate in this
release makes an authenticity or signature claim.
Per-package publication source commits
These are not all the tag commit. eggup-acquisition 0.1.3 had to publish
first, because the other publications in this train resolve or exact-pin it, so
it was released from an earlier commit than the tag:
| Package | Published from | Registry checksum |
|---|---|---|
eggup-acquisition 0.1.3 |
bb8fe41 |
71ce1a0d…a285a7 |
eggup-eggfetch 0.1.3 |
bd43683 (this tag) |
e2bdffe9…56ada |
eggup-archive 0.1.3 |
bd43683 (this tag) |
a28af652…9824c |
eggup-core 0.1.3 |
bd43683 (this tag) |
161b244b…789ad |
bb8fe41 is an ancestor of this tag. No existing tag was moved.
eggup-acquisition 0.1.3 — the composed-transport deadline defect is closed
Published 0.1.2 was built from a commit that predated two workspace bug-audit
fixes. The reachable one: ComposedTransport handed the fallback adapter the
caller's full FetchLimits instead of the remaining budget, so a single
composed fetch could run for roughly twice the documented total_timeout — the
connect phase is part of that wall-clock budget. The fallback now receives only
what is left, with connect_timeout clamped alongside it so
connect_timeout <= total_timeout still holds, and an already-exhausted budget
reports Timeout without starting a doomed attempt. The second fix removes a
staged part file that could be left behind when its 0600 hardening failed.
eggup-curl 0.1.2 and eggup-eggfetch 0.1.2 keep caret requirements and now
receive the fix automatically on their next resolve.
Still open for
eggup-eggpack 0.1.2: it exact-pinseggup-acquisition =0.1.2and therefore still composes against the defective seam. Consumers of
that adapter must pineggup-acquisition 0.1.3themselves until
eggup-eggpack 0.1.3publishes. This caveat is unchanged from the 0.1.2 notes.
eggup-eggfetch 0.1.3 — a fallible API no longer aborts the process
Runtime construction used .expect(), so a runtime-build failure (fd exhaustion,
driver creation failure) aborted the process from inside a fallible fetch; it now
returns AcquisitionError::Unavailable, which composition already knows how to
handle. The runtime is built once per calling thread rather than once per fetch,
which keeps EggfetchTransport Send + Sync — a stored runtime would make it
!Sync and break callers sharing one transport across threads. TooLarge now
reports the bound it actually enforces instead of 0.
eggup-archive 0.1.3 — Windows device aliases and truthful cleanup
validate_output_name rejected COM1..COM9 but accepted COM0/LPT0 and the
reserved console names CONIN$, CONOUT$, CLOCK$. All are now rejected.
Near misses such as com10 and console remain valid. residue_path() is now
truthful: a private root that still holds evidence is promoted to
CleanupFailed instead of being described as cleaned.
eggup-core 0.1.3 — self-update, stale-lock recovery, and a compatible error surface
First registry appearance of current-executable transaction parity (M010,
staging inside the installation root so a self-update never needs write authority
above the executable's own directory) and proof-authorized stale-lock recovery
(M011, opt-in; the default acquire still never recovers).
Compatibility. Error keeps exactly the seven variants 0.1.2
published, so an exhaustive match on it compiles unchanged across the upgrade.
This was verified by an external fixture that is byte-identical between the two
versions and that fails against the pre-correction tree. Retained evidence
moved to a new #[non_exhaustive] RecoveryError, used only by the new
opt-in recovery entry points; every previously published signature keeps
Result<T, Error>.
self-replace remains Windows-only, so the Unix/macOS dependency surface is
still sha2 only.
eggup-service 0.1.2 resolves and runs against this Core through its caret
requirement; that graph was proven from the registry with no path or Git
override.
Verification
Hosted Stable, MSRV (1.89), macOS, and Windows lanes green on the
publication commit. Every crate was additionally proven by registry-only
external fixtures that resolve from crates.io with no [patch], path, or Git
override — including control runs against the defective 0.1.2 packages to show
the fixtures actually detect the defects they claim to.
Publication is manual and is never performed by CI.
eggup-eggpack 0.1.3 — archive-member identity is now cross-checked
Added after the rest of the train; published from bd43683 (this tag), checksum
952e88b8…19c5.
Published 0.1.2 bound archive members to declared members positionally,
without cross-checking a bound member's recorded source_path/output_name
against the declaration it was about to represent. A mismatched or reordered
BoundExtraction could therefore bind bytes under a different member identity
whenever the content digests happened to match. Each bound member is now checked
against its declared counterpart and fails closed with
AdapterError::MapMismatch; identical-content members still cannot substitute for
one another.
This version also moves the adapter's exact Eggup dependency set to =0.1.3, which
closes the eggup-eggpack 0.1.2 caveat above: adapter consumers now receive
the acquisition composed-budget fix automatically, with no action required.
The adapter still selects no release, verifies no authenticity, and authorizes no
filesystem destination. Caller-bound destination APIs are unchanged.
Additional package publication — eggup-service 0.1.3 (2026-10-09)
Service M011 publishes the source-compatible M010 correction for stopping an
exact-owned failed systemd unit only after ownership, manager state, process IDs,
job state, and cgroup evidence prove quiescence. Foreign, malformed, restarting,
or still-populated units remain incomplete or denied. No public API migration is
required.
| Package | Source revision | crates.io checksum | Package size |
|---|---|---|---|
eggup-service 0.1.3 |
feb6ae5aea4c9b61c4051957f3662ca49d845f9e |
9f7f7ea854577158e66aa202709ab1c97a3aedcf00b06c1ab914d25b132124dc |
72.7 KiB compressed; 396.0 KiB unpacked |
The package-specific source is later than the shared v0.1.3 tag; that existing
tag remains unchanged. The exact-version registry-only fixture resolves
eggup-service = "=0.1.3" and eggup-core 0.1.3 from crates.io. Hosted run
37883703334 passed
Stable, Rust 1.89 MSRV, macOS, Windows, and the privileged Linux systemd lane,
including positive failed-unit quiescence and Foreign/malformed controls.
wg-basic Distribution M004 C001a adoption: change its service dependency to
eggup-service = "=0.1.3" and refresh the lockfile. The public API is unchanged;
the new runtime behavior lets its failed-candidate recovery path confirm an
owned failed unit is quiescent. M004 retains its independent rootful
qualification and production trust-root requirements.
Packaged changelog note: the immutable .crate includes the pre-upload
changelog snapshot from its recorded source revision, where 0.1.3 is labelled a
release candidate. The checked-in crate changelog and this release record now
reflect publication; the package bytes and checksum above are unchanged.
0.1.2
crates.io publication of the workspace 0.1.2 source version, in three steps.
Step 1 — 2026-09-28 (Verified Update Core M009), published in that order from
release-prep commit e8e07eb, tagged v0.1.2:
eggup-core 0.1.2— https://crates.io/crates/eggup-core/0.1.2eggup-archive 0.1.2(first publication) — https://crates.io/crates/eggup-archive/0.1.2
Step 2 — 2026-10-02 (Eggpack Manifest Interoperability M004), published in that
order from publication source 02a1d32:
eggup-acquisition 0.1.2— https://crates.io/crates/eggup-acquisition/0.1.2eggup-eggfetch 0.1.2— https://crates.io/crates/eggup-eggfetch/0.1.2eggup-eggpack 0.1.2(first publication) — https://crates.io/crates/eggup-eggpack/0.1.2
Step 3 — 2026-10-04 (Acquisition Transport M009), published from release-prep
commit b485228:
eggup-curl 0.1.2(first publication) — https://crates.io/crates/eggup-curl/0.1.2
Complete crates.io 0.1.2 publication set: eggup-core, eggup-archive,
eggup-acquisition, eggup-eggfetch, eggup-eggpack, eggup-curl.
eggup-service and eggup-transport-footprint share the 0.1.2 source version
and are still not published. eggup-transport-footprint is
publish = false by design and has no edge in the published adapter graph.
Step 3: the external-curl adapter promoted to the registry
eggup-curl implements AcquisitionTransport on top of an external curl
process, so a consumer can acquire artifacts without embedding an HTTP/TLS
stack in its binary. It was fully qualified under Acquisition M005–M008 but had
never been published, which left the lightweight path reachable only from a
local checkout. M009 published it as a package promotion; no transport
semantics changed, and no crates/ source, manifest, or version was edited.
What the published version carries:
- Exact caller-selected URLs only. No discovery and no fallback inside the
adapter; release/version/mirror policy stays caller-owned. - A caller-supplied
curlexecutable invoked with no shell and no internal
sudo. Transport fallback (curl <-> Eggfetch) lives in
eggup-acquisition::ComposedTransportand is never release/source fallback. - Explicit connect/total ceilings as
min(request, adapter)plus an
independent parent wall deadline, serialized at microsecond precision so
sub-second ceilings are passed truthfully instead of being widened. - Cancellation and timeout kill and reap the owned child before returning.
- Exact HTTP 404 becomes
FetchOutcome::NotFound; TLS/5xx/timeout/cancellation/
size/staging failures stay hard acquisition failures. - Bounded streaming into Eggup-owned staging with a private temp sibling and
race-safe no-clobber promotion. The temp pathname is never handed back to
curl for reopening. - Redirect, protocol, and proxy policy are explicit. Diagnostics use category
text plus the redacted URL, so raw curl output, command lines, and proxy
credentials never appear in an error.
Two defects from the 2026-10-04 workspace bug audit are fixed in this
version, because it was published after that commit: an https request could
previously follow a redirect down to cleartext http with no error and no
diagnostic (--proto-redir is now narrowed per request), and coincident
connect/total ceilings mislabelled a total-deadline timeout as a connect
timeout.
Platform note
Live local HTTP/curl evidence is carried by the Linux and macOS lanes. Hosted
Windows runners refused the historical spawned-curl loopback case, so the
Windows lane carries the portable adapter, process, and error-path fixtures
only. No Windows live HTTP/curl result is claimed for this release.
Known caveat: eggup-acquisition 0.1.2 published content
eggup-acquisition 0.1.2 was published from 02a1d32 on 2026-10-02 and does
not contain the two workspace bug-audit fixes that landed afterwards in
0b8cb98:
- the owned
.partfile leaked when the permission-hardening step failed; ComposedTransporthanded the secondary adapter the caller's full
FetchLimitsinstead of the remaining budget, so one composed fetch could run
for roughly twice the caller's documented total deadline.
The second is reachable today by any consumer that composes two transports from
the registry. Until eggup-acquisition is republished with the fix, such
consumers should either pin a later version or set a total deadline that
tolerates the doubled composed window. This predates step 3 and is not
introduced by it. eggup-curl keeps a caret-compatible eggup-acquisition
requirement, so it inherits an eggup-acquisition 0.1.3 automatically once one
is published.
M004: producer manifest promoted to the registry
eggup-eggpack previously pinned eggpack-manifest to an immutable Eggpack Git
revision and was publish = false, so the adapter could not be consumed from a
registry at all. Eggpack published eggpack-manifest 0.1.0 on 2026-10-02
(https://crates.io/crates/eggpack-manifest/0.1.0), and M004 promoted the adapter
to the exact registry dependency eggpack-manifest = "=0.1.0".
The published eggpack-manifest 0.1.0 src/lib.rs is byte-identical to the
source at the revision the adapter used to pin, so this is a promotion of the
same bytes rather than a substitution of a source. No adapter requalification
was needed.
The adapter also gains the caller-bound destination seam:
ManifestProjection::default_destinationsmaterialize_artifact_set_with_destinationscore_plan_for_archive_with_destinations
Manifest install values remain producer default identity only. The adapter
still selects no release, verifies no authenticity, and authorizes no
filesystem destination.
Why the publication order matters
cargo package and cargo publish resolve the packaged manifest's
dependencies from crates.io, so the order is a hard constraint, not a
convention. Before eggup-acquisition 0.1.2 existed, eggup-eggfetch 0.1.2
could not pass its own package verification (two E0308 mismatches: the
published 0.1.1 seam types max_artifact_bytes as Option<u64> while the
0.1.2 finite-bounds seam types it as u64), and eggup-eggpack 0.1.2 could
not produce a package at all because its exact =0.1.2 pin had no registry
candidate. Publishing acquisition first resolved both. Step 3 was likewise
ordered after step 2 so that eggup-curl's packaged manifest had a registry
candidate for its eggup-acquisition requirement.
Verification
Hosted CI green on each publication source (Stable checks, MSRV check,
macOS tests, Windows archive/acquisition/service tests). cargo package and
cargo publish --dry-run clean for all six crates from a clean tree with no
--allow-dirty.
Three temporary external projects outside the repository, with only registry
dependencies and no [patch], path, or Git override, resolved exact =0.1.2
and passed smoke: the adapter-only graph, the Eggsact-shaped four-crate graph,
and the eggup-curl graph. The last one exercises the published package end to
end — public API construction, deadline-ceiling clamping, typed unavailability
for an unspawnable executable, typed cancellation, and live loopback HTTP where
200 is an ordinary success, exact 404 is NotFound, and an artifact stream is
promoted into caller-owned staging — 6/6 passing. All three lockfiles show one
registry source per package with no git+ or path entry, and the lockfile
checksums match the registry.
Source tag caveat
The v0.1.2 tag was not moved and still points at e8e07eb. As of the
2026-10-04 bug-audit commit, none of the six published crates is
reproducible from that tag any more; each has moved since it. Do not treat
v0.1.2 as a source reference for any published artifact. Each crates.io
version instead carries its own exact publication commit in
.cargo_vcs_info.json:
eggup-core,eggup-archive—e8e07ebeggup-acquisition,eggup-eggfetch,eggup-eggpack—02a1d32eggup-curl—b485228
Contract
MSRV 1.89, edition 2021, MIT. Integrity is SHA-256 checksum evidence only; no
authenticity or signature verification is claimed by any crate in this release.
Egress archive/pair adoption (Consumer M006 / Egress Delivery M003) is
unblocked against the published packages. The producer manifest seam is now
registry-consumable; Eggsact's own Git-to-registry migration remains separately
authorized in eggstack/eggsact. The cargo-cleanme Phase 10 self-update path is
unblocked against the published eggup-curl; cargo-cleanme retains
release/version/fallback/install policy.
0.1.1
Lockstep patch release over 0.1.0, published to crates.io in seam-then-adapter order: eggup-acquisition, eggup-core, eggup-eggfetch, eggup-service (all 0.1.1). eggup-eggpack remains unpublished by design.
Highlights since 0.1.0 (see CHANGELOG.md for the full list):
- core: canonical Absent | Owned | Foreign | Unknown ownership, staged-digest revalidation under lock, ADR-0002 post-commit KeepInstalled | RollBack policy
- acquisition + eggfetch: effective min(request, adapter) timeouts, race-safe no-clobber promotion, credential redaction
- service: Unix adapters (systemd/launchd/cron), M003 hardening, Windows SCM adapter, commit_with_lifecycle composition
- consumer evidence: eggsact, stegoeggo, eggsearch, CodeGG M005
MSRV 1.89. Integrity is SHA-256 checksum evidence only; no authenticity claims.