Skip to content

Commit 2a140e8

Browse files
committed
fix(eql): re-emit against the published 3.0.5, which kept the old name
The subtree sync brought upstream's actual 3.0.5 release, and it is not the bundle this branch had been carrying under that number. Upstream 142f41d restored `eql_v3.ste_vec_contains` as a deprecated delegating alias — both overloads — and retargeted its own changeset from `major` to `patch` in the same commit. The two decisions are one decision: it is a patch BECAUSE the old name still resolves. This branch had taken the other half of that trade — hard removal, still shipped as a patch — so the tree held SQL stamped 3.0.5 that differed from published 3.0.5 by 32 lines. That is the defect 9b1c44d exists to prevent, one level up, and nothing would have caught it: `verify-release-assets.mjs` compares the manifest's version to package.json and hashes nothing, and `sync-generated.mjs` preserves `src/generated/release-manifest.ts` rather than regenerating it, so `check:generated` is blind to it too. The merge landed on upstream's bytes exactly — every artefact here now hashes to `accde0030…`, the digest in the published tarball — so no regeneration was needed beyond re-emitting the two prisma migrations that bake the bundle. ONLY TWO MIGRATIONS WERE RE-EMITTED, deliberately. All four `migration.ts` files call `readVerifiedInstallSql()`, so re-running the 3.0.2 and 3.0.4 edges would silently bake 3.0.5 SQL into artefacts describing historical releases. Looping over the directory is the obvious thing to do and it is wrong; the frozen-digest test catches it, but only after the damage. The one assertion whose MEANING changed is `not.toContain('ste_vec_contains')`. Re-pinning it would have been wrong in both directions, so it now asserts the SHAPE the alias has to take: exactly two definitions, every body delegating to the new name rather than copying the implementation, and both marked deprecated with `COMMENT ON FUNCTION` so a DBA reading the schema sees it — not only the generated docs. Everything else that moved is prose that had inverted. The upgrade note was the worst of it: `v3.0.5.md` told readers to verify with a query commented "Must return zero rows" against `proname = 'ste_vec_contains'`, which now returns two — a reader following it would conclude the upgrade had failed. The release is now genuinely non-breaking, which leaves U-002 (every EQL install opens `DROP SCHEMA … CASCADE`) as the only item in it with operational consequences.
1 parent 10fca72 commit 2a140e8

14 files changed

Lines changed: 135 additions & 80 deletions

File tree

‎.changeset/eql-3-0-5-migration.md‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,23 @@ are what a PostgREST caller invokes, so PostgREST callers on the documented
1414
surface are **not** affected. The renamed function is the typed implementation
1515
those operators dispatch into.
1616

17-
**What does break is hand-written SQL naming the old function** — an
18-
application query, a view, an RLS policy, or a per-function
19-
`GRANT EXECUTE ON FUNCTION eql_v3.ste_vec_contains(…)`. After the upgrade
20-
those fail loudly (`function eql_v3.ste_vec_contains(…) does not exist`)
21-
rather than silently, but they fail. Grep your migrations, views and policies
22-
for `ste_vec_contains`.
17+
**And the old name still works.** eql-3.0.5 ships `eql_v3.ste_vec_contains` as
18+
a deprecated delegating alias for both overloads, so hand-written SQL naming it
19+
— an application query, a view, an RLS policy, or a per-function
20+
`GRANT EXECUTE ON FUNCTION eql_v3.ste_vec_contains(…)` — keeps resolving. The
21+
typed overload stays inlinable, so a function-form query through the alias
22+
still matches the same functional GIN index. Migrate to
23+
`jsonb_document_contains` when convenient; nothing forces it at upgrade time.
2324

