Repository navigation
node packages: private libexec prefixes + guard against a second npm (#751) - #753
Conversation
#751) Two follow-ups to #752: 1. cf, wrangler, next, mermaid-cli and capy installed into the shared usr/lib/node_modules, the tree the node runtime's own npm lives in (Tom's #370 warning). They now install into usr/libexec/<pkg> with relative usr/bin symlinks, like vlt and pnpm. A `test -e` on each link fails the build if an upstream bin is renamed, rather than shipping a dangling link. mermaid-cli's wrapper and next's sharp/test paths follow the move. 2. node-runtime-guard (BLOCKING, as Karl suggested in #751). It evaluates the whole catalog on amd64 and arm64 and rejects: - outputs under usr/lib/node_modules; - runtime deps that carry a node runtime's npm; - packages on `node` rather than `node-lts`. A dump failure exits 2 and fails the check, so an unverified run cannot go green. Full-catalog dry run: - main: FAILS 20 packages (34 flavor, 19 runtime-npm, 5 shared-tree). - main + #752 + this: PASSES all 531 packages. This check is red until #752 lands. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Next included review available in 22 minutes. View limit detailsLimit details: You’ve used all 2 included reviews currently available. Your 56 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour. Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. Review configuration: ⚙️ Run configurationConfiguration used: Repository: gominimal/pkgs/.coderabbit.yaml Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (13)
Comment |
The rules that node-runtime-guard enforces are now written down where package authors and agents look first: - node-lts, not node; - interpreter-only at runtime; - a private libexec prefix, with a worked build.sh and build.ncl. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
mitodrummer
left a comment
There was a problem hiding this comment.
This looks good and I'm happy to approve after the two fixes below, merging after #752.
Checked:
- Every
npm install -gin the repo at this head now uses a privateusr/libexec/<pkg>prefix, so no package was missed. - The
test -eandcli.jschecks fail the build instead of shipping a dangling link. Thenextandmermaid-clitests point at the new paths. - gominimal/webapp doesn't reference
lib/node_modulesanywhere, so movingcfis safe for us. - #752 now uses
subsetOf node-lts ["node"]at runtime andnode-ltsfor builds, which matches what theflavorrule enforces. - The guard's current failure ("20 package(s) FAIL (of 531)") is the expected pre-#752 result.
Should fix
shared-treemisses broad globs. It only flags a glob equal to or underusr/lib/node_modules, butusr/**andusr/lib/**capture that tree too. The catalog already has 11 of these (gnupg, lsof, stow, postgres, gcc, libgcrypt, …). None are Node packages today, but a future npm-installing package witheverything = { glob = "usr/**" }would ship an npm tree and pass the guard. Suggest also flagging any glob whose literal prefix (the part before the first wildcard) is an ancestor ofusr/lib/node_modules. To avoid failing the existing C libraries, limit that to packages whosebuild_depsinclude a node runtime.- AGENTS.md says more than the guard checks. The Node pattern section says
node-ltsapplies tobuild_deps,runtime_depsandtest_deps.check()only readsbuild_depsandruntime_deps. No package usesnodein a test dep today as far as I can see. Either extend theflavorrule to test deps, or droptest_depsfrom the doc so the two agree.
Consider
- In
capy/build.nclthe output is still callednode_modules, and its comment still says "Same shape as cf's node_modules". Both are stale now; the other four packages call itlibexec. - On required-check status: yes, let's make
node-runtime-guarda required check once #752 is in and it's green. It only protects anything if it's enforced.
…ame (review) Addresses Karl's review on #753: - shared-tree now also rejects a broad recursive glob (`usr/**`, `usr/lib/**`, `**`) whose literal prefix is an ancestor of usr/lib/node_modules, in any package that BUILDS with a node runtime. Such a glob would capture an npm install and ship it. Non-node packages are exempt, so the 11 C libraries using `usr/**` are untouched. - Synthetic cases: usr/**, usr/lib/** and ** are flagged; usr/bin/*, usr/lib/*.so, usr/share/** and a C lib's usr/** are not. - Full catalog: main still fails the same 20 packages; with #752 it passes all 531. - AGENTS.md now claims only what the guard checks: build and runtime deps. node-lts for test_deps is stated as convention, since `minimal dump` has no tests to check. - capy: rename the output node_modules -> libexec to match the other four, and drop the stale "same shape as cf's node_modules" comment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Thanks! Both should-fixes are in 9df85ff.
Agreed on making the guard a required check once #752 is in and green. |
Companion to #752. Covers the two follow-ups from #751.
1. Out of the shared
usr/lib/node_modulescf,wrangler,next,mermaid-cliandcapyrannpm install -g --prefix=$OUTPUT_DIR/usr, which writes intousr/lib/node_modules, the tree where the Node runtime's own npm lives. Tom warned about exactly this on #370. They now install into a privateusr/libexec/<pkg>prefix, with relativeusr/binsymlinks, the same pattern asvltandpnpm.wrangler/wrangler2/cf-wrangler, capy, next. Linking by name means a package can't drop an unclaimed or colliding file intousr/bin. Atest -eon each link fails the build if upstream renames a bin, instead of shipping a dangling link.mermaid-cli: themmdcwrapper andinstall_checkpoint at the new path, and the build checks thatsrc/cli.jslanded.next: the sharp source build writes into the newNEXT_DIR, and the tworequire(...)tests use the new path.NODE_PATH. Node never resolvesrequirefrom the global prefix anyway, so projects are unaffected.2.
node-runtime-guard(blocking)This is the structural guard Karl suggested. A general "no two closure members ship different bytes at one path" check needs built trees, so it belongs in
minimalitself. The npm case of it has static causes that are visible in the evaluated catalog, and this guard rejects them. It runsminimal dump -p --format jsonfor amd64 and arm64 and checks every package exceptnode/node-ltsthemselves:shared-treeusr/lib/node_modulesruntime-npmnpm/npx/node_modulesflavornodeinstead ofnode-lts. This is Karl's convention from #752;CURRENT_ALLOWEDis the documented escape hatch, with a reason per entry.Collections (stacks) are exempt from
runtime-npmandflavor, because a stack naming a Node runtime is the user choosing one. It fails closed: a dump or parse failure exits 2, and the check goes red instead of passing unverified. Unlike the report-only sibling workflows, this one is meant to block. Whether to make it a branch-protection required check is your call.Full-catalog dry run (both arches):
main(negative control): FAIL, 20 packages (34 flavor, 19 runtime-npm, 5 shared-tree findings). That's exactly the node consumers: node-lts interpreter only at runtime, node-lts to build (fixes #751) #752 set plus these five. No unexpected packages, so no false positives on today's catalog.main+ node consumers: node-lts interpreter only at runtime, node-lts to build (fixes #751) #752 + this PR: PASS, 531 packages.⚠ This check is red until #752 merges. Merge #752 first, then I'll update this branch.
3. Documented in AGENTS.md
AGENTS.md gets a new Node pattern section beside the Go and Rust patterns. It covers the three rules and gives a worked
build.shandbuild.ncl, so authors and agents learn the convention before the guard has to reject anything.pkgmgr import npmgenerates the same layout (gominimal/pkgmgr-rs#873, merged).Verification
It hasn't been built locally (Linux sandbox builds only). CI builds the five changed packages and runs their standalone tests. Those tests exercise the new bin symlinks (
cf --version,wrangler --version,capy --version,mmdc --help,next --version, plus next's sharp/libvips requires).🤖 Generated with Claude Code