All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[0.2.0] - 2026-08-15
Changed
Installing the version already running is now refused. The version gate gated only
:lt, so an:eqcomparison fell through and re-downloaded, re-flashed and rebooted into the same firmware. That achieves nothing while costing a download, a flash-cycle of wear and a reboot — and it is a replay vector, because the busy guard rejects only concurrent installs and never repeats, so any caller able to reachinstall_latest/1could loop a device indefinitely.:eqnow fails as{:reinstall_refused, tag}.Set the new
:allow_reinstallopt (defaultfalse) to keep the old behaviour, or for a deliberate re-flash such as recovering a corrupted partition. It is a mutable opt, soupdate_config/2can flip it at runtime like:allow_downgrade.:gt,:missingand:incomparableare unaffected.This is a behaviour change for anyone relying on same-version reinstall, hence the minor bump.
[0.1.1] - 2026-07-16
Fixed
- Isolate the
fwupport in a monitored worker process so an fwup process that dies mid-stream (broken pipe /:epipe) surfaces as{:error, {:fwup_port_exit, reason}}instead of propagating an exit signal that crashes the caller. Adds host-safe unit coverage for the port-streaming path via a fake fwup executable. Updater.state/1andupdate_config/2no longer crash a caller that polls during a long check/install (the loop blocks by design): they return a busy snapshot /{:error, :busy}on call timeout.- Bound the manifest (4 MiB) and signature (64 KiB) downloads so an oversized pre-verification asset can't exhaust device memory.
Changed
Signature.verify_manifest/3returns:invalid_public_key_size(distinct from:missing_public_key) for a wrong-length key.- Drop the unused
nerves_runtimedependency — KV/reboot/target are all opts-injected — which also removes thelibmnlbuild requirement in CI. - Bump
aws-actions/configure-aws-credentialsandactions/cacheto v6.
[0.1.0] - 2026-07-16
Added
- Signed release-manifest verification: Ed25519 signature over a
sha512digest of the manifest, per-target asset/sha256/size pinning, and a monotonic rollback counter persisted via host-supplied:kv_get/:kv_put. SeeNervesGithubUpdater.ManifestandNervesGithubUpdater.Signature, andguides/manifest-format.mdfor the wire contract. - Legacy unverified install path (
verification_required: false) for bootstrapping fleets before a signing key is provisioned, gated by an audit-trailLogger.warningon every unverified install. :channelsupport (:stable/:prerelease) and a downgrade gate (:allow_downgrade, defaultfalse) comparing release tags against the running firmware version.- Streamed, incrementally-hashed asset downloads
(
NervesGithubUpdater.GithubClient) with atomic.part→ rename, a hard size ceiling against runaway/malicious responses, andIf-None-Match/ETag support to avoid burning GitHub API rate limit. NervesGithubUpdater.Fwup: a length-framedfwup --apply --framingwrapper over an Erlang Port, with progress callbacks and a documented caller-must-serialize contract.NervesGithubUpdater.UpdaterGenServer state machine (:idle/:checking/:verifying/:downloading/:flashing/:error) with PubSub progress broadcasts and runtimeupdate_config/2for mutable opts.NervesGithubUpdater.VersionComparefor semver-aware "update available" / "up to date" comparisons independent of the install flow.NervesGithubUpdater.Supervisoras the library's single public entry point for host supervision trees.