Skip to content

Prisma Next 0.16, payload-identifier routing, and digest-verified baked EQL migration artefacts#763

Open
coderdan wants to merge 6 commits into
mainfrom
feat/prisma-next-0-16-baked-eql
Open

Prisma Next 0.16, payload-identifier routing, and digest-verified baked EQL migration artefacts#763
coderdan wants to merge 6 commits into
mainfrom
feat/prisma-next-0-16-baked-eql

Conversation

@coderdan

@coderdan coderdan commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Three related pieces of work on the Prisma Next integration, in review order per commit:

1. Upgrade to Prisma Next 0.16 (from 0.14)

All 31 @prisma-next/* pins move to 0.16.0 in lockstep. The CipherStash encryption surface is unchanged. Notable:

  • createNamespace is now required in prismaContract(...) (0.15 stopped materialising a placeholder namespace) — added to both configs and documented in the bundled stash-prisma-next skill.
  • The PSL interpreter test moves to the 0.15 CST symbol-table input (parse + buildSymbolTable).
  • Contracts re-emitted: postgres-schema namespace kind, StorageColumnTypes maps, scalarList capability, discrete FK/index entities. Storage hashes unchanged.

Verified: unit + live-PG (27) + integration (595) suites green with a ~/.cipherstash device profile and the local compose Postgres.

2. Route v3 decoding from the EQL payload's own identifier

Every EQL v3 payload carries its required i: {"t", "c"} identifier, and ZeroKMS commits the cell key to it — making it the authoritative routing source, not the query AST. decode now reads it first (projected-column context kept as fallback for non-v3 documents), and decodeJson builds fully-routed envelopes from it instead of throwing.

This unblocks relation include() (the SQL ORM decodes included cells through decodeJson with no column ref available) and aggregate/computed projections. A two-model include() e2e test remains a follow-up (needs the db-ref planning workflow — see #762).

3. Bake the EQL install SQL into migration artefacts, digest-verified

Replaces the runtime-injection design. The framework applies extension migrations from on-disk vendored copies without the descriptor, and the CLI seed phase never refreshes an existing package directory — so injection's environment-dependent hashes orphaned every consumer's vendored copy on each EQL bump (PN-MIG-5002), and recomputing the hash from installed content meant tampering could never be detected.

Now each migration's self-emit embeds readVerifiedInstallSql() — refused unless its sha256 matches @cipherstash/eql's releaseManifest.installSqlSha256. One content-addressed identity flows from this repo's git history through the npm tarball into consumers' vendored copies and the DB ledger. EQL upgrades ship as new append-only migration directories (the existing invariant-edge pattern).

CI guards added:

  • Provenance pin — committed SQL digest must equal the installed manifest's; an EQL bump without the matching migration fails.
  • Frozen-hash pins — published migration hashes are literals; any byte change to published history fails.
  • Vendored-space parity — the example's migrations/cipherstash/ must be byte-identical to the shipped artefacts (catches the exact staleness class that wedged it).

Proven end-to-end: seed phase materialises byte-identical copies; fresh-DB migrate installs EQL 3.0.2 and records both invariants; a tampered vendored ops.json (injected DROP TABLE) is rejected by hash verification before execution; example e2e (40), live-PG (27), and unit (341) suites green. dist/control.js grows to ~5 MB (inlined artefacts, control-plane entry only — runtime entries unchanged, pinned by the bundling-isolation test).

Also fixes the upgrade migration's stale describe() space hashes and the eql-3.0.03.0.2 label drift.

rc consumers (none external today): delete migrations/cipherstash/ and re-run prisma-next migration plan once — the seed phase regenerates it byte-identical.

Follow-ups tracked in #762.

Summary by CodeRabbit

  • New Features
    • Improved encrypted-cell decoding by deriving routing from the EQL v3 payload identifier, improving decryption in ORM includes, JSON aggregates, and computed projections.
    • Added working JSON-plane decoding for EQL v3 encrypted values.
    • Added Prisma/SQL capability support for scalarList and expanded generated storage type mappings.
  • Bug Fixes
    • Migrations now use digest-verification for embedded EQL v3 install SQL to better detect mismatches and tampering.
  • Documentation
    • Updated guidance for Prisma Next 0.16, including required createNamespace setup and post-upgrade regeneration expectations; clarifies changes when upgrading EQL v3 and migration publication behavior.

Closes #765.

coderdan added 3 commits July 22, 2026 21:33
All @prisma-next/* deps move 0.14.0 -> 0.16.0 in lockstep. prismaContract
now requires the target's createNamespace factory (0.15 stopped
materialising a placeholder namespace) — added to both configs and the
bundled skill. The PSL interpreter test moves to the CST symbol-table
input. Contracts re-emitted: postgres-schema namespace kind,
StorageColumnTypes maps, scalarList capability; storage hashes unchanged.
…ifier

Every EQL v3 payload carries its required i: {t, c} identifier, and
ZeroKMS commits the cell key to it — the authoritative routing source.
decode now reads it first (ctx.column kept as fallback for non-v3
documents), and decodeJson builds fully-routed envelopes from it instead
of throwing, unblocking relation include() and aggregate projections.
…est-verified

Replaces runtime injection: the framework applies extension migrations
from on-disk vendored copies without the descriptor, and the seed phase
never refreshes an existing package dir, so injection's environment-
dependent hashes orphaned every consumer copy on each EQL bump
(PN-MIG-5002) and the recomputed hash laundered tampering.

Each migration self-emit now embeds readVerifiedInstallSql() — refused
unless sha256 matches @cipherstash/eql's releaseManifest.installSqlSha256.
One content-addressed identity flows from git through npm to vendored
copies and the DB ledger. CI guards: provenance pin (committed SQL digest
== installed manifest), frozen published-migration hashes, and byte-parity
between the example's vendored space and the shipped artefacts. The
example's stale vendored space is regenerated (stale v2 dir removed).
Also fixes the upgrade migration's stale describe() space hashes.

Follow-ups tracked in #762.
@coderdan
coderdan requested a review from a team as a code owner July 22, 2026 11:34
@changeset-bot

changeset-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e02c2b9

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

This PR includes changesets to release 11 packages
Name Type
@cipherstash/prisma-next Minor
stash Minor
@cipherstash/prisma-next-example Patch
@cipherstash/basic-example Patch
@cipherstash/e2e Patch
@cipherstash/stack Minor
@cipherstash/stack-drizzle Minor
@cipherstash/stack-supabase 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

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR upgrades Prisma Next dependencies and contracts, embeds digest-verified EQL v3 SQL in published migrations, adds migration parity and integrity checks, and changes EQL v3 decoding to derive routing from payload identifiers.

Changes

Prisma Next 0.16 contract and configuration

Layer / File(s) Summary
Dependency and namespace configuration
packages/prisma-next/package.json, examples/prisma/package.json, packages/prisma-next/prisma-next.config.ts, examples/prisma/prisma-next.config.ts
Prisma Next dependencies move to 0.16, and createNamespace is wired to postgresCreateNamespace.
Generated contract updates
packages/prisma-next/src/contract.*, examples/prisma/src/prisma/contract.*, examples/prisma/migrations/cipherstash/contract.json
Contracts add storage type maps and scalarList, change the namespace kind to postgres-schema, and remove EQL v2 mappings and the EQL v2 configuration model.
PSL validation and guidance
packages/prisma-next/test/psl-interpretation.test.ts, skills/stash-prisma-next/SKILL.md, .changeset/prisma-next-0-16.md
PSL tests use CST symbol tables and target configuration; documentation records the required namespace factory and regenerated contract changes.

Digest-verified EQL v3 migrations

Layer / File(s) Summary
Emit-time SQL embedding and descriptor wiring
packages/prisma-next/src/migration/eql-bundle-v3.ts, packages/prisma-next/src/exports/control.ts, packages/prisma-next/migrations/*/migration.ts
Install SQL is digest-verified and embedded in migration operations; descriptors use committed metadata and operations without runtime injection.
Published migration references
packages/prisma-next/migrations/*/migration.json, examples/prisma/migrations/cipherstash/*/migration.json, examples/prisma/migrations/cipherstash/refs/head.json
Baseline and upgrade hashes and references are updated for the baked artifacts.
Artifact integrity and parity tests
packages/prisma-next/test/v3/migration-v3.test.ts, packages/prisma-next/test/v3/vendored-space-parity.test.ts, packages/prisma-next/test/bundling-isolation.test.ts, packages/prisma-next/test/descriptor.test.ts, .changeset/eql-baked-digest-verified.md
Tests verify manifest digests, frozen hashes, byte-preserved descriptor artifacts, vendored parity, and runtime bundle isolation.

