Skip to content

chore(stack): source EQL v3 bundle from @cipherstash/eql#590

Merged
tobyhede merged 2 commits into
feat/eql-v3-text-search-schemafrom
use-cipherstash-eql
Jul 9, 2026
Merged

chore(stack): source EQL v3 bundle from @cipherstash/eql#590
tobyhede merged 2 commits into
feat/eql-v3-text-search-schemafrom
use-cipherstash-eql

Conversation

@tobyhede

@tobyhede tobyhede commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Replaces the hand-vendored EQL v3 SQL bundle with the published @cipherstash/eql package.

packages/stack installed EQL v3 from a 43,339-line SQL bundle committed to the test tree, hand-vendored in 63ca540 with no generator script and no recorded provenance. Nothing tied it to a released EQL version, and nothing detected drift from the protect-ffi payload format it has to match. Its eql_v3.version() returns DEV — it was never a release.

@cipherstash/eql publishes the SQL bundle and the TypeScript wire types from the same eql-bindings commit, so one pinned version supplies both. This PR reads the bundle via readInstallSql() and deletes the fixture.

The load-bearing change: the staleness sentinel

hasCurrentEqlV3() gated reinstall on to_regtype('public.timestamp') — a hand-picked type meant to exist only in the newest bundle. That domain exists in the released bundle too. Swapping the source without touching the sentinel would have reported a stale install as current, skipped the install, and left the suite silently exercising the old SQL while appearing green.

It now compares eql_v3.version() against releaseManifest.eqlVersion. That carries the release identity, so it needs no maintenance when the pin moves. to_regprocedure() yields NULL rather than raising, so an empty database (or one predating eql_v3.version()) reads as stale and gets installed.

Every hand-picked sentinel decays this way — the previous one, public.text_search, had already been replaced for exactly the same reason.

The domain rename is a non-event

The published bundle renames query-operand domains from public.<type>_query to eql_v3.query_<type>. Nothing in this repo referenced those names. Verified against a live database after installing alpha.3:

  • 0 functions accept public.*_query
  • 425 functions accept eql_v3.query_*
  • protect-ffi@0.28.0 operands round-trip unchanged through eq / contains / gte / lte / ORE

Function names are identical across both bundles (1,758 each); only operand signatures moved.

Verification

Run against a pristine ghcr.io/cipherstash/postgres-eql:17-2.3.1 container (fresh volume, so initdb actually seeds EQL):

  • Full packages/stack suite: 1,055 passed, 0 failed across 48 files — including v3-matrix/matrix-live-pg.test.ts (57 tests, the ORE ordering matrix), which had never been exercised against a released bundle.
  • Sentinel proven: a database on the stale DEV bundle is detected and reinstalled to 3.0.0-alpha.3; a second run is idempotent.
  • Skip-gate intact: env -u DATABASE_URL → suite SKIPPED, 0 failures.
  • pnpm build, pnpm test:types (60 tests), biome check clean.
  • npm pack --dry-run ships no __tests__, no SQL, and no new runtime dependency.

Review notes

Two things deserve a second pair of eyes:

  1. pnpm-workspace.yaml gains a minimumReleaseAgeExclude entry. alpha.3 is days old and the repo's 7-day supply-chain cooldown blocked the install outright. @cipherstash/eql is first-party and released in lockstep with protect-ffi, which is already excluded — so this matches the list's documented intent ("first-party packages we publish or integrate against directly"). It is still a security-relevant setting change.

  2. @cipherstash/eql is a devDependency, exact-pinned to 3.0.0-alpha.3. Nothing in src/ imports it, and files already excludes __tests__. No range — an alpha SQL bundle that opens with DROP SCHEMA … CASCADE must never float.

Not in scope

  • The Docker image pin stays at 17-2.3.1. That image supplies eql_v2; v3 now arrives at runtime from the package. I checked the published v3 images (17-3.0.0-alpha.2): they are v3-only and drop eql_v2 entirely, which would break searchable-json-pg, protect, cli, drizzle, and prisma-next. There is also no alpha.3 image, and it wouldn't matter — the version check would reinstall over it.
  • cli / drizzle / prisma-next remain on eql-2.3.1 / the eql_v2 schema. @cipherstash/eql ships v3 only.
  • src/eql/v3/columns.ts domain constants stay hand-written. Their eqlType strings are metadata only — build() emits cast_as + capability-derived indexes, never the domain name.

Unrelated findings

  • packages/prisma-next/src/migration/eql-bundle.ts cites a regeneration script scripts/vendor-eql-install.ts that does not exist. Its 7,655-line vendored bundle has no reproducible provenance.
  • json-schema-to-typescript is an unreferenced orphan devDependency in packages/stack. Left alone as unrelated.
  • Installing alpha.3 over a fixture-installed database leaves 78 orphan public.*_query domains. Unreferenced and harmless; CI is unaffected (fresh container per run). Only long-lived local dev databases carry them.

The v3 install SQL was a 43,339-line bundle hand-vendored into the test
tree with no generator script and no recorded provenance. Nothing tied it
to a released EQL version, and nothing detected drift from the protect-ffi
payload format it has to match. Its eql_v3.version() reports DEV — it was
never a release.

