Skip to content

Commit 2e6f032

Browse files
authored
feat(prisma-next)!: make the adapter EQL v3 only (fixes Supabase superuser block, #709) (#712)
* feat(prisma-next)!: make the adapter EQL v3 only Remove the EQL v2 surface from `@cipherstash/prisma-next` entirely — the install path, the authoring constructors, the runtime codecs, and the v2 subpath exports — so the adapter installs only EQL v3 and works on managed Postgres (e.g. Supabase) as a non-superuser. Install path (the root cause of the Supabase block): - Re-root the v3 baseline migration as an invariant-only genesis edge (`from: null`); the contract now models no storage; the head ref requires only `cipherstash:install-eql-v3-bundle-v1`. The v2 and v3 baselines were chained (v3 started from v2's `to` state, head required both invariants), so `migration apply` always ran the v2 install first — which fails on a non-superuser role. Re-emit the contract-space artefacts. - Delete the v2 baseline migration (`20260601T0000_install_eql_bundle`). API/code removal: - Delete the v2 authoring/runtime/codec code: `cipherstashFromStackV2`, the `*V2` constructors, the v2 codec runtime + composite wire, the baked `eql-install.generated`, and the v2 codec-control hooks. - Remove the `./middleware` and `./migration` subpath exports. - Move the version-neutral `stampRoutingKeysFromAst` into `execution/routing` so `src/middleware/` can be removed; keep the shared value envelopes (`EncryptedString`/`BigInt`/`Boolean`/`Date`/`Json`) and `decryptAll`. The v3 surface is unchanged. Prune the v2 tests and update the shared/v3 tests (descriptor, migration, bundling-isolation, operator/type gating) for the v3-only reality. Refs #709 * docs(prisma-next): update README, DEVELOPING, skill, and layout for v3-only Rewrite `DEVELOPING.md` for the v3 architecture (catalog-derived domains, the `eql*` operator surface, the query-term seam, the genesis-edge migration) and match this repo's actual `src/` layout. Drop the removed v2 surface from the README subpath table, the bundled `stash-prisma-next` skill, the `AGENTS.md` repository layout, and the prisma example JSDoc. Refs #709 * fix(prisma-next): address review — wire the v3 encode diagnostic, fix stale docs James's review (#712) and CodeRabbit. Wire the "middleware not wired" diagnostic on the v3 write path. `isBulkEncryptMiddlewareRegistered` was marked-but-never-read: the read site lived in the v2 `cell-codec-factory.ts`, deleted in this PR, and v3 never had one. Port it to `CipherstashV3CellCodec#encode` so an SDK with no `bulkEncryptMiddlewareV3(sdk)` registered fails fast with `RUNTIME.ENCODE_FAILED` and a copy-pasteable wiring snippet instead of an opaque pg serialise error. Memoised per codec (the registry is add-only), so it costs one WeakSet lookup rather than one per cell. Docs and comments naming removed symbols: - README: drop the "legacy v2 surface keeps its `cipherstash*` names" clause, and switch the query example from `cipherstashIlike` to `eqlMatch`. The LIKE wildcard goes too — `eqlMatch` is bloom token containment (`eql_v3.contains`), not SQL `LIKE`, so `"%@example.com"` would have been misleading. - migration.ts: the trailing rationale still said "invariant-only self-edge" after the edge was re-rooted as genesis. - runtime-v3.ts: referenced the removed `createCipherstashRuntimeDescriptor`, and described a v2/v3 co-registration constraint that no longer exists. - operator-gating-v3.test.ts: header claimed to pin v2/v3 method-name disjointness; the body now pins the `eql*` prefix instead. - from-stack-v3.test.ts: described `cipherstashFromStackV2` as "separate, untouched" when it was removed outright. - DEVELOPING.md: said the v3 codec raises no wiring diagnostic — now it does. 320 -> 322 unit tests (both new cases cover the diagnostic: it fires for an unregistered SDK, and stays silent for an already-encrypted envelope). Typecheck, build, and biome clean.
1 parent 5edef3b commit 2e6f032

99 files changed

Lines changed: 1123 additions & 20200 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
'@cipherstash/prisma-next': minor
3+
---
4+
5+
Make `@cipherstash/prisma-next` **EQL v3 only**. The EQL v2 surface is removed
6+
entirely — install path, authoring constructors, runtime codecs, and the v2
7+
subpath exports.
8+
9+
**Why:** the v2 and v3 baselines were chained — the v3 migration edge started
10+
from the v2 baseline's `to` state and the head ref required both invariants — so
11+
the only path to head ran the v2 install first. The v2 bundle's install fails on
12+
managed Postgres (e.g. Supabase) where the connecting role is **not a
13+
superuser**, which made the adapter unusable there even for v3-only apps.
14+
Installing only EQL v3 (which applies fine as a non-superuser) fixes this.
15+
16+
**Breaking — install path:** the EQL v2 baseline migration
17+
(`20260601T0000_install_eql_bundle`) is removed, and the contract now models no
18+
storage (the retired `eql_v2_configuration` table is gone). The v3 baseline
19+
(`20260601T0100_install_eql_v3_bundle`) is re-rooted as the sole invariant-only
20+
**genesis** edge (`from: null`); the head ref requires only
21+
`cipherstash:install-eql-v3-bundle-v1`. `prisma-next migration apply` now
22+
installs EQL v3 exclusively and works on Supabase as a non-superuser.
23+
24+
**Breaking — API:** the EQL v2 authoring/runtime surface is removed:
25+
26+
- `cipherstashFromStackV2`, `deriveStackSchemas`, and `createCipherstashSdk`
27+
(from `./stack`) — use `cipherstashFromStack` (v3).
28+
- The `encrypted*V2` TS column factories and the `cipherstash.Encrypted*V2` PSL
29+
constructors (from `./column-types`) — use the v3 domain factories/constructors
30+
(`text`/`textSearch`/`bigIntOrd`/… and `cipherstash.TextSearch()` etc.).
31+
- The v2 runtime codecs, `createCipherstashRuntimeDescriptor`, the `cipherstash*`
32+
query operators/helpers, and the `EncryptedDouble` envelope (from `./runtime`)
33+
— use the v3 runtime (`createCipherstashV3RuntimeDescriptor`,
34+
`bulkEncryptMiddlewareV3`, the `eql*` operators, `EncryptedNumber`). The
35+
version-neutral envelopes (`EncryptedString`/`BigInt`/`Boolean`/`Date`/`Json`)
36+
and `decryptAll` are unchanged.
37+
- The `./middleware` and `./migration` subpath exports are removed (the v2
38+
bulk-encrypt middleware and call-classes). Use `bulkEncryptMiddlewareV3` from
39+
`./runtime` / `./v3`.
40+
41+
Apps still on the v2 surface must move to the v3 constructors and regenerate
42+
their contract (`prisma-next contract emit`); there is no supported EQL v2 path
43+
in this package anymore.
44+
45+
**Also:** the "bulk-encrypt middleware not wired" diagnostic is now raised on the
46+
v3 write path. Encoding an unencrypted value with an SDK that has no
47+
`bulkEncryptMiddlewareV3(sdk)` registered against it fails fast with
48+
`RUNTIME.ENCODE_FAILED` and a copy-pasteable wiring snippet, instead of surfacing
49+
as an opaque pg-level serialise error. (The guard existed on the v2 codec; the v3
50+
codec had never wired it up.)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'stash': patch
3+
---
4+
5+
Update the bundled `stash-prisma-next` skill for the EQL v3-only
6+
`@cipherstash/prisma-next`: drop the stale references to the removed EQL v2
7+
surface (`cipherstashFromStackV2`, the `cipherstash*` operators, the "legacy v2"
8+
subpath note) so the guidance copied into customer repos matches the package.

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ If these variables are missing, tests that require live encryption will fail or
8181
- `packages/cli`: The `stash` CLI — auth, init, encryption schema, and database setup (`stash eql install`). Has its own `AGENTS.md`.
8282
- `packages/wizard`: AI-powered encryption setup (`@cipherstash/wizard`)
8383
- `packages/migrate`: Plaintext-to-encrypted column migration (`@cipherstash/migrate`) — resumable backfill, per-column state
84-
- `packages/prisma-next`: Prisma Next integration (`@cipherstash/prisma-next`) — searchable field-level encryption for Postgres. EQL v2 (`*V2` constructors, `cipherstashFromStack`) and EQL v3 (per-domain constructors, `./v3` entry with `cipherstashFromStackV3`)
84+
- `packages/prisma-next`: Prisma Next integration (`@cipherstash/prisma-next`) — searchable field-level encryption for Postgres. **EQL v3 only**: per-domain constructors (`cipherstash.TextSearch()` / `text()` / `bigIntOrd()` / …) and `cipherstashFromStack` (the `./v3` and `./stack` entries). The EQL v2 surface was removed — the adapter's baseline migration installs the EQL v3 bundle only (works on Supabase as a non-superuser)
8585
- `packages/stack-drizzle`: Drizzle ORM integration (`@cipherstash/stack-drizzle`), depends on `@cipherstash/stack` — EQL v2 (`.`) and EQL v3 (`./v3`). Split out of `@cipherstash/stack`.
8686
- `packages/stack-supabase`: Supabase integration (`@cipherstash/stack-supabase`), depends on `@cipherstash/stack``encryptedSupabase` (v2) and `encryptedSupabaseV3` (v3). Split out of `@cipherstash/stack`.
8787
- `packages/schema`: Schema builder utilities and types (`encryptedTable`, `encryptedColumn`, `encryptedField`)

examples/prisma/src/db.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
* returns ready-to-spread arrays for `extensions` and `middleware`.
1010
* Override `schemasV3` only if you have additional tables the contract
1111
* does not model.
12-
*
13-
* A v3 client is v3-only: a contract carrying v2 cipherstash codec ids
14-
* is rejected at setup (use `cipherstashFromStackV2` from
15-
* `@cipherstash/prisma-next/stack` for a v2 contract).
1612
*/
1713

1814
import 'dotenv/config'

0 commit comments

Comments
 (0)