EQL v3 payload routing

Layer / File(s) Summary
Payload-derived decode routing
packages/prisma-next/src/v3/codec-runtime-v3.ts, packages/prisma-next/test/v3/codec-runtime-v3.test.ts, .changeset/v3-payload-routing.md
decode derives table and column from payload identifier i, falls back to projected context, and decodeJson builds routed encrypted envelopes while rejecting invalid identifiers.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: calvinbrewer

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the three main changes: Prisma Next 0.16 upgrade, payload-identifier routing, and baked digest-verified EQL migrations.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/prisma-next-0-16-baked-eql

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/prisma-next/src/v3/codec-runtime-v3.ts`:
- Around line 291-312: Update decodeJson in
packages/prisma-next/src/v3/codec-runtime-v3.ts to return null immediately when
the JSON value is null, matching decode’s nullable-column behavior before
routingKeyFromPayload runs. Add coverage in
packages/prisma-next/test/v3/codec-runtime-v3.test.ts at lines 351-361 verifying
decodeJson(null) round-trips as null; no other sites require changes.

In `@packages/prisma-next/test/psl-interpretation.test.ts`:
- Around line 17-20: Move packages/prisma-next/test/psl-interpretation.test.ts
into the appropriate __tests__/ directory and update its relative imports and
test configuration. Move
packages/prisma-next/test/v3/vendored-space-parity.test.ts under __tests__/ as
well, adjusting all relative paths for the new location while preserving both
suites’ behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7078b56a-8625-4946-8ae2-a8a50627609d

📥 Commits

Reviewing files that changed from the base of the PR and between 2aeba94 and cd77afc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • .changeset/eql-baked-digest-verified.md
  • .changeset/prisma-next-0-16.md
  • .changeset/v3-payload-routing.md
  • examples/prisma/migrations/cipherstash/20260601T0000_install_eql_bundle/migration.json
  • examples/prisma/migrations/cipherstash/20260601T0000_install_eql_bundle/ops.json
  • examples/prisma/migrations/cipherstash/20260601T0100_install_eql_v3_bundle/migration.json
  • examples/prisma/migrations/cipherstash/20260601T0100_install_eql_v3_bundle/ops.json
  • examples/prisma/migrations/cipherstash/20260720T0000_upgrade_eql_v3_3_0_2/migration.json
  • examples/prisma/migrations/cipherstash/contract.json
  • examples/prisma/migrations/cipherstash/refs/head.json
  • examples/prisma/package.json
  • examples/prisma/prisma-next.config.ts
  • examples/prisma/src/prisma/contract.d.ts
  • examples/prisma/src/prisma/contract.json
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.json
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.ts
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/ops.json
  • packages/prisma-next/migrations/20260720T0000_upgrade_eql_v3_3_0_2/migration.json
  • packages/prisma-next/migrations/20260720T0000_upgrade_eql_v3_3_0_2/migration.ts
  • packages/prisma-next/migrations/20260720T0000_upgrade_eql_v3_3_0_2/ops.json
  • packages/prisma-next/package.json
  • packages/prisma-next/prisma-next.config.ts
  • packages/prisma-next/src/contract.d.ts
  • packages/prisma-next/src/contract.json
  • packages/prisma-next/src/exports/control.ts
  • packages/prisma-next/src/migration/eql-bundle-v3.ts
  • packages/prisma-next/src/v3/codec-runtime-v3.ts
  • packages/prisma-next/test/bundling-isolation.test.ts
  • packages/prisma-next/test/psl-interpretation.test.ts
  • packages/prisma-next/test/v3/codec-runtime-v3.test.ts
  • packages/prisma-next/test/v3/migration-v3.test.ts
  • packages/prisma-next/test/v3/vendored-space-parity.test.ts
  • skills/stash-prisma-next/SKILL.md
💤 Files with no reviewable changes (1)
  • examples/prisma/migrations/cipherstash/20260601T0000_install_eql_bundle/migration.json

Comment thread packages/prisma-next/src/v3/codec-runtime-v3.ts
Comment thread packages/prisma-next/test/psl-interpretation.test.ts
Addresses code-review findings on the baked-EQL work:

- migration-v3.test.ts: the provenance pin compared each migration's baked
  SQL digest against the LIVE @cipherstash/eql manifest, so it self-
  destructed on the next EQL bump (frozen 3.0.2 bytes can't match a 3.0.3
  manifest) — pushing a maintainer toward re-emitting the published
  baseline. Reworked to a PUBLISHED_MIGRATIONS table with per-migration
  FROZEN digests (identity + baked-SQL, tied to each migration's own
  release) plus one bump-safe lockstep check (the installed release must be
  baked by SOME published migration) and an on-disk completeness check (no
  unpinned or stale migration dirs).

- descriptor.test.ts: the 'injects the runtime EQL install SQL' test still
  named and described the deleted sentinel-injection design and compared
  against a live readInstallSql() (also bump-unsafe). Rewritten to assert
  the op carries the baked bundle verbatim, without the live comparison;
  dropped the now-unused import.

- DEVELOPING.md: refreshed the sections that still documented the sentinel/
  runtime-injection design and instructed re-emitting published migrations
  (the exact action the new doctrine and frozen-hash guard forbid); added
  the second (upgrade) migration to the layout and invariants.

Reviewed in this branch; follow-ups (#4/#6/#8 payload-routing edges,
efficiency items) tracked separately.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/prisma-next/test/descriptor.test.ts`:
- Around line 120-129: The descriptor test’s loose substring and size checks do
not verify the exact migration bundle. Update the assertions around installOp
and its execute SQL to reuse the frozen SHA-256/digest verification established
by migration-v3.test.ts, comparing the embedded SQL against the expected release
provenance without calling readInstallSql() or reading the installed package at
runtime.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e96a0ffb-1adb-43ed-afdc-ae47ebe331c1

