Skip to content

Commit aa581b9

Browse files
Version Packages (rc)
1 parent a2f80ea commit aa581b9

25 files changed

Lines changed: 513 additions & 14 deletions

.changeset/pre.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
"changesets": [
2424
"adapter-package-split",
2525
"adapter-split-skills",
26+
"auth-binding-lockstep",
2627
"cli-anonymous-telemetry",
2728
"cli-eql-v3-single-bundle",
29+
"drizzle-kit-eql-v3-ddl",
30+
"eql-migration-command",
2831
"eql-v3-adapter-type-robustness",
2932
"eql-v3-bigint-domains",
3033
"eql-v3-bundle-from-package",
@@ -37,16 +40,24 @@
3740
"eql-v3-json-selector",
3841
"eql-v3-json-skills",
3942
"eql-v3-json",
43+
"eql-v3-prisma-next",
4044
"eql-v3-public-domains",
4145
"eql-v3-rename-contains-to-matches",
4246
"eql-v3-sole-docs",
47+
"eql-v3-source-from-package",
4348
"eql-v3-supabase-adapter",
4449
"eql-v3-text-search",
4550
"eql-v3-typed-client",
4651
"eql-v3-typed-schema",
4752
"eql-v3-wasm-inline",
53+
"honest-noninteractive-init",
4854
"init-pins-runtime-versions",
55+
"migrate-eql-v3",
56+
"plan-complete-rollout-yes",
57+
"prisma-example-eql-v3",
4958
"prisma-next-0-14",
59+
"prisma-next-drop-encrypted-prefix",
60+
"prisma-next-eql-runtime-source",
5061
"prisma-next-joins-release-train",
5162
"release-train-coupling",
5263
"remove-legacy-drizzle-package",
@@ -59,6 +70,8 @@
5970
"stash-cli-eql-v3-default",
6071
"stash-cli-skill-refresh",
6172
"stash-drizzle-skill-encrypt-query",
73+
"stash-env-mint-credentials",
74+
"stash-prisma-next-skill",
6275
"stash-skills-contains-to-matches",
6376
"stash-supabase-contains-substrings",
6477
"supabase-encryption-error",

e2e/CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# @cipherstash/e2e
22

3+
## 0.0.3-rc.3
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [8b2551a]
8+
- Updated dependencies [b8cb599]
9+
- Updated dependencies [0811330]
10+
- Updated dependencies [175eeb7]
11+
- Updated dependencies [d20e48a]
12+
- Updated dependencies [3a86939]
13+
- Updated dependencies [b0634df]
14+
- Updated dependencies [4923c0a]
15+
- Updated dependencies [f188c7a]
16+
- Updated dependencies [8872d1e]
17+
- @cipherstash/stack@1.0.0-rc.3
18+
- stash@1.0.0-rc.3
19+
- @cipherstash/wizard@1.0.0-rc.3
20+
321
## 0.0.3-rc.2
422

523
### Patch Changes

e2e/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cipherstash/e2e",
3-
"version": "0.0.3-rc.2",
3+
"version": "0.0.3-rc.3",
44
"private": true,
55
"description": "End-to-end tests that exercise built CipherStash binaries and cross-package behaviour.",
66
"type": "module",

examples/basic/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# @cipherstash/basic-example
22

3+
## 1.2.14-rc.3
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [8b2551a]
8+
- Updated dependencies [b8cb599]
9+
- @cipherstash/stack@1.0.0-rc.3
10+
- @cipherstash/stack-drizzle@1.0.0-rc.3
11+
- @cipherstash/stack-supabase@1.0.0-rc.3
12+
313
## 1.2.14-rc.2
414

515
### Patch Changes

examples/basic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@cipherstash/basic-example",
33
"private": true,
4-
"version": "1.2.14-rc.2",
4+
"version": "1.2.14-rc.3",
55
"type": "module",
66
"scripts": {
77
"start": "tsx index.ts"

examples/prisma/CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# @cipherstash/prisma-next-example
22

3+
## 0.1.0-rc.3
4+
5+
### Minor Changes
6+
7+
- 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).
8+
9+
### Patch Changes
10+
11+
- Updated dependencies [8b2551a]
12+
- Updated dependencies [a75513b]
13+
- Updated dependencies [4923c0a]
14+
- Updated dependencies [a2f80ea]
15+
- @cipherstash/stack@1.0.0-rc.3
16+
- @cipherstash/prisma-next@1.0.0-rc.3
17+
318
## 0.0.6-rc.2
419

520
### Patch Changes

examples/prisma/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@cipherstash/prisma-next-example",
33
"private": true,
4-
"version": "0.0.6-rc.2",
4+
"version": "0.1.0-rc.3",
55
"description": "End-to-end example of @cipherstash/prisma-next: searchable application-layer encryption for Postgres with Prisma Next, using @cipherstash/stack as the SDK.",
66
"type": "module",
77
"scripts": {

packages/bench/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# @cipherstash/bench
22

3+
## 0.0.5-rc.3
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [8b2551a]
8+
- Updated dependencies [b8cb599]
9+
- @cipherstash/stack@1.0.0-rc.3
10+
- @cipherstash/stack-drizzle@1.0.0-rc.3
11+
312
## 0.0.5-rc.2
413

514
### Patch Changes

packages/bench/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cipherstash/bench",
3-
"version": "0.0.5-rc.2",
3+
"version": "0.0.5-rc.3",
44
"private": true,
55
"description": "Performance / index-engagement benchmarks for stack integrations (Drizzle, encryptedSupabase, Prisma).",
66
"type": "module",

packages/cli/CHANGELOG.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,235 @@
11
# @cipherstash/cli
22

3+
## 1.0.0-rc.3
4+
5+
### Minor Changes
6+
7+
- 0811330: Add `stash eql migration` — generate an EQL **v3** install migration for your ORM
8+
instead of running the SQL directly against the database (`stash eql install`).
9+
Migration-first is the preferred path: the install lands in your migration history
10+
and ships to every environment through the ORM's own migrate step.
11+
12+
```bash
13+
stash eql migration --drizzle # Drizzle custom migration
14+
stash eql migration --drizzle --supabase # also grants eql_v3 to anon/authenticated/service_role
15+
```
16+
17+
The migration carries the CLI's bundled v3 install SQL (one source of truth) plus
18+
the `cs_migrations` tracking schema, so a single `drizzle-kit migrate` covers
19+
everything `stash encrypt …` needs. `--supabase` appends the `eql_v3` +
20+
`eql_v3_internal` role grants for PostgREST/RLS access.
21+
22+
`--prisma` is registered but not available yet — the Prisma Next migration
23+
emitter is a follow-up (tracked in cipherstash/stack#690) that will let
24+
prisma-next drop its baked install baseline. It fails with a pointer for now.
25+
26+
- d20e48a: `stash init` is honest non-interactively — it no longer reports success for a
27+
setup that didn't fully complete.
28+
29+
- **Fails on version skew.** A non-interactive run can't reconcile an
30+
already-installed `@cipherstash/*` package that's _older_ than this CLI
31+
expects (it won't mutate an install without consent), so instead of warning
32+
and proceeding — scaffolding against mismatched packages and then claiming
33+
success — it now refuses with a non-zero exit and the exact align command.
34+
Interactive runs still offer to align. A _newer_ install stays a warn (the
35+
install is likely fine; update the CLI instead).
36+
- **No false "Setup complete".** If the EQL extension isn't installed at the
37+
end — and the integration isn't one that installs it out-of-band — the
38+
summary reads "Setup incomplete" and init exits non-zero, pointing at
39+
`stash eql install`. Integrations that install EQL via a migration are
40+
reported honestly rather than as failures: Prisma Next (installs it via
41+
`migration apply`) and the Drizzle flow, which _generates_ an EQL migration
42+
and now says "EQL migration generated — apply it with `drizzle-kit migrate`"
43+
instead of claiming the extension is already installed.
44+
- **Honest checkmarks.** The summary no longer claims "Database connection
45+
verified" (init resolves a URL but doesn't open a connection) — it now says
46+
"Database URL resolved" — and only shows "Encryption client scaffolded" when
47+
a client was actually written (skipped for Prisma Next).
48+
- **No false "skills loaded".** The agent handoff prompt only points at the
49+
skills directory when skills were actually copied (a stripped build installs
50+
none), instead of telling the agent to read files that aren't there.
51+
52+
- 3a86939: EQL v3 support for the encryption rollout lifecycle (#648). The `stash
53+
encrypt *` commands (and `@cipherstash/migrate` underneath) now resolve a
54+
column's EQL version and its encrypted counterpart from the **Postgres domain
55+
types** — the EQL v3 types are self-describing, so the `<col>_encrypted`
56+
naming is a convention only, never enforced or relied upon — and follow the
57+
right lifecycle, no new flags:
58+
59+
- **`encrypt backfill`** works on v3 columns unchanged (the engine was always
60+
version-agnostic; pass an `EncryptionV3` client and real v3 envelopes land
61+
in the concrete `eql_v3_*` domain column — verified live against a real
62+
database, including the domain CHECK and a decrypt round-trip). The
63+
manifest records the detected version, the encrypted column's name, and the
64+
v3 target phase, and the command prints v3-appropriate next steps.
65+
- **`encrypt cutover`** on a backfilled v3 column reports "not applicable"
66+
(exit 0) with guidance: v3 has no rename cut-over — the application
67+
switches to the encrypted column by name. Before backfill completes it
68+
exits 1 and says to finish the backfill instead of instructing the switch.
69+
On a database with no `eql_v2_configuration` table (a v3-only install) the
70+
v2 path now explains that instead of surfacing a raw Postgres error.
71+
- **`encrypt drop`** is version-aware: v3 runs from the `backfilled` phase,
72+
**verifies live coverage** (refuses to generate the migration while any row
73+
still has the plaintext set and the encrypted column NULL — the
74+
`countUnencrypted` check), and drops the ORIGINAL plaintext column (there
75+
is no `<col>_plaintext` under v3); v2 behaviour is unchanged. The generated
76+
v3 migration **re-verifies coverage at apply time** — it locks the table,
77+
re-counts, and aborts without dropping if plaintext-only rows appeared
78+
after generation. And because dropping is the one irreversible step, it
79+
requires a positively asserted plaintext↔ciphertext pairing (the
80+
manifest's recorded `encryptedColumn` or the naming convention): a match
81+
found only by being the table's sole EQL column is refused with
82+
instructions, and an ambiguous table (several EQL columns, none
83+
identifiable) fails closed listing the candidates — as does `cutover`.
84+
- **`encrypt status`** classifies each column from the observed domain type
85+
(manifest as fallback), shows `v3` in the EQL column, and no longer raises
86+
the v2-only `not-registered` / `plaintext-col-missing` drift flags for v3
87+
columns. `stash status`'s quest ladder and the `stash init` agent handoff
88+
prompt teach the version-appropriate next step (no more "run cutover" on
89+
v3 columns).
90+
- New `@cipherstash/migrate` exports: `classifyEqlDomain`,
91+
`resolveEncryptedColumn`, `pickEncryptedColumn`, `listEncryptedColumns`
92+
(domain-type resolution — case-exact for quoted/mixed-case table names),
93+
`countEncrypted` / `countUnencrypted` (coverage counts), and manifest
94+
`eqlVersion` + `encryptedColumn` fields. `EqlVersion` is numeric (`2 | 3`),
95+
matching the manifest and the installer. Resolved columns carry `via:
96+
'hint' | 'convention' | 'sole'` so callers can tell a positively asserted
97+
pairing from a by-elimination guess.
98+
- Fixed: `encrypt cutover`/`encrypt drop` precondition failures now actually
99+
exit 1 — the early-return guards previously skipped the exit-code path
100+
entirely, so failed preconditions exited 0. (This also applies to v2
101+
preconditions: scripted pipelines that relied on the erroneous exit 0 will
102+
now see the documented exit 1.)
103+
104+
The `stash-cli` and `stash-encryption` skills and the `@cipherstash/migrate`
105+
README document the two lifecycles (v2: backfill → cutover → drop;
106+
v3: backfill → switch-by-name → drop).
107+
108+
- b0634df: `stash plan --complete-rollout` is now automatable and has an honest exit code.
109+
It skips the production-deploy gate, so it needs explicit consent — previously
110+
that was an interactive prompt with no bypass, so a non-interactive run
111+
auto-cancelled (default-no) and exited **0** without drafting a plan, leaving
112+
automation to assume a plan existed.
113+
114+
- New `--yes` flag confirms the gate-skip without a prompt (for CI/agents).
115+
- Without `--yes`, a non-interactive `--complete-rollout` run now **refuses
116+
with a non-zero exit** and points at `--yes`, instead of silently succeeding.
117+
- Interactive behaviour is unchanged (default-no confirm).
118+
119+
- f188c7a: `stash env` now works: it mints deployment credentials from your device-code
120+
session and prints them as env vars — no dashboard copy-paste. The command
121+
creates a fresh ZeroKMS client and a member-role CipherStash access key (named
122+
via `--name`; the role is pinned in the request and verified on the response —
123+
the CLI deliberately cannot mint admin keys), then emits `CS_WORKSPACE_CRN`,
124+
`CS_CLIENT_ID`, `CS_CLIENT_KEY`, and `CS_CLIENT_ACCESS_KEY`.
125+
126+
Output goes to stdout by default — and stdout is pipe-clean (progress UI is on
127+
stderr), so `stash env --name x > prod.env` and pipes into secret stores are
128+
safe. `--write [path]` writes a file instead (default `.env.production.local`,
129+
enforced mode 0600 even when overwriting), confirming before overwriting and
130+
refusing non-interactively — always _before_ anything is minted, so a refusal
131+
never discards the shown-exactly-once access key. `--json` emits NDJSON; with
132+
`--write` the confirmation event is deliberately secret-free. API responses
133+
are schema-validated so a service change can never print `undefined` into a
134+
credentials file. Creating access keys requires the admin role in the
135+
workspace.
136+
137+
This is also the supported credential path for WASM/edge local development
138+
(Supabase Edge Functions, Cloudflare Workers, Deno), where the runtime cannot
139+
read the `~/.cipherstash` device profile: mint a key and feed it via
140+
`supabase functions serve --env-file` or the platform's secret store.
141+
142+
The `STASH_EXPERIMENTAL_ENV_CMD` gate is removed.
143+
144+
- 8872d1e: `stash init`, `stash plan`, and `stash impl` no longer crash on a Prisma Next
145+
project. `SKILL_MAP` was missing a `prisma-next` entry, so the skills-install
146+
and AGENTS.md-builder steps hit `SKILL_MAP[integration]``undefined` and threw
147+
"not iterable" for any repo the CLI detected as Prisma Next. The entry is added
148+
and both consumers now resolve skills through a `skillsFor()` helper that
149+
degrades an unmapped integration to the base skill set instead of crashing
150+
(`tsup` ships without type-checking, so the `Record<Integration>` type alone
151+
didn't protect the build).
152+
153+
Ships a new **`stash-prisma-next`** agent skill documenting the EQL v3 Prisma
154+
Next surface — the domain-named encrypted column types (`EncryptedTextSearch`,
155+
`EncryptedDoubleOrd`, …), `cipherstashFromStackV3` wiring, the runtime value
156+
envelopes, the `eql*` query operators, and EQL installation via
157+
`prisma-next migration apply`. It is installed for Prisma Next projects and
158+
inlined into `AGENTS.md` for editor agents.
159+
160+
`stash eql install` now refuses to run in a Prisma Next project (pointing you
161+
at `prisma-next migration apply`, which owns EQL installation) unless you pass
162+
`--force` — closing the manual-invocation hole that `stash init --prisma-next`
163+
already avoided.
164+
165+
### Patch Changes
166+
167+
- 8b2551a: Fix "Failed to load native binding" on project-local installs of the CLI/SDK
168+
(npm). `@cipherstash/auth` was pinned at 0.41.0 while the six
169+
`@cipherstash/auth-*` platform bindings declared in stack/stash/wizard's
170+
optionalDependencies were pinned at 0.42.0. Because auth pins its bindings as
171+
exact-version optional peer dependencies, the skew made npm nest per-consumer
172+
binding copies that the hoisted `auth` package could not resolve — any command
173+
or import touching auth then died at startup. All seven packages now move in
174+
lockstep at 0.42.0, Dependabot is barred from bumping any of them
175+
independently, and a supply-chain CI test fails on any future skew.
176+
- b8cb599: Fix invalid DDL from `drizzle-kit generate`/`push` for EQL v3 encrypted columns.
177+
A v3 column declared its SQL type as the schema-qualified domain
178+
(`public.eql_v3_text_search`), but drizzle-kit wraps a custom type's whole name
179+
in a single pair of double quotes — emitting `"public.eql_v3_text_search"`, which
180+
Postgres reads as one dotted identifier and rejects with `type
181+
"public.eql_v3_text_search" does not exist`. Generated migrations had to be
182+
hand-repaired.
183+
184+
The v3 column now emits the **unqualified** domain (`eql_v3_text_search`), which
185+
drizzle-kit renders as the valid `"eql_v3_text_search"` and which resolves via the
186+
search path (the domains live in `public`). This matches how the v2
187+
`encryptedType` surface already declares its type, and how drizzle-kit reads the
188+
type back during a `push` introspection diff, so the two sides no longer disagree.
189+
Builder recovery still yields the canonical `public.eql_v3_*` identity, so
190+
operators and schema extraction are unchanged.
191+
192+
The bundled `stash-drizzle` skill is updated to describe the unqualified generated
193+
type and the search-path requirement (hence the `stash` bump — the skill ships in
194+
its tarball).
195+
196+
- 175eeb7: The EQL **v3** install SQL is now read from the `@cipherstash/eql` package at
197+
runtime instead of a copy vendored into this repo. `@cipherstash/eql` becomes a
198+
runtime dependency of `stash`, and a version bump now flows straight through — no
199+
re-vendor step, no drift between the pin and the shipped bundle.
200+
201+
This removes ~44k lines of generated plpgsql from the repository (which had made
202+
GitHub classify the whole repo as plpgsql — CIP-3518) along with the
203+
`gen:eql-v3-sql` vendor script and its CI drift-check.
204+
205+
No behaviour change: v3 installs the same one-artifact bundle (which self-adapts to
206+
non-superuser environments like Supabase), and the v2 path is unchanged.
207+
208+
- 4923c0a: **Breaking (v3 authoring surface):** the EQL v3 PSL column constructors drop
209+
the `Encrypted` prefix to line up with the stack / Drizzle `types.*` catalog —
210+
the `cipherstash.` namespace already disambiguates. So
211+
`cipherstash.EncryptedTextSearch()``cipherstash.TextSearch()`,
212+
`cipherstash.EncryptedDoubleOrd()``cipherstash.DoubleOrd()`,
213+
`cipherstash.EncryptedBoolean()``cipherstash.Boolean()`, etc.
214+
215+
The v3 one-call setup function is renamed `cipherstashFromStackV3`
216+
`cipherstashFromStack` (v3 is the default), and the existing v2 setup function
217+
becomes `cipherstashFromStackV2`.
218+
219+
The camelCase TS-authoring factory exports move in lockstep:
220+
`encryptedTextSearch``textSearch`, `encryptedDoubleOrd``doubleOrd`, etc.
221+
(a property test enforces the PSL and TS names agree modulo first-letter case).
222+
223+
Unchanged: the runtime value envelopes (`EncryptedString`, `EncryptedNumber`,
224+
`EncryptedBoolean`, …), the `cipherstash.*V2` legacy column constructors, the
225+
generated `contract.json` / codec ids, and the `eql*` query operators.
226+
227+
The `stash-prisma-next` skill is updated to the new names (skills ship in the
228+
`stash` tarball).
229+
230+
- Updated dependencies [3a86939]
231+
- @cipherstash/migrate@1.0.0-rc.1
232+
3233
## 1.0.0-rc.2
4234

5235
### Patch Changes

0 commit comments

Comments
 (0)