Tags: hexclave/hexclave
Tags
Migrate JavaScript execution to Freestyle VMs (#2036) Supersedes #2019 (same three commits by @theswerd, plus one follow-up commit). Follow-up commit: - `freestyle-vm-js-execution.ts`: host-side failures throw `HexclaveAssertionError` (with `vmId`, `exitCode`, etc. in `extraData`) instead of plain `Error`. - `bootstrap-freestyle-snapshot.ts`: run the runtime-collector step with `linuxUser: "root"` — `freestyle/ubuntu-sm` execs as `ubuntu` by default, so the script failed on `mkdir /opt/...`. Verified end-to-end: the bootstrap now creates the snapshot and `executeJavascriptInFreestyleVm` runs against it (plain code ~1.3s, `@react-email/components` install+render ~5.6s). - `pnpm-workspace.yaml`: drop the `freestyle@0.2.7` `minimumReleaseAgeExclude`. Note: pnpm enforces this on install, and 0.2.7 clears the 7-day window at **2026-09-04 05:39 UTC** — CI will fail until then. Fallback: `runWithFallback` is unchanged; every failure path of the new engine throws, so Freestyle is retried twice and then Vercel Sandbox runs as before. Only a caller abort skips the fallback. Link to Devin session: https://app.devin.ai/sessions/cf5e95e56cfa4ace81ab6fa050fd4786 Open in Devin Desktop: https://app.devin.ai/desktop/session/cf5e95e56cfa4ace81ab6fa050fd4786?variant=devin Requested by: @N2D4 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the production path for custom email and other sandboxed JS (new external dependency on a bootstrapped snapshot and VM lifecycle), though Vercel fallback and extensive unit tests mitigate operational and regression risk. > > **Overview** > **Freestyle JavaScript execution moves from the serverless runs API to short-lived VMs booted from a private BusyBox snapshot with Node 24.** Production runs spawn a VM from `STACK_FREESTYLE_SNAPSHOT_ID` (default `hexclave-js-node24-v2`), write user code and dependencies under `/opt/hexclave-runtime/work`, execute via PTY through `hexclave-run-job`, and always tear down the VM—with deferred cleanup on abort so orphaned VMs are still deleted. > > **Operators must bootstrap that snapshot once** via `pnpm --filter @hexclave/backend freestyle:bootstrap-snapshot` (checksum-pinned Node 24 download, temporary Ubuntu collector VM, snapshot build on `freestyle/busybox`). Env templates and self-host docs now document `HEXCLAVE_FREESTYLE_SNAPSHOT_ID`. The **`freestyle` SDK is bumped to ^0.2.7**; dev still uses the local mock HTTP path when the mock API key is set. > > **Vercel Sandbox fallback and retry behavior are unchanged**—failures from the new VM engine still fall through as before. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0dc7205. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Migrates JavaScript execution (email rendering) from Freestyle's serverless runs API to Freestyle VMs running a private Node 24 BusyBox snapshot. Each execution boots a VM, writes user code and `nodeModules` into it, runs a job script via PTY that npm-installs and executes the code, then reads back the JSON result; the Vercel Sandbox fallback is unchanged. - Aborted requests schedule VM deletion instead of leaking VMs; host-side failures throw `HexclaveAssertionError` with `vmId` and `exitCode` in `extraData`. - Cleanup is bounded by a timeout so a stalled VM deletion doesn't delay a successful result. - Local dev still uses the mock HTTP endpoint when the mock API key is set. **Migration** - Self-hosters must run `pnpm --filter @hexclave/backend freestyle:bootstrap-snapshot` once with `HEXCLAVE_FREESTYLE_API_KEY` set; it installs a checksum-pinned Node 24 glibc-217 build into a temporary BusyBox VM, verifies it, and snapshots it as `hexclave-js-node24-v4`. - The bootstrap enables swap and keeps npm's cache on disk so large installs like `@react-email/components` don't exhaust the tmpfs. - `freestyle` bumps to `0.2.7`; pnpm enforces its 7-day release-age policy, so `pnpm install` fails until 2026-09-04 05:39 UTC. - Existing `STACK_FREESTYLE_*` env names still work. <sup>Written for commit de7606c. Summary will update on new commits.</sup> <a href="/sitelet?url=https%3A%2F%2Fgithub.com%2Fhexclave%2Fhexclave%2F%253Ca%2520href%3D"https://cubic.dev/pr/hexclave/hexclave/pull/2036?utm_source=github" rel="nofollow">https://cubic.dev/pr/hexclave/hexclave/pull/2036?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="/sitelet?url=https%3A%2F%2Fgithub.com%2Fhexclave%2Fhexclave%2F%253Ca href="/sitelet?url=https%3A%2F%2Fwww.cubic.dev%2Fbuttons%2Freview-in-cubic-dark.svg%26quot%3B%26gt%3B%26lt%3Bsource" rel="nofollow">https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="/sitelet?url=https%3A%2F%2Fgithub.com%2Fhexclave%2Fhexclave%2F%253Ca href="/sitelet?url=https%3A%2F%2Fwww.cubic.dev%2Fbuttons%2Freview-in-cubic-light.svg%26quot%3B%26gt%3B%26lt%3Bimg" rel="nofollow">https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Fhexclave%2Fhexclave%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fwww.cubic.dev%2Fbuttons%2Freview-in-cubic-dark.svg%26quot%3B%26gt%3B%26lt%3B%2Fpicture%26gt%3B%26lt%3B%2Fa" rel="nofollow">https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * JavaScript execution now runs in isolated, managed environments with configurable execution and cleanup timeouts. * Improved execution result handling provides clearer success and error information. * Added support for local Freestyle execution through a mock endpoint. * Runtime setup now verifies Node.js and npm functionality before use. * **Bug Fixes** * Cleanup operations are bounded by timeouts, preventing stalled executions from delaying successful results. * Updated the runtime snapshot to Node.js 24. * **Documentation** * Updated self-hosting instructions for the streamlined runtime snapshot setup. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Benjamin Swerdlow <Swerdlowbenjamin@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
PreviousNext