Skip to content

feat(stack-prisma): bake EQL 3.1.0 into the migrations - #1081

Merged
auxesis merged 2 commits into
mainfrom
fix/stack-prisma-bake-eql-3-1-0
Oct 5, 2026
Merged

auxesis merged 2 commits into
mainfrom
fix/stack-prisma-bake-eql-3-1-0

Conversation

@auxesis

@auxesis auxesis commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

This PR bakes EQL 3.1.0 into the stack-prisma migrations

This PR adds a migration that installs EQL 3.1.0. It also re-emits the baseline migration, so a fresh database installs 3.1.0 too. It must merge before the Version Packages PR, #1054.

The Version Packages PR fails without it

#1054 moves @cipherstash/eql from 3.0.6 to 3.1.0. Its Run Tests jobs fail one @cipherstash/stack-prisma test: "the installed @cipherstash/eql release is baked by some published migration (lockstep)". To "bake" SQL is to copy it into a migration file, so the migration's hash covers it. No migration bakes the 3.1.0 install SQL, whose sha256 is af316179….

EQL 3.1.0 is a minor release for the Rust eql-bindings crate. Its install SQL differs from 3.0.6 in three lines, and all three are the version stamp. The stamp still moves the digest, so stack-prisma still needs a migration.

The commit follows the 3.0.6 precedent

This PR follows #1006, which baked EQL 3.0.6, and the steps in languages/typescript/packages/stack-prisma/DEVELOPING.md.

  • It adds the 20261005T0000_upgrade_eql_v3_3_1_0 self-edge. A self-edge is a migration whose start and end states match, so only its invariant decides whether it runs. This edge moves an existing database to the 3.1.0 SQL.
  • It re-emits the baseline so that db init installs 3.1.0. The baseline gains a sixth op that carries the new invariant and runs no SQL.
  • It updates the constants, the control exports, the Prisma example's copies, the tests, the README, the stash-prisma skill, the changesets and the EQL absorption plan.

The package's own emit scripts wrote the migration files from #1054's EQL files. Run again with those files, the scripts reproduce the committed files byte for byte. The baseline keeps its original createdAt, because the migrator uses that field to order paths. Every earlier edge keeps its frozen digest.

Migration migrationHash Baked SQL sha256
Baseline on main (1.2.0 and 1.2.1) 2fdc7caf… 9b6dab78… (3.0.6)
Baseline in this PR f92f5be5… af316179… (3.1.0)
New 3.1.0 edge 73432f18… af316179… (3.1.0)

This is the second re-emit of a published baseline

db init allows only additive operations. Every upgrade self-edge must carry a data-class operation, so db init can never walk one. A new invariant therefore needs either a carrier op in the baseline, or a second from: null genesis edge. A genesis edge is a migration that starts from an empty database.

The repository's docs say this trade must be argued again at each EQL bump. This time, the re-emit replaces bytes that npm has shipped. @cipherstash/stack-prisma 1.2.0 and 1.2.1 ship baseline 2fdc7caf…, and both were released on 2 October 2026. The 3.0.6 re-emit was different: it replaced baseline bytes that npm never shipped.

The team chose the re-emit over a second genesis edge on adoption numbers. @cipherstash/stack-prisma had 481 npm downloads in the 30 days to 3 October 2026, and 384 in the last 7 of those days. 305 of them came on 2 October, the 1.2.0 release day. A second genesis edge would add a permanent second copy of the bundle for a release that changes no SQL behaviour.

1.2.x users must delete their copied migrations folder

The seed phase copies migration folders into a user's repo, and it never rewrites a folder that exists. So a user who keeps a migrations/cipherstash/ folder from 1.2.x keeps the old baseline. A fresh db init then fails with this error:

Operation cipherstash.upgrade-eql-v3-bundle-3.1.0 has class "data" which is not allowed by policy.

The fix is to delete the folder and plan again:

rm -rf migrations/cipherstash
npx prisma-next migration plan

The changeset, the README and the stash-prisma skill give that fix and name that error. stale-vendored-space.test.ts now rebuilds the published 1.2.x baseline from files in this repository. It proves the rebuild against 2fdc7caf… and pins the refusal. An existing database keeps its markers, so migrate runs only the edges it lacks:

  • A 1.2.x database walks the 3.1.0 edge only.
  • A 1.0.0 or 1.1.x database walks the 3.0.5, 3.0.6 and 3.1.0 edges, and installs the bundle three times.

