From 4922273831682db08de327f8a528f1ba6ff88414 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 19:54:12 +0000 Subject: [PATCH] Distribute up via npm with trusted publishing Publish the CLI to npm as `up` (2.0.0: the name's earlier 1.x line was an unrelated project, so the major jump keeps `^1` users untouched). Publishing happens exclusively from release.yml via npm trusted publishing: OIDC, no token, provenance attached to every version. - package.json: rename @vercel-labs/up -> up, version 2.0.0, drop `private`, add `files` so the published tarball contains the built CLI (dist/ is gitignored and would otherwise be excluded). - release.yml: id-token permission, registry-url, and a guarded publish step: it publishes only when the pushed tag is exactly v, and prerelease versions go to the `beta` dist-tag so `latest` always resolves to a stable build. - README, package README, SECURITY.md, landing: npm is the install channel; releases verify via provenance (`npm audit signatures`). - install.sh: the curl channel stays frozen at its final beta and now prints a pointer to npm. --- .github/workflows/release.yml | 25 +++++++++++++++++++++++++ README.md | 13 ++++++++----- SECURITY.md | 31 ++++++++++++++++++------------- apps/downloads/public/install.sh | 2 ++ landing/app/page.tsx | 2 +- package.json | 2 +- packages/cli/README.md | 17 +++++++++-------- packages/cli/package.json | 8 +++++--- 8 files changed, 69 insertions(+), 31 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 706a741..cff5186 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,10 @@ on: permissions: contents: write + # Required for npm trusted publishing (OIDC). The npm package `up` is + # configured on npmjs.com to accept publishes only from this repository's + # release.yml workflow; no npm token exists or is needed. + id-token: write env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true @@ -28,6 +32,8 @@ jobs: with: node-version: 24.x cache: pnpm + # Point npm at the public registry so trusted publishing targets it. + registry-url: https://registry.npmjs.org - name: Verify release version run: | @@ -47,6 +53,25 @@ jobs: pnpm test pnpm build + - name: Publish to npm + working-directory: packages/cli + run: | + # Trusted publishing needs npm >= 11.5.1; runner images may lag. + npm install -g npm@^11 + # Publish only when the tag is exactly v. A + # suffixed tag (e.g. v2.0.0-rc.1 while package.json says 2.0.0) must + # never publish 2.0.0. Prerelease versions go to the `beta` dist-tag + # so `npm install up` keeps resolving to the latest stable. + version="$(node -p "require('./package.json').version")" + if [ "$GITHUB_REF_NAME" != "v$version" ]; then + echo "Tag $GITHUB_REF_NAME is not exactly v$version; skipping npm publish." + exit 0 + fi + case "$version" in + *-*) npm publish --tag beta ;; + *) npm publish ;; + esac + - name: Prepare release asset run: | mkdir release diff --git a/README.md b/README.md index 4da915a..b717254 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ `*.vercel.run` URL. Edit locally and changes sync up; stop it and a later `up .` resumes from a snapshot. It is an experimental demo of [persistent Vercel Sandboxes](https://vercel.com/docs/sandbox/concepts/persistent-sandboxes), -distributed only via `curl | sh` (not npm). +distributed as the [`up`](https://www.npmjs.com/package/up) package on npm. > **Experimental.** Try `up` on experimental workloads, not production projects or real data. The > `*.vercel.run` URL is **public and unauthenticated**: anyone with the link can reach your dev @@ -14,14 +14,17 @@ distributed only via `curl | sh` (not npm). ## Install ```sh -curl -fsSL https://cdn.upcli.dev/install.sh | sh +npm install -g up cd ~/projects/my-app up . ``` -Requires Node.js `>=20.19.0`. The installer verifies a SHA-256 checksum and drops `up` in -`~/.local/bin`; installing needs no login. To run, `up` reuses your Vercel CLI login (or -`VERCEL_TOKEN`) and must run inside a project, not your home directory. +Requires Node.js `>=20.19.0`. Releases are published to npm exclusively by this repository's CI +using [npm trusted publishing](https://docs.npmjs.com/trusted-publishers), so every version +carries provenance; installing needs no login. To run, `up` reuses your Vercel CLI login (or +`VERCEL_TOKEN`) and must run inside a project, not your home directory. (Versions up to +`0.1.0-beta.5` were distributed via a `curl | sh` installer; those artifacts remain available +but are frozen.) ## Usage diff --git a/SECURITY.md b/SECURITY.md index eaa947f..ae71920 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,7 +1,13 @@ # Security Policy -`up` is a demonstration of persistent Vercel Sandboxes. It is distributed **only** through the -`curl | sh` installer at `https://cdn.upcli.dev/install.sh` and is **not** published to npm. +`up` is a demonstration of persistent Vercel Sandboxes. It is distributed as the +[`up`](https://www.npmjs.com/package/up) package on npm. Releases are published **exclusively** +by this repository's `release.yml` workflow via +[npm trusted publishing](https://docs.npmjs.com/trusted-publishers): no npm token exists, and +every published version carries a provenance attestation linking it to the exact commit and +workflow run that built it. (Versions up to `0.1.0-beta.5` predate the npm package and were +distributed via the `curl | sh` installer at `cdn.upcli.dev`; those artifacts remain available +for reproducibility but are frozen.) ## Scope and trust model @@ -25,24 +31,23 @@ ## Supported versions -Only the latest released version (the default in `install.sh`) is supported. Older `beta` artifacts -remain downloadable for reproducibility but do not receive fixes. +Only the latest version published to npm is supported. Older versions (including the frozen +`curl | sh` beta artifacts) do not receive fixes. ## Verifying a download -The installer checks the SHA-256 of `up.mjs` before installing. Since `up.mjs`, `checksums.txt`, -and `install.sh` are all served from `cdn.upcli.dev`, that check verifies integrity (it catches a -corrupted download), not origin; trust rests on TLS and Vercel's control of the domain. - -For an independent check, compare the CDN bundle against the matching -[GitHub Release](https://github.com/vercel-labs/upcli/releases), which CI publishes under separate -infrastructure: +Every npm release is published with a provenance attestation generated by npm trusted publishing. +To verify that the installed package was built by this repository's release workflow from the +commit it claims: ```sh -curl -fsSL https://cdn.upcli.dev/releases//up.mjs | shasum -a 256 -# compare with checksums.txt in the GitHub Release for the same tag +npm audit signatures ``` +You can also inspect the provenance on the package's npm page, and compare the published bundle +against the matching [GitHub Release](https://github.com/vercel-labs/upcli/releases), which the +same workflow publishes alongside npm. + `up` is a demo: do not run it against production projects or real data. ## Reporting a vulnerability diff --git a/apps/downloads/public/install.sh b/apps/downloads/public/install.sh index 7e8b981..e231f67 100755 --- a/apps/downloads/public/install.sh +++ b/apps/downloads/public/install.sh @@ -74,3 +74,5 @@ case ":${PATH:-}:" in *":$INSTALL_DIR:"*) printf 'Run: cd && up .\n' ;; *) printf 'Add %s to PATH, then run: up .\n' "$INSTALL_DIR" ;; esac +# This channel is frozen at its final beta. Releases moved to npm. +printf 'Note: up is now distributed via npm: npm install -g up\n' diff --git a/landing/app/page.tsx b/landing/app/page.tsx index d9f70a6..b0fd68d 100644 --- a/landing/app/page.tsx +++ b/landing/app/page.tsx @@ -1,6 +1,6 @@ import { CopyButton } from "@/components/copy-button"; -const INSTALL = "curl -fsSL https://cdn.upcli.dev/install.sh | sh"; +const INSTALL = "npm i -g up"; const CHANGELOG = "https://vercel.com/changelog/sandbox-persistence-is-now-ga"; const DOCS = "https://vercel.com/docs/sandbox/concepts/persistent-sandboxes"; const REPO = "https://github.com/vercel-labs/upcli"; diff --git a/package.json b/package.json index e0ae708..167b9a0 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "packageManager": "pnpm@10.23.0", "scripts": { "build": "pnpm -r build", - "dev": "pnpm --filter @vercel-labs/up dev", + "dev": "pnpm --filter up dev", "test": "pnpm -r test", "typecheck": "pnpm -r typecheck", "lint": "biome check", diff --git a/packages/cli/README.md b/packages/cli/README.md index daee44a..c449f04 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,20 +1,21 @@ -# @vercel-labs/up +# up `up` is an experimental demo of persistent Vercel Sandboxes; we recommend trying it on experimental workloads, not production data. Run a local working directory in a persistent Vercel Sandbox and -receive a public live development URL. Install the beta bundle from the public downloads deployment: +receive a public live development URL: ```sh -curl -fsSL https://cdn.upcli.dev/install.sh | sh +npm install -g up cd ~/projects/my-app up . ``` -The installer requires Node.js `>=20.19.0`, verifies the downloadable JavaScript bundle checksum -and places the `up` command in `~/.local/bin`. Installation needs no login. `up` reuses your -existing Vercel CLI login (or a `VERCEL_TOKEN`); if the machine is not logged in, it tells you to -run `vercel login` first. Run `up .` from a project directory; the CLI refuses the home directory -and filesystem root. +Requires Node.js `>=20.19.0`. Releases are published exclusively by CI from +[vercel-labs/upcli](https://github.com/vercel-labs/upcli) using npm trusted publishing, so every +version carries provenance. Installation needs no login. `up` reuses your existing Vercel CLI +login (or a `VERCEL_TOKEN`); if the machine is not logged in, it tells you to run `vercel login` +first. Run `up .` from a project directory; the CLI refuses the home directory and filesystem +root. The `up` command supports Node projects automatically and supports Python or custom servers through `--command` or `up.config.json`. Projects declaring Bun, pnpm, Yarn, or a fixed npm diff --git a/packages/cli/package.json b/packages/cli/package.json index 7f56f79..8b8819d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { - "name": "@vercel-labs/up", - "version": "0.1.0", + "name": "up", + "version": "2.0.0", "description": "Instant, shareable dev environments on Vercel Sandbox", "repository": { "type": "git", @@ -18,10 +18,12 @@ "bin": { "up": "./dist/cli.js" }, + "files": [ + "dist" + ], "engines": { "node": ">=20.19.0" }, - "private": true, "scripts": { "build": "tsup && node scripts/check-bundle-size.mjs", "dev": "tsup --watch",