This repository was archived by the owner on Aug 25, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathROADMAP.html
More file actions
612 lines (556 loc) · 64.7 KB
/
Copy pathROADMAP.html
File metadata and controls
612 lines (556 loc) · 64.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
<title>Roadmap to Prisma 8 RC1</title>
<style>
:root {
--bg: oklch(0.985 0.003 220);
--surface: oklch(1 0 0);
--surface-2: oklch(0.965 0.006 215);
--ink: oklch(0.28 0.045 235);
--ink-soft: oklch(0.42 0.035 235);
--line: oklch(0.9 0.01 220);
--line-strong: oklch(0.82 0.015 220);
--accent: oklch(0.62 0.11 180);
--accent-ink: oklch(0.45 0.09 180);
--accent-tint: oklch(0.95 0.025 180);
--good: oklch(0.5 0.12 155);
--good-bg: oklch(0.94 0.045 155);
--open: oklch(0.42 0.03 235);
--open-bg: oklch(0.93 0.008 220);
--warn: oklch(0.53 0.11 70);
--warn-bg: oklch(0.95 0.04 85);
--mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
--dur: 180ms;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: oklch(0.21 0.025 235);
--surface: oklch(0.25 0.028 235);
--surface-2: oklch(0.28 0.03 235);
--ink: oklch(0.92 0.012 220);
--ink-soft: oklch(0.74 0.02 220);
--line: oklch(0.34 0.03 235);
--line-strong: oklch(0.42 0.03 235);
--accent: oklch(0.75 0.1 180);
--accent-ink: oklch(0.8 0.1 180);
--accent-tint: oklch(0.3 0.04 190);
--good: oklch(0.78 0.13 155);
--good-bg: oklch(0.32 0.05 155);
--open: oklch(0.74 0.02 220);
--open-bg: oklch(0.31 0.02 235);
--warn: oklch(0.8 0.11 80);
--warn-bg: oklch(0.33 0.04 80);
}
}
:root[data-theme="light"] {
--bg: oklch(0.985 0.003 220); --surface: oklch(1 0 0); --surface-2: oklch(0.965 0.006 215);
--ink: oklch(0.28 0.045 235); --ink-soft: oklch(0.42 0.035 235);
--line: oklch(0.9 0.01 220); --line-strong: oklch(0.82 0.015 220);
--accent: oklch(0.62 0.11 180); --accent-ink: oklch(0.45 0.09 180); --accent-tint: oklch(0.95 0.025 180);
--good: oklch(0.5 0.12 155); --good-bg: oklch(0.94 0.045 155);
--open: oklch(0.42 0.03 235); --open-bg: oklch(0.93 0.008 220);
--warn: oklch(0.53 0.11 70); --warn-bg: oklch(0.95 0.04 85);
}
:root[data-theme="dark"] {
--bg: oklch(0.21 0.025 235); --surface: oklch(0.25 0.028 235); --surface-2: oklch(0.28 0.03 235);
--ink: oklch(0.92 0.012 220); --ink-soft: oklch(0.74 0.02 220);
--line: oklch(0.34 0.03 235); --line-strong: oklch(0.42 0.03 235);
--accent: oklch(0.75 0.1 180); --accent-ink: oklch(0.8 0.1 180); --accent-tint: oklch(0.3 0.04 190);
--good: oklch(0.78 0.13 155); --good-bg: oklch(0.32 0.05 155);
--open: oklch(0.74 0.02 220); --open-bg: oklch(0.31 0.02 235);
--warn: oklch(0.8 0.11 80); --warn-bg: oklch(0.33 0.04 80);
}
* { box-sizing: border-box; }
body {
margin: 0; background: var(--bg); color: var(--ink);
font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
font-variant-numeric: tabular-nums;
padding: 52px 24px 96px;
}
.wrap { max-width: 780px; margin: 0 auto; }
a { color: var(--accent-ink); text-decoration-thickness: 1px; text-underline-offset: 2px; }
code {
font-family: var(--mono); font-size: 0.86em;
background: var(--surface-2); border: 1px solid var(--line);
border-radius: 4px; padding: 0.08em 0.35em;
}
h1 { font-size: 32px; line-height: 1.2; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 18px; text-wrap: balance; }
h2 { font-size: 20px; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 10px; text-wrap: balance; }
p { margin: 0 0 14px; max-width: 72ch; text-wrap: pretty; }
.soft { color: var(--ink-soft); }
.masthead { margin-bottom: 40px; }
.masthead .org { font-family: var(--mono); font-size: 12.5px; color: var(--ink-soft); margin: 0 0 14px; }
.statusline {
display: flex; flex-wrap: wrap; gap: 10px 28px; align-items: baseline;
background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
padding: 14px 20px; margin-top: 22px;
}
.statusline .item { display: flex; gap: 8px; align-items: baseline; }
.statusline .k { font-size: 12.5px; color: var(--ink-soft); }
.statusline .v { font-family: var(--mono); font-size: 15px; font-weight: 700; }
.statusline .v.teal { color: var(--accent-ink); }
.statusline .v.ok { color: var(--good); }
.statusline .v.link { font-size: 14px; }
.progress {
background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
padding: 14px 20px 15px; margin-top: 12px;
}
.progress .cap { font-size: 12.5px; color: var(--ink-soft); margin: 0 0 8px; }
.progress .bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden; background: var(--open-bg); }
.progress .bar .done { background: var(--good); }
.progress .bar .flight { background: var(--accent); }
.progress .legend { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 9px; font-size: 13.5px; color: var(--ink-soft); }
.progress .legend b { color: var(--ink); }
.progress .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; }
.owner {
flex: none; font-family: var(--mono); font-size: 11px; font-weight: 600;
color: var(--ink-soft); background: var(--surface-2); border: 1px solid var(--line);
border-radius: 5px; padding: 2px 8px; white-space: nowrap; align-self: center;
}
.musts { margin: 44px 0 10px; }
.musts ol { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); overflow: hidden; }
.musts li { display: flex; gap: 16px; align-items: baseline; padding: 14px 18px; border-top: 1px solid var(--line); }
.musts li:first-child { border-top: none; }
.musts .n { font-family: var(--mono); font-size: 14px; font-weight: 700; color: var(--accent-ink); flex: none; width: 16px; }
.musts .what { flex: 1 1 auto; min-width: 0; }
.musts .what a { color: var(--ink); font-weight: 650; text-decoration: none; }
.musts .what a:hover { color: var(--accent-ink); text-decoration: underline; }
.musts .what .note { display: block; font-size: 14px; color: var(--ink-soft); margin-top: 1px; }
.musts .mini { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.musts .minibar { flex: 1 1 auto; max-width: 340px; height: 6px; border-radius: 3px; overflow: hidden; display: flex; background: var(--open-bg); }
.musts .minibar .d { background: var(--good); }
.musts .minibar .f { background: var(--accent); }
.musts .minicount { font-family: var(--mono); font-size: 11px; color: var(--ink-soft); white-space: nowrap; }
.pill {
flex: none; font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
padding: 3px 10px; border-radius: 999px; white-space: nowrap; align-self: center;
}
.pill.flight { color: var(--good); background: var(--good-bg); }
.pill.open { color: var(--open); background: var(--open-bg); }
.pill.done { color: var(--good); background: var(--good-bg); }
.pill.decide { color: var(--warn); background: var(--warn-bg); }
section.req { margin-top: 52px; scroll-margin-top: 24px; }
section.req > p { color: var(--ink); }
section.req .reqno { font-family: var(--mono); font-size: 13px; font-weight: 700; color: var(--accent-ink); display: inline-block; margin-bottom: 4px; }
details.task {
background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
margin: 10px 0; overflow: hidden;
}
details.task[open] { border-color: var(--line-strong); }
details.task > summary {
display: flex; gap: 12px; align-items: center; padding: 13px 16px;
cursor: pointer; list-style: none; user-select: none;
transition: background-color var(--dur) cubic-bezier(0.22, 1, 0.36, 1);
}
details.task > summary::-webkit-details-marker { display: none; }
details.task > summary:hover { background: var(--surface-2); }
details.task > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 10px; }
details.task > summary .chev {
flex: none; width: 16px; height: 16px; color: var(--ink-soft);
transition: transform var(--dur) cubic-bezier(0.22, 1, 0.36, 1);
}
details.task[open] > summary .chev { transform: rotate(90deg); }
details.task > summary .t { flex: 1 1 auto; font-weight: 650; font-size: 15px; min-width: 0; }
details.task .body { padding: 2px 18px 16px 44px; }
details.task .body p, details.task .body li { font-size: 15px; color: var(--ink); }
details.task .body ul { margin: 0 0 12px; padding-left: 20px; display: flex; flex-direction: column; gap: 7px; max-width: 70ch; }
.crit { font-family: var(--mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; color: var(--accent-ink); background: var(--accent-tint); border-radius: 4px; padding: 3px 7px; flex: none; }
.meter { margin: 14px 0 6px; }
.meter .bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden; background: var(--open-bg); }
.meter .seg1 { background: var(--accent); }
.meter .seg2 { background: var(--warn-bg); border-left: 1px solid var(--bg); }
.meter .seg2d { background: var(--warn); opacity: 0.45; }
.meter .legend { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 10px; font-size: 13.5px; color: var(--ink-soft); }
.meter .legend b { color: var(--ink); font-variant-numeric: tabular-nums; }
.meter .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: baseline; }
.landed { margin-top: 56px; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 20px 24px 8px; }
.landed ul { margin: 6px 0 16px; padding-left: 20px; display: flex; flex-direction: column; gap: 9px; max-width: 70ch; }
.landed li { font-size: 15px; }
footer { margin-top: 44px; font-size: 13.5px; color: var(--ink-soft); max-width: 72ch; }
@media (prefers-reduced-motion: reduce) {
details.task > summary, details.task > summary .chev { transition: none; }
}
@media (max-width: 560px) {
body { padding: 32px 16px 72px; }
.musts li { flex-wrap: wrap; }
.musts .what { flex-basis: 100%; order: 3; }
}
</style>
<div class="wrap">
<header class="masthead">
<p class="org">Prisma Engineering</p>
<h1>Roadmap to Prisma 8 RC1</h1>
<p>Prisma Next — the contract-first rewrite of Prisma — ships as <strong>Prisma 8</strong>. On <strong>July 31</strong> we publish <strong><code>prisma@8.0.0-rc.1</code></strong> from the <code>prisma/prisma</code> repository: the same repository and the same npm package Prisma users already know. The release candidate is published under a pre-release tag, so <code>npm install prisma</code> keeps installing Prisma 7 until 8.0.0 final ships.</p>
<p>Prisma 8 carries <strong>PostgreSQL to general availability</strong> — and that is all: <strong>MongoDB ships in early access</strong>, and <strong>SQLite is a proof of concept</strong> at this stage. A release candidate freezes the public API; it does not promise Prisma 7 feature parity. Its promise is different: <strong>everything it ships works and is proven by a test</strong>, everything experimental is labeled, and everything absent is named rather than silently missing.</p>
<div class="statusline">
<span class="item"><span class="k">Ships</span> <span class="v teal">July 31</span></span>
<span class="item"><span class="k">Health</span> <span class="v ok">On track</span></span>
<span class="item"><span class="k">Updated</span> <span class="v">July 23</span></span>
<span class="item"><span class="k">Scoreboard</span> <span class="v link"><a href="https://github.com/prisma/prisma-next/pull/1000">450 proven · 500 unproven · 30 experimental · 250 not in 8.0</a></span></span>
</div>
<div class="progress">
<p class="cap">Work on this page: <b>34 tasks</b> — 6 done, 11 in flight, 17 not started</p>
<div class="bar" role="img" aria-label="34 tasks: 6 done, 11 in flight, 17 not started">
<div class="done" style="width: 18%"></div>
<div class="flight" style="width: 32%"></div>
</div>
<div class="legend">
<span><span class="dot" style="background: var(--good)"></span><b>5</b> done</span>
<span><span class="dot" style="background: var(--accent)"></span><b>12</b> in flight</span>
<span><span class="dot" style="background: var(--open-bg); outline: 1px solid var(--line-strong); outline-offset: -1px;"></span><b>17</b> not started</span>
</div>
<p class="cap" style="margin-top: 16px;"><a href="https://github.com/prisma/prisma-next/pull/1000">Feature scoreboard</a>: <b>~1,230 cells</b> (~326 features × 3 databases) — 450 proven, 500 unproven, 30 experimental, 250 not in 8.0</p>
<div class="bar" role="img" aria-label="Scoreboard: about 450 cells proven, 500 unproven, 30 experimental, 250 not in 8.0">
<div style="width: 36.5%; background: var(--accent);"></div>
<div style="width: 40.7%; background: var(--warn); opacity: 0.45;"></div>
<div style="width: 2.5%; background: var(--line-strong);"></div>
<div style="width: 20.3%; background: var(--open); opacity: 0.35;"></div>
</div>
<div class="legend">
<span><span class="dot" style="background: var(--accent)"></span><b>~450</b> proven by a named test</span>
<span><span class="dot" style="background: var(--warn); opacity: 0.45"></span><b>~500</b> unproven — the test-writing queue</span>
<span><span class="dot" style="background: var(--line-strong)"></span><b>~30</b> experimental</span>
<span><span class="dot" style="background: var(--open); opacity: 0.35"></span><b>~250</b> not in 8.0 (named absences)</span>
</div>
</div>
</header>
<section class="musts" aria-labelledby="musts-h">
<h2 id="musts-h">What needs to happen to release v8-RC1</h2>
<p class="soft">Six things must be true on release day. Everything on this page belongs to one of them.</p>
<ol>
<li>
<span class="n">1</span>
<span class="what"><a href="#req1">Queries must return correct values</a>
<span class="note">The main remaining defect: values read through relation-loading corrupt or fail.</span><span class="mini" aria-hidden="false"><span class="minibar" role="img" aria-label="5 tasks: 1 done · 4 in flight"><span class="d" style="width: 20.0%"></span><span class="f" style="width: 80.0%"></span></span><span class="minicount">1 done · 4 in flight</span></span></span>
<span class="owner">Alexey</span>
<span class="pill flight">In progress</span>
</li>
<li>
<span class="n">2</span>
<span class="what"><a href="#req2">The schema language must reach its final form</a>
<span class="note">Whatever syntax the RC ships is permanent for the life of v8; three language projects are running.</span><span class="mini" aria-hidden="false"><span class="minibar" role="img" aria-label="6 tasks: 3 in flight · 3 not started"><span class="f" style="width: 50.0%"></span></span><span class="minicount">3 in flight · 3 not started</span></span></span>
<span class="owner">Serhii</span>
<span class="pill flight">In flight</span>
</li>
<li>
<span class="n">3</span>
<span class="what"><a href="#req3">Every name and format users depend on must be final</a>
<span class="note">Error codes, hashes, the migration snapshot layout, and the config-key rename are done; the name sweep remains.</span><span class="mini" aria-hidden="false"><span class="minibar" role="img" aria-label="5 tasks: 4 done · 1 not started"><span class="d" style="width: 80.0%"></span></span><span class="minicount">4 done · 1 not started</span></span></span>
<span class="owner">Will</span>
<span class="pill flight">In progress</span>
</li>
<li>
<span class="n">4</span>
<span class="what"><a href="#req4">The release's claims must be proven</a>
<span class="note">"It works" and "you can migrate incrementally" each need a runnable receipt.</span><span class="mini" aria-hidden="false"><span class="minibar" role="img" aria-label="6 tasks: 1 done · 3 in flight · 2 not started"><span class="d" style="width: 16.7%"></span><span class="f" style="width: 50.0%"></span></span><span class="minicount">1 done · 3 in flight · 2 not started</span></span></span>
<span class="owner">Everyone</span>
<span class="pill flight">Scoreboard drafted</span>
</li>
<li>
<span class="n">5</span>
<span class="what"><a href="#req5">The code must move into prisma/prisma</a>
<span class="note">Repository merge, publishing pipeline, and years of open v7 issues.</span><span class="mini" aria-hidden="false"><span class="minibar" role="img" aria-label="5 tasks: 1 in flight · 4 not started"><span class="f" style="width: 20.0%"></span></span><span class="minicount">1 in flight · 4 not started</span></span></span>
<span class="owner">Alexey</span>
<span class="pill open">Starting</span>
</li>
<li>
<span class="n">6</span>
<span class="what"><a href="#req6">The rough edges users hit on day one must be gone</a>
<span class="note">Small fixes that would be embarrassing under announcement-day attention.</span><span class="mini" aria-hidden="false"><span class="minibar" role="img" aria-label="7 tasks: 1 in flight · 6 not started"><span class="f" style="width: 14.3%"></span></span><span class="minicount">1 in flight · 6 not started</span></span></span>
<span class="owner">Everyone</span>
<span class="pill open">Open</span>
</li>
</ol>
<p class="soft" style="margin-top: 16px;">Two dated decisions still bound the work. One is now overdue: the minimum supported Postgres version, whose <strong>July 22</strong> target has passed and still blocks final scoreboard verdicts until it is set. One is imminent: the polymorphism stable-or-experimental call (<strong>July 24</strong>, decided by whether its bug stream has flattened). A third is already made and delivered: error codes standardize on dotted namespace codes (like <code>ORM.DECODE_FAILED</code>), and the consolidation has landed. July 24 is also the day the scoreboard verdicts freeze and scope stops moving. There is no other internal schedule: we work these sections as fast as they'll go and ship when they're done.</p>
</section>
<section class="req" id="req1">
<span class="reqno">Requirement 1</span>
<span class="owner" style="margin-left: 8px;">Alexey</span>
<h2>Queries must return correct values</h2>
<p class="soft">Prisma 8's core promise at the RC is that the query paths it ships are correct. One significant defect class remains, plus the tail of an almost-finished one.</p>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Values read through relation-loading bypass their type codecs — big numbers silently corrupt, date columns throw</span><span class="crit">CRITICAL PATH</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>When a query loads a relation (say, a post together with its author), Postgres assembles the nested rows into JSON inside the database, using its <code>json_agg</code> function. JSON numbers cannot represent everything a database column can hold: a 64-bit integer or arbitrary-precision decimal gets silently rounded to the nearest JavaScript-representable number before Prisma's type codecs ever see it, and date/time values arrive in a format the decoder rejects — so a plain <code>DateTime</code> column read through <code>.include()</code> throws today.</p>
<p>The fix: every type codec gains an explicit <em>lossless</em> JSON form (big numbers travel as strings, for example), and the SQL we generate is changed to produce that form inside the database. It lands as four pull requests in strict sequence — foundations, per-database codec descriptors, the switch-over, then aggregate typing. The switch-over is a breaking change: users regenerate their contract files, and some aggregate result types change (a <code>count()</code> becomes a <code>bigint</code>, decimal sums become strings — precise instead of approximately convenient).</p>
<p>Tracked as <a href="https://linear.app/prisma-company/issue/TML-3060/plan-codec-json-projections">TML-3060</a>; in flight now — the first of the four PRs, the explicit-JSON-projection AST foundations, has landed (<a href="https://linear.app/prisma-company/issue/TML-3062">TML-3062</a>, <a href="https://github.com/prisma/prisma-next/pull/1023">#1023</a>).</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t"><code>date</code> columns fail at runtime when read through relation-loading</span><span class="pill done">Landed</span></summary>
<div class="body">
<p>The codec that correctly handles Postgres <code>date</code> values exists and is strict (it rejects impossible dates like February 31st rather than silently normalizing them), but nothing connected the <code>date</code> column type to it — so reading a <code>date</code> column through <code>.include()</code> threw at decode time, because the column inherited the <code>timestamptz</code> codec, which rejects the bare <code>YYYY-MM-DD</code> that <code>json_agg</code> renders. <code>@db.Date</code> now binds to <code>pg/date@1</code>, and a test proves an included <code>date</code> column comes back as a <code>Date</code> (<a href="https://linear.app/prisma-company/issue/TML-3086">TML-3086</a>, landed as <a href="https://github.com/prisma/prisma-next/pull/1038">#1038</a>).</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Binary columns read through relation-loading return hex text instead of bytes</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Same disease as the big one above, concrete instance: a <code>Bytes</code> column selected inside <code>.include()</code> comes back as the raw hexadecimal text Postgres uses in JSON (<code>\x48656c6c6f</code>) while the TypeScript types promise a <code>Uint8Array</code>. Fixed by the same lossless-JSON work; a separate ticket (<a href="https://linear.app/prisma-company/issue/TML-2990">TML-2990</a>) tracks it so it can't be forgotten in the sweep. In progress.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Places where the TypeScript types and the runtime disagree</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Two known mismatches, both "the type signature promises one thing, the running code returns another":</p>
<ul>
<li><code>Timestamp</code>/<code>Timestamptz</code> columns: the declared output type is a branded string, but the codec actually returns a JavaScript <code>Date</code> (<a href="https://linear.app/prisma-company/issue/TML-2391">TML-2391</a>, in progress).</li>
<li>Projects that use the schema types directly without running contract emission (<code>typeof contract</code>) get types that ignore per-instance codec parameters and enum value sets — so a column can typecheck against values the database will reject (<a href="https://linear.app/prisma-company/issue/TML-2960">TML-2960</a>, in progress).</li>
</ul>
<p>A type that lies is a correctness bug with a delay on it; both must be resolved (or the type corrected to tell the truth) before the types freeze.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Finish the polymorphism bug tail — then decide: stable or experimental</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Polymorphism means models that inherit from a base model, stored across joined tables (multi-table inheritance). It has been the source of most of Prisma 8's recent correctness bugs. The encouraging signal: recent fixes are narrow edge cases rather than missing capabilities, and no known-broken or skipped tests remain in the area. The open list, so the tail is visible rather than vibes:</p>
<ul>
<li>Explicit <code>.select(...)</code> on a polymorphic include doesn't restrict variant-table columns (<a href="https://linear.app/prisma-company/issue/TML-2783">TML-2783</a>, in progress — the core fix landed, follow-up open).</li>
<li>Variant lookup is namespace-flat, so two variants with the same name in different namespaces can't be addressed (<a href="https://linear.app/prisma-company/issue/TML-2841">TML-2841</a>, in progress).</li>
<li>The model accessor's return type isn't variant-aware (<a href="https://linear.app/prisma-company/issue/TML-2847">TML-2847</a>, in progress).</li>
<li>The shorthand <code>.where({priority: 1})</code> form rejects variant fields that the callback form accepts (<a href="https://linear.app/prisma-company/issue/TML-2982">TML-2982</a>, open).</li>
<li>Bulk <code>createAll()</code> on a variant silently drops write annotations (<a href="https://linear.app/prisma-company/issue/TML-2600">TML-2600</a>, open).</li>
<li>A variant model declaring a column that collides with a base-table column silently merges instead of failing validation (<a href="https://linear.app/prisma-company/issue/TML-2827">TML-2827</a>, open).</li>
</ul>
<p>On July 24 we decide from this list and the discovery rate, not from hope: if it's shrinking and nothing new is appearing, polymorphism ships inside the stability promise; otherwise it ships clearly labeled experimental and stabilization continues after the RC without blocking it.</p>
</div>
</details>
</section>
<section class="req" id="req2">
<span class="reqno">Requirement 2</span>
<span class="owner" style="margin-left: 8px;">Serhii</span>
<h2>The schema language must reach its final form</h2>
<p class="soft">Users write their data model in Prisma Schema Language (PSL) files. Whatever syntax the RC accepts is the syntax v8 supports forever — so every planned change to the language must land before July 31 or be abandoned. Four language changes are planned — mixins, native column types, directional relations, and tagged SQL fences — plus two items that follow from them: removing <code>@dbgenerated()</code> builds on the tagged fences, and the example schemas get regenerated once at the end. All of it is coordinated so users' generated files change once, not once per change.</p>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Mixins: reusable, named sets of fields</span><span class="crit">CRITICAL PATH</span><span class="pill flight">Design in progress</span></summary>
<div class="body">
<p>The long-standing ask — share <code>createdAt</code>/<code>updatedAt</code>/tenant-id fields across many models without copy-paste — gets a first-class answer: define the fields once in a named <code>mixin</code> block, include them with <code>@@include(WithTimestamps)</code>. Mixins deliberately take no parameters (variations get their own names), and they replace two existing mechanisms that grew complicated trying to solve the same problem: <em>field presets</em> (pack-shipped field templates with an argument system) and <em>type aliases</em>. Both retire.</p>
<p>Decided by the team on July 20; design in progress. Tracked as <a href="https://linear.app/prisma-company/issue/TML-3055/psl-mixins-named-field-set-reuse-retire-field-presets-type-aliases-and">TML-3055</a>. This is the largest single pre-release work item.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Native column types move onto type constructors; <code>@db.*</code> attributes are deleted</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Prisma 7 spelled database-native column types with attributes: <code>email String @db.VarChar(255)</code>. Prisma 8 replaces that spelling with the type written directly in the type position: <code>email VarChar(255)</code>, <code>id Uuid</code>, <code>payload Jsonb</code>. The type says what the column is; no attribute needed. All <code>@db.*</code> attribute support is deleted from the language before the freeze — shipping both spellings would freeze both forever.</p>
<p>This has its own running project ("Remove <code>@db.*</code> attributes from PSL"). The scalar-type unification — every scalar becomes a zero-argument type constructor under one contribution mechanism, with the Postgres native constructors exposed — has landed (<a href="https://linear.app/prisma-company/issue/TML-2986">TML-2986</a>, <a href="https://github.com/prisma/prisma-next/pull/1022">#1022</a>). What remains is deleting the <code>@db.*</code> channel itself (<a href="https://linear.app/prisma-company/issue/TML-2988">TML-2988</a>) so only the bare-type spelling survives the freeze.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Relations get a directional spelling; <code>@relation(name:)</code> retires</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Prisma 7 expressed relations with paired fields on both models and disambiguated with <code>@relation(name: "...")</code> strings — a spelling users routinely get wrong. Prisma 8 replaces it with directional syntax: a foreign key declares where it points (<code>from</code>/<code>to</code>), many-to-many goes through an explicit junction (<code>through: Junction</code>) or an implicit one synthesized for you, and multi-hop paths spell the route out (<code>a -> J.b -> J.c -> T.d</code>). Five slices, all in flight (<a href="https://linear.app/prisma-company/issue/TML-2940">TML-2940</a> through <a href="https://linear.app/prisma-company/issue/TML-2944">TML-2944</a>). This is frozen-surface work on exactly the same clock as mixins: whatever relation spelling the RC accepts is the spelling for the life of v8.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">SQL embedded in schemas gets proper fences instead of escaped strings</span><span class="pill open">Open</span></summary>
<div class="body">
<p>Schemas sometimes need to carry a piece of literal SQL: a view definition, a partial-index condition, a row-level-security policy expression, a database-computed default. Today those travel as ordinary quoted strings, with all the escaping pain that implies. The accepted design (<a href="https://github.com/prisma/prisma-next/blob/main/docs/architecture%20docs/adrs/ADR%20129%20-%20Template-Tagged%20Literals%20for%20Extensions.md">ADR 129</a>) is a tagged backtick fence — <code>pg.sql`SELECT 1`</code> — with no string interpolation, cleanly handed to the extension that owns it. It is not implemented yet; if it doesn't land, the quoted-string form freezes as the API.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t"><code>@dbgenerated()</code> is removed; database-computed defaults become tagged fences</span><span class="pill open">Open</span></summary>
<div class="body">
<p>Prisma 7 spelled "the database computes this default" as an attribute wrapping a SQL string: <code>@default(dbgenerated("gen_random_uuid()"))</code> — a quoted string with escaping problems and no ownership story. Prisma 8 removes <code>@dbgenerated()</code> entirely: a raw SQL default is written as a tagged backtick fence (the mechanism above), so the same one syntax carries every piece of embedded SQL in a schema. This depends on the tagged-fence implementation landing first. It also reaches beyond the parser: the Postgres and SQLite default-handling code and the introspection path (which meets <code>dbgenerated</code>-shaped defaults in every real existing database, and must <em>emit</em> tagged fences for them) all change with it.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Regenerate every example schema and migration — once, at the end</span><span class="pill open">Open</span></summary>
<div class="body">
<p>All of the above changes what generated schema and migration files look like. The example projects and their committed migrations get regenerated a single time after the last language change lands, rather than churning after each one.</p>
</div>
</details>
</section>
<section class="req" id="req3">
<span class="reqno">Requirement 3</span>
<span class="owner" style="margin-left: 8px;">Will</span>
<h2>Every name and format users depend on must be final</h2>
<p class="soft">Users write <code>catch</code> blocks against error codes, commit generated contract and migration files to their repositories, and write config files against our keys. All of that becomes permanent API at the RC. Five changes must land first — sequenced together, because several of them alter the same generated files and users should see one change, not five.</p>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">One error-code scheme instead of four</span><span class="pill done">Landed</span></summary>
<div class="body">
<p>Prisma 8 grew four separate error systems with two incompatible code formats — about 46 codes shaped like <code>PN-CLI-4001</code> and about 89 shaped like <code>RUNTIME.DECODE_FAILED</code> — plus roughly sixteen error classes carrying no code at all. That's over: every published error is now a structural envelope with a dotted <code>NAMESPACE.SUBCODE</code> code, recognized by a type predicate instead of <code>instanceof</code> (<a href="https://linear.app/prisma-company/issue/TML-3067">TML-3067</a>); the ORM's and the contract-authoring plane's formerly codeless throws carry structured <code>ORM.*</code> / <code>CONTRACT.*</code> codes (<a href="https://linear.app/prisma-company/issue/TML-3070">TML-3070</a>, <a href="https://linear.app/prisma-company/issue/TML-3075">TML-3075</a>); and the reference page documenting all 221 published codes ships in-repo with a CI check that fails any change adding an undocumented code (<a href="https://linear.app/prisma-company/issue/TML-3071">TML-3071</a>). The old→new crosswalk is published in ADR 239 and feeds the v8 upgrade guide. What continues after the freeze is non-breaking by construction: sweeping the adapter and extension planes' remaining codeless throws onto the same scheme only <em>adds</em> codes. Prisma 7's <code>P1001</code>-style codes are deliberately not carried over — the upgrade guide will include a translation table for migrating monitoring rules and runbooks.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Rename the <code>extensionPacks</code> config key to <code>extensions</code></span><span class="pill done">Landed</span></summary>
<div class="body">
<p>A simple rename with a deep reach: the key lived in user config files, in the generated contract document's schema, and in the code that canonicalizes and hashes contracts. It is now <code>extensions</code> everywhere, a guard rejects the old key, and every contract hash, migration, and snapshot was regenerated. The config-format sweep rode along — <code>contract.source.sourceFormat</code> became <code>format</code> and the sugar <code>outputPath</code> became <code>output</code> — with the ADRs and the consumer and extension-author upgrade recipes updated to match. (<a href="https://linear.app/prisma-company/issue/TML-2462">TML-2462</a>, <a href="https://github.com/prisma/prisma-next/pull/1032">#1032</a>)</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Hashes lose their <code>sha256:</code> prefix</span><span class="pill done">Landed</span></summary>
<div class="body">
<p>Prisma 8 identifies contracts and migrations by content hash, and every hash used to be written with an algorithm prefix: <code>"storageHash": "sha256:9f49…"</code>. The prefix added nothing (the algorithm isn't going to vary per hash) and it appeared everywhere users see a hash — generated contract files, migration manifests, the bookkeeping tables Prisma maintains in the user's database. The textual form of hashes freezes at the RC, so the prefix was dropped now, in one sweep across the source plus regenerated examples (<a href="https://linear.app/prisma-company/issue/TML-2756">TML-2756</a>, <a href="https://github.com/prisma/prisma-next/pull/1033">#1033</a>).</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Store each contract snapshot once instead of copying it into every migration</span><span class="pill done">Landed</span></summary>
<div class="body">
<p>Every migration folder used to carry full copies of the data contract it goes from and to — so a project with N migrations stored roughly 2N copies of N+1 distinct documents. They now live in a single <code>migrations/snapshots/<hash>/</code> store, one file per distinct contract, named by its content hash; migration folders already record which hashes they go from and to, so they need no new linking files. A migration's identity hash deliberately doesn't cover the snapshots, so converting the layout invalidated no existing migration (<a href="https://linear.app/prisma-company/issue/TML-3059">TML-3059</a>, <a href="https://github.com/prisma/prisma-next/pull/1018">#1018</a>), and a one-shot migrator converts existing projects' committed migration trees. A follow-up folded the last full-contract copies — the ref-paired snapshots — into the same store, so a ref is now a pure <code>{hash, invariants}</code> pointer and "snapshot" is a single concept (<a href="https://linear.app/prisma-company/issue/TML-3072">TML-3072</a>, <a href="https://github.com/prisma/prisma-next/pull/1024">#1024</a>). This closes the migrations-folder layout ahead of the freeze — users commit these folders to their repositories.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Sweep out the old <code>prisma-next</code> name everywhere it's baked in</span><span class="pill open">Open</span></summary>
<div class="body">
<p>After the package rename (requirement 5), the old name survives in places that are easy to forget and hard to change later: the project templates that <code>prisma-next init</code> writes for new users, the agent skills it installs into user projects, the documentation links embedded inside error messages (which must resolve to real pages on release day), and internal-looking names that are actually permanent — environment variable names, the per-user config file path, telemetry identifiers. Each gets an explicit keep-or-rename decision before the freeze makes the choice for us.</p>
</div>
</details>
</section>
<section class="req" id="req4">
<span class="reqno">Requirement 4</span>
<span class="owner" style="margin-left: 8px;">Everyone</span>
<h2>The release's claims must be proven</h2>
<p class="soft">The announcement will make two big claims: <em>everything Prisma 8 ships works</em>, and <em>you can run Prisma 7 and Prisma 8 side by side and migrate incrementally</em>. With early-access adoption having been thin, tests have to do the confidence-building work that production feedback normally would. Each claim gets a runnable receipt.</p>
<details class="task" open>
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">The feature scoreboard: ~326 features × 3 databases, every "works" backed by a named test</span><span class="pill flight">Draft in review</span></summary>
<div class="body">
<p>A matrix of every feature against every supported database (Postgres, SQLite, MongoDB). Each cell holds a verdict: <strong>works</strong> (and names the test suite that proves it), <strong>unproven</strong> (reachable, but no test demonstrates it yet), <strong>experimental</strong> (shipped, outside the stability promise), or <strong>not in 8.0</strong> (a deliberate, written-down absence — nothing is allowed to be silently missing). The rows come from two directions: everything Prisma 8's public surface exposes, crossed with every notable Prisma 7 capability, so absences are named rather than discovered.</p>
<div class="meter">
<div class="bar" role="img" aria-label="Of roughly 980 availability-claiming cells: about 450 proven, 500 unproven, 30 experimental">
<div class="seg1" style="width: 46%"></div>
<div class="seg2d" style="width: 51%"></div>
</div>
<div class="legend">
<span><span class="dot" style="background: var(--accent)"></span><b>~450</b> proven by a named test</span>
<span><span class="dot" style="background: var(--warn); opacity: 0.45"></span><b>~500</b> unproven — the test-writing queue</span>
<span><span class="dot" style="background: var(--open-bg); outline: 1px solid var(--line-strong); outline-offset: -1px;"></span><b>~30</b> experimental</span>
</div>
</div>
<p>A further <strong>~250</strong> cells are deliberate, named absences ("not in 8.0"). The draft is up for review as <a href="https://github.com/prisma/prisma-next/pull/1000">PR #1000</a>. The unproven column is literally the remaining test-writing queue, and the rendered matrix ships publicly with the RC — progress from here on is cells flipping from unproven to proven.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Capabilities still landing before the verdicts freeze on July 24</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Several features are mid-flight; their scoreboard cells can't get final verdicts until they land or get cut:</p>
<ul>
<li><strong>Native scalar arrays</strong> — <code>String[]</code>, <code>Int[]</code> and friends as real Postgres array columns, end-to-end from schema authoring through querying, filtering, and mutation. Slices 2 and 3 in flight (<a href="https://linear.app/prisma-company/issue/TML-2912">TML-2912</a>, <a href="https://linear.app/prisma-company/issue/TML-2913">TML-2913</a>).</li>
<li><strong>Enums on every database</strong> — the plan to treat enums as an application-level concept so they work uniformly on Postgres, SQLite, and MongoDB rather than only where the database has native enums (<a href="https://linear.app/prisma-company/issue/TML-2815">TML-2815</a>, planning in progress).</li>
<li><strong>Polymorphism in the TypeScript authoring path</strong> — schemas written in TypeScript (instead of PSL) can't declare inheritance yet; the PSL path can (<a href="https://linear.app/prisma-company/issue/TML-2228">TML-2228</a>, open). Until it lands, the scoreboard carries the asymmetry explicitly.</li>
</ul>
<p>Anything on this list that misses July 24 gets its cells stamped as they actually are — unproven, experimental, or not in 8.0 — rather than holding the freeze.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">The side-by-side proof: both versions, one database, migrating incrementally</span><span class="crit">CRITICAL PATH</span><span class="pill open">Open</span></summary>
<div class="body">
<p>The incremental-migration story is: keep Prisma 7 running and owning your database schema; install Prisma 8 alongside it in the same project; let Prisma 8 <em>adopt</em> the database read-only (it derives a schema from the live database, verifies the database matches, and records that fact — without touching Prisma 7's migration state); move code over gradually; cut over once at the end. Every individual mechanism in that story exists and is tested. <strong>The whole story has never been run end-to-end</strong> — a planned real-world evaluation never happened — which makes it the release's biggest untested claim.</p>
<p>So we build it as a permanent test: one project with both versions installed, one Postgres database, Prisma 7 running its migrations and Prisma 8 adopting, querying, and re-adopting after schema changes — run under each of npm, pnpm, Yarn, and Bun, because installing two versions side by side is exactly where package managers differ. Must be green by July 24, or the announcement's migration claim gets scaled back to what's actually proven. The upgrade guide's code samples get lifted from this project, so the documentation is executable by construction.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">TypeScript performance measured before the types freeze</span><span class="pill open">Open</span></summary>
<div class="body">
<p>Prisma 8 leans heavily on advanced TypeScript types, which is exactly the pattern that can make a big project's type-checking slow. We measure now — generated projects of 10, 100, and 500 models, checked with both today's TypeScript and the new Go-based TypeScript 7 compiler — because if the numbers are bad, the types can only be fixed while they're still allowed to change. Results publish to a public dashboard, and pull requests fail if they make type-checking meaningfully more expensive (measured by the compiler's deterministic work counters, not by flaky wall-clock time on shared CI runners).</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Port Prisma 7's accumulated edge-case tests against the unproven cells</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>Prisma 7's functional test suite encodes years of database and query edge cases. Converting it wholesale would take months and mostly port API details that no longer exist — so we mine it instead: for each scoreboard cell that says "works" without a proving test, find the Prisma 7 tests covering that feature and port just those scenarios. Where comparing against Prisma 7's behavior is cheaper than porting assertions, the side-by-side project doubles as the comparison harness. The port has started — a first pass accounting for 488 scenarios from the <code>prisma</code> and <code>prisma-engines</code> corpus landed (<a href="https://github.com/prisma/prisma-next/pull/1035">#1035</a>). This is a stream, not a step; it continues past the RC, visibly, on the public scoreboard.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Adopting an existing database round-trips cleanly</span><span class="pill done">Landed</span></summary>
<div class="body">
<p>The adoption path had a credibility problem: deriving a schema from a live database produced output that Prisma 8's own tooling then rejected or flagged as drifted — a user had independently written a 260-line repair script to fix our output, and it matched the workaround script in our own repository. Seven distinct defects were fixed, and the whole loop (read the database → derive the schema → emit the contract → verify the database matches) now runs as an automated test against live databases. This is the foundation the side-by-side proof builds on.</p>
</div>
</details>
</section>
<section class="req" id="req5">
<span class="reqno">Requirement 5</span>
<span class="owner" style="margin-left: 8px;">Alexey</span>
<h2>The code must move into prisma/prisma</h2>
<p class="soft">Prisma 8 has so far been developed in a separate repository, <code>prisma/prisma-next</code>. Before release, everything moves into <code>prisma/prisma</code> — the repository users already watch, star, and file issues against — so Prisma 8 arrives as the main line of Prisma, not a side project. Moving is much more than copying code: the two repositories' git histories have to be joined, CI has to run green in its new home, the npm publishing pipeline has to serve v8 and v7 side by side, thousands of open v7 issues and pull requests need a decision, and the automation in other repositories that points at prisma/prisma has to keep working afterward. Prisma 7 doesn't stop: it continues from a <code>v7</code> branch in the same repository, with bug fixes promised for 12 months after 8.0.0 final ships.</p>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Join the two repositories' histories on a staging branch</span><span class="crit">CRITICAL PATH</span><span class="pill flight">Starting</span></summary>
<div class="body">
<p>First a rehearsal in a disposable fork: combine prisma-next's history with prisma/prisma's and check the result is livable — <code>git log</code> and <code>git blame</code> still make sense, old tags still resolve, the repository doesn't balloon. Then the real <code>v8</code> branch inside prisma/prisma, with the complete test suite green and kept green until release week, when it becomes <code>main</code>. The merge gets rehearsed for weeks; it is never improvised at the deadline.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Rewire the publishing pipeline — inside prisma/prisma and in the repositories connected to it</span><span class="pill open">Open</span></summary>
<div class="body">
<p>prisma/prisma's release automation currently exists to publish Prisma 7. After the move it does two jobs: publish v8 from <code>main</code> and keep publishing v7 patches from the <code>v7</code> branch, without either disturbing the other. (Publish permissions on the <code>prisma</code> npm package are already in hand; what remains is configuration, including the per-package "trusted publishing" setup that lets CI publish without long-lived secrets.) Beyond the repository itself, workflows in several other repositories and open pull requests are wired into prisma/prisma's publishing today; each connection has to be found and re-pointed. The first concrete task is the inventory — a written list of every workflow that touches prisma/prisma's publishing, so the rewiring is a checklist instead of a surprise.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Take over the <code>prisma</code> package name — carefully</span><span class="pill open">Open</span></summary>
<div class="body">
<p>The <code>prisma</code> package becomes Prisma 8's command-line tool, published under a pre-release tag so <code>npm install prisma</code> keeps giving people Prisma 7 until 8.0.0 final. The three per-database packages users import get new names: <code>@prisma/postgres</code>, <code>@prisma/sqlite</code>, <code>@prisma/mongo</code> (checked for collisions against the many <code>@prisma/*</code> names Prisma 7 already publishes). Only those four packages rename — the ~60 internal packages that arrive automatically as dependencies keep their <code>@prisma-next/*</code> names and are explicitly not part of the supported surface. The v8 tool installs a single command, <code>prisma-next</code> — deliberately <em>not</em> <code>prisma</code>, so in a project that has both versions installed, <code>prisma</code> always unambiguously means Prisma 7, on every package manager. (Whether v8 ever claims the bare <code>prisma</code> command is deferred; adding a command later breaks nothing.) The old <code>prisma-next</code> package gets a deprecation notice pointing at its new home.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Decide the fate of every open v7 issue and pull request</span><span class="pill open">Open</span></summary>
<div class="body">
<p>prisma/prisma has years of open issues and PRs written against Prisma 7. When v8 becomes <code>main</code>, we close everything except genuine v7 bug reports (which stay open against the <code>v7</code> branch), post a pinned issue explaining what happened and why, and answer follow-ups with a saved reply pointing at it. This deliberately happens at merge time, not earlier — closing thousands of issues weeks before there's an announcement to point at would produce weeks of confusion. Issue templates get a version chooser at the same time, so new reports arrive sorted into v7 vs v8.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">The <code>v7</code> maintenance branch, with working CI</span><span class="pill open">Open</span></summary>
<div class="body">
<p>Prisma 7's code, tests, and release automation move to a <code>v7</code> branch in prisma/prisma and must actually work there — this branch is where 12 months of promised bug fixes ship from, so a broken CI setup on it would turn every future v7 patch into an archaeology project.</p>
</div>
</details>
</section>
<section class="req" id="req6">
<span class="reqno">Requirement 6</span>
<span class="owner" style="margin-left: 8px;">Everyone</span>
<h2>The rough edges users hit on day one must be gone</h2>
<p class="soft">None of these block anything technically. All of them are what a skeptical engineer meets in their first hour, under announcement-day attention.</p>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">A dropped database connection can crash the host process</span><span class="pill open">Open</span></summary>
<div class="body">
<p>When an idle pooled connection drops (a database restart, a network blip), the error has no listener attached and crashes the whole Node.js process. A production-readiness bug, not housekeeping — fixed before anyone's production meets it. (<a href="https://linear.app/prisma-company/issue/TML-2655">TML-2655</a>)</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">A deprecation warning prints on every single database connection</span><span class="pill open">Open</span></summary>
<div class="body">
<p>The underlying Postgres driver prints a deprecation notice each time a connection opens. Harmless, but it's the first thing every new user sees, and it reads as "this isn't finished." (<a href="https://linear.app/prisma-company/issue/TML-2628">TML-2628</a>)</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Open security alerts on dependencies</span><span class="pill open">Open</span></summary>
<div class="body">
<p>The announcement puts many eyes on the repository; a visible backlog of automated vulnerability alerts on day one is a bad look and a support-ticket magnet. Cleared before the merge. (<a href="https://linear.app/prisma-company/issue/TML-2789">TML-2789</a>)</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">The npm page and editor experience for the packages people actually open</span><span class="pill open">Open</span></summary>
<div class="body">
<p>The <code>prisma</code> package's README becomes Prisma 8's face on npm. The four public packages' exported functions and types are what users see when they hover in their editor — those documentation comments get an audit. The ~60 internal packages get a short standard notice identifying them as implementation detail. (<a href="https://linear.app/prisma-company/issue/TML-1799">TML-1799</a>)</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">First-class editor support for the schema language</span><span class="pill flight">In flight</span></summary>
<div class="body">
<p>A language users write by hand deserves an editor that helps: formatting, autocomplete, syntax coloring, and diagnostics for Prisma 8's schema language, served by its language server. This work is running now — hooking the formatter to the language server, keyword and model-type completions, semantic-token coloring, and replacing the legacy schema parser with the new syntax-tree parser underneath it all (the "Language Tools Support Prisma Next PSL" project — e.g. <a href="https://linear.app/prisma-company/issue/TML-2929">TML-2929</a>, <a href="https://linear.app/prisma-company/issue/TML-2932">TML-2932</a>, <a href="https://linear.app/prisma-company/issue/TML-2947">TML-2947</a>, <a href="https://linear.app/prisma-company/issue/TML-2948">TML-2948</a>). It also has to track the schema-language changes in requirement 2 as they land, or the editor will underline the new syntax as errors.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">The editor doesn't fight itself in a two-version project</span><span class="pill open">Open</span></summary>
<div class="body">
<p>Users migrating incrementally will have Prisma 7's VS Code extension installed <em>and</em> Prisma 8's language server in the same project. Nobody has verified they coexist peacefully over schema files. Checked — and fixed or documented — before the announcement invites everyone into exactly that setup.</p>
</div>
</details>
<details class="task">
<summary><svg class="chev" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg><span class="t">Claims we haven't verified get verified or softened</span><span class="pill open">Open</span></summary>
<div class="body">
<p>Support statements that end up in the announcement get checked first: Windows, Bun, and Deno support levels; the telemetry first-run notice's wording; and whether the telemetry backend survives announcement-scale traffic.</p>
</div>
</details>
</section>
<section class="landed">
<h2>Recently landed</h2>
<ul>
<li><strong>One error-code scheme, delivered end-to-end</strong> — every published error is a structural envelope with a dotted code; the ORM and contract-authoring planes' codeless throws were swept onto it; the 221-code reference page ships with a CI check that keeps it complete (requirement 3).</li>
<li><strong>Contract snapshots deduplicated into one content-addressed store</strong> — migration folders stopped carrying full contract copies, ref-paired snapshots folded in too, closing the migrations-folder layout ahead of the freeze (requirement 3).</li>
<li><strong>Hashes lost their <code>sha256:</code> prefix</strong> — the textual form of every content hash froze without the redundant algorithm tag (requirement 3).</li>
<li><strong><code>date</code> columns read through <code>.include()</code> now decode correctly</strong> — the <code>@db.Date</code> codec binding that had been missing (requirement 1).</li>
<li><strong>Scalar-type unification landed</strong> — every scalar is a zero-argument type constructor, with Postgres native constructors exposed (requirement 2).</li>
<li><strong>Adopting an existing database round-trips cleanly</strong> — seven defects fixed, proven against live databases (details in requirement 4).</li>
<li><strong>The feature scoreboard draft is up</strong> — 326 features enumerated and verdict-ed across all three databases (<a href="https://github.com/prisma/prisma-next/pull/1000">PR #1000</a>).</li>
</ul>
</section>
<footer>
Detailed working docs: <a href="https://github.com/prisma/prisma-next/pull/986">the release project</a> · tracking: <a href="https://linear.app/prisma-company/project/prisma-8-rc1-7592265f700c">Linear — Prisma 8 RC1</a> · launch communications are planned separately and not covered here. This page is updated as work lands; the URL stays stable.
</footer>
</div>