diff --git a/CHANGELOG.md b/CHANGELOG.md index e64db75..8aab4e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,45 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`). --- +## Unreleased + +### Changed + +- **pi-studio `v0.10.2` → `v0.10.4`** (`c83940d`, `-studio` tags only). Two + upstream patch releases on 2026-10-19. 0.10.3: IPython prints a value once + (`Out[5]: …`), not twice, and after a Quick send the cursor returns to the + input box. 0.10.4: Stop works again on a Mac that has a process running as + `nobody`. That was a 0.10.2 regression: macOS lists that uid as `-2`, and the + 0.10.2 parser refused to stop anything. **It does not affect the image**: + inside the container, `ps` shows only the container's own processes, and none + has a negative uid. Measured 2026-10-19 on tor-ms22. 0.10.2's own + `readStopProcessTable` parsed the live process table (9 rows, min uid 1000). + Control: a macOS-style `-2` row made it throw "Could not parse process + ownership data". Dependencies unchanged: `package-lock.json` packages are + identical to 0.10.1's, and `ws` is still the only runtime dependency. Loaded + into pi `1.3.0` with `pi --no-extensions -e /index.ts -p`, it registers + the same four `studio_*` tools, rc 0. + +### Fixed + +- **`~/.ssh/config` is Included even if it appears after the container + started.** Same rule as the `ssh-lan.conf` fix in v1.12.1. `setup-lan-access.sh` + wrote `Include ~/.ssh/config` into `~/.ssh-local/config` only if + `~/.ssh/config` was readable at container start, so a file that appeared + later (a host provisioned after its first `docker compose up`) was ignored + until a restart. Entries *added* to a file that already existed were never + affected: ssh reads Included files on every connection, and the bind mount is + live. Measured 2026-10-19 on tor-ms22: on the Mac, a newly created file, an + atomic replace (write + `mv`, as editors do) and an append each showed up in + the container within a second. The line is now written whether or not the + file exists. A file that exists but is unreadable is still left out, with a + warning on stderr, because ssh would abort every connection. When the file + exists at start the generated config is byte-identical to v1.12.1's (checked + with and without `ssh-lan.conf`). When it is absent, the only difference is + the added Include block. `scripts/smoke-test.sh` gains two checks, Included + when created after start and left out when unreadable. Against the v1.12.1 + script the first fails and the second passes; against this one both pass. + ## v1.12.1 — 2026-10-19 Patch release. Headline: **`ssh-lan.conf` is Included even if it is created diff --git a/rootfs/usr/local/lib/pi-devbox/setup-lan-access.sh b/rootfs/usr/local/lib/pi-devbox/setup-lan-access.sh index 5a1362f..8f59fd8 100755 --- a/rootfs/usr/local/lib/pi-devbox/setup-lan-access.sh +++ b/rootfs/usr/local/lib/pi-devbox/setup-lan-access.sh @@ -196,8 +196,17 @@ EOF fi fi +# Same rule as ssh-lan.conf above: Included even when ~/.ssh/config does not +# exist yet, so a file that appears after container start (a host provisioned +# after its first `docker compose up`) is read on the next ssh. Entries added to +# a file that already existed were always picked up: ssh reads Includes on every +# connection and the mount is live. Through v1.12.1 the line was written only if +# the file was readable at start. Only a file that EXISTS but cannot be read is +# left out, because ssh would then abort every connection, git included. INCLUDE_BLOCK="" -if [ -r "${HOME}/.ssh/config" ]; then +if [ -e "${HOME}/.ssh/config" ] && [ ! -r "${HOME}/.ssh/config" ]; then + echo "setup-lan-access: ${HOME}/.ssh/config exists but is not readable, so it is not Included (ssh would refuse every connection). Fix its permissions, then rerun this script or restart the container." >&2 +else INCLUDE_BLOCK=$(cat <<'EOF' # Your own target hosts. Scope reset to match-all so this Include applies to diff --git a/scripts/smoke-test.sh b/scripts/smoke-test.sh index 2346af1..7c5a19c 100755 --- a/scripts/smoke-test.sh +++ b/scripts/smoke-test.sh @@ -719,6 +719,28 @@ exec_test "unreadable ssh-lan.conf left out (ssh would abort)" ' ! grep -q "ssh-lan.conf$" $T/.ssh-local/config && HOME=$T ssh -F $T/.ssh-local/config -G lanpeer >/dev/null 2>&1 r=$?; rm -rf $T; exit $r' +# ~/.ssh/config gets the same rule as ssh-lan.conf above: Included whether or +# not it exists at container start, except when it exists but cannot be read. +# Entries added to a file that already existed at start were always picked up +# (ssh reads Includes on every connection, and the mount is live). This covers +# only a file that appears after start, e.g. a host provisioned after its first +# `docker compose up`. Through v1.12.1 that file was ignored until a restart. +exec_test "~/.ssh/config Included even if created after start" ' + T=$(mktemp -d) && + HOME=$T DEVBOX_LAN_ACCESS=jump bash /usr/local/lib/pi-devbox/setup-lan-access.sh >/dev/null 2>&1 && + grep -qx "Include ~/.ssh/config" $T/.ssh-local/config && + HOME=$T ssh -F $T/.ssh-local/config -G ownpeer 2>/dev/null | grep -qx "hostname ownpeer" && + mkdir -p $T/.ssh && printf "Host ownpeer\n HostName 10.8.8.8\n" > $T/.ssh/config && + chmod 600 $T/.ssh/config && + HOME=$T ssh -F $T/.ssh-local/config -G ownpeer 2>/dev/null | grep -qx "hostname 10.8.8.8" + r=$?; rm -rf $T; exit $r' +exec_test "unreadable ~/.ssh/config left out (ssh would abort)" ' + T=$(mktemp -d) && mkdir -p $T/.ssh && printf "Host x\n" > $T/.ssh/config && + chmod 000 $T/.ssh/config && + HOME=$T DEVBOX_LAN_ACCESS=jump bash /usr/local/lib/pi-devbox/setup-lan-access.sh >/dev/null 2>&1 && + ! grep -qx "Include ~/.ssh/config" $T/.ssh-local/config && + HOME=$T ssh -F $T/.ssh-local/config -G ownpeer >/dev/null 2>&1 + r=$?; chmod 600 $T/.ssh/config; rm -rf $T; exit $r' # The vendored mempalace snapshot is refreshed MANUALLY per release (see # rootfs/usr/local/share/pi-devbox/skills/VENDORED.md). Through v1.8.4 it also # silently SHADOWED the live skillset copy, so staleness was invisible — and the