Skip to content

Bump espex to 0.9 and nerves_github_updater to 0.2 - #166

Merged
bbangert merged 1 commit into
mainfrom
chore/bump-espex-0.9-updater-0.2
Aug 15, 2026
Merged

Bump espex to 0.9 and nerves_github_updater to 0.2#166
bbangert merged 1 commit into
mainfrom
chore/bump-espex-0.9-updater-0.2

Conversation

@bbangert

Copy link
Copy Markdown
Owner

Picks up the two library-side security fixes from the /phx:review of #161.

Package Old → New Brings
nerves_github_updater 0.1.1 → 0.2.0 B3 — same-version reinstall refused
espex 0.8.0 → 0.9.0 B2 groundwork — handle_command/2 security context

Lock diff is exactly those two packages; nothing else moved.

nerves_github_updater 0.2.0 — takes effect immediately

The version gate only guarded :lt, so :eq fell through and re-downloaded, re-flashed and rebooted into identical firmware. That was a replay vector: handle_call(:install_latest, ...) rejects only concurrent installs, so once one finished nothing stopped the next — anything able to reach install_latest/1 could loop a device indefinitely, at the same version, with real flash wear.

No app change needed. :allow_reinstall defaults to false, which is the posture we want, and I checked both install entry points already gate on there being a newer version — the web UI on update_available?/2, HA's update card on latest_version != current_version — so neither UI regresses. grep confirms nothing in lib/, test/ or config/ relies on reinstall.

espex 0.9.0 — groundwork, inert on this branch

0.9.0 adds the optional EntityProvider.handle_command/2 carrying %{encrypted?: boolean()}. Nothing on main implements it, so espex keeps calling /1 exactly as before — this bump changes no behaviour today.

The constraint moves to ~> 0.9 rather than staying ~> 0.8 for a specific reason: ~> 0.8 admits 0.8.0, and a provider that implements /2 compiles fine against 0.8.0 and is never called, because 0.8.0's handler only invokes /1. Since that callback is the gate refusing firmware-install and factory-reset on unauthenticated connections, resolving to 0.8.0 would leave the security check silently inert with nothing failing to indicate it. Pinning ~> 0.9 makes that unrepresentable.

Verification

  • mix compile --warnings-as-errors — PASS
  • mise run test953 passed, 3 excluded (matches main's baseline)
  • mix dialyzer — PASS (7 errors, 7 skipped, 0 unnecessary skips)
  • mix format --check-formatted — clean
  • MIX_TARGET=rpi3 mix compile — PASS

Follow-up

#162 (the privileged-command gate, B2) is a draft pinned to an espex branch. Once this merges it should be rebased onto it and its git pin dropped — the ~> 0.9 constraint here is what it needs. Happy to do that rebase on request.

🤖 Generated with Claude Code

nerves_github_updater 0.2.0 refuses installing the version already
running, closing a replay vector: the busy guard rejects only concurrent
installs, so anything able to reach install_latest/1 could previously
loop a device indefinitely at the same version. No app change needed —
:allow_reinstall defaults to false, which is the behaviour we want, and
both install entry points already gate on there being a newer version.

espex 0.9.0 adds the optional EntityProvider.handle_command/2 carrying
the connection's security context. Nothing uses it yet on main; the
constraint moves to ~> 0.9 so that when the privileged-command gate
lands it cannot silently resolve against 0.8.0, where a provider
exporting /2 compiles fine and is simply never called.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bbangert
bbangert merged commit 4a6f4df into main Aug 15, 2026
6 checks passed
@bbangert
bbangert deleted the chore/bump-espex-0.9-updater-0.2 branch August 15, 2026 22:16
@bbangert bbangert mentioned this pull request Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant