@cipherstash/protect-ffi 0.27.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +106 -34
  3. package/dist/wasm/protect_ffi.d.ts +10 -3
  4. package/dist/wasm/protect_ffi_bg.js +63 -14
  5. package/dist/wasm/protect_ffi_bg.wasm +0 -0
  6. package/dist/wasm/protect_ffi_bg.wasm.d.ts +11 -11
  7. package/dist/wasm/protect_ffi_inline.js +1 -1
  8. package/lib/bigintWire.d.ts +56 -0
  9. package/lib/bigintWire.js +83 -0
  10. package/lib/eql-v3-types/Bigint.d.ts +1 -1
  11. package/lib/eql-v3-types/BigintEq.d.ts +1 -1
  12. package/lib/eql-v3-types/BigintEqQuery.d.ts +13 -0
  13. package/lib/eql-v3-types/BigintEqQuery.js +2 -0
  14. package/lib/eql-v3-types/BigintOrd.d.ts +4 -4
  15. package/lib/eql-v3-types/BigintOrdOpe.d.ts +1 -1
  16. package/lib/eql-v3-types/BigintOrdOpeQuery.d.ts +13 -0
  17. package/lib/eql-v3-types/BigintOrdOpeQuery.js +2 -0
  18. package/lib/eql-v3-types/BigintOrdOre.d.ts +1 -1
  19. package/lib/eql-v3-types/BigintOrdOreQuery.d.ts +13 -0
  20. package/lib/eql-v3-types/BigintOrdOreQuery.js +2 -0
  21. package/lib/eql-v3-types/BigintOrdQuery.d.ts +13 -0
  22. package/lib/eql-v3-types/BigintOrdQuery.js +2 -0
  23. package/lib/eql-v3-types/Boolean.d.ts +1 -1
  24. package/lib/eql-v3-types/Date.d.ts +1 -1
  25. package/lib/eql-v3-types/DateEq.d.ts +1 -1
  26. package/lib/eql-v3-types/DateEqQuery.d.ts +13 -0
  27. package/lib/eql-v3-types/DateEqQuery.js +2 -0
  28. package/lib/eql-v3-types/DateOrd.d.ts +4 -4
  29. package/lib/eql-v3-types/DateOrdOpe.d.ts +1 -1
  30. package/lib/eql-v3-types/DateOrdOpeQuery.d.ts +13 -0
  31. package/lib/eql-v3-types/DateOrdOpeQuery.js +2 -0
  32. package/lib/eql-v3-types/DateOrdOre.d.ts +1 -1
  33. package/lib/eql-v3-types/DateOrdOreQuery.d.ts +13 -0
  34. package/lib/eql-v3-types/DateOrdOreQuery.js +2 -0
  35. package/lib/eql-v3-types/DateOrdQuery.d.ts +13 -0
  36. package/lib/eql-v3-types/DateOrdQuery.js +2 -0
  37. package/lib/eql-v3-types/Double.d.ts +1 -1
  38. package/lib/eql-v3-types/DoubleEq.d.ts +1 -1
  39. package/lib/eql-v3-types/DoubleEqQuery.d.ts +13 -0
  40. package/lib/eql-v3-types/DoubleEqQuery.js +2 -0
  41. package/lib/eql-v3-types/DoubleOrd.d.ts +4 -4
  42. package/lib/eql-v3-types/DoubleOrdOpe.d.ts +1 -1
  43. package/lib/eql-v3-types/DoubleOrdOpeQuery.d.ts +13 -0
  44. package/lib/eql-v3-types/DoubleOrdOpeQuery.js +2 -0
  45. package/lib/eql-v3-types/DoubleOrdOre.d.ts +1 -1
  46. package/lib/eql-v3-types/DoubleOrdOreQuery.d.ts +13 -0
  47. package/lib/eql-v3-types/DoubleOrdOreQuery.js +2 -0
  48. package/lib/eql-v3-types/DoubleOrdQuery.d.ts +13 -0
  49. package/lib/eql-v3-types/DoubleOrdQuery.js +2 -0
  50. package/lib/eql-v3-types/Integer.d.ts +1 -1
  51. package/lib/eql-v3-types/IntegerEq.d.ts +1 -1
  52. package/lib/eql-v3-types/IntegerEqQuery.d.ts +13 -0
  53. package/lib/eql-v3-types/IntegerEqQuery.js +2 -0
  54. package/lib/eql-v3-types/IntegerOrd.d.ts +4 -4
  55. package/lib/eql-v3-types/IntegerOrdOpe.d.ts +1 -1
  56. package/lib/eql-v3-types/IntegerOrdOpeQuery.d.ts +13 -0
  57. package/lib/eql-v3-types/IntegerOrdOpeQuery.js +2 -0
  58. package/lib/eql-v3-types/IntegerOrdOre.d.ts +1 -1
  59. package/lib/eql-v3-types/IntegerOrdOreQuery.d.ts +13 -0
  60. package/lib/eql-v3-types/IntegerOrdOreQuery.js +2 -0
  61. package/lib/eql-v3-types/IntegerOrdQuery.d.ts +13 -0
  62. package/lib/eql-v3-types/IntegerOrdQuery.js +2 -0
  63. package/lib/eql-v3-types/Numeric.d.ts +1 -1
  64. package/lib/eql-v3-types/NumericEq.d.ts +1 -1
  65. package/lib/eql-v3-types/NumericEqQuery.d.ts +13 -0
  66. package/lib/eql-v3-types/NumericEqQuery.js +2 -0
  67. package/lib/eql-v3-types/NumericOrd.d.ts +4 -4
  68. package/lib/eql-v3-types/NumericOrdOpe.d.ts +1 -1
  69. package/lib/eql-v3-types/NumericOrdOpeQuery.d.ts +13 -0
  70. package/lib/eql-v3-types/NumericOrdOpeQuery.js +2 -0
  71. package/lib/eql-v3-types/NumericOrdOre.d.ts +1 -1
  72. package/lib/eql-v3-types/NumericOrdOreQuery.d.ts +13 -0
  73. package/lib/eql-v3-types/NumericOrdOreQuery.js +2 -0
  74. package/lib/eql-v3-types/NumericOrdQuery.d.ts +13 -0
  75. package/lib/eql-v3-types/NumericOrdQuery.js +2 -0
  76. package/lib/eql-v3-types/OpeCllw.d.ts +9 -6
  77. package/lib/eql-v3-types/OreBlock256.d.ts +4 -4
  78. package/lib/eql-v3-types/Real.d.ts +1 -1
  79. package/lib/eql-v3-types/RealEq.d.ts +1 -1
  80. package/lib/eql-v3-types/RealEqQuery.d.ts +13 -0
  81. package/lib/eql-v3-types/RealEqQuery.js +2 -0
  82. package/lib/eql-v3-types/RealOrd.d.ts +4 -4
  83. package/lib/eql-v3-types/RealOrdOpe.d.ts +1 -1
  84. package/lib/eql-v3-types/RealOrdOpeQuery.d.ts +13 -0
  85. package/lib/eql-v3-types/RealOrdOpeQuery.js +2 -0
  86. package/lib/eql-v3-types/RealOrdOre.d.ts +1 -1
  87. package/lib/eql-v3-types/RealOrdOreQuery.d.ts +13 -0
  88. package/lib/eql-v3-types/RealOrdOreQuery.js +2 -0
  89. package/lib/eql-v3-types/RealOrdQuery.d.ts +13 -0
  90. package/lib/eql-v3-types/RealOrdQuery.js +2 -0
  91. package/lib/eql-v3-types/Selector.d.ts +1 -1
  92. package/lib/eql-v3-types/Smallint.d.ts +1 -1
  93. package/lib/eql-v3-types/SmallintEq.d.ts +1 -1
  94. package/lib/eql-v3-types/SmallintEqQuery.d.ts +13 -0
  95. package/lib/eql-v3-types/SmallintEqQuery.js +2 -0
  96. package/lib/eql-v3-types/SmallintOrd.d.ts +4 -4
  97. package/lib/eql-v3-types/SmallintOrdOpe.d.ts +1 -1
  98. package/lib/eql-v3-types/SmallintOrdOpeQuery.d.ts +13 -0
  99. package/lib/eql-v3-types/SmallintOrdOpeQuery.js +2 -0
  100. package/lib/eql-v3-types/SmallintOrdOre.d.ts +1 -1
  101. package/lib/eql-v3-types/SmallintOrdOreQuery.d.ts +13 -0
  102. package/lib/eql-v3-types/SmallintOrdOreQuery.js +2 -0
  103. package/lib/eql-v3-types/SmallintOrdQuery.d.ts +13 -0
  104. package/lib/eql-v3-types/SmallintOrdQuery.js +2 -0
  105. package/lib/eql-v3-types/SteVecDocument.d.ts +1 -1
  106. package/lib/eql-v3-types/SteVecEntry.d.ts +4 -4
  107. package/lib/eql-v3-types/SteVecQuery.d.ts +1 -1
  108. package/lib/eql-v3-types/SteVecQueryEntry.d.ts +2 -2
  109. package/lib/eql-v3-types/SteVecTerm.d.ts +4 -4
  110. package/lib/eql-v3-types/Text.d.ts +1 -1
  111. package/lib/eql-v3-types/TextEq.d.ts +1 -1
  112. package/lib/eql-v3-types/TextEqQuery.d.ts +13 -0
  113. package/lib/eql-v3-types/TextEqQuery.js +2 -0
  114. package/lib/eql-v3-types/TextMatch.d.ts +1 -1
  115. package/lib/eql-v3-types/TextMatchQuery.d.ts +13 -0
  116. package/lib/eql-v3-types/TextMatchQuery.js +2 -0
  117. package/lib/eql-v3-types/TextOrd.d.ts +4 -4
  118. package/lib/eql-v3-types/TextOrdOpe.d.ts +1 -1
  119. package/lib/eql-v3-types/TextOrdOpeQuery.d.ts +15 -0
  120. package/lib/eql-v3-types/TextOrdOpeQuery.js +2 -0
  121. package/lib/eql-v3-types/TextOrdOre.d.ts +1 -1
  122. package/lib/eql-v3-types/TextOrdOreQuery.d.ts +15 -0
  123. package/lib/eql-v3-types/TextOrdOreQuery.js +2 -0
  124. package/lib/eql-v3-types/TextOrdQuery.d.ts +15 -0
  125. package/lib/eql-v3-types/TextOrdQuery.js +2 -0
  126. package/lib/eql-v3-types/TextSearch.d.ts +4 -4
  127. package/lib/eql-v3-types/TextSearchOre.d.ts +19 -0
  128. package/lib/eql-v3-types/TextSearchOre.js +2 -0
  129. package/lib/eql-v3-types/TextSearchOreQuery.d.ts +17 -0
  130. package/lib/eql-v3-types/TextSearchOreQuery.js +2 -0
  131. package/lib/eql-v3-types/TextSearchQuery.d.ts +17 -0
  132. package/lib/eql-v3-types/TextSearchQuery.js +2 -0
  133. package/lib/eql-v3-types/Timestamp.d.ts +1 -1
  134. package/lib/eql-v3-types/TimestampEq.d.ts +1 -1
  135. package/lib/eql-v3-types/TimestampEqQuery.d.ts +13 -0
  136. package/lib/eql-v3-types/TimestampEqQuery.js +2 -0
  137. package/lib/eql-v3-types/TimestampOrd.d.ts +4 -4
  138. package/lib/eql-v3-types/TimestampOrdOpe.d.ts +1 -1
  139. package/lib/eql-v3-types/TimestampOrdOpeQuery.d.ts +13 -0
  140. package/lib/eql-v3-types/TimestampOrdOpeQuery.js +2 -0
  141. package/lib/eql-v3-types/TimestampOrdOre.d.ts +1 -1
  142. package/lib/eql-v3-types/TimestampOrdOreQuery.d.ts +13 -0
  143. package/lib/eql-v3-types/TimestampOrdOreQuery.js +2 -0
  144. package/lib/eql-v3-types/TimestampOrdQuery.d.ts +13 -0
  145. package/lib/eql-v3-types/TimestampOrdQuery.js +2 -0
  146. package/lib/eql-v3.d.ts +63 -7
  147. package/lib/errors.d.ts +1 -1
  148. package/lib/errors.js +0 -4
  149. package/lib/index.cjs +23 -11
  150. package/lib/index.d.cts +91 -25
  151. package/lib/normalizeEncryptConfig.d.ts +2 -1
  152. package/lib/normalizeEncryptConfig.js +2 -1
  153. package/package.json +11 -11
  154. package/lib/eql-v3-types/OreCllw.d.ts +0 -7
  155. package/lib/eql-v3-types/OreCllw.js +0 -5
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 CipherStash
3
+ Copyright (c) 2024-2026 CipherStash
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # Protect.js CipherStash Client FFI
1
+ # CipherStash Client FFI (`@cipherstash/protect-ffi`)
2
2
 
