Skip to content

docs(supabase): correct the stash-supabase skill#606

Closed
coderdan wants to merge 4 commits into
feat/eql-v3-text-search-schemafrom
docs/stash-supabase-skill-refresh
Closed

docs(supabase): correct the stash-supabase skill#606
coderdan wants to merge 4 commits into
feat/eql-v3-text-search-schemafrom
docs/stash-supabase-skill-refresh

Conversation

@coderdan

@coderdan coderdan commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Rebased onto #616 (feat/eql-v3-integration-tests), not main. The integration suite in #616 makes order() work on Supabase v3 ordering columns, which this skill previously said was impossible — so this PR now stacks on #616 and carries that correction. Reconciled against CJ's eql-3.0.0 GA re-baseline of the skill (which this branch, originally cut from main, had not seen); the diff is SKILL.md + a stash patch changeset.

Update since first review (rebase onto #616)

  • order() on Supabase is no longer "impossible." The skill's blanket "ORDER BY on encrypted columns is not supported on Supabase" was true for EQL v2 (operator families need superuser) but is now wrong for v3: order() works on OPE-backed ordering columns (*_ord, text_ord, text_search) via the col->op jsonb path. Scoped the v2 statement, added the v3 support matrix (ORE-only and no-ordering-term columns rejected with a clear error), and fixed the typed-narrowing note (order() accepts plaintext and OPE ordering columns).
  • Corrected the v3 export list to the real surface: EncryptedSupabaseV3Options (not V3Config), plus TypedEncryptedSupabaseV3Instance, EncryptedQueryBuilderV3Untyped, V3FreeTextSearchableKeys.
  • Dropped the include_original: false substring workaroundprotect-ffi ignores the flag (proven by test(stack): EQL v3 integration harness + shared test kit, and two Supabase adapter fixes (PR1 of 4) #616's match-bloom suite), so it does not enable substring search. The skill now states the honest exact-match limitation, matching the re-baseline.
  • Added the missing stash patch changeset (skills ship in the tarball).

Why

skills/stash-supabase/SKILL.md ships in the stash tarball and stash init installs it into every Supabase project. Same defect classes as #598 (encryption) and #604 (drizzle), plus two of its own.

This is the correctness pass. The restructure you asked for on #598 (local-dev section, v3 focus, migration split, cross-references) is a separate follow-up, built on the feat/eql-v3-text-search-schema branch.

Defects

Two Linear issue IDs (CIP-3402) were shipping to customers in this skill. It's a public artifact copied into user repos. Removed.

CREATE EXTENSION IF NOT EXISTS eql_v2; — no such extension. eql_v2 is a schema plus public.eql_v2_encrypted, installed by the CLI. The skill omitted the v2 install path entirely; it now documents stash eql install --supabase --migration, and says why --migration beats --direct (a direct install does not survive supabase db reset).

Encrypted columns declared jsonb NOT NULL in the headline schema — forbidden by invariant 1 of the doctrine that ships alongside this skill. The skill even states the rule correctly 550 lines later, and then contradicts it in its own opening example.

An additive db push is promoted by stash db activate, not by cutover. The skill said "Cutover (later) will promote it." It won't — cutover promotes only the rename pending — and the cutover-time db push calls discardPendingConfig() before writing its own (push.ts:119), so the un-activated additive pending is discarded and Proxy serves a stale config for the whole dual-write window. db activate appeared nowhere in the skill. Same bug as #604.

Identity-aware encryption taught the deprecated LockContext.identify() ceremony. Per-operation CTS tokens were removed in protect-ffi 0.25. Replaced with OidcFederationStrategy on config.authStrategy plus a directly-constructed LockContext. Documented a real asymmetry: the Supabase builder's .withLockContext() is typed LockContext only, so unlike the core operations it will not accept a bare { identityClaim } — verified with tsc.

error.encryptionError is always undefined. The skill told users to branch on it. query-builder.ts:371-374 hardcodes encryptionError: undefined when constructing the error, discarding the populated value even for a genuine EncryptionFailedError. Documented the working discriminator (status === 500 && statusText === 'Encryption Error'), and flagged the code bug.

.filter(col, op, value) always encrypts an equality operand regardless of op, so .filter('age','gt',21) builds an equality term for a range operator and cannot match. Documented, along with the two failure modes that differ from Drizzle: a wrong index on a declared column errors (good), while an undeclared column silently compares plaintext against JSONB (bad, and previously undocumented).

Also

Verification

  • Typechecked the identity snippet against the package's real tsconfig.json (with paths and customConditions: ["node"]). new LockContext() and new LockContext({ context: { identityClaim: [...] } }) compile; { identityClaim: ['sub'] } does not — which is why the skill now says so. Only the known config.authStrategy doesn't typecheck: protect-ffi's AuthStrategy type is narrower than its runtime (auth 0.41 Result envelope) #602 authStrategy error remains.
  • Confirmed --supabase --eql-version 3 selects cipherstash-encrypt-v3-supabase.sql and creates schema eql_v3 (ran loadBundledEqlSql).
  • Confirmed the vendoring commit pins eql-3.0.0-alpha.2, and that both eql_v3 and eql_v3_internal schemas are created.
  • Confirmed discardPendingConfig() runs before the new pending insert.
  • Audit verified the rest is accurate: every filter method, the v3 domain names and capabilities, transparent decrypt-on-select, select('*') rejection, ::jsonb casts, and every Result snippet narrowing .failure before .data.

supabase-v3.test.ts fails on main too (needs a live Postgres with an anon role) — pre-existing, unrelated.

Summary by CodeRabbit

  • Documentation
    • Clarified encrypted database schema guidance and updated setup steps for EQL installation.
    • Added clearer warnings about query filtering behavior, failure cases, and encryption error handling.
    • Expanded identity-aware encryption examples and troubleshooting notes.
    • Updated migration and cutover instructions, including activation steps and version-specific setup details.

@coderdan coderdan requested a review from a team as a code owner July 9, 2026 10:07
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7af5a92

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

This PR includes changesets to release 2 packages
Name Type
stash 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

Review Change Stack

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: ca5b9dd5-6086-4ad1-9e55-9d0a6fd55ceb

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
📝 Walkthrough

Walkthrough

Documentation-only update to skills/stash-supabase/SKILL.md revising database schema guidance, EQL install commands, query filter warnings, identity-aware encryption examples, error-handling notes, exported types, EQL v3 install caveats, and migration/cutover operational guidance.

Changes

SKILL.md documentation revisions

Layer / File(s) Summary
Schema and EQL install guidance
skills/stash-supabase/SKILL.md
Changes encrypted-column schema example to nullable jsonb and replaces extension-based EQL v2 setup with stash eql install --supabase --migration CLI flow.
Query filter behavior warnings
skills/stash-supabase/SKILL.md
Adds warning that .filter() always encrypts operands as equality terms and clarifies two failure modes for index/schema mismatches.
Identity-aware encryption example rewrite
skills/stash-supabase/SKILL.md
Rewrites example to use OidcFederationStrategy and .withLockContext(), adds lock-context matching requirements and type workaround notes.
Error handling and exported types
skills/stash-supabase/SKILL.md
Clarifies error.encryptionError is always undefined and expands exported types list with EncryptedSupabaseResponse/EncryptedSupabaseError.
EQL v3 install and query envelope notes
skills/stash-supabase/SKILL.md
Adds v3 direct-path-only install caveat and updates term-only scalar query envelope explanations.
Migration and cutover operational guidance
skills/stash-supabase/SKILL.md
Adds stash db activate steps, pending/activation behavior notes, and updates SDK-only cutover known-gap note.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • cipherstash/stack#448: Adds the same "stash encrypt cutover requires pending EQL config" workaround note referenced in this PR's SDK-only users guidance.
  • cipherstash/stack#543: Corresponds to the CLI rename from stash db install to stash eql install reflected in this PR's install command update.

Suggested reviewers: calvinbrewer

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects a documentation correction to the stash-supabase skill and matches the main change.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/stash-supabase-skill-refresh

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.

Caution

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

⚠️ Outside diff range comments (1)
skills/stash-supabase/SKILL.md (1)

741-749: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clarify the SDK-only cutover workaround stash db push only creates pending when an active config already exists; on a fresh SDK-only project it writes active, so stash encrypt cutover still fails. Qualify this note with that prerequisite or spell out the missing bootstrap step.

🤖 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 `@skills/stash-supabase/SKILL.md` around lines 741 - 749, The SDK-only cutover
note is incomplete because stash db push only creates a pending EQL config after
an active config already exists. Update the guidance in the stash encrypt
cutover section to call out that a fresh SDK-only project must first bootstrap
the initial config before the pending-row workaround applies, and reference the
stash db push / stash encrypt cutover flow so readers know when the workaround
is valid.
🤖 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.

Outside diff comments:
In `@skills/stash-supabase/SKILL.md`:
- Around line 741-749: The SDK-only cutover note is incomplete because stash db
push only creates a pending EQL config after an active config already exists.
Update the guidance in the stash encrypt cutover section to call out that a
fresh SDK-only project must first bootstrap the initial config before the
pending-row workaround applies, and reference the stash db push / stash encrypt
cutover flow so readers know when the workaround is valid.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f3c2082c-a172-4058-9c18-95f4f0e219c4

📥 Commits

Reviewing files that changed from the base of the PR and between 8ac66a8 and 015e8da.

📒 Files selected for processing (1)
  • skills/stash-supabase/SKILL.md

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 corrects and hardens the public stash-supabase skill (skills/stash-supabase/SKILL.md) so that the guidance installed into Supabase user projects matches the actual CLI + SDK behavior (EQL install paths, schema invariants, query semantics, identity-aware encryption, and error discrimination).

Changes:

  • Fixes the database schema and EQL installation guidance (nullable jsonb encrypted columns; document stash eql install --supabase --migration; clarify EQL is not a PG extension).
  • Documents known adapter behaviors and footguns (notably .filter() always encrypting operands as equality, the declared-vs-undeclared column failure modes, and how to distinguish encryption failures given error.encryptionError is always undefined).
  • Updates identity-aware encryption docs to the current strategy-based flow (no LockContext.identify()), adds v3 install caveats, and refreshes the documented export surface.

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

Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Comment thread skills/stash-supabase/SKILL.md Outdated
Rebased onto the EQL v3 integration branch (#616). Reconciled against CJ's
eql-3.0.0 GA re-baseline of the skill, which #606 (branched from main) had not
seen, and corrected the order() guidance now that #616 makes order() work on
Supabase v3 ordering columns.

- order(): the skill said ORDER BY on encrypted columns is unsupported on
  Supabase. That is still true for EQL v2 (operator families need superuser),
  but v3 order() now works on OPE-backed ordering columns (*_ord, text_ord,
  text_search) via the col->op jsonb path. Scoped the v2 statement, documented
  the v3 support matrix (ORE-only ordering columns and no-ordering-term columns
  are rejected), and fixed the typed-narrowing note (order() accepts plaintext
  AND OPE ordering columns, not plaintext only).
- Exports: corrected the v3 type list to the real surface
  (EncryptedSupabaseV3Options not V3Config; added TypedEncryptedSupabaseV3Instance,
  EncryptedQueryBuilderV3Untyped, V3FreeTextSearchableKeys; kept
  EncryptedSupabaseResponse/Error and V3FilterableKeys).
- Kept the newer re-baseline content (single v3 SQL artifact, ORE self-skip,
  --supabase grants, honest contains() exact-match limitation) and preserved the
  additive `supabase db reset` warning.
- Dropped the include_original:false substring workaround: protect-ffi ignores
  the flag (proven by this branch's match-bloom tests), so it does not enable
  substring search.

Claude-Session: https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w
@coderdan coderdan force-pushed the docs/stash-supabase-skill-refresh branch from 015e8da to ee9667e Compare July 11, 2026 02:26
@coderdan coderdan changed the base branch from main to feat/eql-v3-integration-tests July 11, 2026 02:26
Base automatically changed from feat/eql-v3-integration-tests to feat/eql-v3-text-search-schema July 12, 2026 10:57
coderdan added 2 commits July 12, 2026 23:50
Restructures the skill so encryptedSupabaseV3 leads: connect-time introspection
(no schema arg), native public.eql_v3_* domains, select('*'), contains() (not
like/ilike), order() on OPE-backed columns, and a v3 migration guide. Relegates
v2 (encryptedSupabase, still shipped) to a slim "Legacy: EQL v2" section.

Addresses the review comments on #606: EQL 3.0.0 type names in the schema
section, schema declaration presented as optional (introspection), automatic
schema loading as the default, OPE ordering (v3), and the V3-first structure.
Verified the v3 API surface (encryptedSupabaseV3 options.config.authStrategy,
withLockContext/audit/contains/order on the builder, ./eql/v3 exports) and the
referenced CLI commands against `stash manifest --json`.

Claude-Session: https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w
Link the encryptionError caveat to #626 and the interim full-envelope operand
note to #622.

Claude-Session: https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w
@coderdan

Copy link
Copy Markdown
Contributor Author

Superseded by #642. Same reason as #604: predates the adapter split (references @cipherstash/stack/supabase) and the contains()→matches() rename; a near-total rewrite that would regress paths + matches() if rebased. The identity-docs correction it carried is applied fresh in #642 (stash-supabase skill now leads with OidcFederationStrategy + withLockContext, identify() demoted to deprecated). The current candidate skill supersedes the rest.

@coderdan coderdan closed this Jul 13, 2026
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.

2 participants