Skip to content

feat(cli): default EQL to v3, stop recommending db push (v2/Proxy-only)#586

Open
coderdan wants to merge 3 commits into
mainfrom
feat/eql-v3-default-drop-push-recs
Open

feat(cli): default EQL to v3, stop recommending db push (v2/Proxy-only)#586
coderdan wants to merge 3 commits into
mainfrom
feat/eql-v3-default-drop-push-recs

Conversation

@coderdan

@coderdan coderdan commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Closes #585. Follow-up to the config-scaffold DX work (#580).

What & why

Two things you asked for after testing eql status on a v3-only database:

1. EQL v3 is now the default

stash eql install / stash eql upgrade target v3 (native eql_v3.* domain schema) with no --eql-version 3 needed. A single DEFAULT_EQL_VERSION constant drives the installer.

The v2-only paths — --drizzle, --migration, --migrations-dir, --latest — require an explicit --eql-version 2 and error with actionable guidance otherwise (v3 installs via the direct path only). The "requires --supabase" check runs first, so a bare --migration still points at its more fundamental missing prerequisite. stash init pins v2 automatically when it drives the Drizzle migration flow.

2. The CLI no longer recommends db push

db push writes public.eql_v2_configuration — a v2 + CipherStash Proxy artifact. EQL v3 has no configuration table (config lives in each column's eql_v3.* type) and nothing in the v3 stack reads it (verified: v3 SQL has zero CREATE TABLE/config functions; the SDK never touches the table; Proxy's reload_config doesn't exist in v3). CipherStash's own v3 spec calls it "now-redundant".

  • eql status is v3-aware: on a v3-only DB it reports config-in-column-types instead of the old "table not found → run db push" dead-end (which never created that table and doesn't apply to v3).
  • db push guards a v3-only DB with a clean "not needed under EQL v3" message instead of a raw relation "public.eql_v2_configuration" does not exist.
  • Removed push recommendations from the help banner, the init/plan/cutover setup-prompt guidance (dropped the now-unused usesProxy branch), and the encrypt status / quest next-step hints.
  • db push / db activate remain available for EQL v2 + Proxy users and are now labelled (EQL v2 + Proxy).

Decisions worth a look

  • db activate / encrypt cutover reactive errors: I kept these commands' own "no pending config" error messages coherent (describing the v2/Proxy config lifecycle) rather than stripping the guidance entirely, since a v2/Proxy user running those commands still needs it. I dropped the explicit db push imperative from them. Tell me if you want them gutted too.
  • usesProxy is now vestigial in the setup prompt (its only consumer). I removed it from SetupPromptContext but left the broader init/context.json plumbing intact. Retiring the "do you use Proxy?" init question is a natural follow-up.
  • Skills (SKILL.md) shipped by stash init still reference db push — those are docs, out of scope here; happy to sweep them in a follow-up.
  • Alpha caveat: v3 is alpha.2 ("version: DEV"). This makes it the default install for everyone, including stash init.

Tests

Reworked validateInstallFlags coverage (v3 default + explicit-v2 gating), made the v2-specific installer tests explicit about eqlVersion: 2, replaced the usesProxy setup-prompt tests with no-db push assertions. 396 unit + 55 e2e green; Biome clean.

Summary by CodeRabbit

  • New Features
    • EQL v3 is now the default for eql install and eql upgrade.
    • eql status is v3-aware, including how v3 encryption config is discovered.
  • Bug Fixes
    • v2-only options now require explicitly selecting EQL v2 (--eql-version 2), with improved guidance.
    • stash db push no longer fails on v3-only databases, and db activate/status/cutover messaging is clearer.
  • Documentation / UX
    • Updated stash db help and init/setup/quest prompts to remove outdated db push recommendations.
  • Tests
    • Updated CLI tests for version-resolution and v2/v3-specific expectations.

Closes #585.

EQL v3 is now the default for `stash eql install` / `eql upgrade` — no
`--eql-version 3` required. The v2-only paths (--drizzle, --migration,
--migrations-dir, --latest) require an explicit `--eql-version 2` and error
with clear guidance otherwise; `stash init` pins v2 for the Drizzle flow.
A single DEFAULT_EQL_VERSION constant drives the installer defaults.

`stash db push` writes `public.eql_v2_configuration`, a v2 + CipherStash
Proxy artifact that EQL v3 neither creates nor reads (v3 config lives in each
column's `eql_v3.*` type). The CLI no longer recommends it:
- `eql status` is v3-aware — reports config-in-column-types on a v3-only DB
  instead of the "table not found → run db push" dead-end.
- `db push` guards a v3-only DB with a clean "not needed under v3" message.
- Removed push recommendations from the help banner, init/plan/cutover
  setup-prompt guidance (dropping the now-unused usesProxy branch), and the
  encrypt-status / quest next-step hints. `db push` / `db activate` remain for
  v2 + Proxy users and are labelled as such.

Tests: reworked validateInstallFlags coverage for the v3 default + explicit-v2
gating; made the v2-specific installer tests explicit about eqlVersion: 2;
replaced the usesProxy setup-prompt tests with no-db-push assertions.
396 unit + 55 e2e green.
@coderdan coderdan requested a review from a team as a code owner July 8, 2026 12:54
@coderdan coderdan self-assigned this Jul 8, 2026
@changeset-bot

changeset-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5d13d2b

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

This PR includes changesets to release 2 packages
Name Type
stash Minor
@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 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR switches EQL install and upgrade defaults to v3, requires explicit v2 selection for v2-only flags, adds v3-aware guards in db push and db status, and rewrites CLI guidance and init prompts to remove db push recommendations.

Changes

EQL v3 Default and db push Removal

Layer / File(s) Summary
Installer default EQL version
packages/cli/src/installer/index.ts, packages/cli/src/__tests__/installer.test.ts, packages/cli/src/__tests__/supabase-migration.test.ts
Adds the v3 default constant and version resolver, updates installer defaults and bundled SQL selection, and adjusts tests for explicit v2 calls and v3-default resolution.
Install and upgrade validation
packages/cli/src/commands/db/install.ts, packages/cli/src/commands/db/upgrade.ts, packages/cli/src/cli/registry.ts, packages/cli/src/cli/__tests__/help.test.ts, packages/cli/src/commands/init/steps/install-eql.ts
Updates command defaults, validation order, and error messages so v2-only flags require --eql-version 2, and pins the Drizzle path to v2.
db push and status guards
packages/cli/src/commands/db/push.ts, packages/cli/src/commands/db/status.ts, packages/cli/src/commands/db/supabase-migration.ts
Adds a v3-only no-op path for db push, makes db status detect v2 explicitly before probing Proxy configuration, and pins Supabase migration SQL to the v2 bundle.
CLI guidance and setup prompts
packages/cli/src/commands/db/activate.ts, packages/cli/src/commands/encrypt/*, packages/cli/src/commands/status/quest.ts, packages/cli/src/bin/main.ts, packages/cli/src/commands/init/lib/setup-prompt.ts, packages/cli/src/commands/init/lib/write-context.ts, packages/cli/src/commands/init/lib/__tests__/setup-prompt.test.ts
Removes db push recommendations from help text, lifecycle messages, and prompt templates, and removes Proxy-specific prompt context wiring.
Changeset documentation
.changeset/stash-cli-eql-v3-default.md
Updates the changeset entry for the EQL v3 default and db push guidance changes.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related issues

Possibly related PRs

  • cipherstash/stack#357: Touches the same db push and db activate lifecycle codepaths around eql_v2_configuration.
  • cipherstash/stack#366: Shares the Supabase install and permissions flow that this PR updates for explicit EQL version handling.
  • cipherstash/stack#448: Modifies the init prompt context and usesProxy-driven db push guidance in the same area.

Suggested reviewers: tobyhede, freshtonic

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: EQL defaults to v3 and db push guidance is being removed for v2/Proxy-only use.
Linked Issues check ✅ Passed The PR matches the linked issue: v3 is the default, v2-only flows require explicit v2, db push guidance is removed, and v3-only push errors are handled cleanly.
Out of Scope Changes check ✅ Passed The changed files stay focused on the EQL v3 default and db push guidance cleanup, with no clear unrelated feature work introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/eql-v3-default-drop-push-recs

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/installer/index.ts (1)

471-492: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Pass eqlVersion: 2 into the Supabase migration helper.
loadBundledEqlSql() now defaults to v3, so writeSupabaseEqlMigration() will emit the wrong bundle for the v2-only --migration path unless it threads the version through. The direct install path can keep the default.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/installer/index.ts` around lines 471 - 492, The Supabase
migration path is using the default Eql bundle version instead of v2, so update
writeSupabaseEqlMigration() to pass eqlVersion: 2 into loadBundledEqlSql() when
generating the --migration script. Keep the direct install flow unchanged, and
use the existing loadBundledEqlSql() and writeSupabaseEqlMigration() symbols to
wire the version through explicitly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/commands/db/status.ts`:
- Around line 94-109: The v2/v3 guard in statusCommand is using the wrong
install check, so `installedV2` and `versionV2` are actually reading the default
v3 schema. Update the v2 probe calls in `statusCommand` to explicitly pass `{
eqlVersion: 2 }` when calling `installer.isInstalled()` and
`installer.getInstalledVersion()`, then keep the `if (!installedV2)` early
return so v3-only databases skip the `public.eql_v2_configuration` query path.

---

Outside diff comments:
In `@packages/cli/src/installer/index.ts`:
- Around line 471-492: The Supabase migration path is using the default Eql
bundle version instead of v2, so update writeSupabaseEqlMigration() to pass
eqlVersion: 2 into loadBundledEqlSql() when generating the --migration script.
Keep the direct install flow unchanged, and use the existing loadBundledEqlSql()
and writeSupabaseEqlMigration() symbols to wire the version through explicitly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b22cc4ac-dee4-47ae-aa6f-d98e3efe4b12

📥 Commits

Reviewing files that changed from the base of the PR and between c67169f and e25eb22.

📒 Files selected for processing (20)
  • .changeset/stash-cli-eql-v3-default.md
  • packages/cli/src/__tests__/installer.test.ts
  • packages/cli/src/__tests__/supabase-migration.test.ts
  • packages/cli/src/bin/main.ts
  • packages/cli/src/cli/__tests__/help.test.ts
  • packages/cli/src/cli/registry.ts
  • packages/cli/src/commands/db/activate.ts
  • packages/cli/src/commands/db/install.ts
  • packages/cli/src/commands/db/push.ts
  • packages/cli/src/commands/db/status.ts
  • packages/cli/src/commands/db/upgrade.ts
  • packages/cli/src/commands/encrypt/backfill.ts
  • packages/cli/src/commands/encrypt/cutover.ts
  • packages/cli/src/commands/encrypt/status.ts
  • packages/cli/src/commands/init/lib/__tests__/setup-prompt.test.ts
  • packages/cli/src/commands/init/lib/setup-prompt.ts
  • packages/cli/src/commands/init/lib/write-context.ts
  • packages/cli/src/commands/init/steps/install-eql.ts
  • packages/cli/src/commands/status/quest.ts
  • packages/cli/src/installer/index.ts
💤 Files with no reviewable changes (1)
  • packages/cli/src/commands/init/lib/write-context.ts

Comment thread packages/cli/src/commands/db/status.ts

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 the stash CLI’s EQL workflows to default installs/upgrades to EQL v3 and removes outdated guidance that recommended stash db push (a v2 + Proxy-only step) in general CLI output. It also adds version-aware gating so v2-only installer paths require an explicit --eql-version 2, and adjusts status/prompt messaging to align with v3’s “config-in-column-types” model.

Changes:

  • Default EQL targeting to v3 across installer logic and CLI flags/help, while requiring explicit --eql-version 2 for v2-only install/upgrade paths.
  • Remove broad CLI recommendations for db push, and relabel db push / db activate as (EQL v2 + Proxy).
  • Make eql status / db push behave sensibly on v3-only databases (avoid v2 config-table dead ends).

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/cli/src/installer/index.ts Introduces DEFAULT_EQL_VERSION = 3 and threads defaulting through installer helpers.
packages/cli/src/commands/status/quest.ts Removes db push from quest “next step” guidance.
packages/cli/src/commands/init/steps/install-eql.ts Pins v2 for Drizzle init flow while leaving v3 as default elsewhere.
packages/cli/src/commands/init/lib/write-context.ts Removes usesProxy from setup-prompt context building.
packages/cli/src/commands/init/lib/setup-prompt.ts Removes Proxy-conditional branches and strips db push recommendations from prompts/plans.
packages/cli/src/commands/init/lib/tests/setup-prompt.test.ts Updates setup prompt tests to assert no db push mentions.
packages/cli/src/commands/encrypt/status.ts Rewords “no encrypted columns” guidance to avoid db push.
packages/cli/src/commands/encrypt/cutover.ts Rewords “no pending config” error to remove db push imperative.
packages/cli/src/commands/encrypt/backfill.ts Updates unsupported cast_as warning to avoid db push guidance.
packages/cli/src/commands/db/upgrade.ts Defaults upgrade targeting to v3 and improves --latest + default-version messaging.
packages/cli/src/commands/db/status.ts Makes config-table probing conditional on v2 installation, to avoid v3-only dead ends.
packages/cli/src/commands/db/push.ts Adds v3-only DB guard so db push exits cleanly when not applicable.
packages/cli/src/commands/db/install.ts Makes v3 the default install target; adds explicit v2-only flag validation.
packages/cli/src/commands/db/activate.ts Rewords “no pending config” error to remove db push imperative.
packages/cli/src/cli/registry.ts Updates flag descriptions and defaults to show v3 default + v2-only flag gating.
packages/cli/src/cli/tests/help.test.ts Updates help output expectation for default eql version = 3.
packages/cli/src/bin/main.ts Relabels db push / db activate as (EQL v2 + Proxy) and removes example db push.
packages/cli/src/tests/supabase-migration.test.ts Updates tests around v3-default + explicit-v2 gating behavior.
packages/cli/src/tests/installer.test.ts Makes v2 installer tests pass explicit eqlVersion: 2 where needed.
.changeset/stash-cli-eql-v3-default.md Adds release notes for v3 defaulting + messaging changes.

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

Comment thread packages/cli/src/installer/index.ts
Comment thread packages/cli/src/commands/db/push.ts Outdated
Comment thread packages/cli/src/commands/db/status.ts
Comment thread packages/cli/src/commands/encrypt/cutover.ts
Comment thread packages/cli/src/commands/db/activate.ts
coderdan added 2 commits July 9, 2026 00:04
- status.ts (critical, self-inflicted regression): `installedV2` used bare
  `isInstalled()` / `getInstalledVersion()`, which now default to v3 after the
  DEFAULT_EQL_VERSION flip — so on a v2-only DB status wrongly reported "EQL is
  not installed", and on a v3 DB it mislabelled the version and re-hit the
  eql_v2_configuration dead-end. Pass `{ eqlVersion: 2 }` explicitly.

- push.ts: replace the two `isInstalled` probes (3 connections, missed the
  fresh-DB case, diverged when the schema exists without the table, and
  swallowed transient errors via `.catch(() => false)`) with a single
  `to_regclass('public.eql_v2_configuration')` check on the connection push
  already opens. One connection; covers v3-only, fresh, and partial installs.

- Centralize the default-version resolution in `resolveEqlVersion()` next to
  DEFAULT_EQL_VERSION and use it in install.ts (both sites) + upgrade.ts, so the
  default lives in one place instead of three hand-inlined `=== '2' ? 2 : 3`.

- Document the Supabase-init behavior change (now a v3 direct install rather
  than the v2 migration-file flow) in the changeset.

- Add resolveEqlVersion unit coverage.

398 unit + 55 e2e green.
…review)

writeSupabaseEqlMigration called loadBundledEqlSql without an eqlVersion, so
after the DEFAULT_EQL_VERSION flip to v3 it emitted cipherstash-encrypt-v3-
supabase.sql into a migration that still appends the v2 SUPABASE_PERMISSIONS_SQL
— a mismatched v3-body/v2-perms file. The Supabase migration-file flow is
v2-only (v3 has no migration-file path), so pin eqlVersion: 2 explicitly.

The existing test passed despite the bug because the header + permissions text
mention eql_v2 regardless of the body; strengthened it to assert
`eql_v2_encrypted` is present and no `eql_v3` leaks in.

Caught by Copilot on the PR.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/cli/src/commands/db/supabase-migration.ts (1)

102-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

EQL v2 pin is correct and well-documented.

The explicit eqlVersion: 2 correctly prevents the v3 default from leaking into the Supabase migration-file flow. The comment clearly explains the rationale and the downstream test asserts eql_v2_encrypted is present and eql_v3 is absent, confirming the contract holds.

One minor observation on line 112: excludeOperatorFamily: excludeOperatorFamily || true always evaluates to true regardless of the option value (since false || true === true), making the excludeOperatorFamily option from WriteSupabaseEqlMigrationOptions effectively dead. If the intent is "always exclude operator family for Supabase," passing true directly would be clearer and avoid implying the option has an effect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/db/supabase-migration.ts` around lines 102 - 113,
The Supabase migration flow in supabase-migration.ts correctly pins eqlVersion
through loadBundledEqlSql, but excludeOperatorFamily is effectively ignored
because excludeOperatorFamily || true always resolves to true. Update the
loadBundledEqlSql call to reflect the intended behavior explicitly: either pass
a literal true if Supabase must always exclude the operator family, or wire the
WriteSupabaseEqlMigrationOptions value through without the unconditional
fallback if the option should remain configurable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/cli/src/commands/db/supabase-migration.ts`:
- Around line 102-113: The Supabase migration flow in supabase-migration.ts
correctly pins eqlVersion through loadBundledEqlSql, but excludeOperatorFamily
is effectively ignored because excludeOperatorFamily || true always resolves to
true. Update the loadBundledEqlSql call to reflect the intended behavior
explicitly: either pass a literal true if Supabase must always exclude the
operator family, or wire the WriteSupabaseEqlMigrationOptions value through
without the unconditional fallback if the option should remain configurable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b13aa794-6d38-4536-bf0e-3ca7a919e297

📥 Commits

Reviewing files that changed from the base of the PR and between 8502cdf and 5d13d2b.

📒 Files selected for processing (2)
  • packages/cli/src/__tests__/supabase-migration.test.ts
  • packages/cli/src/commands/db/supabase-migration.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/cli/src/tests/supabase-migration.test.ts

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.

EQL v3: make it the default, and stop the CLI recommending db push (a v2/Proxy-only step)

2 participants