pnpm: disable package-manager self-switch in sandbox (entrypoint) #33

Merged
chad merged 2 commits from glen/pnpm-entrypoint-selfswitch into main 2026-10-27 15:52:56 -04:00
Collaborator

What

pnpm/entrypoint.toml — two env additions:

  1. PNPM_CONFIG_MANAGE_PACKAGE_MANAGER_VERSIONS = "false" — pnpm ≥ 12 self-installs the version a project pins under packageManager (e.g. 360-polymer's pnpm@12.5.1) into its store and re-execs into it before any command. Inside the sandbox that self-install died with:

    Error: create the temporary package manager install directory
      ╰─▶ Read-only file system (os error 30)
    

    failing every pnpm invocation in the project (pnpm/crates/cli/src/engine_pm/install.rs:154 — create_dir_all(<store>/tmp/pnpm-engine-<ver>-…) resolving onto the read-only scratch root). With the switch off, the sandboxed 12.6.0 is the single deterministic package manager — upstream fidelity: we don't run unverified upstream pnpm builds by design. Per-invocation escape hatch: npm_config_manage_package_manager_versions=true.

  2. XDG_STATE_HOME = "/persist/state" — pnpm's state dir (env lockfiles, managed-runtime materializations) defaults to ~/.local/state; redirect to the writable /persist bind per the repo's persist pattern, alongside the existing DATA/CACHE redirects.

Evidence

tools/verify.sh pnpm on bee (isolated store/config, release engine):

bubblebox: built pnpm -> .../descriptors/pnpm.cfs
  smoke[1]: ok --version
  smoke[2]: ok store path
  footprint: 57 MB (limit 120 MB)
verify: all selected packages passed

Behavioral check in a project pinning pnpm@12.5.1 (the polymer case):

$ bubblebox run pnpm -- --version
12.6.0            # old entrypoint: read-only-fs error before any output

(bee's sandbox has no DNS, so the suppressed-download path can't be exercised there; the suppression env is the same mechanism Chad verified live on the thinkpad via the npm_config_…=false env var — polymer's pnpm secrets:set then worked.)

No pin/Containerfile changes — entrypoint only.

## What `pnpm/entrypoint.toml` — two env additions: 1. **`PNPM_CONFIG_MANAGE_PACKAGE_MANAGER_VERSIONS = "false"`** — pnpm ≥ 12 self-installs the version a project pins under `packageManager` (e.g. 360-polymer's `pnpm@12.5.1`) into its store and re-execs into it **before any command**. Inside the sandbox that self-install died with: ``` Error: create the temporary package manager install directory ╰─▶ Read-only file system (os error 30) ``` failing every pnpm invocation in the project (`pnpm/crates/cli/src/engine_pm/install.rs:154` — `create_dir_all(<store>/tmp/pnpm-engine-<ver>-…)` resolving onto the read-only scratch root). With the switch off, the sandboxed 12.6.0 is the single deterministic package manager — upstream fidelity: we don't run unverified upstream pnpm builds by design. Per-invocation escape hatch: `npm_config_manage_package_manager_versions=true`. 2. **`XDG_STATE_HOME = "/persist/state"`** — pnpm's state dir (env lockfiles, managed-runtime materializations) defaults to `~/.local/state`; redirect to the writable `/persist` bind per the repo's persist pattern, alongside the existing DATA/CACHE redirects. ## Evidence `tools/verify.sh pnpm` on bee (isolated store/config, release engine): ``` bubblebox: built pnpm -> .../descriptors/pnpm.cfs smoke[1]: ok --version smoke[2]: ok store path footprint: 57 MB (limit 120 MB) verify: all selected packages passed ``` Behavioral check in a project pinning `pnpm@12.5.1` (the polymer case): ``` $ bubblebox run pnpm -- --version 12.6.0 # old entrypoint: read-only-fs error before any output ``` (bee's sandbox has no DNS, so the suppressed-download path can't be exercised there; the suppression env is the same mechanism Chad verified live on the thinkpad via the `npm_config_…=false` env var — polymer's `pnpm secrets:set` then worked.) No pin/Containerfile changes — entrypoint only.
pnpm: disable package-manager self-switch in sandbox (entrypoint)
Some checks failed
verify / verify (pull_request) Failing after 1s
6df314889d
pnpm >= 12 installs the version a project pins under `packageManager`
(e.g. 360-polymer's pnpm@12.5.1) into its store and re-execs into it
before any command. Inside the bubblebox sandbox that self-install hit
a read-only path: 'create the temporary package manager install
directory: Read-only file system (os error 30)' — failing every pnpm
invocation in the project, including --version-class ones.

- PNPM_CONFIG_MANAGE_PACKAGE_MANAGER_VERSIONS=false: the sandboxed
  12.6.0 stays the single deterministic package manager (upstream
  fidelity — we don't run unverified upstream pnpm versions by design).
- XDG_STATE_HOME=/persist/state: env lockfiles / managed-runtime state
  land on the writable persist bind per the /persist pattern.

Repro'd + quick fix verified on think (env-var form suppressed the
switch; polymer's pnpm secrets:set then worked).
ci: re-run verify (runner engine cache was corrupt — healed + re-cloned)
All checks were successful
verify / verify (pull_request) Successful in 6s
bf682bc6f1
chad approved these changes 2026-10-27 15:30:51 -04:00
chad merged commit 3e18e5ea5b into main 2026-10-27 15:52:56 -04:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chad/bubblebox-pkgs!33
No description provided.