Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
8735545
TML-3475: migration plan and db update rename a model or field stated…
wmadden-electric Oct 7, 2026
8e967c1
TML-3475: ignore a Gitleaks false positive on constraint names in the…
wmadden-electric Oct 7, 2026
4f84a05
TML-3476: slice 2 spec and plan, the engine statement-prompt slice sp…
wmadden-electric Oct 7, 2026
362922e
TML-3475: the ref-aware plan test expects a refused delta to write no…
wmadden-electric Oct 7, 2026
1a5aaf4
TML-3476: Postgres classes SET NOT NULL and the safe type widenings a…
wmadden-electric Oct 7, 2026
989d9cf
TML-3476: SQLite classes a table rebuild for a nullability change alo…
wmadden-electric Oct 7, 2026
35170f8
TML-3476: MongoDB classes index drops, validator changes and change-s…
wmadden-electric Oct 7, 2026
37e37ab
TML-3476: define each operation class by what it does to the data
wmadden-electric Oct 7, 2026
6fb4428
TML-3476: regenerate the retail-store migration whose setValidation i…
wmadden-electric Oct 7, 2026
95ea624
TML-3476: upgrade fragment for operations that are now widening
wmadden-electric Oct 7, 2026
c69c033
TML-3476: journeys and end-to-end tests follow the widening classes
wmadden-electric Oct 7, 2026
35e6609
TML-3475: merge main
wmadden-electric Oct 7, 2026
7e0d2f0
TML-3475: main's planner tests pass an origin and no statements
wmadden-electric Oct 7, 2026
47b7ec7
TML-3475: rename constraints on the schema the rename statements left
wmadden-electric Oct 7, 2026
2b9a019
TML-3476: declare AlterColumnTypeClass once, beside alterColumnType
wmadden-electric Oct 7, 2026
8034bef
TML-3476: test that a SQLite nullability tightening fails on a NULL a…
wmadden-electric Oct 7, 2026
d3d67fd
TML-3476: the Mongo consent journey checks the refusal code and that …
wmadden-electric Oct 7, 2026
ec6c18d
TML-3476: docs name what the widening classes change and document alt…
wmadden-electric Oct 7, 2026
dc2d87e
TML-3476: dispatch 2 brief, and the engine spec records per-command s…
wmadden-electric Oct 7, 2026
bdce343
TML-3476: MigrationStatementSubject names what an operation is about,…
wmadden-electric Oct 7, 2026
a5bbdd1
TML-3476: the SQL family maps an operation's table or column to a mod…
wmadden-electric Oct 7, 2026
1496f57
TML-3476: a SQLite recreate call records the columns whose type it ch…
wmadden-electric Oct 7, 2026
8b55955
TML-3476: every planner names what each operation that loses data wou…
wmadden-electric Oct 7, 2026
959fecd
TML-3476: db update classes a safe Postgres type widening as widening
wmadden-electric Oct 7, 2026
ccf0149
TML-3476: a delete statement passes through resolution, and only rena…
wmadden-electric Oct 7, 2026
1808553
TML-3476: db update lists the destructive operations of recorded migr…
wmadden-electric Oct 7, 2026
300d725
TML-3476: a subject on a table or collection that several models shar…
wmadden-electric Oct 7, 2026
a3ab0c9
TML-3476: a SQLite recreate that leaves a live column out is destruct…
wmadden-electric Oct 7, 2026
450e5bc
TML-3476: Postgres data-loss tests run with a rename statement, asser…
wmadden-electric Oct 7, 2026
29ea5a0
TML-3476: a destructive codec hook call names its field, and unknown …
wmadden-electric Oct 7, 2026
e556f96
TML-3476: every family names the storage of a recorded operation
wmadden-electric Oct 7, 2026
7df4d8e
TML-3476: dispatch 3 brief, the delete text rule, and a test dispatch…
wmadden-electric Oct 7, 2026
0e98b77
TML-3476: pin the @prisma/cli-engine 0.7.0 preview build from prisma/…
wmadden-electric Oct 7, 2026
cc03800
TML-3476: migration plan asks what each operation that loses data mea…
wmadden-electric Oct 7, 2026
8859399
TML-3476: journeys that plan a drop or a lossy type change pass --delete
wmadden-electric Oct 7, 2026
d86db58
TML-3476: document migration plan's data-loss questions and delete st…
wmadden-electric Oct 7, 2026
4a72d55
TML-3476: dispatch 4 brief, and two open items the PR and dispatch 5 …
wmadden-electric Oct 7, 2026
0bf6536
TML-3476: merge the slice 1 branch
wmadden-electric Oct 7, 2026
cfdb07c
TML-3476: data-loss questions name renamed models' fields, and positi…
wmadden-electric Oct 7, 2026
853ed18
TML-3476: docs name a field of a renamed model through its new name
wmadden-electric Oct 7, 2026
a3b124b
TML-3476: declare @prisma/cli-engine 0.7.0 everywhere, with the previ…
wmadden-electric Oct 7, 2026
4acb1b1
TML-3476: dispatch 4 carries the delete description note from dispatc…
wmadden-electric Oct 7, 2026
deb62d2
TML-3476: one question loop for every plan question, and a delete is …
wmadden-electric Oct 7, 2026
2f20f4c
TML-3476: db update plans the same operations with and without the or…
wmadden-electric Oct 7, 2026
5296571
TML-3476: db update asks what each data loss means and whether each a…
wmadden-electric Oct 7, 2026
66bc75e
TML-3476: a storage subject says the origin contract is unknown when …
wmadden-electric Oct 7, 2026
264dcda
TML-3476: db update journeys answer data loss with --delete instead o…
wmadden-electric Oct 7, 2026
f3606b8
TML-3476: docs describe db update's questions, --allow, and the snaps…
wmadden-electric Oct 7, 2026
c238652
TML-3476: dispatch 5 brief
wmadden-electric Oct 7, 2026
b38f7b7
TML-3476: codec field-event hooks get the prior contract only when th…
wmadden-electric Oct 7, 2026
c7019fb
TML-3476: a wrong answer callback throws InternalError, and an unused…
wmadden-electric Oct 8, 2026
d2586ee
TML-3476: docs say answerQuestions is called with an empty list when …
wmadden-electric Oct 8, 2026
b33b7e2
TML-3476: dispatch 5 carries the dry-run statement check from dispatc…
wmadden-electric Oct 8, 2026
0cd5c7d
TML-3476: a db update dry run refuses delete and allow statements tha…
wmadden-electric Oct 8, 2026
edc7bf5
TML-3476: a destructive codec-hook call is named by its field after t…
wmadden-electric Oct 8, 2026
1e8ee99
TML-3476: journeys for delete and allow statements on Postgres, SQLit…
wmadden-electric Oct 8, 2026
439d232
TML-3476: skills and the Migration System doc describe statements as …
wmadden-electric Oct 8, 2026
aad84b8
TML-3476: upgrade fragments for statements as the consent to data loss
wmadden-electric Oct 8, 2026
1b2d07c
TML-3476: the MongoDB journey reads its contracts from fixtures, so t…
wmadden-electric Oct 8, 2026
e50eb94
TML-3476: defer the SQLite required-field gap under db update
wmadden-electric Oct 8, 2026
21bceb7
TML-3476: manual QA script for the refusal slice
wmadden-electric Oct 8, 2026
2254bf0
TML-3476: dbUpdate examples pass the options it takes, and the --conf…
wmadden-electric Oct 8, 2026
51ecc59
TML-3476: the MongoDB required-field journey checks the validator and…
wmadden-electric Oct 8, 2026
5d17aac
TML-3476: engine spec records take, the ':' subject rule and the long…
wmadden-electric Oct 8, 2026
4fe1ebe
TML-3476: defer the namespace-wide delete to slice 3, and name the su…
wmadden-electric Oct 8, 2026
5dacf8d
TML-3476: dispatch 6 brief, the whole-slice review fixes
wmadden-electric Oct 8, 2026
3371083
TML-3476: pin the engine build that gives a value the subject it equa…
wmadden-electric Oct 8, 2026
3d43f94
TML-3476: a typed rename resolves its loss when the operation asked a…
wmadden-electric Oct 8, 2026
c06bd5b
TML-3476: executeMigrationPlanCommand takes delete statements as answ…
wmadden-electric Oct 8, 2026
a772c8f
TML-3476: pin the engine build that shell-quotes the refusal's flag f…
wmadden-electric Oct 8, 2026
fbbc5c8
TML-3476: a dry run lists each subject as the apply's question writes it
wmadden-electric Oct 8, 2026
8714ddf
TML-3476: a dry run checks its delete and allow flags instead of refu…
wmadden-electric Oct 8, 2026
7884a7a
TML-3476: the aggregate planner names what a recorded path loses
wmadden-electric Oct 8, 2026
bd62dec
TML-3476: acceptAccessWidening answers access questions, apart from a…
wmadden-electric Oct 8, 2026
f90595d
TML-3476: replacing a generated-name policy is not an access widening
wmadden-electric Oct 8, 2026
6e761d4
TML-3476: a data-loss question offers rename only where one can succe…
wmadden-electric Oct 8, 2026
0aee3bc
TML-3476: name the subject for what it is, and declare the subject li…
wmadden-electric Oct 8, 2026
4bca5d7
TML-3476: one table declares the statement verbs both ORM commands use
wmadden-electric Oct 8, 2026
dea0b33
TML-3476: comments and docs say what widening and data mean now
wmadden-electric Oct 8, 2026
3f99617
TML-3476: the three targets' data-loss tests check dataLoss against t…
wmadden-electric Oct 8, 2026
23d4c36
TML-3476: upgrade fragments and docs follow the review fixes
wmadden-electric Oct 8, 2026
0ad977e
TML-3476: pin the engine build that also quotes a value starting with =
wmadden-electric Oct 8, 2026
41f6a14
TML-3476: a question does not offer rename for a field the plan alrea…
wmadden-electric Oct 8, 2026
72bb682
TML-3476: the slice spec and plan say each command declares its verbs…
wmadden-electric Oct 8, 2026
2b2cad2
TML-3476: the plan names MigrationSubject
wmadden-electric Oct 8, 2026
812e8a5
TML-3476: slice 4 removes the temporary refusesRenameStatements member
wmadden-electric Oct 8, 2026
7080961
TML-3476: the no-snapshot refusal gives the snapshot steps once, with…
wmadden-electric Oct 8, 2026
c1889e4
TML-3476: the data-loss check passes an unnamed destructive operation…
wmadden-electric Oct 8, 2026
b3d9052
TML-3476: a dry run marks the questions its flags answer and suggests…
wmadden-electric Oct 8, 2026
1ba19fd
TML-3476: export the subject types DbUpdateSuccess uses, and fix thre…
wmadden-electric Oct 8, 2026
7cbc9f9
TML-3476: the snapshot recovery text names no storage object
wmadden-electric Oct 8, 2026
dacbca4
TML-3476: a target that refuses renames says how to keep the data by …
wmadden-electric Oct 8, 2026
202731c
TML-3476: access questions say whether an operation widens or changes…
wmadden-electric Oct 8, 2026
791e0e0
TML-3476: the aggregate planner test gives its access change a widens…
wmadden-electric Oct 8, 2026
62a513e
TML-3476: the snapshot steps in a question name the prisma command
wmadden-electric Oct 8, 2026
acbda5d
TML-3476: a dry run's suggested apply repeats --to, --advance-ref and…
wmadden-electric Oct 8, 2026
2966304
TML-3476: docs, skills and fragments follow the QA fixes, and record …
wmadden-electric Oct 8, 2026
d194745
TML-3476: engine spec records the narrowed unused --confirm rule
wmadden-electric Oct 8, 2026
a50d17e
TML-3476: the engine spec's scope matches the narrowed --confirm rule
wmadden-electric Oct 8, 2026
61d5f23
TML-3476: pin the engine build that names stray flags in a refusal an…
wmadden-electric Oct 8, 2026
cf0efc5
TML-3476: pin engine 1cc84f8
wmadden-electric Oct 8, 2026
aa34e19
TML-3476: the spec says a policy drop changes access and disabling RL…
wmadden-electric Oct 8, 2026
13b0040
TML-3476: manual QA report for the refusal slice
wmadden-electric Oct 8, 2026
7b662cf
TML-3476: the spec types accessWidening with widens, and the refusal'…
wmadden-electric Oct 8, 2026
81d7b90
TML-3476: MongoDB's keep-the-documents advice is right for migration …
wmadden-electric Oct 8, 2026
b3e5005
TML-3476: a programmatic allow statement answers one operation, as an…
wmadden-electric Oct 8, 2026
a448bd7
TML-3476: the Prisma 7 handover example answers the drop of User.bio …
wmadden-electric Oct 8, 2026
73829a7
TML-3476: the command summary's statements paragraph sits below the f…
wmadden-electric Oct 8, 2026
c132b01
TML-3476: an allowed access change survives a re-plan, and MongoDB qu…
wmadden-electric Oct 8, 2026
d87adbc
TML-3476: merge main up to the commit before slice 1
wmadden-electric Oct 8, 2026
cdb6897
TML-3476: record slice 1's squash merge, whose content this branch al…
wmadden-electric Oct 8, 2026
ba05233
TML-3476: merge main
wmadden-electric Oct 8, 2026
b99bda1
TML-3476: use the published @prisma/cli-engine 0.7.0 instead of the p…
wmadden-electric Oct 8, 2026
0d93ccd
TML-3476: the drop-column and rollback journeys state their drops wit…
wmadden-electric Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/lsp-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"ws": "^8.21.2"
},
"devDependencies": {
"@prisma/cli-engine": "0.6.3",
"@prisma/cli-engine": "0.7.0",
"@repo/tsconfig": "workspace:8.0.0-rc.16",
"@types/node": "catalog:",
"@types/ws": "^8.5.13",
Expand Down
2 changes: 1 addition & 1 deletion apps/telemetry-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"evlog": "^2.24.0"
},
"devDependencies": {
"@prisma/cli-engine": "0.6.3",
"@prisma/cli-engine": "0.7.0",
"@prisma/compute-sdk": "^0.43.0",
"@prisma/management-api-sdk": "^1.76.0",
"@repo/test-utils": "workspace:8.0.0-rc.16",
Expand Down
14 changes: 10 additions & 4 deletions docs/CLI Style Guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,29 @@ The CLI checks `process.stdout.isTTY` once at startup to determine the output mo

### Destructive operation confirmation

Destructive operations (drops, type changes, overwriting generated files, overwriting an existing signature marker, …) require **explicit consent**: the user types the name of the thing being changed, or passes that name as `--confirm <token>`. Consent is separate from the `-y` "accept prompt defaults" mechanism, and no command invents a flag that skips it.
Operations that lose data (dropping a table or a column, a type change that can change values), operations that widen who can read or write rows, overwriting generated files, and overwriting an existing signature marker require **explicit consent**. Dropping an object that holds no data, such as an index or a constraint, is `widening` and asks nothing. Consent takes one of two forms:

- **Statements**, for a plan that would lose data or widen access. The command asks one question per model, field or storage name at stake, and each is answered with a statement naming it: `--delete <subject>`, `--rename <subject>:<new name>` or `--allow <subject>`. `migration plan` and `db update` use this form.
- **A consent token**, for a command with one thing at stake. The user types the name of the thing being changed, or passes that name as `--confirm <token>`. `init` uses this form.

Consent is separate from the `-y` "accept prompt defaults" mechanism, and no command invents a flag that skips it.

This is a deliberate divergence from clig.dev §Arguments §Confirmation. AI agents and CI scripts routinely pass `-y` to suppress prompts on long-running pipelines; conflating "skip prompts" with "consent to destruction" is a footgun the project has decided to avoid. Typing a name also rules out the other accident a yes/no prompt allows — consenting to the right operation against the wrong database.

#### Rules

- A command that performs a destructive action MUST ask for it with `ctx.prompt.consent(question, { token })`. The token is the natural noun of what is at stake: the database name for `db update`, the working directory's basename for an `init` re-scaffold. Interactively the user types the token; non-interactively `--confirm <token>` grants it. There is no `--force`.
- A command whose plan can lose data or widen access MUST ask about each subject with `ctx.prompt.statements(questions)`, one question per subject, before it writes or applies anything. A statement that answers no question fails the run with the engine's `CLI.CONSENT_UNUSED`; non-interactively, unanswered questions fail it with `CLI.CONSENT_REQUIRED`, listing each question and the flags that answer it. `--confirm` answers none of these questions.
- A command with one thing at stake MUST ask for it with `ctx.prompt.consent(question, { token })`. The token is the natural noun of what is at stake: the working directory's basename for an `init` re-scaffold. Interactively the user types the token; non-interactively `--confirm <token>` grants it. There is no `--force`.
- The question MUST list the destructive operations (or describe them concretely, e.g. "this will overwrite all generated files") so the user can decline knowing what's at stake. A command that cannot fill the list, or cannot derive a token, MUST fail with a structured error rather than ask a question that says nothing or accepts anything.
- The token MUST identify the thing being changed as precisely as the invocation allows. Falling back to something a whole class of runs shares — a target id, a product name — makes one `--confirm` value grant data loss in every project that shares it.
- Non-interactively (closed stdin, CI, `--no-interactive`) without `--confirm`: no prompt is shown; the command fails with the engine's `CLI.CONSENT_REQUIRED` (exit `2`), whose `meta.consentToken` and `nextActions` name the token to pass. A cancelled prompt is `CLI.PROMPT_CANCELLED` (exit `3`); a mistyped token is `CLI.PROMPT_INVALID` (exit `2`).
- `--confirm` is read only when the run is non-interactive or `--yes` is set. A script that runs from a terminal must pass `--no-interactive --confirm <token>`, or it will stop at the prompt.
- Each `--confirm` value grants at most one consent; a command that asks twice needs two.
- The internal control API retains a programmatic equivalent (e.g. `acceptDataLoss: boolean`) for consumers that drive the planner directly; `--confirm` is the user-facing CLI form. Note that consent authorises the operations the user was shown, and the plan is recomputed on the call that carries it — a command that cannot bind the two SHOULD report what it applied beyond what was consented to.
- The control API takes the same consent programmatically: `migration plan` and `db update` take an answer callback for their questions, and `db update`'s `acceptDataLoss: true` answers every data-loss question and `acceptAccessWidening: true` every access question.

#### Examples

- `db update`: when the plan includes destructive ops, asks the user to type the database name; `--no-interactive --confirm <database>` applies without a prompt. The name is the `database` a driver connection object carries, or the connection URL's first path segment, else its host, falling back to the target id.
- `db update`: asks one question per model, field or storage name an operation would lose data from, answered by `--delete` or `--rename`, and one per model whose rows an operation would open up, answered by `--allow`; `--no-interactive --delete Legacy --allow User` applies without a prompt.
- `init`: re-running `init` in a directory with a generated `prisma.config.ts` asks the user to type the directory's basename; `-y` alone is not sufficient to authorise overwriting generated files. (The commander-era `--force` retired with the commander shell in the S5 cutover; the engine-hosted `init` uses the consent form above.)
- `db sign`: overwriting a marker that holds a different hash happens without consent (the previous hash is reported). This is an intentional exception to the rule above: `db sign` verifies the live schema against the contract before writing, so the overwrite only ever records a contract the database already satisfies. If that ever grows a switch, it takes the consent form above — not a `--force`.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ADR 195 — Planner IR with two renderers (OpFactoryCall pattern)

> **Note (2026-10-07).** A MongoDB validator change and a change-stream image setting are now classed `widening` whatever they change, because neither removes a document; the planner no longer runs `classifyValidatorUpdate`. The planner still chooses the class where it depends on the origin: a Postgres type change is `widening` when it keeps every value and `destructive` otherwise, so `AlterColumnTypeCall` carries a computed `operationClass` too.

## At a glance

The planner diffs two contracts and determines that a unique ascending index on `users.email` needs to be created. Rather than directly constructing the full operation ([ADR 188](ADR%20188%20-%20MongoDB%20migration%20operation%20model.md)), it produces an IR node:
Expand Down
Loading
Loading