📥 Commits

Reviewing files that changed from the base of the PR and between cd77afc and f395dde.

📒 Files selected for processing (3)
  • packages/prisma-next/DEVELOPING.md
  • packages/prisma-next/test/descriptor.test.ts
  • packages/prisma-next/test/v3/migration-v3.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/prisma-next/test/v3/migration-v3.test.ts

Comment thread packages/prisma-next/test/descriptor.test.ts
coderdan added 2 commits July 22, 2026 22:37
CodeRabbit flagged decodeJson(null) as throwing. It is unreachable: the
SQL runtime null-guards before both codec methods — decodeField before
decode, and sql-orm-client's include-decode loop (plus its many-typed
element path) before decodeJson — so a NULL cell never reaches the codec.
Null-handling is the runtime's contract; returning null here would also
break the framework's decodeJson(json): TInput envelope signature.
Comment only, no behavior change.
…t migrate'

Prisma Next has no 'migration apply' subcommand — the apply verb is the
top-level 'prisma-next migrate' ('migration' only groups plan/new/show/
status/log/list/graph/check). Running the prescribed 'migration apply'
errors: 'Unknown command: apply. Use prisma-next migrate --to <contract>'.

Fixes the stale name in the stash-prisma-next and stash-cli skills, the
@cipherstash/prisma-next README, and — user-visibly — stash init
--prisma-next's printed next-steps, the init flag help, and the stash eql
install Prisma-Next refusal message. Updated the CLI unit + e2e assertions
that pinned the old string. Historical CHANGELOG entries left as-is.

Surfaced by the rc.4 skilltester run (found at PN 0.14.0, confirmed 0.16.0);
tracked with the other skilltester findings in a follow-up issue.
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.

Docs/CLI: prisma-next migration apply does not exist — use top-level prisma-next migrate

1 participant