Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
566 commits
Select commit Hold shift + click to select a range
aabedb8
feat: support date and timestamp plaintexts
coderdan Apr 24, 2026
4dafcc8
Merge pull request #81 from cipherstash/add-date-timestamp-support
coderdan Apr 24, 2026
db984ee
fix(deps): patch aws-lc-sys to 0.40.0
tobyhede Apr 28, 2026
fb3e2d3
fix(deps): patch vite to 7.3.2
tobyhede Apr 28, 2026
1b25484
fix(deps): patch rustls-webpki to 0.103.13
tobyhede Apr 28, 2026
4718d29
Merge pull request #83 from cipherstash/fix-cip-3017-aws-lc-sys-patch
tobyhede Apr 28, 2026
7b8cd8c
Merge pull request #84 from cipherstash/fix-cip-3018-vite-patch
tobyhede Apr 28, 2026
9e7b7a4
Merge pull request #85 from cipherstash/fix-cip-3019-rustls-webpki-patch
tobyhede Apr 28, 2026
cf9e58c
Merge pull request #79 from cipherstash/chore/set-glibc-version
yujiyokoo Apr 28, 2026
22dc9ec
v0.21.3
invalid-email-address Apr 28, 2026
7d21304
v0.21.4
invalid-email-address Apr 30, 2026
3433824
chore(deps): upgrade cipherstash-client to 0.34.1-alpha.4
freshtonic May 12, 2026
ab61d6f
Merge pull request #86 from cipherstash/chore/upgrade-cipherstash-cli…
coderdan May 17, 2026
46aec68
chore(deps): upgrade cipherstash-client to 0.34.1-alpha.5
freshtonic May 19, 2026
53390b4
feat(ste-vec): expose SteVec encoding mode option
freshtonic May 19, 2026
aaa6946
chore: ignore .worktrees/ directory
freshtonic May 19, 2026
df62066
chore(deps): upgrade cipherstash-client to 0.34.1-alpha.7
freshtonic May 19, 2026
6dcba63
feat: add normalizeEncryptConfig cast_as translation helper
freshtonic May 19, 2026
1d1f911
refactor: replace hand-rolled encrypt config with CanonicalEncryption…
freshtonic May 19, 2026
27205fe
feat: normalize encrypt config vocabulary at the FFI boundary
freshtonic May 19, 2026
dba94ff
docs: document CanonicalEncryptionConfig migration and breaking changes
freshtonic May 19, 2026
1893410
docs: correct SteVecMode default in JSDoc + cast_as union snippet
freshtonic May 20, 2026
5697774
test: cover newClient encrypt config validation paths
freshtonic May 20, 2026
a17a6ee
test: update SteVec entry field assertions for Standard mode
freshtonic May 20, 2026
89125ba
docs: update EqlCiphertext field reference for Standard SteVec mode
freshtonic May 20, 2026
fdcf26f
docs: clarify root-level hm is unique-index only
freshtonic May 20, 2026
e424fa0
test: use it.each for cast_as normalization cases
freshtonic May 20, 2026
d83b06b
Merge pull request #92 from cipherstash/refactor/use-eql-types-from-c…
freshtonic May 20, 2026
ff2c8c4
refactor: upgrade cipherstash-client to 0.35.0
freshtonic May 20, 2026
aca3bfe
test: align json-containment with EQL v2.3 SteVec storage layout
freshtonic May 20, 2026
049d808
Merge pull request #93 from cipherstash/refactor/upgrade-cipherstash-…
freshtonic May 20, 2026
529bf11
chore: address PR feedback
calvinbrewer May 20, 2026
67bf65d
chore: simplify
calvinbrewer May 20, 2026
1e6b228
chore: feedback
calvinbrewer May 20, 2026
4d4fa9f
Merge pull request #94 from cipherstash/refactor/upgrade-cipherstash-…
calvinbrewer May 20, 2026
8428cd9
v0.22.0
invalid-email-address May 20, 2026
db9a8cf
fix(types): split storage Encrypted from query payload types
coderdan May 21, 2026
a125a86
fix(types): forbid ciphertext on EncryptedScalarQuery
freshtonic May 21, 2026
37066c0
Merge pull request #95 from cipherstash/fix/split-storage-query-types
freshtonic May 21, 2026
d4d9ff0
v0.23.0
invalid-email-address May 21, 2026
5f327c0
chore: bump deps for wasm-ready cipherstash-client + vitaminc
coderdan May 16, 2026
c6b9220
feat(wasm): cfg-gate Neon-only code so wasm32 compiles
coderdan May 16, 2026
16101c1
feat(wasm): add wasm-bindgen surface in src/wasm.rs
coderdan May 16, 2026
000fc94
fix(wasm): use CanonicalEncryptionConfig after the #92 config refactor
coderdan May 20, 2026
d3aef99
fix: address CodeRabbit review feedback
coderdan May 25, 2026
a026f22
fix(wasm): tighter typing + zeroize for client credentials
coderdan May 25, 2026
b0944c6
fix(wasm): wrap client_key hex in ZeroizeOnDrop newtype from deserial…
coderdan May 25, 2026
143f654
chore: address review feedback from PR #87
coderdan May 25, 2026
4507a42
Merge pull request #87 from cipherstash/feat/wasm-bindings
coderdan May 25, 2026
fa0a7cf
feat(wasm): build pipeline + CI integration
coderdan May 17, 2026
b631340
style: collapse to single template literal in inline-wasm.mjs
coderdan May 25, 2026
967494c
style: apply biome format to inline-wasm.mjs
coderdan May 25, 2026
4cd6acf
chore: address CodeRabbit review on PR #88
coderdan May 25, 2026
d21d84e
fix(wasm): match Neon's flat API shape
coderdan May 25, 2026
b20e9c8
Merge pull request #88 from cipherstash/feat/wasm-build-pipeline
coderdan May 25, 2026
e5d8850
Merge pull request #89 from cipherstash/feat/wasm-api-parity
coderdan May 25, 2026
c476c36
fix(wasm): drop @ts-self-types directive from inline shim
coderdan May 17, 2026
188f706
test(wasm): integration test for end-to-end round-trip
coderdan May 25, 2026
6043402
Merge pull request #90 from cipherstash/feat/wasm-edge-spike
coderdan May 26, 2026
35444a6
v0.24.0
invalid-email-address May 26, 2026
f5ae97f
feat: accept opts.strategy on both Node and WASM newClient
coderdan May 28, 2026
f3ac1c6
fix(clippy): box AutoStrategy variant and use async fn syntax
coderdan May 28, 2026
77d1094
feat: bump cipherstash-client to 0.36 release branch
coderdan May 28, 2026
7469ee7
chore: swap 0.36 release-plz branch deps for crates.io versions
coderdan May 28, 2026
1ac1bde
fix(node): capture per-isolate Channel for JsBacked strategy
coderdan May 28, 2026
ee151a7
fix(node): unref the JS-backed strategy Channel so scripts can exit
coderdan May 28, 2026
ecdc3b1
test: update auth env to CS_WORKSPACE_CRN for stack-auth 0.36
coderdan May 28, 2026
b6a4e9e
test(wasm): update wasm-round-trip to EQL v2.3 scalar shape
coderdan May 28, 2026
a59200e
test: add behavioural suite for opts.strategy (JsBacked) path
coderdan May 28, 2026
29c1fe5
fix(node): use Context::try_catch around the get_token JS call
coderdan May 28, 2026
147e624
style: apply biome 1.8.3 formatting to integration-test additions
coderdan May 28, 2026
8e23da7
ci: build wasm artifacts before running integration tests
coderdan May 28, 2026
a8676b2
ci: install wasm-pack on the Tests workflow
coderdan May 28, 2026
66244c7
test: cover non-callable getToken and wasm required-strategy guards
coderdan May 29, 2026
e77dc23
Merge pull request #96 from cipherstash/feat/strategy-in-opts
coderdan May 29, 2026
88a969c
v0.25.0
invalid-email-address May 29, 2026
d4c70c7
ci: publish to npm via OIDC trusted publishing
coderdan Jun 2, 2026
6f46bfc
chore: bump cipherstash-client and stack-auth to 0.37.0
coderdan Jun 6, 2026
0ef5cff
test: scaffold pending OidcFederation strategy tests
coderdan Jun 6, 2026
6e891ab
test: wire OidcFederation against @cipherstash/auth 0.39.0
coderdan Jun 6, 2026
06195dc
test: address review on OidcFederation test
coderdan Jun 6, 2026
245532b
test: keep a single hermetic OidcFederation contract test
coderdan Jun 8, 2026
5992207
Merge pull request #100 from cipherstash/chore/bump-cipherstash-stack…
coderdan Jun 8, 2026
acafdda
ci: harden release publish job (address review)
coderdan Jun 8, 2026
6d542f4
ci: scope the publisher app token to contents:write (address review)
coderdan Jun 8, 2026
1b64ada
fix(npm): point dryrun script at release.yml
coderdan Jun 8, 2026
6184293
Merge pull request #99 from cipherstash/ci/npm-oidc-trusted-publishing
coderdan Jun 8, 2026
7de2728
v0.26.0
invalid-email-address Jun 8, 2026
aa6858d
chore(deps): bump cipherstash-client to 0.38.0 (stack-auth access-key…
freshtonic Jun 24, 2026
a328882
Merge pull request #103 from cipherstash/james/cip-3233-bump-cipherst…
freshtonic Jun 24, 2026
2e7e805
build(deps): add eql-bindings path dependency for EQL v3 payloads
freshtonic Jul 2, 2026
50dc8dd
feat: eqlVersion validation and v3 target domain selection
freshtonic Jul 2, 2026
8b0de6b
feat: dual-format storage/query conversion and version-agnostic decry…
freshtonic Jul 2, 2026
3d89ded
feat: dual-format wiring for Neon and wasm exports
freshtonic Jul 2, 2026
8eafe13
feat(ts): eqlVersion option, vendored EQL v3 types, EncryptedPayload …
freshtonic Jul 2, 2026
0e116ac
test: EQL v3 integration suites and eql_v3 schema provisioning
freshtonic Jul 2, 2026
3d33703
docs: EQL version selection (README) and v3 output shapes (jsonb API …
freshtonic Jul 2, 2026
3d843bd
fix: address code review feedback
freshtonic Jul 2, 2026
cbf62a2
fix(eql-v3): v3 SteVec documents carry k:"sv"; probe v3 before the v2…
freshtonic Jul 2, 2026
35b8992
chore(types): re-vendor EQL v3 TS types — SteVecDocument gains k: Ste…
freshtonic Jul 2, 2026
d128989
docs: v3 SteVec documents carry k:"sv" on the wire
freshtonic Jul 2, 2026
285bd33
test: address code review feedback on the k:"sv" reconciliation
freshtonic Jul 2, 2026
690e5e6
chore(deps): swap eql-bindings to the crates.io release (=0.2.0)
freshtonic Jul 3, 2026
2db5b0a
fix(decrypt): map Plaintext Int/SmallInt/Decimal to JS numbers
freshtonic Jul 3, 2026
7ac8d82
test(integration): commit the EQL v3 installer snapshot so CI can pro…
freshtonic Jul 3, 2026
c293d38
fix(eql-v3): fail closed on term-dropping index combinations
freshtonic Jul 3, 2026
54df2f7
fix(auth): try_catch the token getter in the strategy promise callback
freshtonic Jul 3, 2026
99e3e4e
docs(readme): fix the EncryptedPayload narrowing example
freshtonic Jul 3, 2026
17d6f9a
test(config): assert the new canonical cast_as values survive normali…
freshtonic Jul 3, 2026
062f06a
test(integration): decryptBulk round-trips a mixed v2 + v3 batch
freshtonic Jul 3, 2026
e2f9c87
test(integration): type the common helper with the EncryptedPayload u…
freshtonic Jul 3, 2026
90fff9d
fix(integration): make the v3 snapshot rebuild opt-in and self-verifying
freshtonic Jul 3, 2026
d64d777
fix(errors): map InvalidCiphertext to a stable INVALID_CIPHERTEXT code
freshtonic Jul 3, 2026
27010ff
fix(types): add 'ope' to IndexTypeName so configured ope indexes are …
freshtonic Jul 3, 2026
d03d6d0
fix(encrypt): error instead of truncating JS numbers for integer casts
freshtonic Jul 3, 2026
0f593a7
refactor(imports): share the eql_v3 import between Neon and wasm targets
freshtonic Jul 3, 2026
2698082
refactor(eql-v3): replace the raw u8 eql version with a #[repr(u8)] E…
freshtonic Jul 3, 2026
bbc3404
fix(eql-v3): fail closed on text index combinations that would drop a…
freshtonic Jul 3, 2026
7e3e17d
test(integration): float-as-integer encrypt now errors instead of tru…
freshtonic Jul 3, 2026
6de5d65
refactor(eql-v3): carry DomainPayload in EncryptedOutput::V3 (eql-bin…
freshtonic Jul 3, 2026
47a765a
test(integration): make the config -> eql_v3 domain mapping load-bearing
freshtonic Jul 3, 2026
aaf7dc7
chore(types): re-vendor EQL v3 TS types from eql-bindings 0.3.0 (SQL-…
freshtonic Jul 3, 2026
25dbfef
refactor(eql-v3): carry QueryPayload in QueryOutput::V3 (eql-bindings…
freshtonic Jul 3, 2026
8ae3b36
test(integration): refresh the v3 SQL snapshot past the domain renames
freshtonic Jul 3, 2026
298e466
chore(deps): bump eql-bindings to 0.4.2
freshtonic Jul 3, 2026
f1cd4de
ci: run the Test workflow for the eql_v3 staging branch
freshtonic Jul 3, 2026
57ce453
Merge pull request #104 from cipherstash/feat/eql-v3-dual-format
freshtonic Jul 3, 2026
9b8f52f
chore(deps): bump cipherstash-client and stack crates to 0.38.1
freshtonic Jul 3, 2026
13a2a77
test(eql-v3): real-ciphertext _ord_ope coverage on client 0.38.1
freshtonic Jul 3, 2026
d2cc510
docs+meta: resolve license contradiction (MIT), fix rename fallout an…
coderdan Jul 4, 2026
4fa02f7
docs+meta: address review feedback
coderdan Jul 4, 2026
a5a211d
docs(jsonb): replace ASCII diagrams with Mermaid
coderdan Jul 4, 2026
c4b9039
Merge pull request #116 from cipherstash/docs/meta-refresh
coderdan Jul 4, 2026
1296016
ci: pass glibc-versioned target to cargo-zigbuild as a flag
freshtonic Jul 4, 2026
471bbac
Merge pull request #118 from cipherstash/fix/zigbuild-glibc-target-flag
freshtonic Jul 4, 2026
a427841
v0.26.1-0
invalid-email-address Jul 4, 2026
ca379eb
v0.27.0
invalid-email-address Jul 4, 2026
6d9c155
Merge pull request #115 from cipherstash/feat/cip-3348-ope-round-trip
freshtonic Jul 5, 2026
62b10ed
ci: pin zig and cargo-zigbuild in mise.toml (CIP-3405)
freshtonic Jul 5, 2026
15a8092
ci: pass glibc-versioned target to cargo-zigbuild as a flag
freshtonic Jul 4, 2026
72db5c5
docs: add CHANGELOG, automate release notes, refresh README
coderdan Jul 5, 2026
262a358
docs+ci: address Copilot review on #121
coderdan Jul 6, 2026
32ec50a
changelog: harden extract link-block detection; note Breaking category
coderdan Jul 6, 2026
15d8f04
Merge pull request #121 from cipherstash/docs/changelog-and-release-n…
coderdan Jul 6, 2026
9d8a74a
ci: gate the binaries job's version input (match the wasm job)
coderdan Jul 6, 2026
76a6a5a
ci: harden release.yml Tag Release version input
coderdan Jul 6, 2026
cf52261
ci: correct allowlist comment to match patterns (drop 'build metadata')
coderdan Jul 6, 2026
c39d929
v0.27.1-0
invalid-email-address Jul 6, 2026
e8abfcc
Merge pull request #124 from cipherstash/ci/gate-binaries-version-input
coderdan Jul 6, 2026
752de6a
feat!: accept and return JS BigInt plaintexts (i64-bounded)
freshtonic Jul 5, 2026
46606f9
test: cover bigint round-trips, bounds rejection, and v3 bigint domains
freshtonic Jul 5, 2026
46a5fa5
docs: document BigInt plaintext support and the breaking decrypt change
freshtonic Jul 5, 2026
486e1d1
fix(wasm): canonicalize plaintexts through JSON.stringify for Neon pa…
freshtonic Jul 6, 2026
b3ab5d5
fix,test,docs: address PR #120 review feedback
freshtonic Jul 6, 2026
053fc4b
fix(wasm): decrypt json documents to plain objects, not JS Maps
freshtonic Jul 6, 2026
3482f4b
Merge pull request #120 from cipherstash/feat/js-bigint-plaintext
freshtonic Jul 6, 2026
7ace44b
Merge pull request #119 from cipherstash/james/cip-3405-pin-cargo-zig…
freshtonic Jul 6, 2026
dceaea8
fix: consume @cipherstash/auth 0.41 Result-shaped getToken
coderdan Jul 7, 2026
3397baa
fix: accept both bare and Result-shaped getToken (backward compatible)
coderdan Jul 7, 2026
6bfcb9e
feat: reconstruct auth failures via stack_auth::AuthError::from_error…
coderdan Jul 7, 2026
359707a
fix(wasm): guard non-object getToken result; propagate Reflect errors
coderdan Jul 7, 2026
c37f1a1
test: cover the 0.41 Result success + failure envelopes (js-strategy)
coderdan Jul 7, 2026
faf492d
Merge pull request #125 from cipherstash/fix/auth-0.41-result-gettoken
coderdan Jul 7, 2026
4e12f1a
docs(changelog): record unreleased changes since 0.26.0
coderdan Jul 7, 2026
e1fafc9
Merge branch 'main' into eql_v3
coderdan Jul 8, 2026
a1bb91a
fix(auth): harden failure-envelope reconstruction on both seams
coderdan Jul 8, 2026
9590220
test: cover the gaps flagged in the PR test-coverage review
coderdan Jul 8, 2026
f998f7c
test+fix: address remaining PR review threads (CodeRabbit + Toby)
coderdan Jul 8, 2026
70bd8ff
Merge pull request #127 from cipherstash/eql_v3
coderdan Jul 8, 2026
fc58f7d
v0.28.0
invalid-email-address Jul 8, 2026
768f97c
build(deps): eql-bindings 3.0.0-alpha.3
freshtonic Jul 8, 2026
f7ad9d6
feat(rust): EQL v3 scalar + selector query encryption — CIP-3423
freshtonic Jul 8, 2026
6a1dd13
feat(ts): v3 query operand types, errors, vendored bindings
freshtonic Jul 8, 2026
fe60256
chore(sql): refresh the EQL v3 snapshot to 3.0.0-alpha.3 from the crate
freshtonic Jul 8, 2026
3bea534
test(integration): EQL v3 query round-trips
freshtonic Jul 8, 2026
e1893b1
docs: EQL v3 query support
freshtonic Jul 8, 2026
1133fca
chore(changelog): 0.29.0 notes for the EQL v3 query path
freshtonic Jul 8, 2026
30c44ca
chore(types): vendor TS types from the locked eql-bindings release
freshtonic Jul 8, 2026
49c944e
docs: release-agnostic phrasing for scalar query support
freshtonic Jul 8, 2026
0723c5a
docs: the SteVec storage domain is public.json, not eql_v3.json
freshtonic Jul 8, 2026
e5274ec
refactor(rust): one prepare_query_plaintext seam for all query entry …
freshtonic Jul 8, 2026
1268c52
Merge pull request #128 from cipherstash/james/cip-3423-protectjs-ffi…
freshtonic Jul 8, 2026
4381bd3
fix: type AuthStrategy as the contract the runtime already implements
coderdan Jul 9, 2026
b52b1b9
docs: address review — name the Promise contract, fix the wasm.rs path
coderdan Jul 9, 2026
05cba5c
Merge pull request #131 from cipherstash/fix/authstrategy-result-enve…
coderdan Jul 9, 2026
e78985f
chore(deps)!: eql-bindings 3.0.0, cipherstash-client 0.40.0
freshtonic Jul 9, 2026
9307db4
fix(types): SteVecEntry carries `op`; migrate v2 sv assertions to CLL…
freshtonic Jul 9, 2026
d12df48
fix(tests): call the renamed v3 ord extractors in postgres-v3
coderdan Jul 9, 2026
ba7ec04
fix(tests): pin v2 ste_vec to `standard`, restoring the `oc` assertions
coderdan Jul 9, 2026
ce5a806
Merge pull request #132 from cipherstash/james/cip-3423-protectjs-ffi…
coderdan Jul 9, 2026
8c1da6b
v0.29.0
invalid-email-address Jul 9, 2026
8e2e28d
fix: reject match query needles that tokenize to nothing (SHORT_MATCH…
coderdan Jul 17, 2026
a9df66e
chore(deps): bump cipherstash-client to 0.41.1
claude Jul 17, 2026
e17830b
fix(errors): add sentence separator in ShortMatchNeedle message
claude Jul 17, 2026
d445749
Merge pull request #139 from cipherstash/fix/short-match-needle-guard
coderdan Jul 17, 2026
d652e4b
fix(deps): resolve open Dependabot security alerts
coderdan Jul 17, 2026
85abaa7
Merge pull request #140 from cipherstash/fix/dependabot-security-alerts
coderdan Jul 17, 2026
d21a87a
Merge pull request #126 from cipherstash/docs/changelog-unreleased
coderdan Jul 17, 2026
74c9fae
feat(protect-ffi): emit v3 storage payloads natively via encrypt_eql_v3
freshtonic Jul 14, 2026
fada52f
feat(protect-ffi): emit v3 query operands natively via encrypt_eql_v3
freshtonic Jul 15, 2026
9ee584d
build(deps): drop the [patch.crates-io] suite redirect for released 0…
freshtonic Jul 17, 2026
469cd76
build(deps)!: adopt eql-bindings 3.0.1 — json_search domain + @@ matc…
freshtonic Jul 17, 2026
2df823c
fix(errors): keep the EQL_V3_CONVERSION_FAILED contract on native par…
freshtonic Jul 17, 2026
dee3ea5
Merge pull request #136 from cipherstash/james/cip-3359-c-protect-ffi…
coderdan Jul 18, 2026
a8ea398
feat: support cipherstash-client 0.42 SteVec wire format
coderdan Jul 19, 2026
5c57d8d
build: adopt published EQL 3.0.2 packages
coderdan Jul 20, 2026
347d8f7
test: emit an actual v2 domain fixture
coderdan Jul 20, 2026
5cffa3c
fix: address PR 141 review feedback
coderdan Jul 20, 2026
0f92dbb
Merge pull request #141 from cipherstash/dan/cipherstash-client-0.42
coderdan Jul 20, 2026
361f026
v0.30.0
invalid-email-address Jul 20, 2026
00cec83
fix(query): strip match include_original from query-term generation
freshtonic Jul 20, 2026
5cb3140
refactor(query): build the query config in a single map pass
freshtonic Jul 23, 2026
90315fb
feat: declare the real option types on the wasm build (#142)
coderdan Jul 26, 2026
3f663a0
feat!: rename strategy to authStrategy, and fix the wasm newClient type
coderdan Jul 26, 2026
2616b6a
refactor!: wasm newClient takes the same NewClientOptions as native
coderdan Jul 26, 2026
c3b3238
refactor!: normalise encryptConfig in Rust, and fix the wasm integrat…
coderdan Jul 26, 2026
72eac91
docs(changelog): the wasm newClient divergences are resolved, not shi…
coderdan Jul 26, 2026
7c37849
fix: drop the now-unused CanonicalEncryptionConfig import
coderdan Jul 26, 2026
f6f7bc7
refactor: generate the wasm .d.ts from Rust, dropping the patch script
coderdan Jul 26, 2026
7a126e7
docs: document the breaking wasm changes, and fix the stale docs revi…
coderdan Jul 26, 2026
0609540
Merge pull request #135 from cipherstash/james/issue-134-reject-inclu…
coderdan Jul 27, 2026
45e4c34
merge main, and address the PR 143 review
coderdan Jul 27, 2026
0098f13
refactor: make queryOp a named type in its own module
coderdan Jul 27, 2026
de0b9a9
docs: record what null-pruning costs for non-finite numbers
coderdan Jul 27, 2026
634881f
fix!: reject unknown option keys instead of dropping them (#144)
coderdan Jul 26, 2026
8aaeb2a
fix: address review on the auth-key strip, and drop the war story fro…
coderdan Jul 26, 2026
42d7f3e
fix: copy option objects with try_assign, not assign
coderdan Jul 27, 2026
1f787c0
test: cover the option structs that had no unknown-key test
coderdan Jul 27, 2026
2a2f306
fix: name the newClient option JSON.stringify cannot carry
coderdan Jul 27, 2026
9f34c58
docs: correct the DenyUnknown notes against serde-wasm-bindgen
coderdan Jul 27, 2026
a19b732
Merge pull request #143 from cipherstash/fix/142-wasm-option-types
coderdan Jul 27, 2026
4fe0190
Merge pull request #147 from cipherstash/fix/144-deny-unknown-fields
coderdan Jul 27, 2026
789fb6f
fix: make the wasm32 build lint clean (#145)
coderdan Jul 26, 2026
f9be4d1
ci: give the Rust checks one entry point, and cover wasm32 (#145)
coderdan Jul 26, 2026
a804fd8
feat: derive the error code in Rust and carry it to JS (#146)
coderdan Jul 26, 2026
0ac3b22
feat!: read the error code off the error, not out of the message (#146)
coderdan Jul 26, 2026
794afef
refactor!: delete ProtectError and the wrapper layer around it (#146)
coderdan Jul 26, 2026
4d2cbe2
fix: export wasm error helpers and preserve native stacks
coderdan Jul 27, 2026
71b78ff
fix: keep lint wiring checks inside their task block
coderdan Jul 27, 2026
dccd2fc
Merge pull request #148 from cipherstash/fix/145-lint-wasm-and-fmt
coderdan Jul 27, 2026
5515d97
fix: preserve Neon query operation error codes
coderdan Jul 27, 2026
ac0bb1a
Merge pull request #150 from cipherstash/fix/146-derive-error-codes
coderdan Jul 27, 2026
ce820bb
v0.31.0
invalid-email-address Jul 27, 2026
aa69b3e
Add 'packages/protect-ffi/' from commit 'ce820bb14d19f8d67ad9263df637…
tobyhede Aug 6, 2026
144aa3d
chore(protect-ffi): reconcile the vendored package with this repo
tobyhede Aug 6, 2026
a1b53af
ci: run protect-ffi's own checks from root workflows
tobyhede Aug 6, 2026
9ad87f2
ci: build the binding for the root test job too
tobyhede Aug 6, 2026
e2c7874
test(protect-ffi): cover the missing-binary path of assertNativeBindi…
tobyhede Aug 6, 2026
6ff1608
chore(protect-ffi): give the deferred changeset somewhere to wait
tobyhede Aug 6, 2026
d348f84
ci: drop the dead semver-major cooldown window from Dependabot
tobyhede Aug 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .changeset/brave-hounds-monitor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'stash': patch
---

Correct the Dependabot section of the bundled `stash-supply-chain-security`
skill. It described two monitored ecosystems (`npm`, `github-actions`); there
are now three, because the in-tree Rust workspace at `packages/protect-ffi`
brought a `Cargo.lock` that nothing proposed updates for. The skill now names
the `cargo` entry, its non-root `directory`, its monthly cadence, and the
exact-pinned CipherStash crates it ignores.

Two things the section previously got wrong are also fixed. Major bumps do not
"stay un-grouped — one PR each": every entry ignores
`version-update:semver-major`, so Dependabot proposes no major bumps at all and
they are applied by hand. And `ignore` conditions suppress Dependabot *security*
PRs as well as version updates — the skill now says so, and points at
`osv-scanner.yml` (which scans every lockfile in the tree, `Cargo.lock`
included) as the compensating control.
9 changes: 9 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
"@cipherstash/stack-supabase",
"@cipherstash/stack-prisma",
"@cipherstash/wizard"
],
[
"@cipherstash/protect-ffi",
"@cipherstash/protect-ffi-darwin-x64",
"@cipherstash/protect-ffi-darwin-arm64",
"@cipherstash/protect-ffi-win32-x64-msvc",
"@cipherstash/protect-ffi-linux-x64-gnu",
"@cipherstash/protect-ffi-linux-arm64-gnu",
"@cipherstash/protect-ffi-linux-x64-musl"
]
],
"linked": [],
Expand Down
7 changes: 7 additions & 0 deletions .changeset/protect-ffi-lazy-load.md.deferred
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@cipherstash/protect-ffi': minor
---

The native binding now loads lazily. Importing the package no longer resolves the platform binary: the CJS entry pulls in `./load.cjs` with `import native = require(...)`, which emits a plain `require` and leaves the `@neon-rs/load` proxy untouched, where the previous `import * as native from` compiled to an `__importStar` that enumerated the module and forced resolution at module-evaluation time. `require('@cipherstash/protect-ffi')` therefore succeeds with no binding installed, and the same `MODULE_NOT_FOUND` — identical `code` and `message` — is raised on first use instead of at import.

Adds `assertNativeBindingAvailable()`: a diagnostic entry point that resolves the platform binary and throws the loader's error unwrapped if it is missing, without constructing a client, reading credentials or touching the network. It exists because laziness removed the implicit probe that importing the package used to be, and there is no consumer-side replacement — `lib/load.cjs` is not an exported path (`ERR_PACKAGE_PATH_NOT_EXPORTED`), reading one of this module's own exports never reaches the proxy, and forcing it through a real wrapper means picking one whose argument validation does not reject first.
5 changes: 5 additions & 0 deletions .changeset/quiet-moons-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'stash': patch
---

Document the Dependabot major-version policy in `skills/stash-supply-chain-security`: no entry configures a `semver-major-days` cooldown, because every entry ignores `version-update:semver-major` and cooldown applies to version updates only. The supply-chain e2e suite now pins both halves of that relationship.
229 changes: 229 additions & 0 deletions .github/actions/build-ffi-binding/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
name: Build the protect-ffi binding
description: >-
Compile `packages/protect-ffi` into the artifacts its JS consumers load at
runtime — `lib/` (tsc), `index.node` (cargo), and optionally `dist/wasm/**`
(wasm-pack) — then prove they load.

WHY THIS EXISTS: until the monorepo absorption, `@cipherstash/protect-ffi`
was installed from npm and all three arrived prebuilt inside the tarball. As
a workspace package it ships source only, so every job that encrypts,
decrypts, or typechecks against it has to build them first — and nothing else
in CI does. Without this action the credentialed suites fail with
`Cannot find module '.../protect-ffi-linux-x64-gnu/index.node'`, the Deno
smoke test with `Module not found ".../dist/wasm/protect_ffi_inline.js"`, and
stack's type tests with four unresolved-declaration errors.

DO NOT USE FROM A PUBLISHING WORKFLOW. It restores the GitHub Actions cache,
which `scripts/lint-no-workflow-caching.mjs` forbids anywhere an artifact
gets published. Release builds go through the target-explicit matrix instead,
which compiles every platform from scratch.

inputs:
wasm:
description: >-
Also build `dist/wasm/**`. Only jobs that exercise
`@cipherstash/stack/wasm-inline` need it — the Deno smoke test and the
`integration/wasm/**` suites — and it costs a wasm-pack install plus a
second cargo build against wasm32, so it is off by default.
required: false
default: 'false'

runs:
using: composite
steps:
# `index.node` is a pure function of the Rust inputs, so it caches on a
# content hash of them rather than on a lockfile alone — a crates/ edit
# must miss. The path is one gitignored file, so unlike the WASM step
# below there is nothing tracked for a restore to overwrite, and the key
# needs nothing beyond the Rust inputs. Caching the 13MB output, NOT
# cargo's `target/`: a release
# build of the cipherstash-client graph leaves gigabytes there, which is
# slower to save and restore than the compile it saves.
#
# GitHub scopes a PR's cache writes to its own ref, so the payoff arrives
# once this lands on main and PR runs can read main's entry. Until then
# each PR pays one cold build and reuses it across re-runs.
- name: Restore the compiled binding
id: cache-native
uses: actions/cache@v4
with:
path: packages/protect-ffi/index.node
# package.json and mise.toml are in the key because they are build
# INPUTS, not just metadata: `build:native` is `cargo-build` plus a
# `postcargo-build` hook (`neon dist < cargo.log`), both defined in
# package.json, and mise.toml pins the toolchain that compiles it.
# Edit either and the Rust hash is unchanged, so the cache hit skips
# the build step below and the job proceeds on a stale index.node.
key: >-
ffi-native-${{ runner.os }}-${{ runner.arch }}-${{
hashFiles('packages/protect-ffi/crates/**',
'packages/protect-ffi/Cargo.toml',
'packages/protect-ffi/Cargo.lock',
'packages/protect-ffi/package.json',
'packages/protect-ffi/mise.toml') }}

# Always, hit or miss: `lib/` is `tsc` over `src/`, which is seconds, and
# it tracks a different input set than the cached binary.
- name: Build lib/ (the package `main`, and what tsc consumers resolve)
shell: bash
run: pnpm --filter @cipherstash/protect-ffi run build

# `build:native` is `tsc && cargo build --release`, then a `postcargo-build`
# hook running `neon dist < cargo.log`. That bare `neon dist` writes
# `index.node` at the PACKAGE ROOT, which is what `src/load.cts` registers
# as its `debug:` fallback — so the loader finds it without any platform
# package being populated. Release packaging needs `neon dist -o` to place
# a binary inside `platforms/<p>/`; testing deliberately does not.
- name: Build index.node (cargo)
if: steps.cache-native.outputs.cache-hit != 'true'
shell: bash
run: pnpm --filter @cipherstash/protect-ffi run build:native

# Unlike index.node, this path is NOT purely generated. `dist/wasm` holds
# wasm-pack's output alongside three declaration files that are tracked in
# git — see packages/protect-ffi/.gitignore for why they have to be. A
# restore untars over the checkout, so with a key hashed from the Rust
# inputs alone, an entry saved before a `.d.ts` edit silently reverts that
# edit: no diff, no log line, and the next `tsc` against wasm-inline
# typechecks the old declarations.
#
# So the `.d.ts` are hashed into the key too. Any edit to one now misses,
# and any entry that *does* hit was necessarily saved from a checkout whose
# declarations were byte-identical — which makes the overwrite a no-op by
# construction rather than by luck. The glob is load-bearing: it covers a
# fourth declaration file the day someone tracks one, where three literal
# paths would quietly stop covering the set they were written for.
#
# The alternative — keeping them out of the archive with a `!` exclusion —
# does not work, and reads as though it does. `actions/cache` resolves
# `path:` with `implicitDescendants: false` and hands the result to
# `tar --files-from`; a bare directory therefore resolves to one entry and
# tar recurses into it itself, so an exclusion aimed at files underneath
# never matches anything. Narrowing to explicit file globs would work, but
# trades a no-op overwrite for a worse failure: a file wasm-pack starts
# emitting is then silently absent on every cache hit.
#
# No key prefix bump is needed for the changed hash inputs — and none would
# be needed had `path:` changed either, since `getCacheVersion` hashes the
# path list into the entry's version.
- name: Restore the compiled WASM output
if: inputs.wasm == 'true'
id: cache-wasm
uses: actions/cache@v4
with:
path: packages/protect-ffi/dist/wasm
# The last five are the same build-input argument as on the native key,
# and `build:wasm` is the longer pipeline of the two: wasm-pack, then
# `tsc -p tsconfig.wasm-errors.json`, then a `postbuild:wasm` hook
# running scripts/inline-wasm.mjs — which is what emits the
# protect_ffi_inline.js that stack's wasm-inline entry imports. An edit
# to the inliner with no Rust change is the likely one here, and it is
# exactly the edit a Rust-only hash cannot see.
#
# src/errors.ts is that tsc step's only input (`files:` in the tsconfig
# names it alone), and hashing the EMITTED dist/wasm/*.d.ts does not
# stand in for it. Rewriting the body of `isProtectErrorCode` leaves
# errors.d.ts byte-identical while changing errors.js — so the key hits,
# this step is skipped, and the restored errors.js is the old one.
# Nothing tracked forces a miss: errors.js is gitignored. It is not
# inert output either — scripts/inline-wasm.mjs re-exports it from both
# the ./wasm and ./wasm-inline entries, so the WASM integration suites
# would run an implementation the release build does not ship.
#
# It is the one source file here for the same reason the whole of src/**
# is NOT in this key: a wasm miss costs a wasm-pack install and a cargo
# wasm32 build of the cipherstash-client graph, and 104 of the 122 files
# under src/ are the eql-v3-types declarations, which that tsconfig
# never reads. ffi-binding-action.test.mjs walks the tsconfig's imports
# and fails if this stops being the complete input set.
key: >-
ffi-wasm-${{ runner.os }}-${{
hashFiles('packages/protect-ffi/crates/**',
'packages/protect-ffi/Cargo.toml',
'packages/protect-ffi/Cargo.lock',
'packages/protect-ffi/dist/wasm/*.d.ts',
'packages/protect-ffi/src/errors.ts',
'packages/protect-ffi/package.json',
'packages/protect-ffi/mise.toml',
'packages/protect-ffi/tsconfig.wasm-errors.json',
'packages/protect-ffi/scripts/inline-wasm.mjs') }}

# mise carries the pinned wasm-pack (see packages/protect-ffi/mise.toml)
# and, run from that directory, trusts the nested config — a bare `mise`
# call elsewhere refuses it with "Config files are not trusted", which
# reads as a toolchain problem rather than a trust one.
#
# `install_args` narrows this to wasm-pack alone. A bare `mise install`
# would also build `cargo:cargo-zigbuild` from source, which this job has
# no use for — zigbuild is the release matrix's glibc-pinning path.
#
# The argument is the full backend id, matching mise.toml. The short name
# is not in mise's registry: `mise install wasm-pack` exits non-zero with
# "not found in mise tool registry" and a did-you-mean list.
#
# SHA-pinned, per the convention the deposited upstream workflows already
# use for third-party actions. mise-action is a trust dependency this repo
# did not have before the absorption, and it runs in jobs holding live
# CipherStash credentials — a mutable `@v3` lets the code executing there
# change with no commit here. Dependabot moves the pin and the comment
# together (.github/dependabot.yml covers github-actions).
- name: Install wasm-pack
if: inputs.wasm == 'true' && steps.cache-wasm.outputs.cache-hit != 'true'
uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3.6.3
with:
install: true
install_args: aqua:wasm-bindgen/wasm-pack
working_directory: packages/protect-ffi

# `--all-targets` in the Rust lint means all target KINDS, not platforms;
# wasm32 has to be installed explicitly before anything can build for it.
- name: Add the wasm32 target
if: inputs.wasm == 'true' && steps.cache-wasm.outputs.cache-hit != 'true'
shell: bash
run: rustup target add wasm32-unknown-unknown

- name: Build dist/wasm (wasm-pack)
if: inputs.wasm == 'true' && steps.cache-wasm.outputs.cache-hit != 'true'
shell: bash
run: pnpm --filter @cipherstash/protect-ffi run build:wasm

# Always, and the reason this action is not just three `run:` lines inline.
# A cache that restores nothing, or a build whose output lands somewhere
# unexpected, otherwise surfaces as dozens of unrelated encryption failures
# deep in a credentialed suite. Fail here instead, naming the artifact.
- name: Verify the binding loads
shell: bash
working-directory: packages/protect-ffi
env:
WANT_WASM: ${{ inputs.wasm }}
run: |
set -euo pipefail

test -s index.node || {
echo "::error::index.node was neither restored from cache nor built"
exit 1
}

# Exercises the real loader, including the platform-package-then-debug
# fallback in src/load.cts. `require` alone proves nothing since the
# laziness change — the binding resolves on first use, not on import.
node -e "require('./lib/index.cjs').assertNativeBindingAvailable()"
echo "index.node loads"

if [ "$WANT_WASM" = "true" ]; then
for f in dist/wasm/protect_ffi.js \
dist/wasm/protect_ffi_inline.js \
dist/wasm/protect_ffi_bg.wasm ; do
test -s "$f" || {
echo "::error::$f missing — the WASM build did not produce it"
exit 1
}
done
node --input-type=module -e "
const m = await import('./dist/wasm/protect_ffi_inline.js')
if (typeof m.newClient !== 'function') {
throw new Error('wasm-inline resolved but exports no newClient')
}
"
echo "dist/wasm loads"
fi
Loading
Loading