0.8.0 โ 2026-09-25
Upgrading: corral upgrade, then corral rebuild <box> for every box โ the template changed (every box shows as drifted in list).
Added
- Per-box egress log (#15). Every box with a broker (
network = "broker", orapi_brokers) now gets~/.corral/logs/egress-<box>.jsonl: one line per connection the box attempted through the broker โhost:portandallowed/deniedโ plus everyapi_brokerscall (route, method, path, upstream status) and asession start/endmarker with the session id and exit code, so one run's traffic can be sliced out of a long-lived box. Until now the broker only counted allowed connections and audited denials, so "a box ran untrusted dependency code โ what did it try to reach?" had no answer. Names only, never payloads.corral egress <box>gains a Destinations attempted section (deduplicated, denied first, with counts and last-seen), plus--log(the record in order,<time> <box> <host:port> allowed|denied),--since 2hand--json. The log is rotated at 16 MiB (one generation kept) and outlives the box on purpose;corral gcremoves a deleted box's log after 14 days. The audit log (sessions.jsonl) is unchanged. No template change. - Contributor workflow: issue forms with status labels, a pull request template, a Code of Conduct, Dependabot, and an issue-first process documented in CONTRIBUTING.md.
mainis protected: every change lands via pull request with all CI checks green, so a work item is never closed by a broken build.
Changed
- Under
network = "broker"/"offline", docker is installed but not usable by the box user, and repositoryprovisionscripts run withoutsudo(usepackages = [...]). Template hash changes for broker/offline boxes:corral rebuildthem.
Fixed
- Box metadata is now written atomically (temp file + rename) (#18). Several processes read and write it at once โ the launcher, the broker child it has just spawned, a second session, the idle sweep โ and the old truncate-then-write left a window in which a reader saw an empty file. The visible symptom was a first
corral up/runon anetwork = "broker"box occasionally failing withegress broker โฆ did not come up(the child had loggedunknown box) while the box itself was fine; the next command worked. corral upgradenow runsbrew updatefirst (#19). Homebrew auto-updates at most once a day, so a user whose Homebrew had refreshed in the last 24 h was told "corral X already installed" while the tap already carried a newer formula.corral upgradeis meant to be the one command, and now it is.- Dashboard: while a start/stop/delete runs, the busy line now shows the elapsed time and
lopens the log pane in follow mode so the whole operation can be trailed; previously every key was blocked and nothing moved until the state change landed. - The test suite no longer writes a stray box metadata stub (
boxes/x.json) into the developer's real~/.corralโTestSessionBeforeMetadataIsAdoptednow runs under a tempCORRAL_HOME.
Security
network = "broker"/"offline"no longer leave guest root reachable through thedockergroup (#16). The lockdown removedsudobut not thedockergroup, andtoolchains = ["docker"]is a key a repository may set, so a repo-owned.corral.tomlgot guest root back (the daemon runs a container with/mounted). A newcorral-drop-privilegesstep now removes the box user fromsudo,admin,docker,lxd,incus-adminanddisk, makes/run/docker.sockroot-only (a process that kept a stale docker gid cannot reach it either) and fails closed if any member remains. It runs before the project'sprovisionscripts: those were already user-only in these modes, but still ran with the box user's NOPASSWDsudo, so a repository script could pre-empt the lockdown the same way. The broker/offline units call it again before every session.doctor <box>/run --preflightgain acontrol privilegescheck; the launcher warns that docker is root-only in these modes. The VM/Mac boundary was never affected.toolchainsstays project-ok โ the group, not the install, is the problem.- No unattended package installer inside a box (#17). Ubuntu's
apt-dailyandapt-daily-upgradetimers were enabled in every box: they fire on a schedule and try to download and install.debs. Undernetwork = "broker"the broker refused them, burying the denials that matter incorral egress; undernetwork = "full"they could change a box's toolchain under a running agent.base.shnow masks both timers and their services and turns theAPT::Periodicknobs off before its ownapt-getruns;apt-getin toolchains andpackagesis unaffected. Template change: every box shows drifted โcorral rebuild.