@cipherstash/eql publishes the SQL bundle and the TypeScript wire types
from the same eql-bindings commit, so one pinned version supplies both.
Read the bundle from readInstallSql() and delete the fixture.

Replace the staleness sentinel with a version check. It previously probed
to_regtype('public.timestamp'), a hand-picked type meant to exist only in
the newest bundle. That domain exists in the released bundle too, so the
check would have reported a stale install as current and left the suite
silently exercising the wrong SQL. eql_v3.version() carries the release
identity, so the check needs no maintenance when the pin moves;
to_regprocedure() yields NULL rather than raising on an empty database.

The published bundle renames query-operand domains from public.<type>_query
to eql_v3.query_<type>. Nothing here referenced those names: 0 functions
accept the old domains, 425 accept the new ones, and protect-ffi 0.28.0
operands round-trip unchanged.

@cipherstash/eql is a devDependency — nothing in src/ imports it, and the
package's files array already excludes __tests__. It is added to
minimumReleaseAgeExclude alongside protect-ffi and auth: it is first-party,
released in lockstep, and the 7-day cooldown would otherwise block an alpha.

The image pin stays at 17-2.3.1. That image supplies eql_v2; v3 now arrives
at runtime from the package. The published v3 images are v3-only and would
drop eql_v2 out from under the v2 suites.

Verified against a clean postgres-eql:17-2.3.1 container: full packages/stack
suite 1,055 passed / 0 failed, including the 57-test ORE matrix; a stale DEV
install is detected and reinstalled to 3.0.0-alpha.3; the skip-gate still
skips without DATABASE_URL; npm pack ships no tests, no SQL, no new dep.
@tobyhede tobyhede requested a review from a team as a code owner July 9, 2026 05:16
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 70e9f19

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

This PR includes changesets to release 6 packages
Name Type
@cipherstash/stack Patch
@cipherstash/bench Patch
@cipherstash/prisma-next Patch
@cipherstash/basic-example Patch
@cipherstash/prisma-next-example Patch
@cipherstash/e2e 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 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c839ce9b-99bf-4b96-b48d-7cc76e6dc665

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch use-cipherstash-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.

CI failed on a fresh database with
`PostgresError: schema "eql_v3" does not exist` (3F000) from hasCurrentEqlV3.

Postgres resolves function references while parsing a statement, before any
branch of it executes. So in

    SELECT CASE
      WHEN to_regprocedure('eql_v3.version()') IS NULL THEN NULL
      ELSE eql_v3.version()
    END

the ELSE branch is resolved even when the guard would have short-circuited:
the statement raises 3F000 when the eql_v3 schema is absent, and 42883 when
the schema exists but the function does not. The guard only ever succeeded
when it was not needed.

to_regprocedure() itself is fine — it takes the name as a string and yields
NULL rather than raising. Split the probe into its own statement and only
then call eql_v3.version(), so the call is parsed after existence is known.

Every local run had already installed EQL v3, so the empty-database path was
never exercised — the case the previous commit message claimed was safe.

Verified against a fresh ghcr.io/cipherstash/postgres-eql:17-2.3.1 (no eql_v3):
v3 suites 237 passed; full packages/stack suite 1,055 passed / 0 failed. Also
covers the schema-present-but-no-version() case: reinstalls rather than raising.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates @cipherstash/stack’s EQL v3 test/install workflow to source the v3 SQL bundle (and its release identity) from the published @cipherstash/eql package instead of a large, hand-vendored SQL fixture, and makes the “is the DB current?” sentinel robust by checking eql_v3.version() against the pinned release manifest.

Changes:

  • Add @cipherstash/eql@3.0.0-alpha.3 as an exact-pinned devDependency for packages/stack and wire the v3 installer helper to execute readInstallSql().
  • Replace the previous type-based “current bundle” sentinel with a release-identity check using eql_v3.version() vs releaseManifest.eqlVersion.
  • Update docs and add a changeset documenting the switch away from the vendored SQL fixture.

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pnpm-workspace.yaml Excludes @cipherstash/eql from the minimum release age cooldown to allow installing the newly-pinned first-party package.
pnpm-lock.yaml Records the locked @cipherstash/eql@3.0.0-alpha.3 dependency.
packages/stack/scripts/install-eql-v3.ts Prints the pinned EQL v3 release version after ensuring installation.
packages/stack/package.json Adds @cipherstash/eql as an exact devDependency for packages/stack.
packages/stack/tests/helpers/eql-v3.ts Reads and installs the SQL bundle from @cipherstash/eql and switches staleness detection to eql_v3.version() comparison.
docs/eql-v3-ord-term-ordering-defect.md Updates references from the vendored SQL fixture to the published @cipherstash/eql bundle location/API.
.changeset/eql-v3-bundle-from-package.md Adds a patch changeset describing the bundle source change and the new staleness sentinel.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tobyhede tobyhede merged commit 222be16 into feat/eql-v3-text-search-schema Jul 9, 2026
8 checks passed
@tobyhede tobyhede deleted the use-cipherstash-eql branch July 9, 2026 06:17
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.

3 participants