@cipherstash/stack 0.18.0 → 1.0.0-rc.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.
- package/CHANGELOG.md +704 -0
- package/README.md +97 -79
- package/dist/adapter-kit.cjs +923 -0
- package/dist/adapter-kit.cjs.map +1 -0
- package/dist/adapter-kit.d.cts +82 -0
- package/dist/adapter-kit.d.ts +82 -0
- package/dist/adapter-kit.js +47 -0
- package/dist/adapter-kit.js.map +1 -0
- package/dist/base-operation-AOAIvsSB.d.cts +32 -0
- package/dist/base-operation-FXEzUXIq.d.ts +32 -0
- package/dist/{chunk-VPOTNP4K.js → chunk-3B5ZX3IS.js} +3 -1
- package/dist/chunk-3B5ZX3IS.js.map +1 -0
- package/dist/chunk-7333ZC6L.js +48 -0
- package/dist/chunk-7333ZC6L.js.map +1 -0
- package/dist/{chunk-XWPGAHBZ.js → chunk-BNO32ZMV.js} +1 -1
- package/dist/chunk-BNO32ZMV.js.map +1 -0
- package/dist/chunk-CLM7E4I6.js +4439 -0
- package/dist/chunk-CLM7E4I6.js.map +1 -0
- package/dist/{chunk-LLCCNKDL.js → chunk-HQANMV7R.js} +3 -3
- package/dist/{chunk-LLCCNKDL.js.map → chunk-HQANMV7R.js.map} +1 -1
- package/dist/chunk-JSG2AMDI.js +17 -0
- package/dist/chunk-JSG2AMDI.js.map +1 -0
- package/dist/chunk-OFQ555AX.js +191 -0
- package/dist/chunk-OFQ555AX.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-V2Q3NYIH.js +494 -0
- package/dist/chunk-V2Q3NYIH.js.map +1 -0
- package/dist/chunk-X3JRXEIB.js +98 -0
- package/dist/chunk-X3JRXEIB.js.map +1 -0
- package/dist/{chunk-ZYOZHZMJ.js → chunk-ZTP5QJ27.js} +193 -169
- package/dist/chunk-ZTP5QJ27.js.map +1 -0
- package/dist/client.cjs +4124 -49
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +6 -5
- package/dist/client.d.ts +6 -5
- package/dist/client.js +3 -1
- package/dist/columns-D2_YzrCX.d.cts +622 -0
- package/dist/columns-rZc7fQHI.d.ts +622 -0
- package/dist/dynamodb/index.cjs +19 -12
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +3 -2
- package/dist/dynamodb/index.d.ts +3 -2
- package/dist/dynamodb/index.js +8 -10
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/encryption/index.cjs +4496 -222
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +807 -6
- package/dist/encryption/index.d.ts +807 -6
- package/dist/encryption/index.js +15 -7
- package/dist/encryption/v3.cjs +7896 -0
- package/dist/encryption/v3.cjs.map +1 -0
- package/dist/encryption/v3.d.cts +103 -0
- package/dist/encryption/v3.d.ts +103 -0
- package/dist/encryption/v3.js +189 -0
- package/dist/encryption/v3.js.map +1 -0
- package/dist/eql/v3/index.cjs +663 -0
- package/dist/eql/v3/index.cjs.map +1 -0
- package/dist/eql/v3/index.d.cts +173 -0
- package/dist/eql/v3/index.d.ts +173 -0
- package/dist/eql/v3/index.js +99 -0
- package/dist/eql/v3/index.js.map +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/identity/index.cjs +55 -35
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.d.cts +54 -30
- package/dist/identity/index.d.ts +54 -30
- package/dist/identity/index.js +9 -177
- package/dist/identity/index.js.map +1 -1
- package/dist/index-BquA71_Y.d.ts +24 -0
- package/dist/index-fhWTOV0K.d.cts +24 -0
- package/dist/index.cjs +4547 -243
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -19
- package/dist/index.d.ts +18 -19
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/schema/index.cjs +4128 -49
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +3 -1
- package/dist/{types-public-BTxqjmtv.d.cts → types-public-QMjYNfQO.d.cts} +448 -251
- package/dist/{types-public-BTxqjmtv.d.ts → types-public-QMjYNfQO.d.ts} +448 -251
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +2 -2
- package/dist/types-public.d.ts +2 -2
- package/dist/types-public.js +2 -1
- package/dist/wasm-inline.d.ts +1643 -0
- package/dist/wasm-inline.js +4901 -0
- package/dist/wasm-inline.js.map +1 -0
- package/package.json +74 -52
- package/dist/chunk-VPOTNP4K.js.map +0 -1
- package/dist/chunk-XWPGAHBZ.js.map +0 -1
- package/dist/chunk-YWQXTZ5M.js +0 -383
- package/dist/chunk-YWQXTZ5M.js.map +0 -1
- package/dist/chunk-ZYOZHZMJ.js.map +0 -1
- package/dist/client-CIsfZ2zg.d.ts +0 -692
- package/dist/client-Dt98Rugc.d.cts +0 -692
- package/dist/drizzle/index.cjs +0 -1558
- package/dist/drizzle/index.cjs.map +0 -1
- package/dist/drizzle/index.d.cts +0 -358
- package/dist/drizzle/index.d.ts +0 -358
- package/dist/drizzle/index.js +0 -1215
- package/dist/drizzle/index.js.map +0 -1
- package/dist/supabase/index.cjs +0 -1526
- package/dist/supabase/index.cjs.map +0 -1
- package/dist/supabase/index.d.cts +0 -144
- package/dist/supabase/index.d.ts +0 -144
- package/dist/supabase/index.js +0 -899
- package/dist/supabase/index.js.map +0 -1
|
@@ -1,26 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveLockContext
|
|
3
|
+
} from "./chunk-OFQ555AX.js";
|
|
1
4
|
import {
|
|
2
5
|
formatEncryptedResult,
|
|
3
6
|
isEncryptedPayload,
|
|
4
7
|
toFfiKeysetIdentifier
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BNO32ZMV.js";
|
|
6
9
|
import {
|
|
7
10
|
buildEncryptConfig,
|
|
8
11
|
encryptConfigSchema
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CLM7E4I6.js";
|
|
10
13
|
import {
|
|
11
14
|
queryTypeToFfi,
|
|
12
15
|
queryTypeToQueryOp
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3B5ZX3IS.js";
|
|
17
|
+
import {
|
|
18
|
+
withResult
|
|
19
|
+
} from "./chunk-JSG2AMDI.js";
|
|
14
20
|
import {
|
|
15
21
|
createRequestLogger,
|
|
16
22
|
logger
|
|
17
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-HQANMV7R.js";
|
|
18
24
|
import {
|
|
19
25
|
EncryptionErrorTypes
|
|
20
26
|
} from "./chunk-LBMC4D6D.js";
|
|
21
27
|
|
|
22
28
|
// src/encryption/index.ts
|
|
23
|
-
import { withResult as withResult11 } from "@byteslice/result";
|
|
24
29
|
import { newClient } from "@cipherstash/protect-ffi";
|
|
25
30
|
|
|
26
31
|
// ../../node_modules/.pnpm/uuid@14.0.0/node_modules/uuid/dist-node/regex.js
|
|
@@ -37,6 +42,11 @@ function isScalarQueryTermArray(value) {
|
|
|
37
42
|
return Array.isArray(value) && value.length > 0 && typeof value[0] === "object" && value[0] !== null && "column" in value[0] && "table" in value[0];
|
|
38
43
|
}
|
|
39
44
|
|
|
45
|
+
// src/encryption/operations/batch-encrypt-query.ts
|
|
46
|
+
import {
|
|
47
|
+
encryptQueryBulk as ffiEncryptQueryBulk
|
|
48
|
+
} from "@cipherstash/protect-ffi";
|
|
49
|
+
|
|
40
50
|
// src/encryption/helpers/error-code.ts
|
|
41
51
|
import {
|
|
42
52
|
ProtectError as FfiProtectError
|
|
@@ -45,12 +55,6 @@ function getErrorCode(error) {
|
|
|
45
55
|
return error instanceof FfiProtectError ? error.code : void 0;
|
|
46
56
|
}
|
|
47
57
|
|
|
48
|
-
// src/encryption/operations/batch-encrypt-query.ts
|
|
49
|
-
import { withResult } from "@byteslice/result";
|
|
50
|
-
import {
|
|
51
|
-
encryptQueryBulk as ffiEncryptQueryBulk
|
|
52
|
-
} from "@cipherstash/protect-ffi";
|
|
53
|
-
|
|
54
58
|
// src/encryption/helpers/infer-index-type.ts
|
|
55
59
|
function inferIndexType(column) {
|
|
56
60
|
const config = column.build();
|
|
@@ -61,6 +65,7 @@ function inferIndexType(column) {
|
|
|
61
65
|
if (indexes.unique) return "unique";
|
|
62
66
|
if (indexes.match) return "match";
|
|
63
67
|
if (indexes.ore) return "ore";
|
|
68
|
+
if (indexes.ope) return "ope";
|
|
64
69
|
if (indexes.ste_vec) return "ste_vec";
|
|
65
70
|
throw new Error(
|
|
66
71
|
`Column "${column.getName()}" has no suitable index for queries`
|
|
@@ -70,7 +75,7 @@ function inferQueryOpFromPlaintext(plaintext) {
|
|
|
70
75
|
if (typeof plaintext === "string") {
|
|
71
76
|
return "ste_vec_selector";
|
|
72
77
|
}
|
|
73
|
-
if (typeof plaintext === "object" || typeof plaintext === "number" || typeof plaintext === "boolean"
|
|
78
|
+
if (typeof plaintext === "object" || typeof plaintext === "number" || typeof plaintext === "boolean") {
|
|
74
79
|
return "ste_vec_term";
|
|
75
80
|
}
|
|
76
81
|
return "ste_vec_term";
|
|
@@ -82,6 +87,7 @@ function validateIndexType(column, indexType) {
|
|
|
82
87
|
unique: !!indexes.unique,
|
|
83
88
|
match: !!indexes.match,
|
|
84
89
|
ore: !!indexes.ore,
|
|
90
|
+
ope: !!indexes.ope,
|
|
85
91
|
ste_vec: !!indexes.ste_vec
|
|
86
92
|
};
|
|
87
93
|
if (!indexMap[indexType]) {
|
|
@@ -90,9 +96,26 @@ function validateIndexType(column, indexType) {
|
|
|
90
96
|
);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
99
|
+
function equalityOrderingIndex(column) {
|
|
100
|
+
if (!("getQueryCapabilities" in column)) return null;
|
|
101
|
+
if (!column.getQueryCapabilities().equality) return null;
|
|
102
|
+
const indexes = column.build().indexes ?? {};
|
|
103
|
+
if (indexes.unique) return null;
|
|
104
|
+
if (indexes.ore) return "ore";
|
|
105
|
+
if (indexes.ope) return "ope";
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
93
108
|
function resolveIndexType(column, queryType, plaintext) {
|
|
94
|
-
|
|
109
|
+
let indexType = queryType ? queryTypeToFfi[queryType] : inferIndexType(column);
|
|
95
110
|
if (queryType) {
|
|
111
|
+
if (queryType === "equality") {
|
|
112
|
+
const ordering = equalityOrderingIndex(column);
|
|
113
|
+
if (ordering) return { indexType: ordering };
|
|
114
|
+
}
|
|
115
|
+
if (queryType === "orderAndRange" && indexType === "ore") {
|
|
116
|
+
const indexes = column.build().indexes ?? {};
|
|
117
|
+
if (!indexes.ore && indexes.ope) indexType = "ope";
|
|
118
|
+
}
|
|
96
119
|
validateIndexType(column, indexType);
|
|
97
120
|
if (queryType === "searchableJson") {
|
|
98
121
|
if (plaintext === void 0 || plaintext === null) {
|
|
@@ -112,6 +135,11 @@ function resolveIndexType(column, queryType, plaintext) {
|
|
|
112
135
|
}
|
|
113
136
|
|
|
114
137
|
// src/encryption/helpers/validation.ts
|
|
138
|
+
var INT64_MIN = -9223372036854775808n;
|
|
139
|
+
var INT64_MAX = 9223372036854775807n;
|
|
140
|
+
function isBigintOutOfInt64Range(value) {
|
|
141
|
+
return typeof value === "bigint" && (value < INT64_MIN || value > INT64_MAX);
|
|
142
|
+
}
|
|
115
143
|
function validateNumericValue(value) {
|
|
116
144
|
if (typeof value === "number" && Number.isNaN(value)) {
|
|
117
145
|
return {
|
|
@@ -129,6 +157,14 @@ function validateNumericValue(value) {
|
|
|
129
157
|
}
|
|
130
158
|
};
|
|
131
159
|
}
|
|
160
|
+
if (isBigintOutOfInt64Range(value)) {
|
|
161
|
+
return {
|
|
162
|
+
failure: {
|
|
163
|
+
type: EncryptionErrorTypes.EncryptionError,
|
|
164
|
+
message: "[encryption]: Cannot encrypt bigint value out of int64 range"
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
132
168
|
return void 0;
|
|
133
169
|
}
|
|
134
170
|
function assertValidNumericValue(value) {
|
|
@@ -138,9 +174,14 @@ function assertValidNumericValue(value) {
|
|
|
138
174
|
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
139
175
|
throw new Error("[encryption]: Cannot encrypt Infinity value");
|
|
140
176
|
}
|
|
177
|
+
if (isBigintOutOfInt64Range(value)) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
"[encryption]: Cannot encrypt bigint value out of int64 range"
|
|
180
|
+
);
|
|
181
|
+
}
|
|
141
182
|
}
|
|
142
183
|
function assertValueIndexCompatibility(value, indexType, columnName) {
|
|
143
|
-
if (typeof value === "number" && indexType === "match") {
|
|
184
|
+
if ((typeof value === "number" || typeof value === "bigint") && indexType === "match") {
|
|
144
185
|
throw new Error(
|
|
145
186
|
`[encryption]: Cannot use 'match' index with numeric value on column "${columnName}". The 'freeTextSearch' index only supports string values. Configure the column with 'orderAndRange()' or 'equality()' for numeric queries.`
|
|
146
187
|
);
|
|
@@ -300,22 +341,16 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
300
341
|
log.emit();
|
|
301
342
|
return { data: this.terms.map(() => null) };
|
|
302
343
|
}
|
|
303
|
-
const lockContextResult = await this.lockContext.getLockContext();
|
|
304
|
-
if (lockContextResult.failure) {
|
|
305
|
-
log.emit();
|
|
306
|
-
return { failure: lockContextResult.failure };
|
|
307
|
-
}
|
|
308
|
-
const { ctsToken, context } = lockContextResult.data;
|
|
309
344
|
const result = await withResult(
|
|
310
345
|
async () => {
|
|
311
346
|
if (!this.client) throw noClientError();
|
|
347
|
+
const context = resolveLockContext(this.lockContext);
|
|
312
348
|
const { metadata } = this.getAuditData();
|
|
313
349
|
const queries = nonNullTerms.map(
|
|
314
350
|
({ term }) => buildQueryPayload(term, context)
|
|
315
351
|
);
|
|
316
352
|
const encrypted = await ffiEncryptQueryBulk(this.client, {
|
|
317
353
|
queries,
|
|
318
|
-
serviceToken: ctsToken,
|
|
319
354
|
unverifiedContext: metadata
|
|
320
355
|
});
|
|
321
356
|
return assembleResults(this.terms.length, encrypted, nonNullTerms);
|
|
@@ -335,7 +370,6 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
335
370
|
};
|
|
336
371
|
|
|
337
372
|
// src/encryption/operations/bulk-decrypt.ts
|
|
338
|
-
import { withResult as withResult2 } from "@byteslice/result";
|
|
339
373
|
import {
|
|
340
374
|
decryptBulkFallible
|
|
341
375
|
} from "@cipherstash/protect-ffi";
|
|
@@ -383,7 +417,7 @@ var BulkDecryptOperation = class extends EncryptionOperation {
|
|
|
383
417
|
count: this.encryptedPayloads?.length ?? 0,
|
|
384
418
|
lockContext: false
|
|
385
419
|
});
|
|
386
|
-
const result = await
|
|
420
|
+
const result = await withResult(
|
|
387
421
|
async () => {
|
|
388
422
|
if (!this.client) throw noClientError();
|
|
389
423
|
if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
|
|
@@ -438,17 +472,14 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
438
472
|
count: encryptedPayloads?.length ?? 0,
|
|
439
473
|
lockContext: true
|
|
440
474
|
});
|
|
441
|
-
const result = await
|
|
475
|
+
const result = await withResult(
|
|
442
476
|
async () => {
|
|
443
477
|
if (!client) throw noClientError();
|
|
444
478
|
if (!encryptedPayloads || encryptedPayloads.length === 0) return [];
|
|
445
|
-
const
|
|
446
|
-
if (context.failure) {
|
|
447
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
448
|
-
}
|
|
479
|
+
const lockContext = resolveLockContext(this.lockContext);
|
|
449
480
|
const nonNullPayloads = createDecryptPayloads(
|
|
450
481
|
encryptedPayloads,
|
|
451
|
-
|
|
482
|
+
lockContext
|
|
452
483
|
);
|
|
453
484
|
if (nonNullPayloads.length === 0) {
|
|
454
485
|
return createNullResult(encryptedPayloads);
|
|
@@ -456,7 +487,6 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
456
487
|
const { metadata } = this.getAuditData();
|
|
457
488
|
const decryptedData = await decryptBulkFallible(client, {
|
|
458
489
|
ciphertexts: nonNullPayloads,
|
|
459
|
-
serviceToken: context.data.ctsToken,
|
|
460
490
|
unverifiedContext: metadata
|
|
461
491
|
});
|
|
462
492
|
return mapDecryptedDataToResult(encryptedPayloads, decryptedData);
|
|
@@ -475,9 +505,6 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
475
505
|
}
|
|
476
506
|
};
|
|
477
507
|
|
|
478
|
-
// src/encryption/operations/bulk-decrypt-models.ts
|
|
479
|
-
import { withResult as withResult3 } from "@byteslice/result";
|
|
480
|
-
|
|
481
508
|
// src/encryption/helpers/model-helpers.ts
|
|
482
509
|
import {
|
|
483
510
|
decryptBulk,
|
|
@@ -559,6 +586,17 @@ function prepareFieldsForDecryption(model) {
|
|
|
559
586
|
processNestedFields(model);
|
|
560
587
|
return { otherFields, operationFields, keyMap, nullFields };
|
|
561
588
|
}
|
|
589
|
+
function resolveEncryptColumnMap(table) {
|
|
590
|
+
const keyMap = table.buildColumnKeyMap?.();
|
|
591
|
+
if (keyMap) {
|
|
592
|
+
return {
|
|
593
|
+
columnPaths: Object.keys(keyMap),
|
|
594
|
+
toColumnName: (path) => keyMap[path] ?? path
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
const columnPaths = Object.keys(table.build().columns);
|
|
598
|
+
return { columnPaths, toColumnName: (path) => path };
|
|
599
|
+
}
|
|
562
600
|
function prepareFieldsForEncryption(model, table) {
|
|
563
601
|
const otherFields = { ...model };
|
|
564
602
|
const operationFields = {};
|
|
@@ -581,6 +619,7 @@ function prepareFieldsForEncryption(model, table) {
|
|
|
581
619
|
);
|
|
582
620
|
}
|
|
583
621
|
} else if (columnPaths2.includes(fullKey)) {
|
|
622
|
+
assertValidNumericValue(value);
|
|
584
623
|
const id = index.toString();
|
|
585
624
|
keyMap[id] = fullKey;
|
|
586
625
|
operationFields[fullKey] = value;
|
|
@@ -594,7 +633,7 @@ function prepareFieldsForEncryption(model, table) {
|
|
|
594
633
|
}
|
|
595
634
|
}
|
|
596
635
|
};
|
|
597
|
-
const columnPaths =
|
|
636
|
+
const { columnPaths } = resolveEncryptColumnMap(table);
|
|
598
637
|
processNestedFields(model, "", columnPaths);
|
|
599
638
|
return { otherFields, operationFields, keyMap, nullFields };
|
|
600
639
|
}
|
|
@@ -633,12 +672,13 @@ async function encryptModelFields(model, table, client, auditData) {
|
|
|
633
672
|
throw new Error("Client not initialized");
|
|
634
673
|
}
|
|
635
674
|
const { otherFields, operationFields, keyMap, nullFields } = prepareFieldsForEncryption(model, table);
|
|
675
|
+
const { toColumnName } = resolveEncryptColumnMap(table);
|
|
636
676
|
const bulkEncryptPayload = Object.entries(operationFields).map(
|
|
637
677
|
([key, value]) => ({
|
|
638
678
|
id: key,
|
|
639
679
|
plaintext: value,
|
|
640
680
|
table: table.tableName,
|
|
641
|
-
column: key
|
|
681
|
+
column: toColumnName(key)
|
|
642
682
|
})
|
|
643
683
|
);
|
|
644
684
|
const encryptedData = await handleSingleModelBulkOperation(
|
|
@@ -672,14 +712,13 @@ async function decryptModelFieldsWithLockContext(model, client, lockContext, aud
|
|
|
672
712
|
([key, value]) => ({
|
|
673
713
|
id: key,
|
|
674
714
|
ciphertext: value,
|
|
675
|
-
lockContext
|
|
715
|
+
lockContext
|
|
676
716
|
})
|
|
677
717
|
);
|
|
678
718
|
const decryptedFields = await handleSingleModelBulkOperation(
|
|
679
719
|
bulkDecryptPayload,
|
|
680
720
|
(items) => decryptBulk(client, {
|
|
681
721
|
ciphertexts: items,
|
|
682
|
-
serviceToken: lockContext.ctsToken,
|
|
683
722
|
unverifiedContext: auditData?.metadata
|
|
684
723
|
}),
|
|
685
724
|
keyMap
|
|
@@ -703,20 +742,20 @@ async function encryptModelFieldsWithLockContext(model, table, client, lockConte
|
|
|
703
742
|
throw new Error("Lock context is not initialized");
|
|
704
743
|
}
|
|
705
744
|
const { otherFields, operationFields, keyMap, nullFields } = prepareFieldsForEncryption(model, table);
|
|
745
|
+
const { toColumnName } = resolveEncryptColumnMap(table);
|
|
706
746
|
const bulkEncryptPayload = Object.entries(operationFields).map(
|
|
707
747
|
([key, value]) => ({
|
|
708
748
|
id: key,
|
|
709
749
|
plaintext: value,
|
|
710
750
|
table: table.tableName,
|
|
711
|
-
column: key,
|
|
712
|
-
lockContext
|
|
751
|
+
column: toColumnName(key),
|
|
752
|
+
lockContext
|
|
713
753
|
})
|
|
714
754
|
);
|
|
715
755
|
const encryptedData = await handleSingleModelBulkOperation(
|
|
716
756
|
bulkEncryptPayload,
|
|
717
757
|
(items) => encryptBulk(client, {
|
|
718
758
|
plaintexts: items,
|
|
719
|
-
serviceToken: lockContext.ctsToken,
|
|
720
759
|
unverifiedContext: auditData?.metadata
|
|
721
760
|
}),
|
|
722
761
|
keyMap
|
|
@@ -759,6 +798,7 @@ function prepareBulkModelsForOperation(models, table) {
|
|
|
759
798
|
);
|
|
760
799
|
}
|
|
761
800
|
} else if (columnPaths.includes(fullKey)) {
|
|
801
|
+
assertValidNumericValue(value);
|
|
762
802
|
const id = index.toString();
|
|
763
803
|
keyMap[id] = { modelIndex, fieldKey: fullKey };
|
|
764
804
|
modelOperationFields[fullKey] = value;
|
|
@@ -773,7 +813,7 @@ function prepareBulkModelsForOperation(models, table) {
|
|
|
773
813
|
}
|
|
774
814
|
};
|
|
775
815
|
if (table) {
|
|
776
|
-
const columnPaths =
|
|
816
|
+
const { columnPaths } = resolveEncryptColumnMap(table);
|
|
777
817
|
processNestedFields(model, "", columnPaths);
|
|
778
818
|
} else {
|
|
779
819
|
const processEncryptedFields = (obj, prefix = "", columnPaths = []) => {
|
|
@@ -811,6 +851,15 @@ function prepareBulkModelsForOperation(models, table) {
|
|
|
811
851
|
}
|
|
812
852
|
return { otherFields, operationFields, keyMap, nullFields };
|
|
813
853
|
}
|
|
854
|
+
function fieldsForModelIndex(fields, modelIndex) {
|
|
855
|
+
const result = {};
|
|
856
|
+
for (const [id, value] of Object.entries(fields)) {
|
|
857
|
+
const sep = id.indexOf("-");
|
|
858
|
+
if (Number.parseInt(id.slice(0, sep), 10) !== modelIndex) continue;
|
|
859
|
+
result[id.slice(sep + 1)] = value;
|
|
860
|
+
}
|
|
861
|
+
return result;
|
|
862
|
+
}
|
|
814
863
|
async function bulkEncryptModels(models, table, client, auditData) {
|
|
815
864
|
if (!client) {
|
|
816
865
|
throw new Error("Client not initialized");
|
|
@@ -819,12 +868,13 @@ async function bulkEncryptModels(models, table, client, auditData) {
|
|
|
819
868
|
return [];
|
|
820
869
|
}
|
|
821
870
|
const { otherFields, operationFields, keyMap, nullFields } = prepareBulkModelsForOperation(models, table);
|
|
871
|
+
const { toColumnName } = resolveEncryptColumnMap(table);
|
|
822
872
|
const bulkEncryptPayload = operationFields.flatMap(
|
|
823
873
|
(fields, modelIndex) => Object.entries(fields).map(([key, value]) => ({
|
|
824
874
|
id: `${modelIndex}-${key}`,
|
|
825
875
|
plaintext: value,
|
|
826
876
|
table: table.tableName,
|
|
827
|
-
column: key
|
|
877
|
+
column: toColumnName(key)
|
|
828
878
|
}))
|
|
829
879
|
);
|
|
830
880
|
const encryptedData = await handleMultiModelBulkOperation(
|
|
@@ -841,15 +891,7 @@ async function bulkEncryptModels(models, table, client, auditData) {
|
|
|
841
891
|
const parts = key.split(".");
|
|
842
892
|
setNestedValue(result, parts, value);
|
|
843
893
|
}
|
|
844
|
-
const modelData =
|
|
845
|
-
Object.entries(encryptedData).filter(([key]) => {
|
|
846
|
-
const [idx] = key.split("-");
|
|
847
|
-
return Number.parseInt(idx) === modelIndex;
|
|
848
|
-
}).map(([key, value]) => {
|
|
849
|
-
const [_2, fieldKey] = key.split("-");
|
|
850
|
-
return [fieldKey, value];
|
|
851
|
-
})
|
|
852
|
-
);
|
|
894
|
+
const modelData = fieldsForModelIndex(encryptedData, modelIndex);
|
|
853
895
|
for (const [key, value] of Object.entries(modelData)) {
|
|
854
896
|
const parts = key.split(".");
|
|
855
897
|
setNestedValue(result, parts, value);
|
|
@@ -885,15 +927,7 @@ async function bulkDecryptModels(models, client, auditData) {
|
|
|
885
927
|
const parts = key.split(".");
|
|
886
928
|
setNestedValue(result, parts, value);
|
|
887
929
|
}
|
|
888
|
-
const modelData =
|
|
889
|
-
Object.entries(decryptedFields).filter(([key]) => {
|
|
890
|
-
const [idx] = key.split("-");
|
|
891
|
-
return Number.parseInt(idx) === modelIndex;
|
|
892
|
-
}).map(([key, value]) => {
|
|
893
|
-
const [_2, fieldKey] = key.split("-");
|
|
894
|
-
return [fieldKey, value];
|
|
895
|
-
})
|
|
896
|
-
);
|
|
930
|
+
const modelData = fieldsForModelIndex(decryptedFields, modelIndex);
|
|
897
931
|
for (const [key, value] of Object.entries(modelData)) {
|
|
898
932
|
const parts = key.split(".");
|
|
899
933
|
setNestedValue(result, parts, value);
|
|
@@ -913,14 +947,13 @@ async function bulkDecryptModelsWithLockContext(models, client, lockContext, aud
|
|
|
913
947
|
(fields, modelIndex) => Object.entries(fields).map(([key, value]) => ({
|
|
914
948
|
id: `${modelIndex}-${key}`,
|
|
915
949
|
ciphertext: value,
|
|
916
|
-
lockContext
|
|
950
|
+
lockContext
|
|
917
951
|
}))
|
|
918
952
|
);
|
|
919
953
|
const decryptedFields = await handleMultiModelBulkOperation(
|
|
920
954
|
bulkDecryptPayload,
|
|
921
955
|
(items) => decryptBulk(client, {
|
|
922
956
|
ciphertexts: items,
|
|
923
|
-
serviceToken: lockContext.ctsToken,
|
|
924
957
|
unverifiedContext: auditData?.metadata
|
|
925
958
|
}),
|
|
926
959
|
keyMap
|
|
@@ -931,15 +964,7 @@ async function bulkDecryptModelsWithLockContext(models, client, lockContext, aud
|
|
|
931
964
|
const parts = key.split(".");
|
|
932
965
|
setNestedValue(result, parts, value);
|
|
933
966
|
}
|
|
934
|
-
const modelData =
|
|
935
|
-
Object.entries(decryptedFields).filter(([key]) => {
|
|
936
|
-
const [idx] = key.split("-");
|
|
937
|
-
return Number.parseInt(idx) === modelIndex;
|
|
938
|
-
}).map(([key, value]) => {
|
|
939
|
-
const [_2, fieldKey] = key.split("-");
|
|
940
|
-
return [fieldKey, value];
|
|
941
|
-
})
|
|
942
|
-
);
|
|
967
|
+
const modelData = fieldsForModelIndex(decryptedFields, modelIndex);
|
|
943
968
|
for (const [key, value] of Object.entries(modelData)) {
|
|
944
969
|
const parts = key.split(".");
|
|
945
970
|
setNestedValue(result, parts, value);
|
|
@@ -955,20 +980,20 @@ async function bulkEncryptModelsWithLockContext(models, table, client, lockConte
|
|
|
955
980
|
throw new Error("Lock context is not initialized");
|
|
956
981
|
}
|
|
957
982
|
const { otherFields, operationFields, keyMap, nullFields } = prepareBulkModelsForOperation(models, table);
|
|
983
|
+
const { toColumnName } = resolveEncryptColumnMap(table);
|
|
958
984
|
const bulkEncryptPayload = operationFields.flatMap(
|
|
959
985
|
(fields, modelIndex) => Object.entries(fields).map(([key, value]) => ({
|
|
960
986
|
id: `${modelIndex}-${key}`,
|
|
961
987
|
plaintext: value,
|
|
962
988
|
table: table.tableName,
|
|
963
|
-
column: key,
|
|
964
|
-
lockContext
|
|
989
|
+
column: toColumnName(key),
|
|
990
|
+
lockContext
|
|
965
991
|
}))
|
|
966
992
|
);
|
|
967
993
|
const encryptedData = await handleMultiModelBulkOperation(
|
|
968
994
|
bulkEncryptPayload,
|
|
969
995
|
(items) => encryptBulk(client, {
|
|
970
996
|
plaintexts: items,
|
|
971
|
-
serviceToken: lockContext.ctsToken,
|
|
972
997
|
unverifiedContext: auditData?.metadata
|
|
973
998
|
}),
|
|
974
999
|
keyMap
|
|
@@ -979,15 +1004,7 @@ async function bulkEncryptModelsWithLockContext(models, table, client, lockConte
|
|
|
979
1004
|
const parts = key.split(".");
|
|
980
1005
|
setNestedValue(result, parts, value);
|
|
981
1006
|
}
|
|
982
|
-
const modelData =
|
|
983
|
-
Object.entries(encryptedData).filter(([key]) => {
|
|
984
|
-
const [idx] = key.split("-");
|
|
985
|
-
return Number.parseInt(idx) === modelIndex;
|
|
986
|
-
}).map(([key, value]) => {
|
|
987
|
-
const [_2, fieldKey] = key.split("-");
|
|
988
|
-
return [fieldKey, value];
|
|
989
|
-
})
|
|
990
|
-
);
|
|
1007
|
+
const modelData = fieldsForModelIndex(encryptedData, modelIndex);
|
|
991
1008
|
for (const [key, value] of Object.entries(modelData)) {
|
|
992
1009
|
const parts = key.split(".");
|
|
993
1010
|
setNestedValue(result, parts, value);
|
|
@@ -1015,7 +1032,7 @@ var BulkDecryptModelsOperation = class extends EncryptionOperation {
|
|
|
1015
1032
|
count: this.models.length,
|
|
1016
1033
|
lockContext: false
|
|
1017
1034
|
});
|
|
1018
|
-
const result = await
|
|
1035
|
+
const result = await withResult(
|
|
1019
1036
|
async () => {
|
|
1020
1037
|
if (!this.client) {
|
|
1021
1038
|
throw noClientError();
|
|
@@ -1062,20 +1079,17 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1062
1079
|
count: models.length,
|
|
1063
1080
|
lockContext: true
|
|
1064
1081
|
});
|
|
1065
|
-
const result = await
|
|
1082
|
+
const result = await withResult(
|
|
1066
1083
|
async () => {
|
|
1067
1084
|
if (!client) {
|
|
1068
1085
|
throw noClientError();
|
|
1069
1086
|
}
|
|
1070
|
-
const context =
|
|
1071
|
-
if (context.failure) {
|
|
1072
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1073
|
-
}
|
|
1087
|
+
const context = resolveLockContext(this.lockContext);
|
|
1074
1088
|
const auditData = this.getAuditData();
|
|
1075
1089
|
return await bulkDecryptModelsWithLockContext(
|
|
1076
1090
|
models,
|
|
1077
1091
|
client,
|
|
1078
|
-
context
|
|
1092
|
+
context,
|
|
1079
1093
|
auditData
|
|
1080
1094
|
);
|
|
1081
1095
|
},
|
|
@@ -1094,16 +1108,18 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1094
1108
|
};
|
|
1095
1109
|
|
|
1096
1110
|
// src/encryption/operations/bulk-encrypt.ts
|
|
1097
|
-
import { withResult as withResult4 } from "@byteslice/result";
|
|
1098
1111
|
import { encryptBulk as encryptBulk2 } from "@cipherstash/protect-ffi";
|
|
1099
1112
|
var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
1100
|
-
return plaintexts.filter(({ plaintext }) => plaintext !== null).map(({ id, plaintext }) =>
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1113
|
+
return plaintexts.filter(({ plaintext }) => plaintext !== null).map(({ id, plaintext }) => {
|
|
1114
|
+
assertValidNumericValue(plaintext);
|
|
1115
|
+
return {
|
|
1116
|
+
id,
|
|
1117
|
+
plaintext,
|
|
1118
|
+
column: column.getName(),
|
|
1119
|
+
table: table.tableName,
|
|
1120
|
+
...lockContext && { lockContext }
|
|
1121
|
+
};
|
|
1122
|
+
});
|
|
1107
1123
|
};
|
|
1108
1124
|
var createNullResult2 = (plaintexts) => plaintexts.map(({ id }) => ({ id, data: null }));
|
|
1109
1125
|
var mapEncryptedDataToResult = (plaintexts, encryptedData) => {
|
|
@@ -1143,7 +1159,7 @@ var BulkEncryptOperation = class extends EncryptionOperation {
|
|
|
1143
1159
|
count: this.plaintexts?.length ?? 0,
|
|
1144
1160
|
lockContext: false
|
|
1145
1161
|
});
|
|
1146
|
-
const result = await
|
|
1162
|
+
const result = await withResult(
|
|
1147
1163
|
async () => {
|
|
1148
1164
|
if (!this.client) {
|
|
1149
1165
|
throw noClientError();
|
|
@@ -1209,7 +1225,7 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1209
1225
|
count: plaintexts?.length ?? 0,
|
|
1210
1226
|
lockContext: true
|
|
1211
1227
|
});
|
|
1212
|
-
const result = await
|
|
1228
|
+
const result = await withResult(
|
|
1213
1229
|
async () => {
|
|
1214
1230
|
if (!client) {
|
|
1215
1231
|
throw noClientError();
|
|
@@ -1217,15 +1233,12 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1217
1233
|
if (!plaintexts || plaintexts.length === 0) {
|
|
1218
1234
|
return [];
|
|
1219
1235
|
}
|
|
1220
|
-
const
|
|
1221
|
-
if (context.failure) {
|
|
1222
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1223
|
-
}
|
|
1236
|
+
const lockContext = resolveLockContext(this.lockContext);
|
|
1224
1237
|
const nonNullPayloads = createEncryptPayloads(
|
|
1225
1238
|
plaintexts,
|
|
1226
1239
|
column,
|
|
1227
1240
|
table,
|
|
1228
|
-
|
|
1241
|
+
lockContext
|
|
1229
1242
|
);
|
|
1230
1243
|
if (nonNullPayloads.length === 0) {
|
|
1231
1244
|
return createNullResult2(plaintexts);
|
|
@@ -1233,7 +1246,6 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1233
1246
|
const { metadata } = this.getAuditData();
|
|
1234
1247
|
const encryptedData = await encryptBulk2(client, {
|
|
1235
1248
|
plaintexts: nonNullPayloads,
|
|
1236
|
-
serviceToken: context.data.ctsToken,
|
|
1237
1249
|
unverifiedContext: metadata
|
|
1238
1250
|
});
|
|
1239
1251
|
return mapEncryptedDataToResult(plaintexts, encryptedData);
|
|
@@ -1253,7 +1265,6 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1253
1265
|
};
|
|
1254
1266
|
|
|
1255
1267
|
// src/encryption/operations/bulk-encrypt-models.ts
|
|
1256
|
-
import { withResult as withResult5 } from "@byteslice/result";
|
|
1257
1268
|
var BulkEncryptModelsOperation = class extends EncryptionOperation {
|
|
1258
1269
|
client;
|
|
1259
1270
|
models;
|
|
@@ -1275,7 +1286,7 @@ var BulkEncryptModelsOperation = class extends EncryptionOperation {
|
|
|
1275
1286
|
count: this.models.length,
|
|
1276
1287
|
lockContext: false
|
|
1277
1288
|
});
|
|
1278
|
-
const result = await
|
|
1289
|
+
const result = await withResult(
|
|
1279
1290
|
async () => {
|
|
1280
1291
|
if (!this.client) {
|
|
1281
1292
|
throw noClientError();
|
|
@@ -1329,21 +1340,18 @@ var BulkEncryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1329
1340
|
count: models.length,
|
|
1330
1341
|
lockContext: true
|
|
1331
1342
|
});
|
|
1332
|
-
const result = await
|
|
1343
|
+
const result = await withResult(
|
|
1333
1344
|
async () => {
|
|
1334
1345
|
if (!client) {
|
|
1335
1346
|
throw noClientError();
|
|
1336
1347
|
}
|
|
1337
|
-
const context =
|
|
1338
|
-
if (context.failure) {
|
|
1339
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1340
|
-
}
|
|
1348
|
+
const context = resolveLockContext(this.lockContext);
|
|
1341
1349
|
const auditData = this.getAuditData();
|
|
1342
1350
|
return await bulkEncryptModelsWithLockContext(
|
|
1343
1351
|
models,
|
|
1344
1352
|
table,
|
|
1345
1353
|
client,
|
|
1346
|
-
context
|
|
1354
|
+
context,
|
|
1347
1355
|
auditData
|
|
1348
1356
|
);
|
|
1349
1357
|
},
|
|
@@ -1362,7 +1370,6 @@ var BulkEncryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1362
1370
|
};
|
|
1363
1371
|
|
|
1364
1372
|
// src/encryption/operations/decrypt.ts
|
|
1365
|
-
import { withResult as withResult6 } from "@byteslice/result";
|
|
1366
1373
|
import {
|
|
1367
1374
|
decrypt as ffiDecrypt
|
|
1368
1375
|
} from "@cipherstash/protect-ffi";
|
|
@@ -1387,7 +1394,7 @@ var DecryptOperation = class extends EncryptionOperation {
|
|
|
1387
1394
|
op: "decrypt",
|
|
1388
1395
|
lockContext: false
|
|
1389
1396
|
});
|
|
1390
|
-
const result = await
|
|
1397
|
+
const result = await withResult(
|
|
1391
1398
|
async () => {
|
|
1392
1399
|
if (!this.client) {
|
|
1393
1400
|
throw noClientError();
|
|
@@ -1439,7 +1446,7 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1439
1446
|
op: "decrypt",
|
|
1440
1447
|
lockContext: true
|
|
1441
1448
|
});
|
|
1442
|
-
const result = await
|
|
1449
|
+
const result = await withResult(
|
|
1443
1450
|
async () => {
|
|
1444
1451
|
const { client, encryptedData } = this.operation.getOperation();
|
|
1445
1452
|
if (!client) {
|
|
@@ -1449,15 +1456,11 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1449
1456
|
return null;
|
|
1450
1457
|
}
|
|
1451
1458
|
const { metadata } = this.getAuditData();
|
|
1452
|
-
const
|
|
1453
|
-
if (context.failure) {
|
|
1454
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1455
|
-
}
|
|
1459
|
+
const lockContext = resolveLockContext(this.lockContext);
|
|
1456
1460
|
return await ffiDecrypt(client, {
|
|
1457
1461
|
ciphertext: encryptedData,
|
|
1458
1462
|
unverifiedContext: metadata,
|
|
1459
|
-
lockContext
|
|
1460
|
-
serviceToken: context.data.ctsToken
|
|
1463
|
+
lockContext
|
|
1461
1464
|
});
|
|
1462
1465
|
},
|
|
1463
1466
|
(error) => {
|
|
@@ -1475,7 +1478,6 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1475
1478
|
};
|
|
1476
1479
|
|
|
1477
1480
|
// src/encryption/operations/decrypt-model.ts
|
|
1478
|
-
import { withResult as withResult7 } from "@byteslice/result";
|
|
1479
1481
|
var DecryptModelOperation = class extends EncryptionOperation {
|
|
1480
1482
|
client;
|
|
1481
1483
|
model;
|
|
@@ -1493,7 +1495,7 @@ var DecryptModelOperation = class extends EncryptionOperation {
|
|
|
1493
1495
|
op: "decryptModel",
|
|
1494
1496
|
lockContext: false
|
|
1495
1497
|
});
|
|
1496
|
-
const result = await
|
|
1498
|
+
const result = await withResult(
|
|
1497
1499
|
async () => {
|
|
1498
1500
|
if (!this.client) {
|
|
1499
1501
|
throw noClientError();
|
|
@@ -1538,21 +1540,18 @@ var DecryptModelOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1538
1540
|
op: "decryptModel",
|
|
1539
1541
|
lockContext: true
|
|
1540
1542
|
});
|
|
1541
|
-
const result = await
|
|
1543
|
+
const result = await withResult(
|
|
1542
1544
|
async () => {
|
|
1543
1545
|
const { client, model } = this.operation.getOperation();
|
|
1544
1546
|
if (!client) {
|
|
1545
1547
|
throw noClientError();
|
|
1546
1548
|
}
|
|
1547
|
-
const context =
|
|
1548
|
-
if (context.failure) {
|
|
1549
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1550
|
-
}
|
|
1549
|
+
const context = resolveLockContext(this.lockContext);
|
|
1551
1550
|
const auditData = this.getAuditData();
|
|
1552
1551
|
return await decryptModelFieldsWithLockContext(
|
|
1553
1552
|
model,
|
|
1554
1553
|
client,
|
|
1555
|
-
context
|
|
1554
|
+
context,
|
|
1556
1555
|
auditData
|
|
1557
1556
|
);
|
|
1558
1557
|
},
|
|
@@ -1571,7 +1570,6 @@ var DecryptModelOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1571
1570
|
};
|
|
1572
1571
|
|
|
1573
1572
|
// src/encryption/operations/encrypt.ts
|
|
1574
|
-
import { withResult as withResult8 } from "@byteslice/result";
|
|
1575
1573
|
import {
|
|
1576
1574
|
encrypt as ffiEncrypt
|
|
1577
1575
|
} from "@cipherstash/protect-ffi";
|
|
@@ -1602,7 +1600,7 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
1602
1600
|
column: this.column.getName(),
|
|
1603
1601
|
lockContext: false
|
|
1604
1602
|
});
|
|
1605
|
-
const result = await
|
|
1603
|
+
const result = await withResult(
|
|
1606
1604
|
async () => {
|
|
1607
1605
|
if (!this.client) {
|
|
1608
1606
|
throw noClientError();
|
|
@@ -1610,14 +1608,12 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
1610
1608
|
if (this.plaintext === null) {
|
|
1611
1609
|
return null;
|
|
1612
1610
|
}
|
|
1613
|
-
|
|
1614
|
-
throw new Error("[encryption]: Cannot encrypt NaN value");
|
|
1615
|
-
}
|
|
1616
|
-
if (typeof this.plaintext === "number" && !Number.isFinite(this.plaintext)) {
|
|
1617
|
-
throw new Error("[encryption]: Cannot encrypt Infinity value");
|
|
1618
|
-
}
|
|
1611
|
+
assertValidNumericValue(this.plaintext);
|
|
1619
1612
|
const { metadata } = this.getAuditData();
|
|
1620
1613
|
return await ffiEncrypt(this.client, {
|
|
1614
|
+
// `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via
|
|
1615
|
+
// `toJSON` at the boundary); cast until the upstream `JsPlaintext` input
|
|
1616
|
+
// union is corrected to include it.
|
|
1621
1617
|
plaintext: this.plaintext,
|
|
1622
1618
|
column: this.column.getName(),
|
|
1623
1619
|
table: this.table.tableName,
|
|
@@ -1666,7 +1662,7 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1666
1662
|
column: column.getName(),
|
|
1667
1663
|
lockContext: true
|
|
1668
1664
|
});
|
|
1669
|
-
const result = await
|
|
1665
|
+
const result = await withResult(
|
|
1670
1666
|
async () => {
|
|
1671
1667
|
if (!client) {
|
|
1672
1668
|
throw noClientError();
|
|
@@ -1674,17 +1670,14 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1674
1670
|
if (plaintext === null) {
|
|
1675
1671
|
return null;
|
|
1676
1672
|
}
|
|
1673
|
+
assertValidNumericValue(plaintext);
|
|
1677
1674
|
const { metadata } = this.getAuditData();
|
|
1678
|
-
const
|
|
1679
|
-
if (context.failure) {
|
|
1680
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1681
|
-
}
|
|
1675
|
+
const lockContext = resolveLockContext(this.lockContext);
|
|
1682
1676
|
return await ffiEncrypt(client, {
|
|
1683
1677
|
plaintext,
|
|
1684
1678
|
column: column.getName(),
|
|
1685
1679
|
table: table.tableName,
|
|
1686
|
-
lockContext
|
|
1687
|
-
serviceToken: context.data.ctsToken,
|
|
1680
|
+
lockContext,
|
|
1688
1681
|
unverifiedContext: metadata
|
|
1689
1682
|
});
|
|
1690
1683
|
},
|
|
@@ -1703,7 +1696,6 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1703
1696
|
};
|
|
1704
1697
|
|
|
1705
1698
|
// src/encryption/operations/encrypt-model.ts
|
|
1706
|
-
import { withResult as withResult9 } from "@byteslice/result";
|
|
1707
1699
|
var EncryptModelOperation = class extends EncryptionOperation {
|
|
1708
1700
|
client;
|
|
1709
1701
|
model;
|
|
@@ -1724,7 +1716,7 @@ var EncryptModelOperation = class extends EncryptionOperation {
|
|
|
1724
1716
|
table: this.table.tableName,
|
|
1725
1717
|
lockContext: false
|
|
1726
1718
|
});
|
|
1727
|
-
const result = await
|
|
1719
|
+
const result = await withResult(
|
|
1728
1720
|
async () => {
|
|
1729
1721
|
if (!this.client) {
|
|
1730
1722
|
throw noClientError();
|
|
@@ -1777,21 +1769,18 @@ var EncryptModelOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1777
1769
|
table: table.tableName,
|
|
1778
1770
|
lockContext: true
|
|
1779
1771
|
});
|
|
1780
|
-
const result = await
|
|
1772
|
+
const result = await withResult(
|
|
1781
1773
|
async () => {
|
|
1782
1774
|
if (!client) {
|
|
1783
1775
|
throw noClientError();
|
|
1784
1776
|
}
|
|
1785
|
-
const context =
|
|
1786
|
-
if (context.failure) {
|
|
1787
|
-
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1788
|
-
}
|
|
1777
|
+
const context = resolveLockContext(this.lockContext);
|
|
1789
1778
|
const auditData = this.getAuditData();
|
|
1790
1779
|
return await encryptModelFieldsWithLockContext(
|
|
1791
1780
|
model,
|
|
1792
1781
|
table,
|
|
1793
1782
|
client,
|
|
1794
|
-
context
|
|
1783
|
+
context,
|
|
1795
1784
|
auditData
|
|
1796
1785
|
);
|
|
1797
1786
|
},
|
|
@@ -1810,7 +1799,6 @@ var EncryptModelOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1810
1799
|
};
|
|
1811
1800
|
|
|
1812
1801
|
// src/encryption/operations/encrypt-query.ts
|
|
1813
|
-
import { withResult as withResult10 } from "@byteslice/result";
|
|
1814
1802
|
import {
|
|
1815
1803
|
encryptQuery as ffiEncryptQuery
|
|
1816
1804
|
} from "@cipherstash/protect-ffi";
|
|
@@ -1852,7 +1840,7 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
1852
1840
|
log.emit();
|
|
1853
1841
|
return { failure: validationError.failure };
|
|
1854
1842
|
}
|
|
1855
|
-
const result = await
|
|
1843
|
+
const result = await withResult(
|
|
1856
1844
|
async () => {
|
|
1857
1845
|
if (!this.client) throw noClientError();
|
|
1858
1846
|
const { metadata } = this.getAuditData();
|
|
@@ -1867,6 +1855,9 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
1867
1855
|
this.opts.column.getName()
|
|
1868
1856
|
);
|
|
1869
1857
|
const encrypted = await ffiEncryptQuery(this.client, {
|
|
1858
|
+
// `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via
|
|
1859
|
+
// `toJSON` at the boundary); cast until the upstream input union is
|
|
1860
|
+
// corrected to include it.
|
|
1870
1861
|
plaintext,
|
|
1871
1862
|
column: this.opts.column.getName(),
|
|
1872
1863
|
table: this.opts.table.tableName,
|
|
@@ -1924,15 +1915,10 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1924
1915
|
log.emit();
|
|
1925
1916
|
return { failure: validationError.failure };
|
|
1926
1917
|
}
|
|
1927
|
-
const
|
|
1928
|
-
if (lockContextResult.failure) {
|
|
1929
|
-
log.emit();
|
|
1930
|
-
return { failure: lockContextResult.failure };
|
|
1931
|
-
}
|
|
1932
|
-
const { ctsToken, context } = lockContextResult.data;
|
|
1933
|
-
const result = await withResult10(
|
|
1918
|
+
const result = await withResult(
|
|
1934
1919
|
async () => {
|
|
1935
1920
|
if (!this.client) throw noClientError();
|
|
1921
|
+
const context = resolveLockContext(this.lockContext);
|
|
1936
1922
|
const { metadata } = this.getAuditData();
|
|
1937
1923
|
const { indexType, queryOp } = resolveIndexType(
|
|
1938
1924
|
this.opts.column,
|
|
@@ -1945,13 +1931,15 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1945
1931
|
this.opts.column.getName()
|
|
1946
1932
|
);
|
|
1947
1933
|
const encrypted = await ffiEncryptQuery(this.client, {
|
|
1934
|
+
// `Plaintext` widens the FFI `JsPlaintext` with `Date` (serialized via
|
|
1935
|
+
// `toJSON` at the boundary); cast until the upstream input union is
|
|
1936
|
+
// corrected to include it.
|
|
1948
1937
|
plaintext,
|
|
1949
1938
|
column: this.opts.column.getName(),
|
|
1950
1939
|
table: this.opts.table.tableName,
|
|
1951
1940
|
indexType,
|
|
1952
1941
|
queryOp,
|
|
1953
1942
|
lockContext: context,
|
|
1954
|
-
serviceToken: ctsToken,
|
|
1955
1943
|
unverifiedContext: metadata
|
|
1956
1944
|
});
|
|
1957
1945
|
return formatEncryptedResult(encrypted, this.opts.returnType);
|
|
@@ -1974,6 +1962,20 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1974
1962
|
var noClientError = () => new Error(
|
|
1975
1963
|
"The Encryption client has not been initialized. Please call init() before using the client."
|
|
1976
1964
|
);
|
|
1965
|
+
function resolveEqlVersion(schemas, explicit) {
|
|
1966
|
+
const v3Count = schemas.filter(
|
|
1967
|
+
(schema) => typeof schema.buildColumnKeyMap === "function"
|
|
1968
|
+
).length;
|
|
1969
|
+
if (v3Count > 0 && v3Count < schemas.length) {
|
|
1970
|
+
throw new Error(
|
|
1971
|
+
"[encryption]: cannot mix EQL v2 and EQL v3 tables in one client \u2014 one client emits exactly one wire format. Create separate clients for the v2 and v3 schemas."
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1974
|
+
if (explicit !== void 0) {
|
|
1975
|
+
return explicit;
|
|
1976
|
+
}
|
|
1977
|
+
return v3Count === 0 ? void 0 : 3;
|
|
1978
|
+
}
|
|
1977
1979
|
var EncryptionClient = class {
|
|
1978
1980
|
client;
|
|
1979
1981
|
encryptConfig;
|
|
@@ -1984,7 +1986,7 @@ var EncryptionClient = class {
|
|
|
1984
1986
|
* @returns A promise that resolves to a {@link Result} containing the initialized EncryptionClient or an {@link EncryptionError}.
|
|
1985
1987
|
**/
|
|
1986
1988
|
async init(config) {
|
|
1987
|
-
return await
|
|
1989
|
+
return await withResult(
|
|
1988
1990
|
async () => {
|
|
1989
1991
|
const validated = encryptConfigSchema.parse(
|
|
1990
1992
|
config.encryptConfig
|
|
@@ -2003,7 +2005,9 @@ var EncryptionClient = class {
|
|
|
2003
2005
|
clientId: config.clientId,
|
|
2004
2006
|
clientKey: config.clientKey,
|
|
2005
2007
|
keyset: toFfiKeysetIdentifier(config.keyset)
|
|
2006
|
-
}
|
|
2008
|
+
},
|
|
2009
|
+
strategy: config.authStrategy,
|
|
2010
|
+
eqlVersion: config.eqlVersion
|
|
2007
2011
|
});
|
|
2008
2012
|
this.encryptConfig = validated;
|
|
2009
2013
|
logger.debug("Successfully initialized the Encryption client.");
|
|
@@ -2094,7 +2098,7 @@ var EncryptionClient = class {
|
|
|
2094
2098
|
return new EncryptOperation(this.client, plaintext, opts);
|
|
2095
2099
|
}
|
|
2096
2100
|
encryptQuery(plaintextOrTerms, opts) {
|
|
2097
|
-
if (isScalarQueryTermArray(plaintextOrTerms)) {
|
|
2101
|
+
if (!opts && isScalarQueryTermArray(plaintextOrTerms)) {
|
|
2098
2102
|
return new BatchEncryptQueryOperation(this.client, plaintextOrTerms);
|
|
2099
2103
|
}
|
|
2100
2104
|
if (Array.isArray(plaintextOrTerms) && plaintextOrTerms.length === 0 && !opts) {
|
|
@@ -2402,6 +2406,17 @@ var EncryptionClient = class {
|
|
|
2402
2406
|
return this.encryptConfig;
|
|
2403
2407
|
}
|
|
2404
2408
|
};
|
|
2409
|
+
var warnedStrategyDeprecated = false;
|
|
2410
|
+
function warnStrategyDeprecated() {
|
|
2411
|
+
if (warnedStrategyDeprecated) return;
|
|
2412
|
+
warnedStrategyDeprecated = true;
|
|
2413
|
+
console.warn(
|
|
2414
|
+
"[encryption]: `config.strategy` is deprecated and will be removed in a future release \u2014 use `config.authStrategy` instead."
|
|
2415
|
+
);
|
|
2416
|
+
}
|
|
2417
|
+
function __resetStrategyDeprecationWarningForTests() {
|
|
2418
|
+
warnedStrategyDeprecated = false;
|
|
2419
|
+
}
|
|
2405
2420
|
var Encryption = async (config) => {
|
|
2406
2421
|
const { schemas, config: clientConfig } = config;
|
|
2407
2422
|
if (!schemas.length) {
|
|
@@ -2414,11 +2429,18 @@ var Encryption = async (config) => {
|
|
|
2414
2429
|
"[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
|
|
2415
2430
|
);
|
|
2416
2431
|
}
|
|
2432
|
+
if (clientConfig?.strategy) {
|
|
2433
|
+
warnStrategyDeprecated();
|
|
2434
|
+
}
|
|
2435
|
+
const authStrategy = clientConfig?.authStrategy ?? clientConfig?.strategy;
|
|
2417
2436
|
const client = new EncryptionClient();
|
|
2418
2437
|
const encryptConfig = buildEncryptConfig(...schemas);
|
|
2438
|
+
const eqlVersion = resolveEqlVersion(schemas, clientConfig?.eqlVersion);
|
|
2419
2439
|
const result = await client.init({
|
|
2420
2440
|
encryptConfig,
|
|
2421
|
-
...clientConfig
|
|
2441
|
+
...clientConfig,
|
|
2442
|
+
authStrategy,
|
|
2443
|
+
eqlVersion
|
|
2422
2444
|
});
|
|
2423
2445
|
if (result.failure) {
|
|
2424
2446
|
throw new Error(`[encryption]: ${result.failure.message}`);
|
|
@@ -2438,7 +2460,9 @@ export {
|
|
|
2438
2460
|
EncryptModelOperation,
|
|
2439
2461
|
EncryptQueryOperation,
|
|
2440
2462
|
noClientError,
|
|
2463
|
+
resolveEqlVersion,
|
|
2441
2464
|
EncryptionClient,
|
|
2465
|
+
__resetStrategyDeprecationWarningForTests,
|
|
2442
2466
|
Encryption
|
|
2443
2467
|
};
|
|
2444
|
-
//# sourceMappingURL=chunk-
|
|
2468
|
+
//# sourceMappingURL=chunk-ZTP5QJ27.js.map
|