fix(stack,stack-supabase): edge-safe shared seam — process-free adapter-kit + structural v3 columns#799
fix(stack,stack-supabase): edge-safe shared seam — process-free adapter-kit + structural v3 columns#799tobyhede wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: b223bad The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
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 |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
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.
Plan 1 of the portable
encryptedSupabaseseries (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), notmain— 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 againstmain.Fix 1 —
@cipherstash/stack/adapter-kitimportable without aprocessglobalThe shared core logger read
process.env.STASH_STACK_LOGunguarded while initialising at module scope, so importing adapter-kit — which re-exports that logger — threwReferenceError: process is not definedbefore any user code ran, on any runtime with noprocess(Workers, Deno isolates, Supabase Edge Functions). The read is now guarded.Not Supabase-only:
@cipherstash/stack-supabase,@cipherstash/stack-drizzleand@cipherstash/prisma-nextall 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, itserrordefault, and the point at which it is configured are unchanged.New regression gate:
packages/stack/__tests__/helpers/process-free-realm.mjsevaluates an emitted ESM graph in anode:vmrealm with noprocess;logger-edge-safety.test.tsspawns it againstdist/adapter-kit.js(skips whendist/is absent).packages/stack/turbo.jsonmakestestdepend on the package's ownbuildso the gate can't silently skip in CI.Fix 2 — recognise EQL v3 columns structurally, not by class identity
ColumnMapgated onbuilder instanceof EncryptedV3Column. tsup emits that class twice (dist/adapter-kit.jsanddist/wasm-inline.jsare separate esbuild runs), so a table authored withencryptedTable/typesfrom@cipherstash/stack/wasm-inline— what the edge examples use — failed theinstanceoffor every column.v3Columnscame out empty and the adapter treated encrypted columns as plaintext: filter operands reached PostgREST in the clear, while::jsonbcasts and result decryption kept working (different path), so the failure was silent. Tables authored from@cipherstash/stack/eql/v3were never affected — same class copy the adapter imports.The check is now a structural four-method probe (
isV3ColumnLike), mirroringhasBuildColumnKeyMap— 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.dist/adapter-kit.js.Changesets
@cipherstash/stack: patch@cipherstash/stack-supabase: patchNotes for review
A prior
/code-reviewpass flagged a "duplicateconst v2" (verified false positive — one block-scoped declaration,tscclean) and a probabilisticfc.constantFromsample in the catalog test (applied — swapped to a deterministic loop overObject.keys(types)for guaranteed full-catalog coverage, dropping the lonefast-checkimport).