The tarball grows by about 0.25 MB packed

The new edge adds one more copy of the 2.6 MB install SQL to the built dist/ files. Measured with pnpm pack on this branch and on its parent commit:

Parent commit This PR Change
Packed .tgz 1,467,260 bytes 1,721,851 bytes +254,591 bytes
Unpacked 29,556,420 bytes 35,317,561 bytes +5,761,141 bytes

The unpacked size grows by about two copies of the bundle, because the ESM and CJS builds each embed it.

The stack family moves to 1.3.0, not 1.2.2

The stack-prisma changeset is minor, as the 3.0.5 and 3.0.6 ones were. stack-prisma is in a fixed version group with stash, @cipherstash/stack, @cipherstash/stack-drizzle, @cipherstash/stack-supabase and @cipherstash/wizard. So after this merges, #1054 releases all six at 1.3.0 instead of 1.2.2. Please weigh that when you review. A patch changeset would keep 1.2.2.

Tests show the fix works

  • On this branch, with main's EQL 3.0.6 files: stack-prisma passes 376 tests and skips 30. Its typecheck passes. Biome reports 44 warnings, the same as main. The root code:check passes. test:scripts passes 1,235 tests. The Prisma example's typecheck passes.
  • With Version Packages #1054's EQL 3.1.0 files applied: stack-prisma passes 376 tests, including the lockstep test against af316179…. On main, the same files fail the lockstep test exactly as Version Packages #1054's CI does.
  • Live, against a local Postgres 17 container with Version Packages #1054's files applied: migration-apply-live-pg passes 8 of 8. That includes the db init case, the 1.1.x walk and a new 1.2.x walk. The server allowed 256 locks for each transaction (see the last section).

Some checks wait for #1054

  • Until Version Packages #1054 merges, the live byte-identity check fails on main by design. CI does not run the live suite.
  • The eqlVersion marker accepts both 3.0.6 and 3.1.0 until Version Packages #1054 merges. A follow-up narrows it to 3.1.0.

A known lock-budget problem predates this PR

Two bundle re-installs in one transaction exceed a stock Postgres lock budget, so a 1.0.0 or 1.1.x upgrade already fails on default settings. The 3.1.0 edge makes that upgrade three re-installs. #1080 tracks the problem, and this PR does not change it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a

