Add beta update channel and harden in-place updates #2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/beta-updates"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this PR does
Adds a beta update channel to the
updatesplugin, and hardens the in-place update path, following an adversarial review of it.Beta channel
X.Y.Z(stable) orX.Y.Z-beta.N(beta); the Release workflow refuses anything else. It publishes betas as Forgejo pre-releases and skips PyPI for them.betaoption (a checkbox, off by default). Versions compare by SemVer rules, so0.7.0-beta.1<0.7.0-beta.2<0.7.0.Hardening (numbers refer to the review findings)
pi-owned/var/lib/kestrel/update/, where a planted symlink could redirect a root write.O_EXCL|O_NOFOLLOW) and never chowned. Previously,chown pi:pithrough a symlink handed any file on the device topi./var/lib/kestrel/update-run/.update applytakes host, repo and token only fromconfig.toml, then re-verifies the release as root with a newupdate-apply --verifystep. That step checks: published, not a draft, newer than the installed version, on the device's channel, an app-layer manifest that pins a commit, and no reflash release skipped in between. Thepi-written state file is only a hint for which release to check.pi.kestrel-update-recover.servicerolls back an interrupted update at boot.--unit=kestrel-updatename, stops two updates running at once.plugins-ctlas--expect TAG, so the update installs exactly what the operator confirmed.--refgoes through the same verification.--forceoverrides only the safety checks, and lists each one it overrode.GIT_CONFIG_*environment variables, so it's no longer in the process's arguments.Release signing (#3) is deferred on purpose. The new
docs/developer/deferred.mdtracks it, along with the other items deferred here, and CLAUDE.md points to it.Checklist
make lint(ansible--syntax-check,yamllint,shellcheck --severity=error). The Lint workflow runs this on the PR.make test(thekestrel_pipytest suite). The Test workflow runs this on the PR..envfiles, real names, personal emails, MAC addresses, device serials, or GPS coordinates — placeholders only.docs/, and the on-device operator guide (GUIDE_MDinkestrel_pi/userguide.py) where it applies.Release impact
kestrel_pipackage,plugins/*.py, systemd units, the journald drop-in, a lib script already in the engine'sLIB_SCRIPTS, or the CLI.config.txt/cmdline, kernel modules, the base image or partition size,builder/config.json,builder/config.yml, theMakefile,.forgejo/workflows/, a shipped config default (config.toml/default.conf), or a brand-new lib script.This touches
.forgejo/workflows/main.ymlandbuilder/config.yml(the new root-owned run folder and enabling the recovery unit), so leaveupdate_kindonauto. The engine, CLI, plugin, web page and new unit would themselves reach devices in place. A device updated in place also creates the run folder and enables the recovery unit itself.Notes for review
--verifyrun against the real release server. That run refused 1.0.0 with its own manifest's reflash reason, and refused an unpublished tag. Worth trying on a device before cutting a release: a real update, the health-check rollback, and a power cut during an update.--statepath. The new engine ignores that path, so even that run never writes root state into thepifolder. Every update after that uses the new path.deferred.md.HEALTH_TIMEOUT/HEALTH_SETTLEinupdate-apply.py).🤖 Generated with Claude Code