Skip to content

vlt: package the vlt package manager from npm (BSD-2-Clause-Patent) - #564

Merged
bryan-minimal merged 3 commits into
mainfrom
bryan/vlt-import
Aug 5, 2026
Merged

vlt: package the vlt package manager from npm (BSD-2-Clause-Patent)#564
bryan-minimal merged 3 commits into
mainfrom
bryan/vlt-import

Conversation

@bryan-minimal

@bryan-minimal bryan-minimal commented Aug 4, 2026

Copy link
Copy Markdown
Member

vlt 1.0.1 (vltpkg/vltpkg) shipped today. Seeded with pkgmgr import npm vlt, then refined by hand for the two things discovery mode can't know.

Why this one is unusually clean

The published tarball has zero dependencies. npm ci against the committed lockfile installs exactly one package, pinned by version + integrity — no transitive tree, no native addons, no compile step. npm audit in-build reports 0 vulnerabilities across the whole 2-package graph. For a distro whose premise is supply-chain tracking, that is about as good as an npm-distributed tool gets.

License is BSD-2-Clause-Patent (OSI-approved), confirmed against the repo's own LICENSE, not just the npm field.

What I changed on top of the generated files

Bins enumerated, not globbed. The importer emits bins = { glob = "usr/bin/*" }, which trips the enumerate bins checker for any package with a handful of bins — vlt has five (vlt, plus the documented shorthands vlr/vlx and their variants). The npm registry metadata lists them exactly, so nothing had to be inferred. Fixing that in the importer is pkgmgr-rs follow-up work, not a one-off.

Real standalone tests. The generated package had none — and standalone tests...Pass is what the checker reports for a package with zero tests, so the out-of-the-box green meant nothing. Added three that exercise the artifact rather than the build inputs:

test what it catches
version_is_exact String equality against %{version}, not --version | grep. vlt's usage banner also carries the version, so a grep would pass on a build where --version is broken and only usage prints.
companion_bins_work All four shorthands. They're PATH symlinks into the private libexec prefix; a broken relative link fails here and nowhere else.
reads_a_manifest vlt pkg get name against a fixture package.json — real offline work through the bundled JS. A truncated install still prints --version and fails this.

Mutation-tested, because "the tests pass" was already established as meaningless here: flipping the expected version to 0.0.0-mutant turns the suite red with version_is_exact ... had exit code 1. They can fail for the reason they exist.

Why a registry artifact and not a source build

AGENTS.md requires a prebuilt fallback be called out explicitly. The reason here is not "nobody tried" — source is published (codeload.../vltpkg/tar.gz/refs/tags/v1.0.1, 200, 7.4 MB, 48 real TypeScript workspaces). It cannot be built with a toolchain we have. Measured against the extracted tarball:

npm  -> npm error code EUNSUPPORTEDPROTOCOL
        Unsupported URL Type "catalog:": catalog:
pnpm -> ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC
        No catalog entry '@eslint/js' was found for catalog 'default'
  • The only lockfile in the repo is vlt-lock.json — vlt's own format. No pnpm-lock.yaml, no package-lock.json.
  • Dependency specs use the catalog: protocol with the catalog declared in vlt.json. pnpm does support catalogs, but reads pnpm-workspace.yaml.
  • package.json has no workspaces key at all, so neither tool can even see the 48-workspace layout.
  • Upstream CI agrees: uses: vltpkg/setup-vlt@v1 then vlt install.
  • The published package (infra/cli/package.json) declares bin: null, dependencies: {}, and one script — prepack: vlt-build-prepack. The npm tarball is generated wholesale by their internal bundler.

Building vlt from source requires vlt — a genuine bootstrap cycle, which is the "required toolchain genuinely isn't packaged yet" case AGENTS.md carves out. Breaking it would mean a two-stage vlt-bootstrapvlt pair in the gawk-bootstrap shape. Worth doing if vlt becomes load-bearing; not before.

Verification

Built and checked on the min-native path against a clean-main worktree:

min session activate . --loadout pkgbuild --name vltfinal
min session attach vltfinal --command "min package build --rebuild --verbose vlt"
min session attach vltfinal --command "min check --packages vlt"

npm ciadded 1 package, and audited 2 packages in 300ms, found 0 vulnerabilities; then 15/15 Pass, check finished.

Not verified

  • Reproducibility. AGENTS.md wants byte-identical rebuilds. npm ci from a pinned lockfile ought to be deterministic and there is no compiler involved, but I did not measure it — min materialize is not in the session --command allowlist, so getting the tree back to the host for a two-build hash comparison needs an interactive attach. Flagging rather than assuming.
  • arm64. Built on this host's arch only. Pure JS with no native addons, so arch-independence is expected, not demonstrated.

Reviewer notes

No TODO:/FIXME remain. The importer's generated TODO ("add any peer packages the tool needs") is resolved, not dropped: vlt declares no dependencies, peerDependencies, optionalDependencies, or bundleDependencies.

Note on the sibling project

vltpkg/vsr (the registry) is not packageable on the same terms — it is FSL-1.1-MIT (source-available, competing-use restricted; converts to MIT on 2028-02-04), and it is a Cloudflare Workers app built via wrangler deploy. Details in the thread that prompted this.

vlt 1.0.1 shipped today (vltpkg/vltpkg). Seeded with `pkgmgr import npm vlt`
and refined by hand for the two things discovery mode can't know.

