Pre-set the root version to 8.0.0-rc.1 (merge before #130) - #131
Merged
Conversation
One field, merged under the current workflows (which never read the root version). The incoming prisma/prisma-style publish workflow treats any root-version change as a release; pre-setting the field on main makes the s2a-foundations merge a version no-op, so adopting the lockstep does not itself publish. MERGE THIS BEFORE #130. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Summary by CodeRabbit
WalkthroughThe package version in 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
wmadden
approved these changes
Aug 10, 2026
wmadden
pushed a commit
that referenced
this pull request
Aug 11, 2026
…s, telemetry, and real prompts — the foundations for porting the platform CLI onto the engine (#130) You can now be signed in to several workspaces at once, and say which one you are working in without signing in again. ``` $ prisma auth workspace list ℹ Listing your workspace sessions on this machine. name id status Acme Inc wksp_acme current Globex wksp_globex $ prisma auth workspace use Globex ℹ Switching the current workspace session. previous: Acme Inc workspace: Globex ✔ Current workspace session updated. $ prisma auth workspace use wksp_nope ✖ [AUTH.NO_SESSION_FOR_WORKSPACE] You have no session for workspace 'wksp_nope'. → Sign in and pick 'wksp_nope' in the browser: prisma auth login ``` Today's CLI stores the same per-workspace tokens but only really models one "active" workspace: it re-fetches workspace names on every read, ends a single workspace through `auth logout --workspace`, and can leave entries behind that nothing cleans up. The runs above are the new shell against a real credential file — the second command changed which session is current without opening a browser, and the third failed at exit 2 with an error that tells you the only thing that can fix it. ## The decision We are replacing this repo's commander-based shell with `@prisma/cli-engine` (merged in #129). Every platform command will be re-mounted on the engine and the old shell will be deleted. Before that port can start, the engine has to be production-ready and the auth family has to sit on something the rest of the port can build on. **This pull request builds those foundations and proves them by porting the first command group, `auth`.** The port itself follows in sibling pull requests for resources, services, and init plus shell removal. ## The foundations **An API client on the command context.** Nearly every platform command calls the management API. Rather than each command constructing its own SDK client, the engine builds `ctx.api` once per run, lazily, for the session that process is acting as. A token refreshed mid-run is picked up on the next request, and an expired session surfaces as the standard sign-in error instead of a crash. The test harness accepts a fake client, which is the single mock seam every ported command will use. **Real interactive prompts.** On a terminal, prompts render through `@clack/prompts` — the same library today's CLI uses, so the upcoming `init` wizard keeps its current feel. In tests, pipes, and CI a plain line-based renderer runs instead, so no test depends on terminal rendering. Clack is internal to the engine and invisible in its public API. Its spinners are deliberately unused, because they install process-global signal handlers. **Telemetry, identical to the ORM CLI's.** The detached sender process, the consent configuration with a shared installation id, and the value-free command snapshots move into this repo and report through one engine hook that fires once per command with its id, exit code, and duration. `telemetry status|enable|disable` are ported. Flag values, arguments, and paths never reach the wire, which hostile-input tests hold down. **One version number and prisma/prisma's release machinery.** This repo adopts prisma/prisma's versioning model unchanged: a single lockstep version, now `8.0.0-rc.1`, committed in every manifest and advanced only by a maintainer running `pnpm bump-version` and merging the resulting pull request. `prisma --version` reports it. Merging a bump publishes that version to `latest`; ordinary merges publish `-dev.N` builds. The old publish-time arithmetic against npm dist-tags is deleted. `@prisma/compute`, an app-runtime library slated for extraction to another repo, keeps its own line. **Merge order: merge #131 first.** It pre-sets the root version on `main`, so merging this pull request is a version no-op to the publish workflow and ships only a development build. The first real `latest` release then happens through a deliberate release bump. ## The auth rework: sessions, and the thing that is not one The auth family no longer keeps a pile of credentials with a pointer at one of them. It separates three things that were previously one. A **session** is a stored logged-in-ness for one workspace — at most one per workspace. It is the only thing called a session: what `auth workspace list` lists, what `use` selects, what `logout` ends. The **selection** is a separate scalar of stored state: which session is used where a session is needed. And the **active credential** is what a given process authenticates as, which is either the selected session's or the one `PRISMA_SERVICE_TOKEN` supplies. That third thing is why this went through two revisions. The first modelled the environment token as a session, and it produced four defects that were all the same defect: a `source` field whose job was to say "this one is not really a session", a hardcoded `current: true` that gave the word two meanings, an empty-string workspace id because a non-session was forced to carry a session's key, and a guard rejecting the non-session from APIs that only take sessions. Separating the three made all four stop existing rather than each need a fix. A new component, the credential manager, owns the state. It is the only thing that touches the credential file, and it is also what the platform SDK writes through, so a token refreshed on a 401 lands under the same rules as a fresh login. The engine owns the API client; the manager never hands a token to a command, and never talks to the user or opens a browser. Four decisions are worth knowing: - **A process pins its decision once.** Which credential a command acts as is settled at its first read and does not move for the life of that process, though the material behind it is re-read every time — so another shell switching workspaces mid-run cannot redirect a running command, while a token another process rotates is still picked up. - **Refresh follows the credential, not where it came from.** A credential refreshes if it has a refresh token, full stop. There is one API client over whatever storage the manager hands out: file-backed for a stored session, memory-backed for an environment credential, which is how a 401 that could never be renewed reports that the token was rejected instead of telling a CI job to retry a permanent failure. - **Concurrent refreshes are left to the auth service.** Refresh tokens are single-use with a ten-second reuse grace, and rotation does not invalidate a pair that was already issued, so two CLI processes refreshing the same session both succeed and the file ends up holding a working pair. There is no client-side coordination beyond deduplicating within one process. A cross-process test drives two real refreshes through a scripted token endpoint that reproduces the grace. - **The state file is one file, at the same path as today's.** Writes are atomic — temp file, fsync, rename, mode 0600 — and a short advisory lock covers read-modify-write so two mutations cannot lose each other. No network call ever runs while that lock is held. Reads never write and take no lock. - **The old store migrates by being read, not rewritten.** Existing credentials are adopted as sessions on read; nothing is written until your first mutation, at which point the file is rewritten in the new shape. That is a one-way door: from then on a still-installed older CLI reads as signed out. We chose that over two auth worlds diverging silently, because `prisma auth login` fixes it and nothing else has to. The commands keep their existing names, which the session model makes honest: `auth login`, `auth logout`, `auth whoami`, and `auth workspace list|use|logout`. `auth workspace use` selects among the sessions you already hold and never creates one, because the consent screen cannot be told which workspace to grant — you pick it in the browser. The engine grew three things the auth commands needed, all of which the rest of the port will use. A repeatable global `--confirm <value>` flag carries consent for destructive work: interactively you type the value to confirm, non-interactively you pass it exactly, and `--yes` deliberately cannot grant it. `ctx.openUrl` opens a browser and degrades to printing the URL. `prompt.browserWait` waits for a browser round trip on a terminal and returns a structured "this needs interaction" error at exit 2 everywhere else. ## What changes for users The published binary still runs the old shell; the engine-based shell is an unpublished development binary until the port finishes. For the commands ported here, every behavioural difference is written down in the [divergence record](.drive/projects/prisma-cli-v8/assets/s2/parity-divergences.md) rather than left to be discovered. The ones most likely to affect someone: - `auth logout --workspace <ref>` is gone. `auth workspace logout <ref>` is the one way to end a single session, and `auth logout` now ends every session and reports how many, reaping orphaned entries the old code could leave behind. - **Workspace switching works while `PRISMA_SERVICE_TOKEN` is set**, where the old CLI refused it. The variable supplies the credential this process uses; it does not occupy a slot, so changing stored state is coherent and every mutation succeeds, each saying the environment credential stays in force until you unset it. - **Ending a session is idempotent.** A workspace you never had is still an error, raised when the reference fails to resolve. But if another `prisma` process removes the session between your command reading it and writing, you now get exit 0 rather than an exit 2 telling you something that is no longer true. - Error codes are dotted (`AUTH.NO_SESSION_FOR_WORKSPACE`), and several failures that exited 1 now exit 2, which means "could not complete" rather than "crashed". - `auth whoami` returns the active credential rather than an auth-state snapshot: workspace, user, source, and expiry. Identity comes from the credential's own claims, enriched from `/v1/me` when that answers within a short deadline. A service token whose subject names a workspace reports no user, where a naive reading would have put `workspace:<id>` in the user field. - Workspace names are no longer refreshed on every read. A name is fetched once when the session is created, so a workspace renamed in the console keeps its local name until you next log in to it. Reads are entirely offline. - Scripted consent uses `--confirm <value>`. The mock-only login flags `--provider`, `--user`, and `--workspace` do not port. ## Verification 840 CLI tests, 258 engine tests, 97 telemetry tests, typecheck, and lint all pass on Linux, macOS and Windows. Beyond the usual coverage, the credential manager is tested across real processes on a real filesystem: two processes mutating at once both land, a crashed process's lock is taken over, a running process keeps its pinned session when another switches the marker, and two processes really refresh the same session through a scripted token endpoint. A filesystem spy asserts that no read path writes, including migration adoption, and a leak scan seeds known secrets and asserts they never appear in output, debug logs, error metadata, envelopes, or a worker process's stderr. ## Alternatives considered - **Tracking identity in the stored state**, so the CLI could tell you a session belongs to a different account: rejected. The credential file has always been identity-blind and nothing today depends on it being otherwise. Identity stays a read-time decode in `whoami`. - **Letting `auth workspace use` create a session** by opening the browser: rejected, and it is not actually possible — the authorize request carries no workspace parameter, so the CLI cannot ask for a particular workspace. Creating a session belongs to `auth login` alone. - **Coordinating refreshes across processes** with an epoch or a longer-held lock: rejected once the auth service's reuse grace was confirmed. The server absorbs the race, so the machinery would only add ways to fail. - **A separate auth package** instead of a module: rejected — the boundary matters, the packaging does not, and there is no second consumer. - **A per-family context-extension mechanism** instead of putting the API client on the context: rejected. This engine serves Prisma specifically, and indirection to avoid naming our own API bought nothing. - **Arktype for the telemetry payload guard**, which the ORM uses: a hand-rolled six-field guard, proven equivalent field by field, avoids adding a published dependency. - **Sending telemetry before the command runs**, which is the ORM's timing: replaced by reporting at completion, so exit codes and durations are accurate. The privacy notice still prints first. The trade-off is that a crashed process reports nothing. The remaining open design questions are collected in [s2-overview.md](.drive/projects/prisma-cli-v8/specs/s2-overview.md). --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One field: the root
package.jsongainsversion: 8.0.0-rc.1.Today's workflows never read the root version, so this merge publishes nothing beyond the routine dev build. Its purpose is sequencing: #130 adopts prisma/prisma's publish machinery verbatim, where any root-version change on
mainships a release tolatest. With this field pre-set, #130's merge shows no version change and publishes only a dev build — the first real release then happens through a deliberatechore(release)bump PR (see thepublish-npm-versionskill landing in #130).Merge order matters: this PR first, then #130.
🤖 Generated with Claude Code