3
3
  > [!IMPORTANT]
4
- > If you are looking to implement this package into your application please use the official [protect package](https://github.com/cipherstash/protectjs).
4
+ > If you are looking to implement this package into your application please use the official [`@cipherstash/stack` package](https://github.com/cipherstash/stack).
5
5
 
6
6
  This project provides the JS bindings for the CipherStash Client Rust SDK and is bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).
7
7
 
@@ -19,19 +19,18 @@ This command uses the [@neon-rs/cli](https://www.npmjs.com/package/@neon-rs/cli)
19
19
 
20
20
  ## Local setup
21
21
 
22
- You can use the `stash` CLI tool to set up your local environment.
23
-
24
- You will be prompted to sign in or create an account and follow steps to create a keyset and client key.
22
+ Authenticate the `stash` CLI to set up your local environment. It runs via `npx` — no separate install needed:
25
23
 
26
24
  ```sh
27
- brew install cipherstash/tap/stash
28
- stash setup
25
+ npx stash auth login
29
26
  ```
30
27
 
28
+ You will be prompted to sign in or create an account.
29
+
31
30
  ## Exploring
32
31
 
33
32
  After building `protect-ffi`, you can explore its exports at the Node console.
34
- `CS_CLIENT_ID` and `CS_CLIENT_KEY` must be set in your environment for the call to `newClient()` to succeed.
33
+ Credentials must be available for the call to `newClient()` to succeed resolved from the CipherStash profile store, from environment variables, or from an explicit `strategy` passed to `newClient()`. For local development the simplest option is `npx stash auth login`, which populates the profile store. Alternatively, set `CS_WORKSPACE_CRN`, `CS_ACCESS_KEY`, and the `CS_CLIENT_ID`/`CS_CLIENT_KEY` keypair in your environment.
35
34
 
36
35
  ```sh
37
36
  $ npm i
@@ -60,39 +59,55 @@ const v3 = await addon.newClient({ encryptConfig, eqlVersion: 3 })
60
59
  With `eqlVersion: 3`, each column's payload targets the `eql_v3` domain
61
60
  derived from its `cast_as` and indexes:
62
61
 
62
+ Every public-schema column domain carries an `eql_v3_` prefix (so the SQL
63
+ column type is `public.eql_v3_text_eq`); the term-only query twins do not
64
+ (`eql_v3.query_text_eq`), because the `eql_v3` schema already versions them.
65
+
63
66
  | `cast_as` | family | indexes | domain |
64
67
  |-----------|--------|---------|--------|
65
- | `text` | `text` | `unique` + `ore` + `match` | `text_search` |
66
- | `text` | `text` | `unique` + `ore` | `text_ord_ore` |
67
- | `text` | `text` | `match` | `text_match` |
68
- | `text` | `text` | `unique` | `text_eq` |
69
- | `int` / `small_int` / `bigint` | `integer` / `smallint` / `bigint` | `ore` (with or without `unique`) | `<family>_ord_ore` |
70
- | `int` / `small_int` / `bigint` | `integer` / `smallint` / `bigint` | `unique` | `<family>_eq` |
68
+ | `text` | `text` | `unique` + `ore` + `match` | `eql_v3_text_search_ore` |
69
+ | `text` | `text` | `unique` + `ope` + `match` | `eql_v3_text_search` |
70
+ | `text` | `text` | `unique` + `ore` | `eql_v3_text_ord_ore` |
71
+ | `text` | `text` | `match` | `eql_v3_text_match` |
72
+ | `text` | `text` | `unique` | `eql_v3_text_eq` |
73
+ | `int` / `small_int` / `bigint` | `integer` / `smallint` / `bigint` | `ore` (with or without `unique`) | `eql_v3_<family>_ord_ore` |
74
+ | `int` / `small_int` / `bigint` | `integer` / `smallint` / `bigint` | `unique` | `eql_v3_<family>_eq` |
71
75
  | `number` / `decimal` / `date` / `timestamp` | `double` / `numeric` / `date` / `timestamp` | as above | as above |
72
- | any scalar | — | none | storage-only domain (`text`, `integer`, …) |
73
- | `boolean` | `boolean` | none only | `boolean` (storage-only — any index errors) |
74
- | `json` | `json` | `ste_vec` (required) | `json` |
76
+ | any scalar | — | none | storage-only domain (`eql_v3_text`, `eql_v3_integer`, …) |
77
+ | `boolean` | `boolean` | none only | `eql_v3_boolean` (storage-only — any index errors) |
78
+ | `json` | `json` | `ste_vec` (required, `compat` mode) | `eql_v3_json` |
75
79
 
76
80
  Notes:
77
81
 
78
82
  - The richest matching domain wins, and it must cover every configured
79
83
  capability — a combination that would silently drop a term errors instead
80
- (e.g. `unique` + `match`, `unique` + `ope` + `match`, or `ore` + `match`
81
- on text: no single domain carries those term sets, so add the missing
82
- index to reach `text_search`, split the capabilities across columns, or
83
- use `eqlVersion: 2`).
84
+ (e.g. `unique` + `match` or `ore` + `match` on text: no single domain
85
+ carries those term sets, so add the missing index to reach a search
86
+ domain, split the capabilities across columns, or use `eqlVersion: 2`).
87
+ - The two text search domains differ only in the ordering term they carry:
88
+ `eql_v3_text_search_ore` carries `ob` (ORE), `eql_v3_text_search` carries
89
+ `op` (OPE). Configuring both `ore` and `ope` selects the ORE one.
84
90
  - Exception: dropping a *term* is fine when the *capability* survives.
85
91
  Non-text ordering domains carry only `ob`, so `unique` + `ore` on a
86
92
  numeric column drops `hm` — equality still works via the ORE operators.
87
- - Ordered text requires a `unique` index (`text_ord_ore`/`text_ord_ope`
88
- carry `hm` + `ob`/`op`); `ore`-only text errors.
93
+ - Ordered text requires a `unique` index (`eql_v3_text_ord_ore` /
94
+ `eql_v3_text_ord_ope` carry `hm` + `ob`/`op`); `ore`-only text errors.
95
+ - A `json` column's `ste_vec` index must use the `compat` mode (the
96
+ `cipherstash-client` default since 0.40.0). v3 orders SteVec entries by
97
+ the CLLW-OPE `op` term; a `standard`-mode index emits CLLW-ORE `oc`, which
98
+ has no mechanical conversion, so such a column errors at config time.
89
99
  - `decrypt` accepts **both** formats regardless of `eqlVersion`, so v2 and
90
100
  v3 data can coexist during a migration.
91
- - v3 query encryption currently supports JSON containment only; scalar and
92
- selector queries throw `EQL_V3_QUERY_UNSUPPORTED` and need an
93
- `eqlVersion: 2` client.
94
- - `ope`-indexed columns map to `<family>_ord_ope` but cannot be produced
95
- end-to-end yet: the client does not emit the `op` term (CIP-3280).
101
+ - v3 query encryption returns index-terms-only operands: scalar queries
102
+ produce the column domain's query twin (`{v, i, <terms>}`, no `c`
103
+ ciphertext) — bind with `col = $1::jsonb::eql_v3.query_<name>` (or the
104
+ ordering / `@>` match operator). The operand always carries ALL the
105
+ column domain's terms, whichever `indexType` was queried. JSON
106
+ containment queries produce the `eql_v3.query_jsonb` needle, and
107
+ `ste_vec_selector` queries return the bare selector hash (a string) for
108
+ the `->` / `->>` operators.
109
+ - `ope`-indexed columns map to `<family>_ord_ope` and carry the `op`
110
+ (CLLW-OPE) term (emitted since cipherstash-client 0.38.1).
96
111
 
97
112
  > [!NOTE]
98
113
  > **Breaking TypeScript change:** `encrypt`/`encryptBulk` now return
@@ -104,6 +119,55 @@ Notes:
104
119
  > `payload.v === 3` to detect the v3 members. (A bare `payload.k === 'ct'`
105
120
  > does not compile against the union.)
106
121
 
122
+ ## BigInt plaintexts
123
+
124
+ Encrypted `cast_as: 'bigint'` columns store signed 64-bit integers
125
+ (PostgreSQL `bigint`). `encrypt` / `encryptBulk` / `encryptQuery` /
126
+ `encryptQueryBulk` accept the plaintext as either a JS `number` or a JS
127
+ `bigint`:
128
+
129
+ - `bigint` inputs are exact and bounds-checked against the full i64 range:
130
+ **-9223372036854775808 to 9223372036854775807** (-2^63 to 2^63 - 1).
131
+ Values outside that range throw a `RangeError` (a plain `RangeError`, not
132
+ a `ProtectError`) naming the bounds and the offending direction. Search
133
+ index terms (`hm`, `ob`, `op`) are derived from the same value, so the
134
+ boundary check covers index-term generation too.
135
+ - `number` inputs keep the existing exact-integer guard: fractional,
136
+ non-finite, or out-of-range values error instead of being silently
137
+ truncated.
138
+ - A `bigint` is only accepted as the top-level plaintext of a scalar
139
+ column. JSON has no bigint, so bigints nested inside `cast_as: 'json'`
140
+ documents (or JSON containment query terms) are rejected with a
141
+ `TypeError` on both Neon and wasm. More generally, plaintexts follow
142
+ `JSON.stringify` semantics on both platforms: `toJSON` is honored (a
143
+ `Date` becomes its ISO string), `undefined` properties are dropped, and
144
+ non-finite numbers become `null`.
145
+ - The internal wire form `{"__protect_ffi_bigint__": "<digits>"}` is
146
+ reserved: a `cast_as: 'json'` plaintext consisting of exactly that
147
+ single-key shape (with an in-range i64 decimal string) is read as a
148
+ bigint at the boundary and rejected for json columns. Nested
149
+ occurrences of the key inside a larger document are unaffected.
150
+
151
+ ```js
152
+ const ciphertext = await addon.encrypt(client, {
153
+ plaintext: 9007199254740993n, // beyond Number.MAX_SAFE_INTEGER — stays exact
154
+ column: 'score',
155
+ table: 'users',
156
+ })
157
+ const decrypted = await addon.decrypt(client, { ciphertext })
158
+ // decrypted === 9007199254740993n (a JS bigint)
159
+ ```
160
+
161
+ > [!WARNING]
162
+ > **Breaking change:** `decrypt` / `decryptBulk` / `decryptBulkFallible`
163
+ > now ALWAYS return a JS `bigint` for `cast_as: 'bigint'` columns — even
164
+ > for values that fit in a JS number. Previous releases returned a
165
+ > `number`, silently losing precision beyond `Number.MAX_SAFE_INTEGER`
166
+ > (2^53 - 1). Code comparing or doing arithmetic on decrypted bigint
167
+ > columns must be updated (e.g. `decrypted === 123n` instead of
168
+ > `decrypted === 123`, or `Number(decrypted)` when the value is known to
169
+ > be small).
170
+
107
171
  ## Errors
108
172
 
109
173
  Async API calls throw `ProtectError` with a stable `code` for programmatic handling.
@@ -151,8 +215,7 @@ Initiate a dry run of a patch release of this library via GitHub Actions. This p
151
215
 
152
216
  #### `npm test`
153
217
 
154
- Formats and lints Rust and TypeScript code.
155
- Also runs Rust tests.
218
+ Typechecks the TypeScript and runs the unit tests (tsc + vitest), formats and lints Rust and TypeScript code, and runs Rust tests.
156
219
 
157
220
  Note: `npm test` at project root does not run integration tests.
158
221
  For integration tests, see [below](#integration-tests).
@@ -175,6 +238,8 @@ protect-ffi/
175
238
  | └── src/
176
239
  | └── lib.rs
177
240
  ├── platforms/
241
+ ├── docs/
242
+ ├── scripts/
178
243
  ├── package.json
179
244
  └── target/
180
245
  ```
@@ -191,6 +256,8 @@ protect-ffi/
191
256
  | `crates/` | The directory tree containing the Rust source code for the project. |
192
257
  | `lib.rs` | Entry point for the Rust source code. |
193
258
  | `platforms/` | The directory containing distributions of the binary addon backend for each platform supported by this library. |
259
+ | `docs/` | JSONB integration docs and migration notes. |
260
+ | `scripts/` | Build helper scripts (e.g. WASM inlining). |
194
261
  | `package.json` | The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command. |
195
262
  | `target/` | Binary artifacts generated by the Rust build. |
196
263
 
@@ -208,9 +275,11 @@ Example environment variables:
208
275
  ```
209
276
  CS_CLIENT_ID=
210
277
  CS_CLIENT_KEY=
278
+ # The integration tests read CS_CLIENT_ACCESS_KEY; the library itself reads CS_ACCESS_KEY
211
279
  CS_CLIENT_ACCESS_KEY=
212
280
  CS_WORKSPACE_CRN=
213
- PGPORT=5432
281
+ # Must match the port used by the integration-test setup (mise.toml)
282
+ PGPORT=5436
214
283
  PGDATABASE=cipherstash
215
284
  PGUSER=cipherstash
216
285
  PGPASSWORD=password
@@ -249,7 +318,7 @@ The release workflow is responsible for:
249
318
 
250
319
  To perform a release:
251
320
 
252
- 1. Navigate to the ["Release" workflow page](https://github.com/cipherstash/protect-ffi/actions/workflows/release.yml) in GitHub.
321
+ 1. Navigate to the ["Release" workflow page](https://github.com/cipherstash/protectjs-ffi/actions/workflows/release.yml) in GitHub.
253
322
  1. Click on "Run workflow".
254
323
  1. Select the branch to release from.
255
324
  Use the default of `main` unless you want to do a pre-release version or dry run from a branch.
@@ -260,8 +329,11 @@ To perform a release:
260
329
  Select "custom" in the dropdown and fill in the "Custom version" text box if you want to use a semver string instead of the shorthand (patch, minor, major, etc.).
261
330
  1. Click "Run workflow".
262
331
 
263
- Note that we currently don't have any automation around release notes or a changelog.
264
- However, you can add release notes after running the workflow by editing the release on GitHub.
332
+ Release notes and the changelog are automated. Add notes for your changes under the
333
+ `[Unreleased]` heading in [`CHANGELOG.md`](./CHANGELOG.md). On release, the `version`
334
+ npm lifecycle hook promotes that section to a dated release entry
335
+ (`scripts/changelog-release.mjs`), and the workflow publishes the promoted section as
336
+ the GitHub release notes (`scripts/changelog-extract.mjs`).
265
337
 
266
338
  ## Learn More
267
339
 
@@ -77,8 +77,15 @@ export function isEncrypted(raw: any): boolean;
77
77
  /**
78
78
  * Construct a [`WasmClient`].
79
79
  *
80
- * `opts.strategy` must be an `@cipherstash/auth`-shaped object — anything
81
- * with a `getToken(): Promise<{ token: string, ... }>` method works. It is
82
- * required: wasm has no env / filesystem fallback path.
80
+ * `opts.strategy` must be an `@cipherstash/auth`-shaped object — anything with
81
+ * a `getToken()` method returning a `Promise` works. A non-`Promise` return is
82
+ * rejected with `strategy.getToken() did not return a Promise`.
83
+ *
84
+ * The promise may resolve either the bare `{ token: string, ... }` payload
85
+ * (`@cipherstash/auth` <= 0.40 and custom strategies) or a `@byteslice/result`
86
+ * envelope — `{ data: { token, ... } }` on success, `{ failure }` on error
87
+ * (`@cipherstash/auth` >= 0.41). Both are accepted.
88
+ *
89
+ * `strategy` is required: wasm has no env / filesystem fallback path.
83
90
  */
84
91
  export function newClient(opts: any): Promise<WasmClient>;
@@ -237,9 +237,16 @@ export function isEncrypted(raw) {
237
237
  /**
238
238
  * Construct a [`WasmClient`].
239
239
  *
240
- * `opts.strategy` must be an `@cipherstash/auth`-shaped object — anything
241
- * with a `getToken(): Promise<{ token: string, ... }>` method works. It is
242
- * required: wasm has no env / filesystem fallback path.
240
+ * `opts.strategy` must be an `@cipherstash/auth`-shaped object — anything with
241
+ * a `getToken()` method returning a `Promise` works. A non-`Promise` return is
242
+ * rejected with `strategy.getToken() did not return a Promise`.
243
+ *
244
+ * The promise may resolve either the bare `{ token: string, ... }` payload
245
+ * (`@cipherstash/auth` <= 0.40 and custom strategies) or a `@byteslice/result`
246
+ * envelope — `{ data: { token, ... } }` on success, `{ failure }` on error
247
+ * (`@cipherstash/auth` >= 0.41). Both are accepted.
248
+ *
249
+ * `strategy` is required: wasm has no env / filesystem fallback path.
243
250
  * @param {any} opts
244
251
  * @returns {Promise<WasmClient>}
245
252
  */
@@ -247,6 +254,10 @@ export function newClient(opts) {
247
254
  const ret = wasm.newClient(opts);
248
255
  return ret;
249
256
  }
257
+ export function __wbg_BigInt_7882274c8d2ac74c() { return handleError(function (arg0) {
258
+ const ret = BigInt(arg0);
259
+ return ret;
260
+ }, arguments); }
250
261
  export function __wbg_Error_83742b46f01ce22d(arg0, arg1) {
251
262
  const ret = Error(getStringFromWasm0(arg0, arg1));
252
263
  return ret;
@@ -350,6 +361,10 @@ export function __wbg_arrayBuffer_eb8e9ca620af2a19() { return handleError(functi
350
361
  const ret = arg0.arrayBuffer();
351
362
  return ret;
352
363
  }, arguments); }
364
+ export function __wbg_assign_2c1c53ce7e57ea6e(arg0, arg1) {
365
+ const ret = Object.assign(arg0, arg1);
366
+ return ret;
367
+ }
353
368
  export function __wbg_buffer_60b8043cd926067d(arg0) {
354
369
  const ret = arg0.buffer;
355
370
  return ret;
@@ -473,6 +488,16 @@ export function __wbg_instanceof_Map_f194b366846aca0c(arg0) {
473
488
  const ret = result;
474
489
  return ret;
475
490
  }
491
+ export function __wbg_instanceof_Object_be1962063fcc0c9f(arg0) {
492
+ let result;
493
+ try {
494
+ result = arg0 instanceof Object;
495
+ } catch (_) {
496
+ result = false;
497
+ }
498
+ const ret = result;
499
+ return ret;
500
+ }
476
501
  export function __wbg_instanceof_Promise_7c3bdd7805c2c6e6(arg0) {
477
502
  let result;
478
503
  try {
@@ -551,6 +576,10 @@ export function __wbg_new_ab79df5bd7c26067() {
551
576
  const ret = new Object();
552
577
  return ret;
553
578
  }
579
+ export function __wbg_new_aff07d10ed2fdd7f(arg0, arg1) {
580
+ const ret = new RangeError(getStringFromWasm0(arg0, arg1));
581
+ return ret;
582
+ }
554
583
  export function __wbg_new_c518c60af666645b() { return handleError(function () {
555
584
  const ret = new AbortController();
556
585
  return ret;
@@ -570,7 +599,7 @@ export function __wbg_new_typed_aaaeaf29cf802876(arg0, arg1) {
570
599
  const a = state0.a;
571
600
  state0.a = 0;
572
601
  try {
573
- return wasm_bindgen__convert__closures_____invoke__h0cb80728b35f261e(a, state0.b, arg0, arg1);
602
+ return wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined_______true_(a, state0.b, arg0, arg1);
574
603
  } finally {
575
604
  state0.a = a;
576
605
  }
@@ -605,6 +634,10 @@ export function __wbg_node_84ea875411254db1(arg0) {
605
634
  const ret = arg0.node;
606
635
  return ret;
607
636
  }
637
+ export function __wbg_parse_e9eddd2a82c706eb() { return handleError(function (arg0, arg1) {
638
+ const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
639
+ return ret;
640
+ }, arguments); }
608
641
  export function __wbg_process_44c7a14e11e9f69e(arg0) {
609
642
  const ret = arg0.process;
610
643
  return ret;
@@ -612,6 +645,10 @@ export function __wbg_process_44c7a14e11e9f69e(arg0) {
612
645
  export function __wbg_prototypesetcall_d62e5099504357e6(arg0, arg1, arg2) {
613
646
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
614
647
  }
648
+ export function __wbg_push_e87b0e732085a946(arg0, arg1) {
649
+ const ret = arg0.push(arg1);
650
+ return ret;
651
+ }
615
652
  export function __wbg_queueMicrotask_0c399741342fb10f(arg0) {
616
653
  const ret = arg0.queueMicrotask;
617
654
  return ret;
@@ -643,6 +680,10 @@ export function __wbg_set_282384002438957f(arg0, arg1, arg2) {
643
680
  export function __wbg_set_6be42768c690e380(arg0, arg1, arg2) {
644
681
  arg0[arg1] = arg2;
645
682
  }
683
+ export function __wbg_set_7eaa4f96924fd6b3() { return handleError(function (arg0, arg1, arg2) {
684
+ const ret = Reflect.set(arg0, arg1, arg2);
685
+ return ret;
686
+ }, arguments); }
646
687
  export function __wbg_set_8c0b3ffcf05d61c2(arg0, arg1, arg2) {
647
688
  arg0.set(getArrayU8FromWasm0(arg1, arg2));
648
689
  }
@@ -702,6 +743,10 @@ export function __wbg_status_318629ab93a22955(arg0) {
702
743
  const ret = arg0.status;
703
744
  return ret;
704
745
  }
746
+ export function __wbg_stringify_5ae93966a84901ac() { return handleError(function (arg0) {
747
+ const ret = JSON.stringify(arg0);
748
+ return ret;
749
+ }, arguments); }
705
750
  export function __wbg_subarray_a068d24e39478a8a(arg0, arg1, arg2) {
706
751
  const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);
707
752
  return ret;
@@ -718,6 +763,10 @@ export function __wbg_then_9e335f6dd892bc11(arg0, arg1, arg2) {
718
763
  const ret = arg0.then(arg1, arg2);
719
764
  return ret;
720
765
  }
766
+ export function __wbg_toString_68d455d069f7169a() { return handleError(function (arg0, arg1) {
767
+ const ret = arg0.toString(arg1);
768
+ return ret;
769
+ }, arguments); }
721
770
  export function __wbg_url_7fefc1820fba4e0c(arg0, arg1) {
722
771
  const ret = arg1.url;
723
772
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -742,13 +791,13 @@ export function __wbg_wasmclient_new(arg0) {
742
791
  return ret;
743
792
  }
744
793
  export function __wbindgen_cast_0000000000000001(arg0, arg1) {
745
- // Cast intrinsic for `Closure(Closure { dtor_idx: 879, function: Function { arguments: [], shim_idx: 880, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
746
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__hd9dedd770edb0aa1, wasm_bindgen__convert__closures_____invoke__h8b170b34f8b593df);
794
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 935, function: Function { arguments: [], shim_idx: 936, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
795
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_4fd6a40e72de90f0___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut_____Output_______, wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke_______true_);
747
796
  return ret;
748
797
  }
749
798
  export function __wbindgen_cast_0000000000000002(arg0, arg1) {
750
- // Cast intrinsic for `Closure(Closure { dtor_idx: 932, function: Function { arguments: [Externref], shim_idx: 933, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
751
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h94971d029da3e81d, wasm_bindgen__convert__closures_____invoke__hacad64c6c6b78997);
799
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 983, function: Function { arguments: [Externref], shim_idx: 984, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
800
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_4fd6a40e72de90f0___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_4fd6a40e72de90f0___JsValue____Output___core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_4fd6a40e72de90f0___JsError___, wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___wasm_bindgen_4fd6a40e72de90f0___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_4fd6a40e72de90f0___JsError___true_);
752
801
  return ret;
753
802
  }
754
803
  export function __wbindgen_cast_0000000000000003(arg0) {
@@ -785,19 +834,19 @@ export function __wbindgen_init_externref_table() {
785
834
  table.set(offset + 2, true);
786
835
  table.set(offset + 3, false);
787
836
  }
788
- function wasm_bindgen__convert__closures_____invoke__h8b170b34f8b593df(arg0, arg1) {
789
- wasm.wasm_bindgen__convert__closures_____invoke__h8b170b34f8b593df(arg0, arg1);
837
+ function wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke_______true_(arg0, arg1) {
838
+ wasm.wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke_______true_(arg0, arg1);
790
839
  }
791
840
 
792
- function wasm_bindgen__convert__closures_____invoke__hacad64c6c6b78997(arg0, arg1, arg2) {
793
- const ret = wasm.wasm_bindgen__convert__closures_____invoke__hacad64c6c6b78997(arg0, arg1, arg2);
841
+ function wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___wasm_bindgen_4fd6a40e72de90f0___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_4fd6a40e72de90f0___JsError___true_(arg0, arg1, arg2) {
842
+ const ret = wasm.wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___wasm_bindgen_4fd6a40e72de90f0___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_4fd6a40e72de90f0___JsError___true_(arg0, arg1, arg2);
794
843
  if (ret[1]) {
795
844
  throw takeFromExternrefTable0(ret[0]);
796
845
  }
797
846
  }
798
847
 
799
- function wasm_bindgen__convert__closures_____invoke__h0cb80728b35f261e(arg0, arg1, arg2, arg3) {
800
- wasm.wasm_bindgen__convert__closures_____invoke__h0cb80728b35f261e(arg0, arg1, arg2, arg3);
848
+ function wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined_______true_(arg0, arg1, arg2, arg3) {
849
+ wasm.wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined_______true_(arg0, arg1, arg2, arg3);
801
850
  }
802
851
 
803
852
 
Binary file
@@ -15,26 +15,26 @@ export const newClient: (a: any) => any;
15
15
  export const __wbg_intounderlyingsource_free: (a: number, b: number) => void;
16
16
  export const intounderlyingsource_cancel: (a: number) => void;
17
17
  export const intounderlyingsource_pull: (a: number, b: any) => any;
18
- export const __wbg_intounderlyingsink_free: (a: number, b: number) => void;
19
- export const intounderlyingsink_abort: (a: number, b: any) => any;
20
- export const intounderlyingsink_close: (a: number) => any;
21
- export const intounderlyingsink_write: (a: number, b: any) => any;
22
18
  export const __wbg_intounderlyingbytesource_free: (a: number, b: number) => void;
19
+ export const __wbg_intounderlyingsink_free: (a: number, b: number) => void;
23
20
  export const intounderlyingbytesource_autoAllocateChunkSize: (a: number) => number;
24
21
  export const intounderlyingbytesource_cancel: (a: number) => void;
25
22
  export const intounderlyingbytesource_pull: (a: number, b: any) => any;
26
23
  export const intounderlyingbytesource_start: (a: number, b: any) => void;
27
24
  export const intounderlyingbytesource_type: (a: number) => number;
28
- export const wasm_bindgen__closure__destroy__hd9dedd770edb0aa1: (a: number, b: number) => void;
29
- export const wasm_bindgen__closure__destroy__h94971d029da3e81d: (a: number, b: number) => void;
30
- export const wasm_bindgen__convert__closures_____invoke__hacad64c6c6b78997: (a: number, b: number, c: any) => [number, number];
31
- export const wasm_bindgen__convert__closures_____invoke__h0cb80728b35f261e: (a: number, b: number, c: any, d: any) => void;
32
- export const wasm_bindgen__convert__closures_____invoke__h8b170b34f8b593df: (a: number, b: number) => void;
33
- export const __wbindgen_malloc: (a: number, b: number) => number;
34
- export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
25
+ export const intounderlyingsink_abort: (a: number, b: any) => any;
26
+ export const intounderlyingsink_close: (a: number) => any;
27
+ export const intounderlyingsink_write: (a: number, b: any) => any;
28
+ export const wasm_bindgen_4fd6a40e72de90f0___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
29
+ export const wasm_bindgen_4fd6a40e72de90f0___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_4fd6a40e72de90f0___JsValue____Output___core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_4fd6a40e72de90f0___JsError___: (a: number, b: number) => void;
30
+ export const wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___wasm_bindgen_4fd6a40e72de90f0___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_4fd6a40e72de90f0___JsError___true_: (a: number, b: number, c: any) => [number, number];
31
+ export const wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined___js_sys_64e80f16f18e69d0___Function_fn_wasm_bindgen_4fd6a40e72de90f0___JsValue_____wasm_bindgen_4fd6a40e72de90f0___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
32
+ export const wasm_bindgen_4fd6a40e72de90f0___convert__closures_____invoke_______true_: (a: number, b: number) => void;
35
33
  export const __wbindgen_exn_store: (a: number) => void;
36
34
  export const __externref_table_alloc: () => number;
37
35
  export const __wbindgen_externrefs: WebAssembly.Table;
36
+ export const __wbindgen_malloc: (a: number, b: number) => number;
37
+ export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
38
38
  export const __wbindgen_free: (a: number, b: number, c: number) => void;
39
39
  export const __externref_table_dealloc: (a: number) => void;
40
40
  export const __wbindgen_start: () => void;