Why this one is unusually clean to package: the published tarball has **zero
dependencies**. `npm ci` against the committed lockfile installs exactly one
package, pinned by version + integrity — no transitive tree, no native
addons, no compile step. `npm audit` in-build reports 0 vulnerabilities
across the whole 2-package graph.

Two changes on top of the generated files:

- **Bins enumerated, not globbed.** The importer emits
  `bins = { glob = "usr/bin/*" }`, which trips the `enumerate bins` checker
  for any package with a handful of bins — vlt has five (`vlt`, plus the
  documented shorthands `vlr`/`vlx` and their variants). The npm registry
  metadata lists them exactly, so nothing had to be inferred. Fixing this in
  the importer is pkgmgr-rs follow-up work, not a one-off.

- **Real standalone tests.** The generated package had none, and
  `standalone tests...Pass` is what the checker reports for a package with
  zero tests — so "Pass" out of the box meant nothing. Added three that
  exercise the artifact rather than the build inputs:
    * `version_is_exact` — string equality against `%{version}`, not
      `--version | grep`. vlt's usage banner also carries the version, so a
      grep would pass on a build where `--version` is broken and only usage
      prints.
    * `companion_bins_work` — all four shorthands. They are PATH symlinks
      into the private libexec prefix; a broken relative link fails here and
      nowhere else.
    * `reads_a_manifest` — `vlt pkg get name` against a fixture package.json.
      Real offline work through the bundled JS; a truncated install still
      prints `--version` and fails this.

  Mutation-tested: flipping the expected version to `0.0.0-mutant` turns the
  suite red with `version_is_exact ... had exit code 1`, so these can fail
  for the reason they exist.

**No `source_provenance`, deliberately.** vlt's vuln identity is its npm
package name. minimal-supply-chain routes a node-flavored package with no
provenance to `pkg:npm/<name>` (`scan.rs::npm_purl_for_node_package`) where
the OSV/GHSA npm advisories resolve. Declaring `GithubRepo vltpkg/vltpkg`
would move it onto the repo-purl arm, where GHSA's npm advisories — keyed by
package name, not repo — would stop matching. Absent is correct here.

Built and checked with the min-native path (`min package build` side-op +
`min check`), 15/15 Pass.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 28 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 560cefb2-b660-4322-ae53-d367f089e775

📥 Commits

Reviewing files that changed from the base of the PR and between 31593f0 and 6b6b8aa.

⛔ Files ignored due to path filters (1)
  • packages/vlt/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • packages/vlt/build.ncl
  • packages/vlt/build.sh
  • packages/vlt/package.json

Comment @coderabbitai help to get the list of available commands.

Follows Tom's review on #370 — "I dont think a global `node_modules` is gonna
go so well, particularly if someone uses `node` vs `node-lts`".

The collision half of that was already handled: vlt installs into a private
`usr/libexec/vlt` prefix with relative PATH symlinks, never the shared
`usr/lib/node_modules` the node runtime owns. But the variant question the
comment raises was still answered by the importer's hardcoded default rather
than by evidence.

The evidence says LTS:

  - vlt's own CI tests Node 22.x ONLY (`node-version: '^22.22.0'` and
    `[22.x]`); `engines` says `>=22.22.0`. Our node-lts is 24.14.1 and node is
    25.8.2 — neither is 22.x, but LTS is two majors closer to what upstream
    actually tests against.
  - pnpm is the closest analogue in this repo (a package manager, a node CLI,
    same shape of package) and it is on node-lts, per #97/#98: the node most
    users and hosting providers run is whatever ships with current LTS.

node-lts ships its own npm, so it serves the build (`npm ci`) and the runtime
(`#!/usr/bin/env node`) both — no split between build_deps and runtime_deps.

Rebuilt and re-checked on the min path: 15/15 Pass.
AGENTS.md requires a prebuilt fallback be called out explicitly. The reason
here is not "nobody tried" — source IS published (7.4 MB tarball, 48 real
TypeScript workspaces), it just cannot be built with a toolchain we have.

Measured against the extracted tarball:

  npm  -> EUNSUPPORTEDPROTOCOL: Unsupported URL Type "catalog:"
  pnpm -> ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC

Dependency specs use the `catalog:` protocol with the catalog declared in
`vlt.json`; pnpm supports catalogs but reads pnpm-workspace.yaml. The only
lockfile is `vlt-lock.json` (vlt's own format), and `package.json` has no
`workspaces` key, so neither tool can see the monorepo layout. Upstream CI
agrees: setup-vlt@v1 then `vlt install`. The published package declares
`bin: null`, no deps, and one script — `prepack: vlt-build-prepack`.

Building vlt from source requires vlt. That bootstrap cycle is the "required
toolchain genuinely isn't packaged yet" case AGENTS.md carves out; breaking it
means a two-stage vlt-bootstrap -> vlt pair in the gawk-bootstrap shape, worth
doing if vlt becomes load-bearing and not before.

Comment-only. Rebuilt and re-checked: 15/15 Pass.
@bryan-minimal
bryan-minimal marked this pull request as ready for review August 5, 2026 21:39
@bryan-minimal
bryan-minimal added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit 1d8486c Aug 5, 2026
10 checks passed
@bryan-minimal
bryan-minimal deleted the bryan/vlt-import branch August 5, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants