Skip to content

fix(stack,stack-supabase): edge-safe shared seam — process-free adapter-kit + structural v3 columns#799

Open
tobyhede wants to merge 3 commits into
remove-v2from
feat/edge-safe-shared-seam
Open

fix(stack,stack-supabase): edge-safe shared seam — process-free adapter-kit + structural v3 columns#799
tobyhede wants to merge 3 commits into
remove-v2from
feat/edge-safe-shared-seam

Conversation

@tobyhede

Copy link
Copy Markdown
Contributor

Plan 1 of the portable encryptedSupabase series (docs/superpowers/plans/2026-07-24-edge-safe-shared-seam.md). Two independent defect fixes in the shared seam every first-party adapter's Worker / Edge build imports. Both prerequisites for the rest of the series; neither needs any of it.

Base: remove-v2 (the EQL v3 integration branch this line of work targets), not main — the INDEX notes plan 1 defers its CI gate to plan 4 and the four plans ship as one PR, so this should not land standalone against main.

Fix 1 — @cipherstash/stack/adapter-kit importable without a process global

The shared core logger read process.env.STASH_STACK_LOG unguarded while initialising at module scope, so importing adapter-kit — which re-exports that logger — threw ReferenceError: process is not defined before any user code ran, on any runtime with no process (Workers, Deno isolates, Supabase Edge Functions). The read is now guarded.

Not Supabase-only: @cipherstash/stack-supabase, @cipherstash/stack-drizzle and @cipherstash/prisma-next all value-import adapter-kit, so all three are fixed here.

No behaviour change on Node — the logger is guarded, not deferred: STASH_STACK_LOG, its values, its error default, and the point at which it is configured are unchanged.

New regression gate: packages/stack/__tests__/helpers/process-free-realm.mjs evaluates an emitted ESM graph in a node:vm realm with no process; logger-edge-safety.test.ts spawns it against dist/adapter-kit.js (skips when dist/ is absent). packages/stack/turbo.json makes test depend on the package's own build so the gate can't silently skip in CI.

Fix 2 — recognise EQL v3 columns structurally, not by class identity

ColumnMap gated on builder instanceof EncryptedV3Column. tsup emits that class twice (dist/adapter-kit.js and dist/wasm-inline.js are separate esbuild runs), so a table authored with encryptedTable/types from @cipherstash/stack/wasm-inline — what the edge examples use — failed the instanceof for every column. v3Columns came out empty and the adapter treated encrypted columns as plaintext: filter operands reached PostgREST in the clear, while ::jsonb casts and result decryption kept working (different path), so the failure was silent. Tables authored from @cipherstash/stack/eql/v3 were never affected — same class copy the adapter imports.

The check is now a structural four-method probe (isV3ColumnLike), mirroring hasBuildColumnKeyMap — the repo's canonical answer to the same two-copies-of-a-class hazard. Four probes, not two, so a v2 column builder is still rejected.

Tests

  • @cipherstash/stack-supabase: 466 → 470 (structural-recognition, v2-rejection, wire-level plaintext-leak, and a deterministic full-types.*-catalog completeness guard).
  • @cipherstash/stack-supabase test:types: 44, no type errors.
  • New edge-safety subprocess gate passes against the emitted dist/adapter-kit.js.

Changesets

  • @cipherstash/stack: patch
  • @cipherstash/stack-supabase: patch

Notes for review

A prior /code-review pass flagged a "duplicate const v2" (verified false positive — one block-scoped declaration, tsc clean) and a probabilistic fc.constantFrom sample in the catalog test (applied — swapped to a deterministic loop over Object.keys(types) for guaranteed full-catalog coverage, dropping the lone fast-check import).

@tobyhede
tobyhede requested a review from a team as a code owner July 26, 2026 00:39
@changeset-bot

changeset-bot Bot commented Jul 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b223bad

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

This PR includes changesets to release 11 packages
Name Type
@cipherstash/stack Patch
@cipherstash/stack-supabase Patch
@cipherstash/bench Patch
stash Patch
@cipherstash/prisma-next Patch
@cipherstash/stack-drizzle Patch
@cipherstash/test-kit Patch
@cipherstash/basic-example Patch
@cipherstash/prisma-next-example Patch
@cipherstash/e2e Patch
@cipherstash/wizard 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 26, 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 Plus

Run ID: 48714cb7-fa54-47b8-b55d-88dad129d2a2

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 feat/edge-safe-shared-seam

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.

Addresses review on #799.

- ColumnMap now throws at construction when a builder in an AnyV3Table's
  columnBuilders fails the structural v3 probe, instead of silently
  omitting it. An omitted column dropped out of v3Columns and its filter
  operands went to PostgREST as plaintext — the exact leak this work
  closes, from the other direction. Regression tests prove construction
  throws and no PostgREST request is issued.
- Harden the logger env guard against a process defined without env.
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.

1 participant