EQL 3.1.0 moves the install SQL digest (9b6dab78 -> af316179) by changing
only the version stamp. The Version Packages PR (#1054) fails the
lockstep test because no migration bakes the new digest.

Add the 20261005T0000_upgrade_eql_v3_3_1_0 self-edge for existing
databases. Re-emit the baseline so it bakes 3.1.0 and carries a sixth,
no-SQL carrier op for the new invariant, so a fresh db init stays
additive-only. The baseline keeps its createdAt.

The re-emit changes a published baseline: 1.2.0 and 1.2.1 ship
2fdc7caf. The stale-space suite now proves a 1.2.x fixture against that
hash, and pins the db init refusal a stale 1.2.x space produces. The
README and the stash-prisma skill name that refusal.

The live suite walks a 1.1.x database through 3.0.5, 3.0.6 and 3.1.0,
and a 1.2.x database through 3.1.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
@auxesis
auxesis requested a review from a team as a code owner October 5, 2026 06:41
@changeset-bot

changeset-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3377339

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@cipherstash/stack-prisma Minor
stash Minor
@cipherstash/prisma-example Patch
@cipherstash/basic-example Patch
@cipherstash/e2e Patch
@cipherstash/stack-drizzle Minor
@cipherstash/stack-supabase Minor
@cipherstash/stack Minor
@cipherstash/wizard Minor
@cipherstash/bench Patch
@cipherstash/test-kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cipherstash-bot cipherstash-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommendation: 🟢 merge as it is (2 of 4 review job(s) failed)

Nothing must change before merging. The migration data, the re-emitted baseline and the 1.2.x upgrade tests look correct. Two optional changes below can wait for a follow-up: one missing test and one emit-time check.

Other findings not posted as comments

  • Optional: rewindShippedBaseline assumes the current baseline bakes '3.1.0' (languages/typescript/packages/stack-prisma/test/v3/stale-vendored-space.test.ts:212). At the next EQL bump, replaceAll('3.1.0', …) changes nothing. The 1.1.x and 1.2.x fixture tests then fail with a migrationHash mismatch that does not name this cause. To fix, read the release from the shipped install op's label, for example with /eql-(\d+\.\d+\.\d+)/. The base commit had the same pattern with '3.0.6'.
  • Optional: walkFrom asserts the literal '3.1.0' as the end version, but its comment says "the pinned release" (languages/typescript/packages/stack-prisma/test/live/migration-apply-live-pg.test.ts:251). CI does not run the live suite. So after the next bump, the stale literal fails only when someone runs the suite locally. To fix, pass the expected end version as a parameter, or use releaseManifest.eqlVersion once the bump merges.
How this review was made
Agent Model Review type Result
claude claude-opus-5-5 test-gap 1 found, 1 posted
claude claude-opus-5-5 typescript 1 found, 1 posted
codex gpt-5.6-sol test-gap failed
codex gpt-5.6-sol typescript failed

Synthesis: claude-opus-5-5 merged the findings, removed duplicates and dropped findings it could not confirm in the code. 0 posted finding(s) were raised by two or more models.

Plain language: claude-opus-5-5 read every comment as a new reader would. 2 comment(s) had a problem that stopped the reader acting; it rewrote 2.

Stack: not part of a stack.

Context loaded: the description, 1 linked issue(s) and 1 discussion entries.

- Guard the 3.1.0 edge's emit: reading `operations` against any other
  installed @cipherstash/eql now throws, naming both releases, instead
  of baking that release's SQL under the 3.1.0 id and surfacing later
  as a bare digest mismatch.
- Cover a 1.2.x consumer who deleted and regenerated
  migrations/cipherstash/: an existing database still walks only the
  3.1.0 edge.
- rewindShippedBaseline reads the baked release off the shipped install
  op's label rather than a '3.1.0' literal that goes stale at the next
  bump.
- walkFrom takes the expected end version from its caller.
@auxesis

auxesis commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Optional: rewindShippedBaseline assumes the current baseline bakes '3.1.0' (languages/typescript/packages/stack-prisma/test/v3/stale-vendored-space.test.ts:212). At the next EQL bump, replaceAll('3.1.0', …) changes nothing. The 1.1.x and 1.2.x fixture tests then fail with a migrationHash mismatch that does not name this cause. To fix, read the release from the shipped install op's label, for example with /eql-(\d+\.\d+\.\d+)/. The base commit had the same pattern with '3.0.6'.

Fixed in 3377339.

Optional: walkFrom asserts the literal '3.1.0' as the end version, but its comment says "the pinned release" (languages/typescript/packages/stack-prisma/test/live/migration-apply-live-pg.test.ts:251). CI does not run the live suite. So after the next bump, the stale literal fails only when someone runs the suite locally. To fix, pass the expected end version as a parameter, or use releaseManifest.eqlVersion once the bump merges.

Fixed in 3377339.

@auxesis auxesis mentioned this pull request Oct 5, 2026

@yujiyokoo yujiyokoo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not familiar with prisma-next and reviewed it with Claude Code (Opus 5, 1M context, midium effort)

// resolved bundle, but a DATABASE is on whatever bundle was last applied
// to it, and the Prisma Next adapter installs and upgrades the bundle
// through its own migrations without the CLI at all (this package's
// `migrations/` carries four upgrade edges precisely because databases

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 'five' instead of four?

// In the getter, not at module scope: only an emit reads `operations`.
// Without it, an emit against any other installed release bakes that
// release's SQL under this edge's 3.1.0 id.
if (releaseManifest.eqlVersion !== EDGE_RELEASE) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be present in older versions. Is this something worth addressing?

@auxesis
auxesis merged commit b6e6100 into main Oct 5, 2026
30 checks passed
@auxesis
auxesis deleted the fix/stack-prisma-bake-eql-3-1-0 branch October 5, 2026 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants