Skip to content

feat!: move to Debian 13, Node.js 26, uv 0.13.4 and Rust 1.99.1 - #8

Merged
kalaspuff merged 4 commits into
mainfrom
fctl/107-let-s-update-the-dependencies-in-the-san
Oct 21, 2026
Merged

kalaspuff merged 4 commits into
mainfrom
fctl/107-let-s-update-the-dependencies-in-the-san

Conversation

@fctl-sh

@fctl-sh fctl-sh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Moves the image to Debian 13 and its pinned tools to their latest releases, so that sessions run with current tooling, and checks on every pull request that changes the image that fctl's own development works in it.

Before After
Debian 12 (bookworm) 13 (trixie)
Node.js 22 26
corepack 0.36.0, bundled with Node.js 22 0.36.0, from npm
uv 0.13.1 0.13.4
Rust 1.99.0 1.99.1

TypeScript 7.0.2, Bun 1.4.3 and Python 3.15.0 are already the newest that can be installed. Python 3.15.1 came out today, but uv has no build of it yet (python-build-standalone's newest, 20261020, has 3.15.0); it can follow once uv has one.

Debian 13. Debian 13 has been stable since August 2025 (13.7 now), and 12 is oldstable. Debian's tools in the image move with it: git 2.39 → 2.47, gcc 12 → 14.2, cmake 3.25 → 3.31, curl 7.88 → 8.14, jq 1.6 → 1.7.1, ripgrep 13 → 14.1, ShellCheck 0.9 → 0.10, sqlite 3.40 → 3.46, and Debian's Python, which NodeSource's Node.js depends on, 3.11 → 3.13. provision.sh needs no change for it and still works on Debian 12, which fctl's Lima driver provisions on hosts of fctl 0.14 and earlier and with Lima before 2.0; AGENTS.md and the change-the-image skill say so.

Node.js 26. Node.js 22 has been in maintenance since October 2025, and 24 since 2026-10-20. 26 becomes the active LTS on 2026-10-28 and is supported until April 2029 (schedule). NodeSource publishes it for amd64 and arm64, with npm 11.20 (22 has npm 10.9). Node.js stopped shipping corepack in 25, so provision.sh installs it from npm along with TypeScript, pinned to 0.36.0, the version Node.js 22 bundles now; npm links corepack and its yarn, yarnpkg, pnpm and pnpx shims in /usr/bin, the links corepack enable used to make. A project that still needs Node.js 22 can install it in an image of its own (Sandbox images).

uv 0.13.4 removes the emSign root certificate from the certificates it bundles (GHSA-hq85-5cpj-mr62, high). Rust 1.99.1 fixes regressions in 1.99.0 (announcement); it is the release fctl builds with, and hyperstructure/fctl#168 moves fctl's rust-toolchain.toml to it.

fctl's development in the image. Sessions that work on hyperstructure/fctl build, test and run it in this image, so a new Develop fctl workflow (.github/workflows/fctl.yml) builds a pull request's image for both architectures and runs check-fctl.sh in each, started as fctl hosts start sandboxes (--init, 4 CPUs, 8 GB). It does what such a session does:

  • cargo xtask check, what fctl's CI checks: rustfmt, the generated types, Biome and TypeScript, Clippy for the workspace and for wasm32, cargo test, the web app's and the standalone server's tests, and the web app's production build;
  • cargo xtask dev --smoke, a session through the local stack (wrangler, Vite, a host with fake-claude), which installs worker-build on the way;
  • npm install, which must leave package-lock.json as it is, so that agents adding a package don't rewrite the rest of it;
  • cargo xtask serve and a session through that standalone control plane;
  • screenshots of the web app with Playwright and Chromium, installed with --with-deps as fctl's screenshots skill does, kept as the run's artifacts.

It checks hyperstructure/fctl's branch of the pull request's name when there is one (an fctl session that changes both repositories names their branches alike), else main. For this pull request, that is hyperstructure/fctl#168, which also refreshes fctl's lockfile: npm 11 rewrote it otherwise. The workflow runs on pull requests that change the image, the script or itself, takes 10 to 13 minutes, and isn't required to merge. The Lint workflow runs ShellCheck on the script too.

Size. Debian 13's base image is 3 to 4 MB larger than Debian 12's, the Debian packages the image installs about 28 MB (amd64), and NodeSource's Node.js 26 about 55 MB more than 22. The published image is 0.80 GB compressed and 2.19 GB unpacked on amd64 (0.75 and 2.08 GB on arm64), so this adds about 90 MB unpacked; the Image run's summary lists each architecture's size.

Verification

  • The Image workflow builds both architectures on Debian 13 and check.sh passes in each (run), with Node.js 26.12.1, corepack 0.36.0, TypeScript 7.0.2, Bun 1.4.3, uv 0.13.4, Python 3.15.0 and Rust 1.99.1, the GitHub CLI 2.103.0, fctl 0.14.1 and Claude Code 2.1.306. Before the Debian 13 commit, the same provision.sh passed check.sh on Debian 12 too (run), as the Lima VMs of older hosts need.
  • The Develop fctl workflow passes on both architectures with feat(host): prepare Lima sandboxes on Debian 13, like the sandbox image fctl#168's branch (run): cargo xtask check (all of it, the web app's 350 tests too), a session through cargo xtask dev, which installed worker-build, an unchanged lockfile after npm install, a session through cargo xtask serve, and screenshots of the signed-in home page in the light theme and the dark one at phone width, for which Playwright installed Chromium's libraries from Debian 13. The screenshots are the run's artifacts.
  • In the session (arm64, Debian 12, without Docker), check-fctl.sh passes with Node.js 26.12.1 first on the PATH, in 8 minutes; its screenshot shows the signed-in home page. Node.js 26 with npm install -g corepack@0.36.0 typescript@7.0.2 links corepack, yarn, yarnpkg, pnpm, pnpx and tsc, and uv 0.13.4 installs Python 3.15.0 as provision.sh does.
  • ShellCheck and actionlint pass.

Merge it before hyperstructure/fctl#168: that pull request's docs build an example on the 0.14 tag, which this one's merge rebuilds on Debian 13.

Made in fctl session https://app.fctl.sh/s/ses_01M5FGH6RENBJVF1MS02X2MB51

BREAKING CHANGE: images built FROM this one get Debian 13's packages and Node.js 26. Those that install a package named after a Debian 12 version need Debian 13's name (libicu76 for libicu72), and those that need Node.js 22 install it themselves.

Node.js 22 has been in maintenance since October 2025 and 24 since
2026-10-20; 26 becomes the active LTS on 2026-10-28, supported until
April 2029. Node.js stopped shipping corepack in 25, so it now comes
from npm, pinned like TypeScript; npm links its yarn and pnpm shims,
which `corepack enable` used to make.

uv 0.13.4 updates the root certificates it bundles
(GHSA-hq85-5cpj-mr62). Rust 1.99.1 fixes regressions in 1.99.0;
hyperstructure/fctl moves its rust-toolchain.toml with it.

TypeScript 7.0.2, Bun 1.4.3 and Python 3.15.0 are the latest that can
be installed: uv has no build of Python 3.15.1 yet.
@fctl-sh
fctl-sh Bot requested a review from kalaspuff as a code owner October 21, 2026 15:25
fctl-sh Bot added a commit to hyperstructure/fctl that referenced this pull request Oct 21, 2026
…o it

hyperstructure/sandbox#8 moves the default image to Debian 13 (trixie).
`fctl host image build --driver lima` now prepares the base VM from
Lima's Debian 13 template, so Lima sessions get the same Debian. Lima
added that template in 2.0: with an older Lima, the VM gets Debian 12,
as before, and the command says to upgrade Lima.

The Sandbox images page says the image is Debian 13, and its .NET
example installs Debian 13's ICU (libicu76) on a tag that has it.
fctl-sh Bot added 2 commits October 21, 2026 16:13
Debian 13 (trixie) has been stable since August 2025, and Debian 12 is
oldstable: the image gets trixie's git, gcc, cmake, Python 3.13 (which
Node.js depends on) and the rest. provision.sh still works on Debian 12,
which fctl's Lima driver provisions with Lima before 2.0 and on hosts of
fctl 0.14 and earlier.