2425
**Separately — and true of every EQL upgrade, not just this one:** the install
2526
bundle opens with `DROP SCHEMA IF EXISTS eql_v3 CASCADE`, so applying it
2627
destroys every grant on every object in `eql_v3` / `eql_v3_internal`, along
2728
with anything that depended on them (this is the same mechanism that drops
2829
functional indexes on encrypted columns). **Re-run your grant script after
2930
upgrading.** The schema-wide form EQL documents —
30-
`GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA eql_v3 TO app_role` — picks the new
31-
name up on its own; a hand-written per-function grant has to be edited first.
31+
`GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA eql_v3 TO app_role` — picks up both
32+
the new name and the alias on its own. **With the rename made non-breaking by
33+
the alias, this is the only part of the upgrade that needs action.**
3234

3335
Two artefacts carry the new bundle:
3436

‎examples/prisma/migrations/cipherstash/20260601T0100_install_eql_v3_bundle/migration.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"cipherstash:upgrade-eql-v3-bundle-3.0.5-v1"
99
],
1010
"createdAt": "2026-07-14T20:10:24.325Z",
11-
"migrationHash": "sha256:1ae732828e9a6fb3574ab8dbede16e99bf1173bd4e5cd7a4b522138e71bc5d05"
11+
"migrationHash": "sha256:23c98b0368d22794507a4ef7b02ed4cb04249f36bfcb0b20488005aa62488313"
1212
}

‎examples/prisma/migrations/cipherstash/20260601T0100_install_eql_v3_bundle/ops.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎examples/prisma/migrations/cipherstash/20260814T0000_upgrade_eql_v3_3_0_5/migration.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"cipherstash:upgrade-eql-v3-bundle-3.0.5-v1"
66
],
77
"createdAt": "2026-08-14T00:45:14.365Z",
8-
"migrationHash": "sha256:7bafd9d6c5d244332ff0b0943604dbd026c8369e24d2f335b1365c5f78e49d38"
8+
"migrationHash": "sha256:3b2b838bee634f2de4a5e88f1625a45d47c327e3021b0e2ccba36c09a9666178"
99
}

‎examples/prisma/migrations/cipherstash/20260814T0000_upgrade_eql_v3_3_0_5/ops.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎packages/eql/docs/upgrading/v3.0.5.md‎

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Upgrading to EQL 3.0.5
22

3-
`3.0.5` is a patch release carrying one rename in the public `eql_v3` surface.
4-
It is a patch, not a major, for the reason 3.0.1 was: a patch reaches every
5-
consumer already on a `^3.x` range at their next install, and the affected
6-
call site is one that almost nobody writes by hand.
3+
`3.0.5` is a patch release carrying one rename in the public `eql_v3` surface,
4+
with the old name retained as a deprecated alias. **Nothing in it requires you
5+
to change any SQL.** It is a patch, not a major, for the reason 3.0.1 was: a
6+
patch reaches every consumer already on a `^3.x` range at their next install —
7+
and with the alias in place there is no compatibility argument left to have.
78

89
This guide also records a second thing, which is **not** new in 3.0.5 but bites
910
hardest at upgrade time and has never had a note of its own: applying the EQL
@@ -12,8 +13,9 @@ survive it.
1213

1314
## TL;DR
1415

