diff --git a/.changeset/pre.json b/.changeset/pre.json index 12a91cce..d32644cb 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -23,8 +23,11 @@ "changesets": [ "adapter-package-split", "adapter-split-skills", + "auth-binding-lockstep", "cli-anonymous-telemetry", "cli-eql-v3-single-bundle", + "drizzle-kit-eql-v3-ddl", + "eql-migration-command", "eql-v3-adapter-type-robustness", "eql-v3-bigint-domains", "eql-v3-bundle-from-package", @@ -37,16 +40,22 @@ "eql-v3-json-selector", "eql-v3-json-skills", "eql-v3-json", + "eql-v3-prisma-next", "eql-v3-public-domains", "eql-v3-rename-contains-to-matches", "eql-v3-sole-docs", + "eql-v3-source-from-package", "eql-v3-supabase-adapter", "eql-v3-text-search", "eql-v3-typed-client", "eql-v3-typed-schema", "eql-v3-wasm-inline", "init-pins-runtime-versions", + "migrate-eql-v3", + "plan-complete-rollout-yes", + "prisma-example-eql-v3", "prisma-next-0-14", + "prisma-next-drop-encrypted-prefix", "prisma-next-joins-release-train", "release-train-coupling", "remove-legacy-drizzle-package", @@ -59,6 +68,8 @@ "stash-cli-eql-v3-default", "stash-cli-skill-refresh", "stash-drizzle-skill-encrypt-query", + "stash-env-mint-credentials", + "stash-prisma-next-skill", "stash-skills-contains-to-matches", "stash-supabase-contains-substrings", "supabase-encryption-error", diff --git a/e2e/CHANGELOG.md b/e2e/CHANGELOG.md index 21198d56..20ea6fb8 100644 --- a/e2e/CHANGELOG.md +++ b/e2e/CHANGELOG.md @@ -1,5 +1,22 @@ # @cipherstash/e2e +## 0.0.3-rc.3 + +### Patch Changes + +- Updated dependencies [8b2551a] +- Updated dependencies [b8cb599] +- Updated dependencies [0811330] +- Updated dependencies [175eeb7] +- Updated dependencies [3a86939] +- Updated dependencies [b0634df] +- Updated dependencies [4923c0a] +- Updated dependencies [f188c7a] +- Updated dependencies [8872d1e] + - @cipherstash/stack@1.0.0-rc.3 + - stash@1.0.0-rc.3 + - @cipherstash/wizard@1.0.0-rc.3 + ## 0.0.3-rc.2 ### Patch Changes diff --git a/e2e/package.json b/e2e/package.json index 30073e97..72b91ba7 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/e2e", - "version": "0.0.3-rc.2", + "version": "0.0.3-rc.3", "private": true, "description": "End-to-end tests that exercise built CipherStash binaries and cross-package behaviour.", "type": "module", diff --git a/examples/basic/CHANGELOG.md b/examples/basic/CHANGELOG.md index c49c345a..8496f189 100644 --- a/examples/basic/CHANGELOG.md +++ b/examples/basic/CHANGELOG.md @@ -1,5 +1,15 @@ # @cipherstash/basic-example +## 1.2.14-rc.3 + +### Patch Changes + +- Updated dependencies [8b2551a] +- Updated dependencies [b8cb599] + - @cipherstash/stack@1.0.0-rc.3 + - @cipherstash/stack-drizzle@1.0.0-rc.3 + - @cipherstash/stack-supabase@1.0.0-rc.3 + ## 1.2.14-rc.2 ### Patch Changes diff --git a/examples/basic/package.json b/examples/basic/package.json index 46b47708..734001f7 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -1,7 +1,7 @@ { "name": "@cipherstash/basic-example", "private": true, - "version": "1.2.14-rc.2", + "version": "1.2.14-rc.3", "type": "module", "scripts": { "start": "tsx index.ts" diff --git a/examples/prisma/CHANGELOG.md b/examples/prisma/CHANGELOG.md index 4614b506..a665b552 100644 --- a/examples/prisma/CHANGELOG.md +++ b/examples/prisma/CHANGELOG.md @@ -1,5 +1,19 @@ # @cipherstash/prisma-next-example +## 0.1.0-rc.3 + +### Minor Changes + +- a75513b: Convert the example app to EQL v3. Every column is now a concrete `public.eql_v3_*` domain authored with the per-domain constructors (`EncryptedTextSearch`, `EncryptedDoubleOrd`, `EncryptedBigIntOrd`, `EncryptedDateOrd`, `EncryptedBoolean`, `EncryptedJson`), wired through `cipherstashFromStackV3({ contractJson })`. The e2e harness runs the full v3 surface against live Postgres + ZeroKMS with no skips: the `eql*` operator vocabulary (equality/range plus `eqlMatch` free-text token search), `eqlAsc`/`eqlDesc` order-term sorting, encrypted JSON containment (`eqlJsonContains` — the v2 `cipherstashJsonb*` helpers do not exist in v3), lossless `bigint` beyond `Number.MAX_SAFE_INTEGER`, and the storage-only `eql_v3_boolean` refusal (`EncryptionOperatorError`) pinned as a feature. Migrations regenerate from the v3 contract: the initial app migration creates the `users` table against the v3 domains with zero `add_search_config` ops, and the cipherstash space carries both bundle baselines (v2 + v3). + +### Patch Changes + +- Updated dependencies [8b2551a] +- Updated dependencies [a75513b] +- Updated dependencies [4923c0a] + - @cipherstash/stack@1.0.0-rc.3 + - @cipherstash/prisma-next@1.0.0-rc.3 + ## 0.0.6-rc.2 ### Patch Changes diff --git a/examples/prisma/package.json b/examples/prisma/package.json index 4429e1a9..ea8f3843 100644 --- a/examples/prisma/package.json +++ b/examples/prisma/package.json @@ -1,7 +1,7 @@ { "name": "@cipherstash/prisma-next-example", "private": true, - "version": "0.0.6-rc.2", + "version": "0.1.0-rc.3", "description": "End-to-end example of @cipherstash/prisma-next: searchable application-layer encryption for Postgres with Prisma Next, using @cipherstash/stack as the SDK.", "type": "module", "scripts": { diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md index d36464f8..f78d55b4 100644 --- a/packages/bench/CHANGELOG.md +++ b/packages/bench/CHANGELOG.md @@ -1,5 +1,14 @@ # @cipherstash/bench +## 0.0.5-rc.3 + +### Patch Changes + +- Updated dependencies [8b2551a] +- Updated dependencies [b8cb599] + - @cipherstash/stack@1.0.0-rc.3 + - @cipherstash/stack-drizzle@1.0.0-rc.3 + ## 0.0.5-rc.2 ### Patch Changes diff --git a/packages/bench/package.json b/packages/bench/package.json index b9b961ea..4cd8be52 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/bench", - "version": "0.0.5-rc.2", + "version": "0.0.5-rc.3", "private": true, "description": "Performance / index-engagement benchmarks for stack integrations (Drizzle, encryptedSupabase, Prisma).", "type": "module", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index cd5e4afe..c4798799 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,209 @@ # @cipherstash/cli +## 1.0.0-rc.3 + +### Minor Changes + +- 0811330: Add `stash eql migration` — generate an EQL **v3** install migration for your ORM + instead of running the SQL directly against the database (`stash eql install`). + Migration-first is the preferred path: the install lands in your migration history + and ships to every environment through the ORM's own migrate step. + + ```bash + stash eql migration --drizzle # Drizzle custom migration + stash eql migration --drizzle --supabase # also grants eql_v3 to anon/authenticated/service_role + ``` + + The migration carries the CLI's bundled v3 install SQL (one source of truth) plus + the `cs_migrations` tracking schema, so a single `drizzle-kit migrate` covers + everything `stash encrypt …` needs. `--supabase` appends the `eql_v3` + + `eql_v3_internal` role grants for PostgREST/RLS access. + + `--prisma` is registered but not available yet — the Prisma Next migration + emitter is a follow-up (tracked in cipherstash/stack#690) that will let + prisma-next drop its baked install baseline. It fails with a pointer for now. + +- 3a86939: EQL v3 support for the encryption rollout lifecycle (#648). The `stash +encrypt *` commands (and `@cipherstash/migrate` underneath) now resolve a + column's EQL version and its encrypted counterpart from the **Postgres domain + types** — the EQL v3 types are self-describing, so the `_encrypted` + naming is a convention only, never enforced or relied upon — and follow the + right lifecycle, no new flags: + + - **`encrypt backfill`** works on v3 columns unchanged (the engine was always + version-agnostic; pass an `EncryptionV3` client and real v3 envelopes land + in the concrete `eql_v3_*` domain column — verified live against a real + database, including the domain CHECK and a decrypt round-trip). The + manifest records the detected version, the encrypted column's name, and the + v3 target phase, and the command prints v3-appropriate next steps. + - **`encrypt cutover`** on a backfilled v3 column reports "not applicable" + (exit 0) with guidance: v3 has no rename cut-over — the application + switches to the encrypted column by name. Before backfill completes it + exits 1 and says to finish the backfill instead of instructing the switch. + On a database with no `eql_v2_configuration` table (a v3-only install) the + v2 path now explains that instead of surfacing a raw Postgres error. + - **`encrypt drop`** is version-aware: v3 runs from the `backfilled` phase, + **verifies live coverage** (refuses to generate the migration while any row + still has the plaintext set and the encrypted column NULL — the + `countUnencrypted` check), and drops the ORIGINAL plaintext column (there + is no `_plaintext` under v3); v2 behaviour is unchanged. The generated + v3 migration **re-verifies coverage at apply time** — it locks the table, + re-counts, and aborts without dropping if plaintext-only rows appeared + after generation. And because dropping is the one irreversible step, it + requires a positively asserted plaintext↔ciphertext pairing (the + manifest's recorded `encryptedColumn` or the naming convention): a match + found only by being the table's sole EQL column is refused with + instructions, and an ambiguous table (several EQL columns, none + identifiable) fails closed listing the candidates — as does `cutover`. + - **`encrypt status`** classifies each column from the observed domain type + (manifest as fallback), shows `v3` in the EQL column, and no longer raises + the v2-only `not-registered` / `plaintext-col-missing` drift flags for v3 + columns. `stash status`'s quest ladder and the `stash init` agent handoff + prompt teach the version-appropriate next step (no more "run cutover" on + v3 columns). + - New `@cipherstash/migrate` exports: `classifyEqlDomain`, + `resolveEncryptedColumn`, `pickEncryptedColumn`, `listEncryptedColumns` + (domain-type resolution — case-exact for quoted/mixed-case table names), + `countEncrypted` / `countUnencrypted` (coverage counts), and manifest + `eqlVersion` + `encryptedColumn` fields. `EqlVersion` is numeric (`2 | 3`), + matching the manifest and the installer. Resolved columns carry `via: +'hint' | 'convention' | 'sole'` so callers can tell a positively asserted + pairing from a by-elimination guess. + - Fixed: `encrypt cutover`/`encrypt drop` precondition failures now actually + exit 1 — the early-return guards previously skipped the exit-code path + entirely, so failed preconditions exited 0. (This also applies to v2 + preconditions: scripted pipelines that relied on the erroneous exit 0 will + now see the documented exit 1.) + + The `stash-cli` and `stash-encryption` skills and the `@cipherstash/migrate` + README document the two lifecycles (v2: backfill → cutover → drop; + v3: backfill → switch-by-name → drop). + +- b0634df: `stash plan --complete-rollout` is now automatable and has an honest exit code. + It skips the production-deploy gate, so it needs explicit consent — previously + that was an interactive prompt with no bypass, so a non-interactive run + auto-cancelled (default-no) and exited **0** without drafting a plan, leaving + automation to assume a plan existed. + + - New `--yes` flag confirms the gate-skip without a prompt (for CI/agents). + - Without `--yes`, a non-interactive `--complete-rollout` run now **refuses + with a non-zero exit** and points at `--yes`, instead of silently succeeding. + - Interactive behaviour is unchanged (default-no confirm). + +- f188c7a: `stash env` now works: it mints deployment credentials from your device-code + session and prints them as env vars — no dashboard copy-paste. The command + creates a fresh ZeroKMS client and a member-role CipherStash access key (named + via `--name`; the role is pinned in the request and verified on the response — + the CLI deliberately cannot mint admin keys), then emits `CS_WORKSPACE_CRN`, + `CS_CLIENT_ID`, `CS_CLIENT_KEY`, and `CS_CLIENT_ACCESS_KEY`. + + Output goes to stdout by default — and stdout is pipe-clean (progress UI is on + stderr), so `stash env --name x > prod.env` and pipes into secret stores are + safe. `--write [path]` writes a file instead (default `.env.production.local`, + enforced mode 0600 even when overwriting), confirming before overwriting and + refusing non-interactively — always _before_ anything is minted, so a refusal + never discards the shown-exactly-once access key. `--json` emits NDJSON; with + `--write` the confirmation event is deliberately secret-free. API responses + are schema-validated so a service change can never print `undefined` into a + credentials file. Creating access keys requires the admin role in the + workspace. + + This is also the supported credential path for WASM/edge local development + (Supabase Edge Functions, Cloudflare Workers, Deno), where the runtime cannot + read the `~/.cipherstash` device profile: mint a key and feed it via + `supabase functions serve --env-file` or the platform's secret store. + + The `STASH_EXPERIMENTAL_ENV_CMD` gate is removed. + +- 8872d1e: `stash init`, `stash plan`, and `stash impl` no longer crash on a Prisma Next + project. `SKILL_MAP` was missing a `prisma-next` entry, so the skills-install + and AGENTS.md-builder steps hit `SKILL_MAP[integration]` → `undefined` and threw + "not iterable" for any repo the CLI detected as Prisma Next. The entry is added + and both consumers now resolve skills through a `skillsFor()` helper that + degrades an unmapped integration to the base skill set instead of crashing + (`tsup` ships without type-checking, so the `Record` type alone + didn't protect the build). + + Ships a new **`stash-prisma-next`** agent skill documenting the EQL v3 Prisma + Next surface — the domain-named encrypted column types (`EncryptedTextSearch`, + `EncryptedDoubleOrd`, …), `cipherstashFromStackV3` wiring, the runtime value + envelopes, the `eql*` query operators, and EQL installation via + `prisma-next migration apply`. It is installed for Prisma Next projects and + inlined into `AGENTS.md` for editor agents. + + `stash eql install` now refuses to run in a Prisma Next project (pointing you + at `prisma-next migration apply`, which owns EQL installation) unless you pass + `--force` — closing the manual-invocation hole that `stash init --prisma-next` + already avoided. + +### Patch Changes + +- 8b2551a: Fix "Failed to load native binding" on project-local installs of the CLI/SDK + (npm). `@cipherstash/auth` was pinned at 0.41.0 while the six + `@cipherstash/auth-*` platform bindings declared in stack/stash/wizard's + optionalDependencies were pinned at 0.42.0. Because auth pins its bindings as + exact-version optional peer dependencies, the skew made npm nest per-consumer + binding copies that the hoisted `auth` package could not resolve — any command + or import touching auth then died at startup. All seven packages now move in + lockstep at 0.42.0, Dependabot is barred from bumping any of them + independently, and a supply-chain CI test fails on any future skew. +- b8cb599: Fix invalid DDL from `drizzle-kit generate`/`push` for EQL v3 encrypted columns. + A v3 column declared its SQL type as the schema-qualified domain + (`public.eql_v3_text_search`), but drizzle-kit wraps a custom type's whole name + in a single pair of double quotes — emitting `"public.eql_v3_text_search"`, which + Postgres reads as one dotted identifier and rejects with `type +"public.eql_v3_text_search" does not exist`. Generated migrations had to be + hand-repaired. + + The v3 column now emits the **unqualified** domain (`eql_v3_text_search`), which + drizzle-kit renders as the valid `"eql_v3_text_search"` and which resolves via the + search path (the domains live in `public`). This matches how the v2 + `encryptedType` surface already declares its type, and how drizzle-kit reads the + type back during a `push` introspection diff, so the two sides no longer disagree. + Builder recovery still yields the canonical `public.eql_v3_*` identity, so + operators and schema extraction are unchanged. + + The bundled `stash-drizzle` skill is updated to describe the unqualified generated + type and the search-path requirement (hence the `stash` bump — the skill ships in + its tarball). + +- 175eeb7: The EQL **v3** install SQL is now read from the `@cipherstash/eql` package at + runtime instead of a copy vendored into this repo. `@cipherstash/eql` becomes a + runtime dependency of `stash`, and a version bump now flows straight through — no + re-vendor step, no drift between the pin and the shipped bundle. + + This removes ~44k lines of generated plpgsql from the repository (which had made + GitHub classify the whole repo as plpgsql — CIP-3518) along with the + `gen:eql-v3-sql` vendor script and its CI drift-check. + + No behaviour change: v3 installs the same one-artifact bundle (which self-adapts to + non-superuser environments like Supabase), and the v2 path is unchanged. + +- 4923c0a: **Breaking (v3 authoring surface):** the EQL v3 PSL column constructors drop + the `Encrypted` prefix to line up with the stack / Drizzle `types.*` catalog — + the `cipherstash.` namespace already disambiguates. So + `cipherstash.EncryptedTextSearch()` → `cipherstash.TextSearch()`, + `cipherstash.EncryptedDoubleOrd()` → `cipherstash.DoubleOrd()`, + `cipherstash.EncryptedBoolean()` → `cipherstash.Boolean()`, etc. + + The v3 one-call setup function is renamed `cipherstashFromStackV3` → + `cipherstashFromStack` (v3 is the default), and the existing v2 setup function + becomes `cipherstashFromStackV2`. + + The camelCase TS-authoring factory exports move in lockstep: + `encryptedTextSearch` → `textSearch`, `encryptedDoubleOrd` → `doubleOrd`, etc. + (a property test enforces the PSL and TS names agree modulo first-letter case). + + Unchanged: the runtime value envelopes (`EncryptedString`, `EncryptedNumber`, + `EncryptedBoolean`, …), the `cipherstash.*V2` legacy column constructors, the + generated `contract.json` / codec ids, and the `eql*` query operators. + + The `stash-prisma-next` skill is updated to the new names (skills ship in the + `stash` tarball). + +- Updated dependencies [3a86939] + - @cipherstash/migrate@1.0.0-rc.1 + ## 1.0.0-rc.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index bc2eaf6e..ecb82e00 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "stash", - "version": "1.0.0-rc.2", - "description": "CipherStash CLI \u2014 the one stash command for auth, init, encryption schema, database setup, and secrets.", + "version": "1.0.0-rc.3", + "description": "CipherStash CLI — the one stash command for auth, init, encryption schema, database setup, and secrets.", "repository": { "type": "git", "url": "git+https://github.com/cipherstash/stack.git", @@ -56,7 +56,7 @@ "posthog-node": "^5.40.0", "zod": "^3.25.76" }, - "//optionalDependencies": "@cipherstash/auth ships per-platform native bindings as optional peerDependencies. pnpm does not auto-install platform-matched optional peer deps, so we declare them here as optionalDependencies \u2014 pnpm then picks the binary matching the host's os/cpu (from each sub-package's own package.json) and ignores the rest. All seven names share a single catalog entry to keep them in lockstep.", + "//optionalDependencies": "@cipherstash/auth ships per-platform native bindings as optional peerDependencies. pnpm does not auto-install platform-matched optional peer deps, so we declare them here as optionalDependencies — pnpm then picks the binary matching the host's os/cpu (from each sub-package's own package.json) and ignores the rest. All seven names share a single catalog entry to keep them in lockstep.", "optionalDependencies": { "@cipherstash/auth-darwin-arm64": "catalog:repo", "@cipherstash/auth-darwin-x64": "catalog:repo", diff --git a/packages/migrate/CHANGELOG.md b/packages/migrate/CHANGELOG.md index 8b991d51..ebcfb9bd 100644 --- a/packages/migrate/CHANGELOG.md +++ b/packages/migrate/CHANGELOG.md @@ -1,5 +1,65 @@ # @cipherstash/migrate +## 1.0.0-rc.1 + +### Minor Changes + +- 3a86939: EQL v3 support for the encryption rollout lifecycle (#648). The `stash +encrypt *` commands (and `@cipherstash/migrate` underneath) now resolve a + column's EQL version and its encrypted counterpart from the **Postgres domain + types** — the EQL v3 types are self-describing, so the `_encrypted` + naming is a convention only, never enforced or relied upon — and follow the + right lifecycle, no new flags: + + - **`encrypt backfill`** works on v3 columns unchanged (the engine was always + version-agnostic; pass an `EncryptionV3` client and real v3 envelopes land + in the concrete `eql_v3_*` domain column — verified live against a real + database, including the domain CHECK and a decrypt round-trip). The + manifest records the detected version, the encrypted column's name, and the + v3 target phase, and the command prints v3-appropriate next steps. + - **`encrypt cutover`** on a backfilled v3 column reports "not applicable" + (exit 0) with guidance: v3 has no rename cut-over — the application + switches to the encrypted column by name. Before backfill completes it + exits 1 and says to finish the backfill instead of instructing the switch. + On a database with no `eql_v2_configuration` table (a v3-only install) the + v2 path now explains that instead of surfacing a raw Postgres error. + - **`encrypt drop`** is version-aware: v3 runs from the `backfilled` phase, + **verifies live coverage** (refuses to generate the migration while any row + still has the plaintext set and the encrypted column NULL — the + `countUnencrypted` check), and drops the ORIGINAL plaintext column (there + is no `_plaintext` under v3); v2 behaviour is unchanged. The generated + v3 migration **re-verifies coverage at apply time** — it locks the table, + re-counts, and aborts without dropping if plaintext-only rows appeared + after generation. And because dropping is the one irreversible step, it + requires a positively asserted plaintext↔ciphertext pairing (the + manifest's recorded `encryptedColumn` or the naming convention): a match + found only by being the table's sole EQL column is refused with + instructions, and an ambiguous table (several EQL columns, none + identifiable) fails closed listing the candidates — as does `cutover`. + - **`encrypt status`** classifies each column from the observed domain type + (manifest as fallback), shows `v3` in the EQL column, and no longer raises + the v2-only `not-registered` / `plaintext-col-missing` drift flags for v3 + columns. `stash status`'s quest ladder and the `stash init` agent handoff + prompt teach the version-appropriate next step (no more "run cutover" on + v3 columns). + - New `@cipherstash/migrate` exports: `classifyEqlDomain`, + `resolveEncryptedColumn`, `pickEncryptedColumn`, `listEncryptedColumns` + (domain-type resolution — case-exact for quoted/mixed-case table names), + `countEncrypted` / `countUnencrypted` (coverage counts), and manifest + `eqlVersion` + `encryptedColumn` fields. `EqlVersion` is numeric (`2 | 3`), + matching the manifest and the installer. Resolved columns carry `via: +'hint' | 'convention' | 'sole'` so callers can tell a positively asserted + pairing from a by-elimination guess. + - Fixed: `encrypt cutover`/`encrypt drop` precondition failures now actually + exit 1 — the early-return guards previously skipped the exit-code path + entirely, so failed preconditions exited 0. (This also applies to v2 + preconditions: scripted pipelines that relied on the erroneous exit 0 will + now see the documented exit 1.) + + The `stash-cli` and `stash-encryption` skills and the `@cipherstash/migrate` + README document the two lifecycles (v2: backfill → cutover → drop; + v3: backfill → switch-by-name → drop). + ## 1.0.0-rc.0 ### Patch Changes diff --git a/packages/migrate/package.json b/packages/migrate/package.json index a302385c..b14343ca 100644 --- a/packages/migrate/package.json +++ b/packages/migrate/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/migrate", - "version": "1.0.0-rc.0", + "version": "1.0.0-rc.1", "description": "Plaintext-to-encrypted column migration for CipherStash: resumable backfill, per-column state, and EQL lifecycle orchestration.", "repository": { "type": "git", diff --git a/packages/prisma-next/CHANGELOG.md b/packages/prisma-next/CHANGELOG.md index 3f1a33d0..53885995 100644 --- a/packages/prisma-next/CHANGELOG.md +++ b/packages/prisma-next/CHANGELOG.md @@ -1,5 +1,56 @@ # @cipherstash/prisma-next +## 1.0.0-rc.3 + +### Minor Changes + +- a75513b: **Breaking:** EQL v3 columns are now authored through **concrete per-domain constructors** — the constructor you choose _is_ the capability set. The legacy boolean-option surface (`EncryptedString({ equality, freeTextSearch, orderAndRange })`) is not carried into v3. + + - New per-domain constructors, one per exposed `public.eql_v3_*` domain: + - Text: `EncryptedText` (storage), `EncryptedTextEq`, `EncryptedTextOrd` (eq + order/range), `EncryptedTextMatch` (free-text), `EncryptedTextSearch` (eq + free-text + order/range). + - Scalars (Integer, Smallint, BigInt, Numeric, Real, Double, Date, Timestamp): `Encrypted` (storage), `EncryptedEq`, `EncryptedOrd`. + - `EncryptedBoolean` — storage-only (`public.eql_v3_boolean`); there is no boolean equality constructor. + - `EncryptedJson` — searchable encrypted JSONB (`public.eql_v3_json`, `ste_vec`), queried with `eqlJsonContains` (`@>` containment). Selector querying (comparing the value at a JSONPath) is tracked in #677. + - **Impossible capability combinations have no constructor** (e.g. text equality + free-text without order/range) — they are unrepresentable, not runtime errors. + - **BigInt is a first-class v3 family** (`EncryptedBigInt` / `EncryptedBigIntEq` / `EncryptedBigIntOrd`, JS `bigint` plaintext, backed by `public.eql_v3_bigint*`). + - Use the `*V2` constructors (`EncryptedStringV2`, `EncryptedDoubleV2`, `EncryptedBigIntV2`, `EncryptedDateV2`, `EncryptedBooleanV2`, `EncryptedJsonV2`) to keep EQL v2 columns. A client is v2 or v3 — the two runtime descriptors are never co-registered. + - New `@cipherstash/prisma-next/v3` entry point: `cipherstashFromStackV3({ contractJson })` builds the v3 runtime descriptor, bulk-encrypt middleware, and a stack `EncryptionV3` client from the emitted contract. + - Query operators use an **EQL-derived vocabulary** (`eqlEq`, `eqlNeq`, `eqlIn`, `eqlNotIn`, `eqlGt`, `eqlGte`, `eqlLt`, `eqlLte`, `eqlBetween`, `eqlNotBetween`, `eqlJsonContains`; ordering via `eqlAsc` / `eqlDesc`), lowering to the same-named `eql_v3.*` functions with operands cast to the domain's query type (`$n::eql_v3.query_`); ordering uses `eql_v3.ord_term` / `eql_v3.ord_term_ore` by the column's ordering flavour. The domains are `public.eql_v3_*`; the operator functions live in the `eql_v3` schema. (The v2 surface keeps its `cipherstash*` names.) + - Free-text search is **`eqlMatch`** — fuzzy bloom token matching (`eql_v3.contains`), deliberately NOT named after SQL `ILIKE`: matching is case-insensitive, order/multiplicity-insensitive, and one-sided (may false-positive). Two guards run before encryption: SQL wildcards are normalised (leading/trailing `%` stripped; interior `%` or any `_` rejected), and needles the column's match index cannot answer (empty / below the tokenizer length) are rejected via the shared `matchNeedleError` guard. There is **no negated match operator** — negating a may-false-positive bloom test would silently drop matching rows. + - A new baseline migration `20260601T0100_install_eql_v3_bundle` (invariant `cipherstash:install-eql-v3-bundle-v1`) installs the `public.eql_v3_*` domains and `eql_v3.*` functions from the pinned `@cipherstash/eql` release. Regenerate contracts and run migrations after changing constructors. + - **The v3 ORM surface is fully wired end-to-end** (proven by converting `examples/prisma`): + - The generated `contract.d.ts` type surface covers every v3 codec id: `CodecTypes` gains all 40 `cipherstash/eql-v3/*@1` entries (envelope outputs — `number`-castAs domains decode to the new `EncryptedNumber` — plus trait-accurate operator visibility), and `QueryOperationTypes` gains the `eql*` operator set, surfaced on v3 columns via type-level `cipherstash:v3-*` marker traits (the v2 `cipherstash*` methods never appear on v3 columns, and vice-versa). Storage-only domains (including `EncryptedBoolean`) surface no operator methods at the type level, matching the runtime gate. + - The v3 runtime descriptor now presents the **pack id** (`cipherstash`) with v3's own version, so `postgres({ extensions })` accepts contracts emitted by the cipherstash extension pack instead of failing with `RUNTIME.MISSING_EXTENSION_PACK`. + - Every v3 codec id registers a control-plane `expandNativeType` hook that strips the `public.` qualifier — `prisma-next migration plan` now renders `CREATE TABLE` columns as bare domain names (`eql_v3_bigint_ord`), matching what introspection reports, with **no `add_search_config` ops** (v3 domains carry their own index metadata). No `onFieldEvent` is registered for v3. + - The v3 bundle baseline migration op is reclassified `data` (it is a contract-shape-neutral self-edge; the aggregate integrity checker rejects self-edges without a data-class op), unblocking `prisma-next migration plan` / `migrate` in consuming apps. + +- 4923c0a: **Breaking (v3 authoring surface):** the EQL v3 PSL column constructors drop + the `Encrypted` prefix to line up with the stack / Drizzle `types.*` catalog — + the `cipherstash.` namespace already disambiguates. So + `cipherstash.EncryptedTextSearch()` → `cipherstash.TextSearch()`, + `cipherstash.EncryptedDoubleOrd()` → `cipherstash.DoubleOrd()`, + `cipherstash.EncryptedBoolean()` → `cipherstash.Boolean()`, etc. + + The v3 one-call setup function is renamed `cipherstashFromStackV3` → + `cipherstashFromStack` (v3 is the default), and the existing v2 setup function + becomes `cipherstashFromStackV2`. + + The camelCase TS-authoring factory exports move in lockstep: + `encryptedTextSearch` → `textSearch`, `encryptedDoubleOrd` → `doubleOrd`, etc. + (a property test enforces the PSL and TS names agree modulo first-letter case). + + Unchanged: the runtime value envelopes (`EncryptedString`, `EncryptedNumber`, + `EncryptedBoolean`, …), the `cipherstash.*V2` legacy column constructors, the + generated `contract.json` / codec ids, and the `eql*` query operators. + + The `stash-prisma-next` skill is updated to the new names (skills ship in the + `stash` tarball). + +### Patch Changes + +- Updated dependencies [8b2551a] + - @cipherstash/stack@1.0.0-rc.3 + ## 1.0.0-rc.2 ### Patch Changes diff --git a/packages/prisma-next/package.json b/packages/prisma-next/package.json index bd5b6e5e..1fd9be97 100644 --- a/packages/prisma-next/package.json +++ b/packages/prisma-next/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/prisma-next", - "version": "1.0.0-rc.2", + "version": "1.0.0-rc.3", "license": "MIT", "author": "CipherStash ", "description": "CipherStash extension for Prisma Next: searchable application-layer field-level encryption for Postgres, with six encrypted column types, 17 query operators, bulk encrypt/decrypt middleware, and a baseline migration that installs the vendored EQL bundle SQL byte-for-byte.", diff --git a/packages/stack-drizzle/CHANGELOG.md b/packages/stack-drizzle/CHANGELOG.md index 493aca61..46e49bba 100644 --- a/packages/stack-drizzle/CHANGELOG.md +++ b/packages/stack-drizzle/CHANGELOG.md @@ -1,5 +1,32 @@ # @cipherstash/stack-drizzle +## 1.0.0-rc.3 + +### Patch Changes + +- b8cb599: Fix invalid DDL from `drizzle-kit generate`/`push` for EQL v3 encrypted columns. + A v3 column declared its SQL type as the schema-qualified domain + (`public.eql_v3_text_search`), but drizzle-kit wraps a custom type's whole name + in a single pair of double quotes — emitting `"public.eql_v3_text_search"`, which + Postgres reads as one dotted identifier and rejects with `type +"public.eql_v3_text_search" does not exist`. Generated migrations had to be + hand-repaired. + + The v3 column now emits the **unqualified** domain (`eql_v3_text_search`), which + drizzle-kit renders as the valid `"eql_v3_text_search"` and which resolves via the + search path (the domains live in `public`). This matches how the v2 + `encryptedType` surface already declares its type, and how drizzle-kit reads the + type back during a `push` introspection diff, so the two sides no longer disagree. + Builder recovery still yields the canonical `public.eql_v3_*` identity, so + operators and schema extraction are unchanged. + + The bundled `stash-drizzle` skill is updated to describe the unqualified generated + type and the search-path requirement (hence the `stash` bump — the skill ships in + its tarball). + +- Updated dependencies [8b2551a] + - @cipherstash/stack@1.0.0-rc.3 + ## 1.0.0-rc.2 ### Patch Changes diff --git a/packages/stack-drizzle/package.json b/packages/stack-drizzle/package.json index 1c00bc76..b0ca4bc5 100644 --- a/packages/stack-drizzle/package.json +++ b/packages/stack-drizzle/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/stack-drizzle", - "version": "1.0.0-rc.2", + "version": "1.0.0-rc.3", "description": "CipherStash Stack Drizzle ORM integration: searchable, application-layer field-level encryption for PostgreSQL.", "keywords": [ "encrypted", diff --git a/packages/stack-supabase/CHANGELOG.md b/packages/stack-supabase/CHANGELOG.md index b9d90696..87121f00 100644 --- a/packages/stack-supabase/CHANGELOG.md +++ b/packages/stack-supabase/CHANGELOG.md @@ -1,5 +1,12 @@ # @cipherstash/stack-supabase +## 1.0.0-rc.3 + +### Patch Changes + +- Updated dependencies [8b2551a] + - @cipherstash/stack@1.0.0-rc.3 + ## 1.0.0-rc.2 ### Patch Changes diff --git a/packages/stack-supabase/package.json b/packages/stack-supabase/package.json index af9872c4..f2e2d589 100644 --- a/packages/stack-supabase/package.json +++ b/packages/stack-supabase/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/stack-supabase", - "version": "1.0.0-rc.2", + "version": "1.0.0-rc.3", "description": "CipherStash Stack Supabase integration: transparent, searchable field-level encryption for Supabase.", "keywords": [ "encrypted", diff --git a/packages/stack/CHANGELOG.md b/packages/stack/CHANGELOG.md index cafcead2..b5cac25f 100644 --- a/packages/stack/CHANGELOG.md +++ b/packages/stack/CHANGELOG.md @@ -1,5 +1,19 @@ # @cipherstash/stack +## 1.0.0-rc.3 + +### Patch Changes + +- 8b2551a: Fix "Failed to load native binding" on project-local installs of the CLI/SDK + (npm). `@cipherstash/auth` was pinned at 0.41.0 while the six + `@cipherstash/auth-*` platform bindings declared in stack/stash/wizard's + optionalDependencies were pinned at 0.42.0. Because auth pins its bindings as + exact-version optional peer dependencies, the skew made npm nest per-consumer + binding copies that the hoisted `auth` package could not resolve — any command + or import touching auth then died at startup. All seven packages now move in + lockstep at 0.42.0, Dependabot is barred from bumping any of them + independently, and a supply-chain CI test fails on any future skew. + ## 1.0.0-rc.2 ### Minor Changes diff --git a/packages/stack/package.json b/packages/stack/package.json index d10cf562..db9a5ffc 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/stack", - "version": "1.0.0-rc.2", + "version": "1.0.0-rc.3", "description": "CipherStash Stack for TypeScript and JavaScript", "keywords": [ "encrypted", diff --git a/packages/test-kit/CHANGELOG.md b/packages/test-kit/CHANGELOG.md index a3863335..afdb8935 100644 --- a/packages/test-kit/CHANGELOG.md +++ b/packages/test-kit/CHANGELOG.md @@ -1,5 +1,12 @@ # @cipherstash/test-kit +## 0.0.1-rc.3 + +### Patch Changes + +- Updated dependencies [8b2551a] + - @cipherstash/stack@1.0.0-rc.3 + ## 0.0.1-rc.2 ### Patch Changes diff --git a/packages/test-kit/package.json b/packages/test-kit/package.json index c0fda059..4679f5b6 100644 --- a/packages/test-kit/package.json +++ b/packages/test-kit/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/test-kit", - "version": "0.0.1-rc.2", + "version": "0.0.1-rc.3", "private": true, "description": "Shared EQL v3 test harness: the domain catalog, the plaintext oracle, and the integration-suite driver. Consumed as TypeScript source — no build step.", "type": "module", diff --git a/packages/wizard/CHANGELOG.md b/packages/wizard/CHANGELOG.md index e1d7dc28..9fa7bc2d 100644 --- a/packages/wizard/CHANGELOG.md +++ b/packages/wizard/CHANGELOG.md @@ -1,5 +1,19 @@ # @cipherstash/wizard +## 1.0.0-rc.3 + +### Patch Changes + +- 8b2551a: Fix "Failed to load native binding" on project-local installs of the CLI/SDK + (npm). `@cipherstash/auth` was pinned at 0.41.0 while the six + `@cipherstash/auth-*` platform bindings declared in stack/stash/wizard's + optionalDependencies were pinned at 0.42.0. Because auth pins its bindings as + exact-version optional peer dependencies, the skew made npm nest per-consumer + binding copies that the hoisted `auth` package could not resolve — any command + or import touching auth then died at startup. All seven packages now move in + lockstep at 0.42.0, Dependabot is barred from bumping any of them + independently, and a supply-chain CI test fails on any future skew. + ## 1.0.0-rc.2 ### Patch Changes diff --git a/packages/wizard/package.json b/packages/wizard/package.json index a44cd945..cbeadfd6 100644 --- a/packages/wizard/package.json +++ b/packages/wizard/package.json @@ -1,6 +1,6 @@ { "name": "@cipherstash/wizard", - "version": "1.0.0-rc.2", + "version": "1.0.0-rc.3", "description": "AI-powered encryption setup for CipherStash. Reads your codebase, picks columns to encrypt, and wires everything up.", "repository": { "type": "git",