Releases: cipherstash/stack
Release list
@cipherstash/stack-supabase@1.0.0-rc.1
Minor Changes
-
5fe9a2f: Encrypted-JSON querying on the v3 Supabase surface (#650). A
types.Json
column now supports exact encrypted containment —contains(col, subDocument)
(ste_vec@>via PostgRESTcs, with the sub-document storage-encrypted
against the column) — and JSONPath selector predicates:selectorEq(col, path, value)andselectorNe(col, path, value)(dot-notation paths;neincludes
rows where the path is absent, mirroring the Drizzle selector's semantics).
Raw.filter(col, 'cs', subDocument)andnot(col, 'contains', …)route
through the same encrypted path. Selector ordering is not expressible over
PostgREST yet (needs an EQL-bundle overload — see
cipherstash/encrypt-query-language#407); the Drizzle integration's
ops.selector()covers ordering today.In core,
QueryTypesForColumngains thesearchableJsonarm (atypes.Json
column no longer resolves tonever, so typed adapter key sets can include
it), and the JSONPath selector-path helpers the Drizzle adapter introduced in
#651 moved to@cipherstash/stack/adapter-kitso both adapters share one
validation surface (@cipherstash/stack-drizzlere-exports them unchanged).The bundled
stash-supabaseandstash-encryptionskills are updated to
document the new querying surface (including the array-leaf and SQL-NULL
semantics, and the operand-exposure caveat) — skills ship inside thestash
tarball, hence the patch.
Patch Changes
-
7b53141: Three correctness fixes surfaced while documenting the v3 surface:
- Supabase
matches()now rejects a short free-text needle. A needle
below the tokenizer'stoken_lengthblooms to zero tokens, sobloom @> {}
matched (and the caller decrypted) every row — a fail-open exposure. The
guard (matchNeedleError) was wired into the Drizzle adapter only; the
Supabase adapter now applies it at the same term-resolution choke point, so
both first-party surfaces reject identically. (Authoritative FFI-level backstop
for theencryptQuerypaths tracked in cipherstash/protectjs-ffi#138.) - Supabase
.withLockContext()accepts the plain{ identityClaim }form,
not only aLockContextinstance — matching the stack-level operations and
the documented identity-aware example (widened toLockContextInput). EncryptionErrorTypesis nowas const, so theStackErrorunion
actually discriminates:switch (error.type)narrows anderror.codeis
reachable on the relevant branches. Without it everytypewasstringand
the documented exhaustive error handler did not compile.
- Supabase
-
Updated dependencies [e297f64]
-
Updated dependencies [40ab142]
-
Updated dependencies [5fe9a2f]
-
Updated dependencies [7b53141]
- @cipherstash/stack@1.0.0-rc.1
@cipherstash/stack-drizzle@1.0.0-rc.1
Minor Changes
-
59b994e: Add EQL v3 JSON selector-with-constraint querying to the Drizzle integration
(#623).ops.selector(col, '$.path')returns comparison methods bound to a
JSONPath into atypes.Jsoncolumn —eq/ne/gt/gte/lt/lte— emitting
col->'<selector>' <op> <value>over the encrypted document. Its unique power
overcontainsis ordering at a path (col->'$.age' > 21), which
containment cannot express.Complements the existing
contains(JSONB@>) containment operator. Core
@cipherstash/stackneeds no change — the selector hash and comparison entry are
produced byencryptQuery/encrypton the existingtypes.Jsonsurface. v1
supports dot-notation object paths; array-index/wildcard paths are rejected with
a clear error. The Supabase adapter is tracked separately.The right-hand comparison operand is currently a storage-encrypted needle (its
ste_vec entry carries the ordering term), pending a ciphertext-free ordering
query needle from protect-ffi (cipherstash/protectjs-ffi#137); until then the
value's ciphertext appears in the WHERE clause.The bundled
stash-encryptionandstash-drizzleskills document the new
ops.selector(...)surface (they previously said JSONPath selector queries were
not yet implemented).
Patch Changes
@cipherstash/prisma-next@0.4.0-rc.1
@cipherstash/drizzle@3.0.4-rc.1
Patch Changes
- 3fdd740: Docs: the README's "for new projects" pointer named the removed
@cipherstash/stack/drizzlesubpath; it now points at the separate
@cipherstash/stack-drizzlepackage (EQL v3 on its/v3subpath).
stash@1.0.0-rc.0
Major Changes
-
7c7dbca: CipherStash Stack 1.0 (release candidate).
This is the first 1.0-line release of
@cipherstash/stack, the first published
release of the split-out EQL v3 adapters@cipherstash/stack-drizzleand
@cipherstash/stack-supabase, and moves thestashCLI to 1.0 alongside them.
These four packages now version together as the Stack 1.0 family.
Minor Changes
-
229ce59:
stash eql install --eql-version 3now installs the eql-3.0.0 GA bundle,
vendored from the pinned@cipherstash/eqlpackage (sha256-verified).Since eql-3.0.0 one artifact installs everywhere: the operator-class
statements self-skip when the role lacks superuser (managed Postgres,
Supabase) and the bundle disables the ORE-backed encrypted domains it cannot
support. The separate v3 Supabase bundle variant is gone —--supabaseand
--exclude-operator-familyno longer select a different v3 file (the role
GRANTs foreql_v3/eql_v3_internalstill apply with--supabase).The bundled skills are also refreshed for the eql-3.0.0 naming convention
(public.eql_v3_<name>column domains) and the EQL v3 typed-schema surface. -
0b9b192: Add an EQL v3 install path to
stash eql installvia a new--eql-version <2|3>
flag (default2). v3 installs the native concrete-domain schema (public.*
type domains,eql_v3operators,eql_v3_internalconstructors) from bundles
vendored intopackages/cli/src/sqlbyscripts/build-eql-v3-sql.mjs(full
bundle + a Supabase variant with the two superuser-only operator-class chunks
stripped). v3 currently supports the direct install path only —
--drizzle/--migration/--migrations-dir/--latestare rejected — and the
installer keysisInstalled/version checks and Supabase grants to theeql_v3
schema. -
0b9b192: Rename
stash db installtostash eql install. The command scaffolds
stash.config.tsand installs the EQL extensions, so it now lives under a
dedicatedeqlcommand group.stash db installkeeps working as a
deprecated alias that prints a warning pointing at the new name. All help
text, hints, generated migration headers, and wizard steps now reference
stash eql install. -
e25eb22: Default EQL to v3 and stop the CLI recommending
stash db push(#585).- EQL v3 is now the default.
stash eql installandstash eql upgradetarget v3 (the nativeeql_v3.*domain schema) without--eql-version 3. The v2-only paths —--drizzle,--migration,--migrations-dir, and--latest— now require an explicit--eql-version 2and error with clear guidance otherwise (v3 installs via the direct path only).stash initpins v2 automatically when it drives the Drizzle migration flow. Note: for a Supabase project,stash initnow runs a v3 direct install rather than offering the v2 migration-file flow; runstash eql install --supabase --migration --eql-version 2if you want a checked-in migration file. stash db pushis no longer recommended in CLI output.db pushwrites thepublic.eql_v2_configurationtable, which is a v2 + CipherStash Proxy artifact — EQL v3 has no configuration table (config lives in each column'seql_v3.*type) and nothing in the v3 stack reads it. The push recommendations are removed fromeql status, the help banner, and the init/plan/cutover guidance.db push(anddb activate) remain available for EQL v2 + Proxy users; they're now labelled as such.eql statusis v3-aware. On a v3-only database it reports that encrypt config lives in the column types instead of hitting a "table not found" dead-end that told users to rundb push(which neither creates that table nor applies to v3).stash db pushguards a v3-only database with a clear "not needed under EQL v3" message instead of a rawrelation "public.eql_v2_configuration" does not existerror.
- EQL v3 is now the default.
Patch Changes
-
31ca318: Update the bundled
stash-drizzle,stash-supabase, andstash-encryptionagent
skills (and the stack README / Supabase reference doc) for the adapter package
split: the Drizzle and Supabase integrations import from@cipherstash/stack-drizzle
(+/v3) and@cipherstash/stack-supabaserespectively, installed alongside
@cipherstash/stack, rather than from@cipherstash/stack/{drizzle,supabase,eql/v3/drizzle}
subpaths. Skills ship inside thestashtarball, so the stale import paths would
otherwise become wrong guidance in a user's project. -
82f2e69: Document EQL v3 JSON columns in the bundled skills:
types.Jsonin the
stash-encryptiontyped-schema catalog (capability suffix, family, and an
encrypted-JSONB query section), andcontains(col, subObject)JSON containment
on the v3 Drizzle operators instash-drizzle. -
f23f952: Remove the leftovers from the secrets removal (
1929c8fe), which deleted
packages/stack/src/secrets/but left its export, build entry, skill, and docs
behind. Secrets tooling is not ready; nothing here was functional.- Drop the dead
@cipherstash/stack/secretssubpath export. It pointed at
./dist/secrets/index.js, which has no source and is not in the tarball, so
import '@cipherstash/stack/secrets'has been throwingERR_MODULE_NOT_FOUND
for every consumer since the source was removed. Also drops the dangling
src/secrets/index.tsentry fromtsup.config.ts. Removing an export that
cannot resolve breaks nothing. - Remove the
stash-secretsagent skill and its references inAGENTS.md
and the init setup-prompt skill index. It was never installed bystash init
(it is absent fromSKILL_MAP), so no user project ever received it. - Remove the secrets documentation from both published READMEs: the
Secretsclass API and thenpx stash secretscommand reference in
@cipherstash/stack, and thenpx stash secretssection instash. The CLI
command does not exist —stash secretsreturnsUnknown command.
- Drop the dead
-
1a9d190: Refresh the bundled
stash-cliagent skill and the CLI README against the current
command surface. The skills directory ships inside thestashtarball and is copied
into the user's.claude/skills//.codex/skills/(or inlined intoAGENTS.md) at
handoff time, so a stale skill becomes stale guidance in the user's project.- New
Start hereandAuthenticationsections. Setup is driven through the CLI:
agents readstash manifest --jsonfirst, then triggerstash auth login --jsonand
surface the verification URL for a human to approve, then runstash init. Authenticating
beforeinitmatters —init's auth step is interactive and would otherwise try to open
a browser on the agent's host. - New
Never read theseinvariant, mirrored into theAGENTS.mddoctrine: agents must
never read~/.cipherstash/secretkey.json,~/.cipherstash/auth.json, anything under
~/.cipherstash/workspaces/, or.env*. The wizard already blocks these paths in code;
the other handoff targets had no written rule. - Documents
manifest,doctor,wizard, andauth regions, which the skill omitted
entirely, plus the non-interactive interface (per-command escape hatches, exit codes, the
DATABASE_URLresolution order, theauth login --jsonNDJSON event contract). - Corrects the
db→eqlmove.db install,db upgrade, anddb statusare
deprecated aliases that warn and forward;db push,db activate,db validate,
db test-connection, anddb migrateremain in thedbgroup. - Scopes
db push/db activateas EQL v2 + CipherStash Proxy only, in both the skill
and the README's recommended flow. SDK users hold their encryption config in application
code and don't need them. - Adds the missing
--database-url,--eql-version,--prisma-next,--proxy/--no-proxy,
and--regionflags; corrects six programmatic API signatures; fixes the README's claim
thatstash initends in an agent-handoff menu (that belongs tostash plan/stash impl);
and marksstash envas the non-functional stub it currently is.
- New
-
161f17b: Correct the
stash-drizzleskill:inArray/notInArraynow encrypt the whole
list in a singleencryptQuerybatch crossing (thebulkEncrypt/concurrency
fallback was removed when v3 query operands moved toencryptQuery— #622). The
skill ships inside thestashtarball, so this keeps the bundled guidance in step
with the adapter's behaviour. -
e40c3da: Update the
stash-drizzleandstash-supabaseskills for the EQL v3
contains()→matches()rename (#617): the encrypted free-text operator is now
matches()(fuzzy bloom token matching),contains()is reserved for exact
containment, and Supabaselike()/ilike()on encrypted columns are documented
as an approximate compatibility shim delegating tomatches(). Skills ship inside
thestashtarball, so they must track the adapter surface. -
58d7439: Correct the bundled
stash-supabaseagent skill: EQL v3contains()matches
substrings. The skill previously carried the reverse — thatcontains()matched
only exact values because the query's bloom filter appended the whole search term
as an extra token. That was never true:include_originalis inert in
protect-ffi (the match bloom is trigram-only either way), so any substring of at
least the tokenizer'stoken_length(3 characters) matches, and shorter terms are
rejected rather than silently matching every row. The skills directory ships
inside thestashtarball and is copied into the user's.claude/skills//
.codex/skills/(or inlined intoAGENTS.md) at handoff time, so the stale
sentence was shipping wrong guidance into customer repos. -
Updated dependencies [31ca318]
-
Updated dependencies [c4787c0]
-
Updated dependencies [66a0e02]
-
Updated dependencies [cfd46ee]
-
Updated dependencies [7eba32d]
-
Updated...
@cipherstash/wizard@0.5.0-rc.0
Minor Changes
- 0b9b192: Rename
stash db installtostash eql install. The command scaffolds
stash.config.tsand installs the EQL extensions, so it now lives under a
dedicatedeqlcommand group.stash db installkeeps working as a
deprecated alias that prints a warning pointing at the new name. All help
text, hints, generated migration headers, and wizard steps now reference
stash eql install.
Patch Changes
-
9c673bb: Stop the agent guard from blocking
.env.example.SENSITIVE_FILE_PATTERNSmatched/\.env($|\.)/, which tests true against
.env.example. Because the guard coversEditandWriteas well asRead,
the wizard's agent was blocked from creating or editing the very file the
CipherStash doctrine tells it to write ("New env keys go in.env.examplewith
placeholders"). Committed env templates carry placeholder key names, not values..env.example,.env.sampleand.env.templateare now readable and writable.
Everything else is unchanged:.env,.env.local,.env.production, and
value-bearing files that merely start with a template name
(.env.example.local,.env.example.bak) stay blocked, as doauth.json,
secretkey.jsonand credential files. Bash access to any env file — including
the templates — remains blocked;Read/Writeis the sanctioned path.
@cipherstash/stack@1.0.0-rc.0
Major Changes
-
7c7dbca: CipherStash Stack 1.0 (release candidate).
This is the first 1.0-line release of
@cipherstash/stack, the first published
release of the split-out EQL v3 adapters@cipherstash/stack-drizzleand
@cipherstash/stack-supabase, and moves thestashCLI to 1.0 alongside them.
These four packages now version together as the Stack 1.0 family.
Minor Changes
-
31ca318: Split the Drizzle and Supabase integrations into their own packages.
The adapters now ship as first-party packages that depend on
@cipherstash/stack,
following the@cipherstash/prisma-nextprecedent:@cipherstash/stack-drizzle— Drizzle ORM integration. EQL v2 on the package
root (@cipherstash/stack-drizzle:encryptedType,extractEncryptionSchema,
createEncryptionOperators) and EQL v3 on@cipherstash/stack-drizzle/v3
(typesfactories,createEncryptionOperatorsV3,extractEncryptionSchemaV3, …).@cipherstash/stack-supabase— Supabase integration:encryptedSupabase(v2)
andencryptedSupabaseV3(v3, connect-time introspection).
Breaking (
@cipherstash/stack): the./drizzle,./supabase, and
./eql/v3/drizzlesubpath exports are removed. Migrate imports:@cipherstash/stack/drizzle→@cipherstash/stack-drizzle@cipherstash/stack/eql/v3/drizzle→@cipherstash/stack-drizzle/v3@cipherstash/stack/supabase→@cipherstash/stack-supabase
Add the relevant package to your dependencies alongside
@cipherstash/stack. A new
@cipherstash/stack/adapter-kitsubpath exposes the narrow core internals the
first-party adapters consume; it is the core↔adapter seam, not general-purpose API. -
c4787c0: Restore the EQL v3 envelope and
Resulttypes the adapters were erasing.Both v3 adapters typed their operand-encryption paths as
unknownand dropped
theResultwrapper, so the query-type encoding and the failure channel were
invisible to the type system:eql/v3/drizzle/operators.tstyped the client'sencrypt/bulkEncryptas
returningunknown, collapsed the operation'sResultto
{ data?: unknown; failure?: { message } }, and cast the bulk response to
Array<{ data: unknown }>.supabase/query-builder-v3.tsreturnedPromise<unknown[]>from
encryptCollectedTerms,bulkEncryptGroupandencryptGroupPerTerm, and the
basequery-builder.tsdid the same.
These now carry the SDK's real types —
Encrypted(the storage envelope union,
which includes every v3 per-domain payload),BulkEncryptedData, and
EncryptedQueryResult— threaded through a properly-typed operation surface that
resolvesResult<T, EncryptionError>. The Supabase divergence the erasure hid is
now explicit: the v2 path yieldsencryptQuerycomposite literals and the v3
path yieldsJSON.stringify'd envelope strings, and both areEncryptedQueryResult.Bumped
minor, notpatch:createEncryptionOperatorsV3is a public export
(@cipherstash/stack/eql/v3/drizzle), and tightening its client contract from
unknownto a typed operation surface is a compile-time breaking change — a
downstream consumer passing a loosely-typed (unknown-returning) client double
will now failtsc. That tightening has teeth:operators.test-d.tspins it
with a negative type-test asserting anunknown-returning{ encrypt }double
is rejected (a positive "correctly-typed double is accepted" assertion cannot
catch a re-erasure, since a correct value is assignable tounknown).Behaviour is otherwise unchanged, with one addition: the Supabase v3 bulk path
now rejects anullenvelope returned bybulkEncrypt(the restored
Encrypted | nulltype makes that arm reachable, and anullwould otherwise
beJSON.stringify'd to the literal"null"and sent as a filter operand). -
66a0e02: Add the EQL v3 bigint domain family to the public DSL:
types.Bigint,
types.BigintEq,types.BigintOrdOre, andtypes.BigintOrd, backed by the
public.bigint*concrete domains. Plaintext is a JSbigint, round-tripped
losslessly across the protect-ffi 0.28 boundary (i64 bounds enforced at the
FFI — out-of-range values surface as encryption errors). Index emission follows
the numeric rule:bigint_eq→ unique (hm);bigint_ord/bigint_ord_ore→
ore (equality answered via ob). -
7eba32d: EQL v3 Drizzle: encrypt every query operand with
encryptQuery, notencrypt(#622).The v3 Drizzle operators (
eq/ne/gt/gte/lt/lte/between/notBetween/
inArray/notInArray/contains) previously encrypted their operands with
client.encrypt, producing a full storage envelope (including the ciphertextc)
cast to::jsonb. A WHERE-clause operand should be a query term, not a value to
store. Every operator now usesclient.encryptQuery, which yields a
ciphertext-free query term cast to the column'seql_v3.query_<domain>type — so
predicates carry no ciphertext and reach the bundle's(domain, query_<domain>)
operator overloads. This unifies the scalar/text operators with the JSON
containment path (already onencryptQuery) and removes the previously-optional
encryptQueryguard: it is now a required capability of the operand client.@cipherstash/stackgains a batchencryptQuery(terms)overload on
TypedEncryptionClient(the typeEncryptionV3returns), mirroring the nominal
EncryptionClient. This is additive — it letsinArray/notInArrayencrypt a
whole list of query terms in one crossing. -
0ebf57e: Close two fail-open paths in the EQL v3 Drizzle adapter.
ops.contains()now throwsEncryptionOperatorErrorfor a search term that
tokenizes to nothing: the empty string, or a term shorter than the match index
tokenizer'stoken_length(3 by default). Such a term produces an empty bloom
filter, andstored_bf @> '{}'is true for every row — so a user searching
"ad"silently received the entire table. Measured live, the terms"ad",
"a"and"x"each returned every seeded row, including one in which"x"
did not appear.The floor counts Unicode codepoints, matching the tokenizer. A UTF-16 length
check would wave through an astral-plane term —"👍👍"is 4 code units but
only 2 codepoints, yields no trigram, and matched every row.Breaking for callers passing short terms:
contains()calls that previously
returned every row now throw. Terms of 3+ codepoints are unaffected.v3FromDriver()now throws the newEqlV3CodecErroron a payload that is not
an EQL envelope, instead of surfacing a rawSyntaxErrorfor malformed JSON and
passing a bare scalar through unchecked —v3FromDriver('5')previously returned
5typed asEncrypted, which then reacheddecryptas garbage. The guard
accepts both scalar envelopes (ciphertext atc) and SteVec documents
(ciphertext atsv[0].c). A SteVec'ssvmust be a non-empty array:sv[0]is
the decryption root, sosv: []carries a ciphertext key but no ciphertext, and
is now rejected rather than passed todecrypt.EqlV3CodecErroris exported
from@cipherstash/stack/eql/v3/drizzleso callers can catch it.Also removes an unreachable branch in
inArray/notInArray, whose empty-list
guard already throws before it.Note: the v2 Drizzle adapter's
like/ilikepath builds the same bloom filters
and has the same short-term fail-open. It is not fixed here — v2 terms carry
SQL wildcards, so the floor must be measured against what its tokenizer actually
receives before the shared guard can be reused. Tracked separately. -
d73a03c: Add EQL v3 Drizzle support at
@cipherstash/stack/eql/v3/drizzle. A Drizzle-native
typesnamespace (same PascalCase names as@cipherstash/stack/eql/v3) declares
encrypted columns whose Postgres type is the semanticpublic.<domain>; the concrete
type drives the legal query operators.createEncryptionOperatorsV3provides
capability-checkedeq/ne/gt/gte/lt/lte/between/contains/inArray/
asc/desc/and/orthat emit the latest two-argumenteql_v3SQL functions with
full-envelope operands, and
extractEncryptionSchemaV3rebuilds the schema forEncryptionV3. The existing v2
@cipherstash/stack/drizzleintegration is unchanged.The v3 text-search helper is
contains; obsoletelike/ilikehelpers are not
exposed because v3 free-text search is token containment rather than SQL wildcard
matching. -
89b903f: Upgrade
@cipherstash/protect-ffito 0.28.0 and update EQL v3 concrete Postgres domain names to match the SQL fixture (integer*,smallint*,bool,real*, anddouble*). The public factories remain semantic (Integer,Smallint,Boolean,Real,Double) while their concrete domains change, so this is a minor release. -
229ce59: Re-baseline EQL v3 on the eql-3.0.0 GA release and protect-ffi 0.29.
- Breaking (v3 preview surface): the EQL v3 column domains follow the
eql-3.0.0 naming convention — flat, prefixed names inpublic
(public.eql_v3_text_search,public.eql_v3_integer_ord, …) instead of the
alpha-era bare names. Databases installed from an alpha bundle must be
re-installed (stash eql install --eql-version 3replaces the schema). encryptQueryundereqlVersion: 3now returns EQL v3 query operands
(protect-ffi 0.29): term-only scalar operands for theeql_v3.query_<name>
domains, theeql_v3.query_jsonbcontainment needle, and bare selector
hashes for JSON path queries — v3 scalar and selector queries no longer
throwEQL_V3_QUERY_UNSUPPORTED(the code is gone).- v2
searchableJson()columns now pin the SteVec encoding tostandard
explicitly. protect-ffi 0.29 flipped the library default tocompat
(EQL v3's encoding); without the pin, v2 JSON containment queries would
silently match nothing and newly written rows would...
- Breaking (v3 preview surface): the EQL v3 column domains follow the
@cipherstash/stack-supabase@1.0.0-rc.0
Major Changes
-
7c7dbca: CipherStash Stack 1.0 (release candidate).
This is the first 1.0-line release of
@cipherstash/stack, the first published
release of the split-out EQL v3 adapters@cipherstash/stack-drizzleand
@cipherstash/stack-supabase, and moves thestashCLI to 1.0 alongside them.
These four packages now version together as the Stack 1.0 family.
Minor Changes
-
31ca318: Split the Drizzle and Supabase integrations into their own packages.
The adapters now ship as first-party packages that depend on
@cipherstash/stack,
following the@cipherstash/prisma-nextprecedent:@cipherstash/stack-drizzle— Drizzle ORM integration. EQL v2 on the package
root (@cipherstash/stack-drizzle:encryptedType,extractEncryptionSchema,
createEncryptionOperators) and EQL v3 on@cipherstash/stack-drizzle/v3
(typesfactories,createEncryptionOperatorsV3,extractEncryptionSchemaV3, …).@cipherstash/stack-supabase— Supabase integration:encryptedSupabase(v2)
andencryptedSupabaseV3(v3, connect-time introspection).
Breaking (
@cipherstash/stack): the./drizzle,./supabase, and
./eql/v3/drizzlesubpath exports are removed. Migrate imports:@cipherstash/stack/drizzle→@cipherstash/stack-drizzle@cipherstash/stack/eql/v3/drizzle→@cipherstash/stack-drizzle/v3@cipherstash/stack/supabase→@cipherstash/stack-supabase
Add the relevant package to your dependencies alongside
@cipherstash/stack. A new
@cipherstash/stack/adapter-kitsubpath exposes the narrow core internals the
first-party adapters consume; it is the core↔adapter seam, not general-purpose API. -
e40c3da: Rename the EQL v3 encrypted free-text operator
contains()→matches()(#617).Encrypted free-text search is fuzzy bloom-filter token matching — order- and
multiplicity-insensitive and one-sided (atruemay be a false positive) — not
containment. The namecontains()promised substring/containment semantics it
never had. It is renamed tomatches()on the encrypted surface;contains()is
kept for genuine, exact containment:- Drizzle (
@cipherstash/stack-drizzle/v3):matches()= bloom free-text on
text_match/text_searchcolumns;contains()= exact encrypted-JSON@>on
types.Json(ste_vec) columns. - Supabase (
@cipherstash/stack-supabase):.matches()= encrypted free-text;
.contains()= native jsonb/array@>on plaintext columns (and throws on an
encrypted column, pointing tomatches()).
Also on the Supabase v3 surface,
like()/ilike()on an encrypted column are no
longer rejected — they are delegated tomatches()as a best-effort compatibility
shim. This is APPROXIMATE (fuzzy, case-insensitive, one-sided; anchoring and
wildcards are not honored): surrounding%are stripped, an internal%or any
_is rejected, and a one-time warning is emitted. A plaintext column keeps real
SQL LIKE.Breaking: encrypted
contains()callers must migrate tomatches(). The
encrypted operator has not shipped in a stable release (it lands via the EQL v3
work), so there is no deprecation alias. - Drizzle (
Patch Changes
- 2fd4985: Populate
EncryptedSupabaseError.encryptionErroron encryption failures (#626).
The query builder's catch block previously hardcodedencryptionError: undefined,
so the typed field was always empty and callers had to detect encryption failures
indirectly (viastatus/statusTextor.throwOnError()). It now threads the
underlyingEncryptionErrorthrough — for both the v2 and v3 dialects — when the
failure originates in an encrypt/decrypt step, and leaves it unset for plain
PostgREST/API errors. - Updated dependencies [31ca318]
- Updated dependencies [c4787c0]
- Updated dependencies [66a0e02]
- Updated dependencies [cfd46ee]
- Updated dependencies [7eba32d]
- Updated dependencies [0ebf57e]
- Updated dependencies [d73a03c]
- Updated dependencies [89b903f]
- Updated dependencies [229ce59]
- Updated dependencies [50c0a9c]
- Updated dependencies [63ca540]
- Updated dependencies [5d23e80]
- Updated dependencies [1aa9a11]
- Updated dependencies [af2d04e]
- Updated dependencies [b8a3d20]
- Updated dependencies [a0f3b2c]
- Updated dependencies [f23f952]
- Updated dependencies [7c7dbca]
- Updated dependencies [5411a13]
- Updated dependencies [99f8b0a]
- Updated dependencies [fd33aad]
- Updated dependencies [8cd485d]
- Updated dependencies [9b65ae8]
- @cipherstash/stack@1.0.0-rc.0
@cipherstash/stack-drizzle@1.0.0-rc.0
Major Changes
-
7c7dbca: CipherStash Stack 1.0 (release candidate).
This is the first 1.0-line release of
@cipherstash/stack, the first published
release of the split-out EQL v3 adapters@cipherstash/stack-drizzleand
@cipherstash/stack-supabase, and moves thestashCLI to 1.0 alongside them.
These four packages now version together as the Stack 1.0 family.
Minor Changes
-
31ca318: Split the Drizzle and Supabase integrations into their own packages.
The adapters now ship as first-party packages that depend on
@cipherstash/stack,
following the@cipherstash/prisma-nextprecedent:@cipherstash/stack-drizzle— Drizzle ORM integration. EQL v2 on the package
root (@cipherstash/stack-drizzle:encryptedType,extractEncryptionSchema,
createEncryptionOperators) and EQL v3 on@cipherstash/stack-drizzle/v3
(typesfactories,createEncryptionOperatorsV3,extractEncryptionSchemaV3, …).@cipherstash/stack-supabase— Supabase integration:encryptedSupabase(v2)
andencryptedSupabaseV3(v3, connect-time introspection).
Breaking (
@cipherstash/stack): the./drizzle,./supabase, and
./eql/v3/drizzlesubpath exports are removed. Migrate imports:@cipherstash/stack/drizzle→@cipherstash/stack-drizzle@cipherstash/stack/eql/v3/drizzle→@cipherstash/stack-drizzle/v3@cipherstash/stack/supabase→@cipherstash/stack-supabase
Add the relevant package to your dependencies alongside
@cipherstash/stack. A new
@cipherstash/stack/adapter-kitsubpath exposes the narrow core internals the
first-party adapters consume; it is the core↔adapter seam, not general-purpose API. -
7eba32d: EQL v3 Drizzle: encrypt every query operand with
encryptQuery, notencrypt(#622).The v3 Drizzle operators (
eq/ne/gt/gte/lt/lte/between/notBetween/
inArray/notInArray/contains) previously encrypted their operands with
client.encrypt, producing a full storage envelope (including the ciphertextc)
cast to::jsonb. A WHERE-clause operand should be a query term, not a value to
store. Every operator now usesclient.encryptQuery, which yields a
ciphertext-free query term cast to the column'seql_v3.query_<domain>type — so
predicates carry no ciphertext and reach the bundle's(domain, query_<domain>)
operator overloads. This unifies the scalar/text operators with the JSON
containment path (already onencryptQuery) and removes the previously-optional
encryptQueryguard: it is now a required capability of the operand client.@cipherstash/stackgains a batchencryptQuery(terms)overload on
TypedEncryptionClient(the typeEncryptionV3returns), mirroring the nominal
EncryptionClient. This is additive — it letsinArray/notInArrayencrypt a
whole list of query terms in one crossing. -
e40c3da: Rename the EQL v3 encrypted free-text operator
contains()→matches()(#617).Encrypted free-text search is fuzzy bloom-filter token matching — order- and
multiplicity-insensitive and one-sided (atruemay be a false positive) — not
containment. The namecontains()promised substring/containment semantics it
never had. It is renamed tomatches()on the encrypted surface;contains()is
kept for genuine, exact containment:- Drizzle (
@cipherstash/stack-drizzle/v3):matches()= bloom free-text on
text_match/text_searchcolumns;contains()= exact encrypted-JSON@>on
types.Json(ste_vec) columns. - Supabase (
@cipherstash/stack-supabase):.matches()= encrypted free-text;
.contains()= native jsonb/array@>on plaintext columns (and throws on an
encrypted column, pointing tomatches()).
Also on the Supabase v3 surface,
like()/ilike()on an encrypted column are no
longer rejected — they are delegated tomatches()as a best-effort compatibility
shim. This is APPROXIMATE (fuzzy, case-insensitive, one-sided; anchoring and
wildcards are not honored): surrounding%are stripped, an internal%or any
_is rejected, and a one-time warning is emitted. A plaintext column keeps real
SQL LIKE.Breaking: encrypted
contains()callers must migrate tomatches(). The
encrypted operator has not shipped in a stable release (it lands via the EQL v3
work), so there is no deprecation alias. - Drizzle (
Patch Changes
- Updated dependencies [31ca318]
- Updated dependencies [c4787c0]
- Updated dependencies [66a0e02]
- Updated dependencies [cfd46ee]
- Updated dependencies [7eba32d]
- Updated dependencies [0ebf57e]
- Updated dependencies [d73a03c]
- Updated dependencies [89b903f]
- Updated dependencies [229ce59]
- Updated dependencies [50c0a9c]
- Updated dependencies [63ca540]
- Updated dependencies [5d23e80]
- Updated dependencies [1aa9a11]
- Updated dependencies [af2d04e]
- Updated dependencies [b8a3d20]
- Updated dependencies [a0f3b2c]
- Updated dependencies [f23f952]
- Updated dependencies [7c7dbca]
- Updated dependencies [5411a13]
- Updated dependencies [99f8b0a]
- Updated dependencies [fd33aad]
- Updated dependencies [8cd485d]
- Updated dependencies [9b65ae8]
- @cipherstash/stack@1.0.0-rc.0
@cipherstash/schema@3.0.2-rc.0
Patch Changes
- 229ce59:
searchableJson()now pins the SteVec encoding mode tostandardexplicitly.
protect-ffi 0.29 flipped the library default tocompat(the EQL v3
encoding); pinning keeps the v2 wire format byte-stable so existing encrypted
JSON columns stay queryable and comparable.