15-
1. `eql_v3.ste_vec_contains` is renamed to `eql_v3.jsonb_document_contains` —
16-
[U-001](#u-001-the-containment-implementation-is-renamed).
16+
1. `eql_v3.ste_vec_contains` is renamed to `eql_v3.jsonb_document_contains`.
17+
The old name still works — it is now a deprecated alias. Migrate at your
18+
convenience — [U-001](#u-001-the-containment-implementation-is-renamed).
1719
2. Applying any EQL bundle destroys grants, indexes and dependent objects in
1820
`eql_v3` / `eql_v3_internal`; re-apply them afterwards —
1921
[U-002](#u-002-grants-and-dependent-objects-do-not-survive-an-install).
@@ -24,7 +26,7 @@ survive it.
2426
| --- | --- |
2527
| `@>` / `<@` on `public.eql_v3_json_search` | **Unchanged.** Same operators, same results, same index behaviour. |
2628
| `eql_v3.jsonb_contains(jsonb, jsonb)` / `eql_v3.jsonb_contained_by(jsonb, jsonb)` | **Unchanged**, byte for byte. These are the function-form entry points for platforms without operator support — PostgREST included — and they are not affected by this release. |
27-
| `eql_v3.ste_vec_contains` | **Renamed** to `eql_v3.jsonb_document_contains` (both overloads) — see U-001. |
29+
| `eql_v3.ste_vec_contains` | **Renamed** to `eql_v3.jsonb_document_contains` (both overloads), with the old name kept as a deprecated delegating alias — existing callers keep working. See U-001. |
2830
| `eql_v3.to_ste_vec_query`, `eql_v3.ste_vec`, `eql_v3.jsonb_array` | **Unchanged.** The documented GIN index recipe still reads `USING gin ((eql_v3.to_ste_vec_query(col)::jsonb) jsonb_path_ops)`. |
2931
| Wire format, domains, index terms | **Unchanged.** No re-encryption, no data migration. |
3032

@@ -36,34 +38,35 @@ survive it.
3638
`eql_v3.jsonb_document_contains`, in both overloads —
3739
`(jsonb[], jsonb)` and
3840
`(public.eql_v3_json_search, public.eql_v3_json_search)`. The body is
39-
unchanged. The old name is **removed**; there is no compatibility alias.
41+
unchanged. **The old name is retained** as a deprecated alias for both
42+
overloads, each delegating to the new one — so this release breaks no caller.
4043

4144
**Why.** It was the last object in the public surface still carrying
4245
`ste_vec_` naming, after the SteVec entry and query surface became
4346
`jsonb_entry` / `jsonb_query`. `ste_vec` is an implementation detail of the
4447
encrypted representation; the operator family it backs is the `jsonb_*` one.
4548

46-
**Who is affected.** Only SQL that names the function directly. In particular
47-
this is **not** the PostgREST story it might look like: PostgREST calls
48-
functions rather than operators, but the function-form containment entry points
49-
it calls are `eql_v3.jsonb_contains` and `eql_v3.jsonb_contained_by`, and both
50-
are unchanged. `jsonb_document_contains` is what the typed `@>` / `<@`
51-
operators dispatch into.
49+
**Who is affected.** Nobody is forced to act. In particular this is **not** the
50+
PostgREST story it might look like: PostgREST calls functions rather than
51+
operators, but the function-form containment entry points it calls are
52+
`eql_v3.jsonb_contains` and `eql_v3.jsonb_contained_by`, and both are unchanged.
53+
`jsonb_document_contains` is what the typed `@>` / `<@` operators dispatch into.
5254

53-
So the affected callers are hand-written:
55+
SQL that names the old function directly — application queries, views and
56+
matviews, RLS `USING` / `WITH CHECK` expressions, wrapping functions and
57+
triggers, and per-function `GRANT EXECUTE ON FUNCTION
58+
eql_v3.ste_vec_contains(…)` — all keep resolving, through the alias.
5459

55-
- application queries, views or matviews naming `eql_v3.ste_vec_contains`
56-
- RLS policies whose `USING` / `WITH CHECK` expression names it
57-
- SQL functions or triggers that wrap it
58-
- a per-function grant, `GRANT EXECUTE ON FUNCTION eql_v3.ste_vec_contains(…)`
60+
The typed overload is deliberately `LANGUAGE sql` and stays inlinable, so a
61+
function-form query through the alias still matches the same functional GIN
62+
index it did before the rename. There is no performance cliff for not
63+
migrating.
5964

60-
**What to do.** Grep your migrations, policies and application SQL for
61-
`ste_vec_contains` and replace it with `jsonb_document_contains`. Nothing else
62-
changes — same arguments, same return, same semantics. The failure is loud
63-
(`function eql_v3.ste_vec_contains(…) does not exist`), so an unfixed caller
64-
errors rather than silently returning the wrong rows; a view or policy is the
65-
case to check first, because the error surfaces at query time rather than at
66-
upgrade time.
65+
**What to do.** Nothing, to upgrade. When convenient, grep your migrations,
66+
policies and application SQL for `ste_vec_contains` and replace it with
67+
`jsonb_document_contains` — same arguments, same return, same semantics. The
68+
alias is marked deprecated in the database itself (`COMMENT ON FUNCTION`), so
69+
`\df+ eql_v3.ste_vec_contains` tells a DBA what to move to.
6770

6871
**Verification.**
6972

@@ -73,8 +76,8 @@ SELECT p.oid::regprocedure
7376
FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
7477
WHERE n.nspname = 'eql_v3' AND p.proname = 'jsonb_document_contains';
7578

76-
-- Must return zero rows:
77-
SELECT p.oid::regprocedure
79+
-- Must ALSO return two rows — the deprecated aliases, which 3.0.5 keeps:
80+
SELECT p.oid::regprocedure, obj_description(p.oid, 'pg_proc') AS note
7881
FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
7982
WHERE n.nspname = 'eql_v3' AND p.proname = 'ste_vec_contains';
8083

@@ -147,11 +150,14 @@ WHERE indexdef LIKE '%eql_v3.%_term%' OR indexdef LIKE '%to_ste_vec_query%';
147150

148151
## Rollback
149152

150-
U-001 is reversible by installing the 3.0.4 bundle, which restores the old
151-
function name. Nothing in the wire format or the stored data changes between
152-
3.0.4 and 3.0.5, so no re-encryption is involved in either direction — but note
153-
that rolling back re-runs the `DROP SCHEMA … CASCADE` in U-002, so grants and
154-
indexes need re-applying again afterwards.
153+
U-001 needs no rollback: 3.0.5 adds a name and keeps the old one, so anything
154+
that worked on 3.0.4 works on 3.0.5. Installing the 3.0.4 bundle does reverse
155+
it, and is the only way to remove `jsonb_document_contains` — but the reason to
156+
do so would have to come from somewhere other than this rename. Nothing in the
157+
wire format or the stored data changes between 3.0.4 and 3.0.5, so no
158+
re-encryption is involved in either direction — but note that rolling back
159+
re-runs the `DROP SCHEMA … CASCADE` in U-002, so grants and indexes need
160+
re-applying again afterwards.
155161

156162
## See also
157163

‎packages/eql/packages/eql/CHANGELOG.md‎

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,28 @@
1010
`jsonb_query`). The function backs the `json` `@>` / `<@` containment operators;
1111
its behaviour is unchanged.
1212

13-
**Who is affected is narrower than a rename usually implies.** The operators are
14-
untouched, and so are the two function-form entry points a PostgREST deployment
15-
actually calls — `eql_v3.jsonb_contains(jsonb, jsonb)` and
16-
`eql_v3.jsonb_contained_by(jsonb, jsonb)` are byte-identical to 3.0.4. What
17-
breaks is hand-written SQL that names `ste_vec_contains` directly: queries,
18-
views, RLS policies, and per-function `GRANT`s. The schema-wide grant scripts in
19-
`docs/reference/permissions.md` pick the new name up on their next run, and a
20-
stale per-function grant fails loudly (`function … does not exist`) rather than
21-
silently granting nothing. See [U-001](../../docs/upgrading/v3.0.5.md#u-001-the-containment-implementation-is-renamed),
22-
and [U-002](../../docs/upgrading/v3.0.5.md#u-002-grants-and-dependent-objects-do-not-survive-an-install)
23-
for the larger fact underneath it — the installer opens with
24-
`DROP SCHEMA IF EXISTS eql_v3 CASCADE`, so *every* EQL install drops grants,
25-
functional indexes and dependent views, not just this one.
13+
**Nothing breaks.** The old name remains as a deprecated delegating alias, both
14+
overloads, so direct callers keep working. The operators never moved, and
15+
neither did the two function-form entry points a PostgREST deployment actually
16+
calls — `eql_v3.jsonb_contains(jsonb, jsonb)` and
17+
`eql_v3.jsonb_contained_by(jsonb, jsonb)` are byte-identical to 3.0.4. Hand-written
18+
SQL naming `ste_vec_contains` — queries, views, RLS policies, per-function
19+
`GRANT`s — continues to resolve; update it at your convenience, not under
20+
pressure. See [U-001](../../docs/upgrading/v3.0.5.md#u-001-the-containment-implementation-is-renamed).
21+
22+
**The thing in this release that does have consequences is not the rename.**
23+
The installer opens with `DROP SCHEMA IF EXISTS eql_v3 CASCADE`, so *every* EQL
24+
install drops grants, functional indexes and dependent views — true of every
25+
release, not just this one, and now the only item here with operational weight.
26+
See [U-002](../../docs/upgrading/v3.0.5.md#u-002-grants-and-dependent-objects-do-not-survive-an-install).
2627

2728
Released as a **patch**, matching 3.0.1, which shipped the fuzzy-match operator
2829
change (`@>` / `<@` → `@@`) at the same level. The parked changeset proposed
2930
`major`; a patch reaches every consumer already on a `^3.x` range at their next
30-
install, which a major would not have done.
31+
install, which a major would not have done — and with the alias in place the
32+
patch level is not a judgement call at all. Upstream reached the same
33+
conclusion independently, retargeting its own changeset from `major` to `patch`
34+
in the commit that restored the aliases.
3135

3236
Entered by hand rather than by `changeset version`. The rename landed in the
3337
tree with the monorepo import and was never released, so the package shipped
@@ -37,6 +41,14 @@
3741
the whole repository. The bump is therefore applied directly and
3842
`.changeset/rename-ste-vec-contains.md.deferred` is deleted with it, so the
3943
cutover cannot apply the same bump a second time.
44+
45+
The SQL that actually shipped is upstream's, not this tree's: `@cipherstash/eql@3.0.5`
46+
was published from `cipherstash/encrypt-query-language` (the last release from
47+
there) and carries the restored aliases from upstream `142f41d8`, which this
48+
tree did not have when the entry above was first written. The subtree was
49+
re-synced to that release so the bundle here is byte-identical to the published
50+
one — `installSqlSha256: accde0030…`. The generated entry below is upstream's
51+
own changeset for the same release.
4052
- 4c2bb92: **`eql_v3.ste_vec_contains` is renamed to `eql_v3.jsonb_document_contains`.** This
4153
consolidates the last `ste_vec_*`-named public object into the `jsonb_*` family,
4254
matching the earlier renames of the SteVec entry/query surface (`jsonb_entry`,

‎packages/stack-prisma/migrations/20260601T0100_install_eql_v3_bundle/migration.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"cipherstash:upgrade-eql-v3-bundle-3.0.5-v1"
99
],
1010
"createdAt": "2026-07-14T20:10:24.325Z",
11-
"migrationHash": "sha256:1ae732828e9a6fb3574ab8dbede16e99bf1173bd4e5cd7a4b522138e71bc5d05"
11+
"migrationHash": "sha256:23c98b0368d22794507a4ef7b02ed4cb04249f36bfcb0b20488005aa62488313"
1212
}

‎packages/stack-prisma/migrations/20260601T0100_install_eql_v3_bundle/ops.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎packages/stack-prisma/migrations/20260814T0000_upgrade_eql_v3_3_0_5/migration.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"cipherstash:upgrade-eql-v3-bundle-3.0.5-v1"
66
],
77
"createdAt": "2026-08-14T00:45:14.365Z",
8-
"migrationHash": "sha256:7bafd9d6c5d244332ff0b0943604dbd026c8369e24d2f335b1365c5f78e49d38"
8+
"migrationHash": "sha256:3b2b838bee634f2de4a5e88f1625a45d47c327e3021b0e2ccba36c09a9666178"
99
}

0 commit comments

Comments
 (0)