BREAKING CHANGE: images built FROM this one get Debian 13's packages.
Those that install packages named after a Debian 12 version need Debian
13's names, like libicu76 for libicu72.
Sessions that work on hyperstructure/fctl build, test and run it in the
image. The Develop fctl workflow builds a pull request's image for both
architectures and runs check-fctl.sh in each: what fctl's CI checks, a
session through its local stack and one through its standalone control
plane, an npm install that must leave its lockfile as it is, and
screenshots of its web app with Playwright, as fctl's screenshots skill
takes them. It uses fctl's branch of the pull request's name when there
is one, so that a change to both repositories is checked together.
@fctl-sh fctl-sh Bot changed the title feat: upgrade Node.js to 26, uv to 0.13.4 and Rust to 1.99.1 feat!: move to Debian 13, Node.js 26, uv 0.13.4 and Rust 1.99.1 Oct 21, 2026
@kalaspuff
kalaspuff merged commit 0b35e05 into main Oct 21, 2026
11 checks passed
@kalaspuff
kalaspuff deleted the fctl/107-let-s-update-the-dependencies-in-the-san branch October 21, 2026 17:42
kalaspuff pushed a commit to hyperstructure/fctl that referenced this pull request Oct 21, 2026
…ge (#168)

[hyperstructure/sandbox#8](hyperstructure/sandbox#8)
moves the sandbox image to Debian 13 (trixie), Node.js 26, uv 0.13.4 and
Rust 1.99.1, and checks on its pull requests that fctl's own development
works in it. fctl follows it:

- **Lima sandboxes on Debian 13.** `fctl host image build --driver lima`
prepares the `fctl-base` VM from Lima's `debian-13` template instead of
`debian-12`, so Lima sessions get the image's Debian. Lima added that
template in 2.0 (November 2025): with an older Lima, the VM gets Debian
12 as before, and the command says so and to upgrade Lima (`brew upgrade
lima`). The image's `provision.sh` works on both. A `fctl-base` VM that
is already there stays as it is until it is built again.
- **Rust 1.99.1**, the image's: the two move together, so that sessions
working on fctl have nothing to download. It fixes regressions in 1.99.0
([announcement](https://blog.rust-lang.org/2026/10/15/Rust-1.99.1/)):
missing `wcslen` symbols on some targets, a miscompilation of `bool`
returned through FFI on x86_64, and rust-lld failing to load on macOS.
`rust-version` in Cargo.toml stays `1.99`, and the standalone image
builds its Worker in `rust:1.99.1-slim-bookworm`, which `main` now pins
to the toolchain (a test in `xtask/src/serve.rs` checks that they
match).
- **package-lock.json, refreshed with npm 11.** Node.js 26 comes with
npm 11, which drops two entries npm 10 keeps: the `site` workspace,
which moved to hyperstructure/fctl-site, and `@cloudflare/workers-types`
as an optional peer that nothing installs. Without this, the first `npm
install` in a session rewrites the lockfile. npm 10 keeps the refreshed
one as it is, so CI's Node.js 22 and sessions' Node.js 26 agree on it.
- **The Sandbox images page** says the image is Debian 13 with Node.js
26, and that the Lima VM is Debian 13 unless Lima is older than 2.0. Its
.NET example installs Debian 13's ICU (`libicu76`; Debian 13 has no
`libicu72`), and its examples start from the `0.14` tag, which
sandbox#8's merge rebuilds on Debian 13, instead of `0.5`, which stays
on Debian 12.

fctl's own Node.js doesn't change (CI, the standalone image, "Node.js 22
or newer"): CI keeps checking the oldest Node.js fctl supports, and
sandbox#8's Develop fctl workflow runs fctl's checks and sessions on
Node.js 26 in the image. Release builds (`cargo xtask dist`, with zig)
and deploys stay with the Release and CI workflows.

hyperstructure/sandbox#8 is merged, and its image is published:
`0.14.1`, `0.14` and `latest` are Debian 13 now (2.25 GB unpacked on
amd64, 58 MB more than before; 2.12 GB on arm64, 43 MB more), so the
docs' example works and this can merge.

**Verification**

- CI: `cargo xtask check` and `cargo xtask dev --smoke` pass on Node.js
22 and npm 10 with the refreshed lockfile, and the Standalone image
workflow builds the standalone image with Rust 1.99.1 and runs a session
through it.
- Merged with `main` (#169 to #176): `image.rs` keeps #172's isolated
base VM (`--set` with no mounts and no port forwards) and #173's private
download directory, with the Debian 13 template. Lima 2.2.1 merges its
templates' bases, the home directory mount of `_default/mounts`
included, before it applies `--set`, so `debian-13` gets no mounts
either. The lockfile keeps #176's `@hyperstructure/design` 0.6.0, and
npm 10 and 11 leave it as it is. `cargo xtask check --quick` passes on
the merge.
- A unit test covers the template: Lima 2.x gets Debian 13, 1.x Debian
12, and a version it can't read Debian 13.
- In sandbox#8's Debian 13 image, its Develop fctl workflow runs this
branch (4fcc7ff) as a session would and passes on amd64 and arm64
([run](https://github.com/hyperstructure/sandbox/actions/runs/39635043177)):
`cargo xtask check`, a session through `cargo xtask dev` and one through
`cargo xtask serve`, an `npm install` that leaves the lockfile as it is,
and Playwright screenshots of the signed-in home page, which install
Chromium's libraries from Debian 13.
- In the session (arm64, Debian 12, Node.js 26.12.1 first on the PATH),
the same `check-fctl.sh` passes on this branch in 8 minutes.
- npm 10.9.9 and 11.20.0 both leave the refreshed lockfile as it is
(`npm install --package-lock-only`).
- Lima itself isn't run here: sessions have no VMs. Lima's `debian-13`
template is in its releases from v2.0.0 on, and `debian-12` is still in
them.

Made in fctl session
https://app.fctl.sh/s/ses_01M5FGH6RENBJVF1MS02X2MB51

---------

Co-authored-by: fctl-sh[bot] <fctl-sh[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant