@cipherstash/stack 0.16.0 → 0.18.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 +52 -0
- package/dist/{chunk-6FD7OBGM.js → chunk-LLCCNKDL.js} +3 -3
- package/dist/chunk-LLCCNKDL.js.map +1 -0
- package/dist/{chunk-MD6742R6.js → chunk-VPOTNP4K.js} +1 -1
- package/dist/chunk-VPOTNP4K.js.map +1 -0
- package/dist/{chunk-4RNBI3UH.js → chunk-XWPGAHBZ.js} +1 -1
- package/dist/chunk-XWPGAHBZ.js.map +1 -0
- package/dist/{chunk-JDZ2QUUF.js → chunk-YWQXTZ5M.js} +4 -2
- package/dist/{chunk-JDZ2QUUF.js.map → chunk-YWQXTZ5M.js.map} +1 -1
- package/dist/{chunk-CY5B4LIF.js → chunk-ZYOZHZMJ.js} +160 -52
- package/dist/chunk-ZYOZHZMJ.js.map +1 -0
- package/dist/{client-BLbA6aFD.d.ts → client-CIsfZ2zg.d.ts} +17 -22
- package/dist/{client-C_7TF8EL.d.cts → client-Dt98Rugc.d.cts} +17 -22
- package/dist/client.cjs +2 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +6 -3
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +2 -2
- package/dist/drizzle/index.d.ts +2 -2
- package/dist/drizzle/index.js +6 -5
- package/dist/drizzle/index.js.map +1 -1
- package/dist/dynamodb/index.cjs +14 -4
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +12 -12
- package/dist/dynamodb/index.d.ts +12 -12
- package/dist/dynamodb/index.js +9 -3
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/encryption/index.cjs +168 -50
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +2 -2
- package/dist/encryption/index.d.ts +2 -2
- package/dist/encryption/index.js +25 -5
- package/dist/identity/index.cjs +2 -2
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.js +3 -3
- package/dist/index.cjs +150 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/schema/index.cjs +3 -1
- 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 +1 -1
- package/dist/supabase/index.cjs +2 -2
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +2 -2
- package/dist/supabase/index.d.ts +2 -2
- package/dist/supabase/index.js +3 -3
- package/dist/{types-public-Dv-r6Ik0.d.ts → types-public-BTxqjmtv.d.cts} +95 -80
- package/dist/{types-public-Dv-r6Ik0.d.cts → types-public-BTxqjmtv.d.ts} +95 -80
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -1
- package/dist/types-public.d.ts +1 -1
- package/dist/types-public.js +1 -1
- package/package.json +12 -12
- package/dist/chunk-4RNBI3UH.js.map +0 -1
- package/dist/chunk-6FD7OBGM.js.map +0 -1
- package/dist/chunk-CY5B4LIF.js.map +0 -1
- package/dist/chunk-MD6742R6.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -292,6 +292,8 @@ var EncryptedTable = class {
|
|
|
292
292
|
this.tableName = tableName;
|
|
293
293
|
this.columnBuilders = columnBuilders;
|
|
294
294
|
}
|
|
295
|
+
tableName;
|
|
296
|
+
columnBuilders;
|
|
295
297
|
/**
|
|
296
298
|
* Compile this table schema into a `TableDefinition` used internally by the encryption client.
|
|
297
299
|
*
|
|
@@ -368,7 +370,7 @@ function encryptedField(valueName) {
|
|
|
368
370
|
}
|
|
369
371
|
function buildEncryptConfig(...protectTables) {
|
|
370
372
|
const config = {
|
|
371
|
-
v:
|
|
373
|
+
v: 1,
|
|
372
374
|
tables: {}
|
|
373
375
|
};
|
|
374
376
|
for (const tb of protectTables) {
|
|
@@ -387,7 +389,7 @@ var EncryptionErrorTypes = {
|
|
|
387
389
|
CtsTokenError: "CtsTokenError"
|
|
388
390
|
};
|
|
389
391
|
|
|
390
|
-
// ../../node_modules/.pnpm/evlog@1.
|
|
392
|
+
// ../../node_modules/.pnpm/evlog@1.11.0_next@15.5.10_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/dist/utils.mjs
|
|
391
393
|
function formatDuration(ms) {
|
|
392
394
|
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
393
395
|
return `${(ms / 1e3).toFixed(2)}s`;
|
|
@@ -443,7 +445,7 @@ function matchesPattern(path, pattern) {
|
|
|
443
445
|
return new RegExp(`^${regexPattern}$`).test(path);
|
|
444
446
|
}
|
|
445
447
|
|
|
446
|
-
// ../../node_modules/.pnpm/evlog@1.
|
|
448
|
+
// ../../node_modules/.pnpm/evlog@1.11.0_next@15.5.10_react-dom@19.2.3_react@19.2.3__react@19.2.3__react@19.2.3/node_modules/evlog/dist/logger.mjs
|
|
447
449
|
function isPlainObject(val) {
|
|
448
450
|
return val !== null && typeof val === "object" && !Array.isArray(val);
|
|
449
451
|
}
|
|
@@ -952,6 +954,15 @@ var EncryptionOperation = class {
|
|
|
952
954
|
};
|
|
953
955
|
|
|
954
956
|
// src/encryption/operations/batch-encrypt-query.ts
|
|
957
|
+
function filterNullTerms(terms) {
|
|
958
|
+
const nonNullTerms = [];
|
|
959
|
+
terms.forEach((term, index) => {
|
|
960
|
+
if (term.value !== null && term.value !== void 0) {
|
|
961
|
+
nonNullTerms.push({ term, originalIndex: index });
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
return { nonNullTerms };
|
|
965
|
+
}
|
|
955
966
|
function buildQueryPayload(term, lockContext) {
|
|
956
967
|
assertValidNumericValue(term.value);
|
|
957
968
|
const { indexType, queryOp } = resolveIndexType(
|
|
@@ -972,10 +983,15 @@ function buildQueryPayload(term, lockContext) {
|
|
|
972
983
|
}
|
|
973
984
|
return payload;
|
|
974
985
|
}
|
|
975
|
-
function assembleResults(
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
986
|
+
function assembleResults(totalLength, encryptedValues, nonNullTerms) {
|
|
987
|
+
const results = new Array(totalLength).fill(null);
|
|
988
|
+
nonNullTerms.forEach(({ term, originalIndex }, i) => {
|
|
989
|
+
results[originalIndex] = formatEncryptedResult(
|
|
990
|
+
encryptedValues[i],
|
|
991
|
+
term.returnType
|
|
992
|
+
);
|
|
993
|
+
});
|
|
994
|
+
return results;
|
|
979
995
|
}
|
|
980
996
|
var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
981
997
|
constructor(client, terms) {
|
|
@@ -983,6 +999,8 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
983
999
|
this.client = client;
|
|
984
1000
|
this.terms = terms;
|
|
985
1001
|
}
|
|
1002
|
+
client;
|
|
1003
|
+
terms;
|
|
986
1004
|
withLockContext(lockContext) {
|
|
987
1005
|
return new BatchEncryptQueryOperationWithLockContext(
|
|
988
1006
|
this.client,
|
|
@@ -1002,18 +1020,23 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
1002
1020
|
log.emit();
|
|
1003
1021
|
return { data: [] };
|
|
1004
1022
|
}
|
|
1023
|
+
const { nonNullTerms } = filterNullTerms(this.terms);
|
|
1024
|
+
if (nonNullTerms.length === 0) {
|
|
1025
|
+
log.emit();
|
|
1026
|
+
return { data: this.terms.map(() => null) };
|
|
1027
|
+
}
|
|
1005
1028
|
const result = await (0, import_result.withResult)(
|
|
1006
1029
|
async () => {
|
|
1007
1030
|
if (!this.client) throw noClientError();
|
|
1008
1031
|
const { metadata } = this.getAuditData();
|
|
1009
|
-
const queries =
|
|
1010
|
-
(term) => buildQueryPayload(term)
|
|
1032
|
+
const queries = nonNullTerms.map(
|
|
1033
|
+
({ term }) => buildQueryPayload(term)
|
|
1011
1034
|
);
|
|
1012
1035
|
const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
|
|
1013
1036
|
queries,
|
|
1014
1037
|
unverifiedContext: metadata
|
|
1015
1038
|
});
|
|
1016
|
-
return assembleResults(this.terms, encrypted);
|
|
1039
|
+
return assembleResults(this.terms.length, encrypted, nonNullTerms);
|
|
1017
1040
|
},
|
|
1018
1041
|
(error) => {
|
|
1019
1042
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1036,6 +1059,9 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1036
1059
|
this.lockContext = lockContext;
|
|
1037
1060
|
this.auditMetadata = auditMetadata;
|
|
1038
1061
|
}
|
|
1062
|
+
client;
|
|
1063
|
+
terms;
|
|
1064
|
+
lockContext;
|
|
1039
1065
|
async execute() {
|
|
1040
1066
|
const log = createRequestLogger();
|
|
1041
1067
|
log.set({
|
|
@@ -1047,6 +1073,11 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1047
1073
|
log.emit();
|
|
1048
1074
|
return { data: [] };
|
|
1049
1075
|
}
|
|
1076
|
+
const { nonNullTerms } = filterNullTerms(this.terms);
|
|
1077
|
+
if (nonNullTerms.length === 0) {
|
|
1078
|
+
log.emit();
|
|
1079
|
+
return { data: this.terms.map(() => null) };
|
|
1080
|
+
}
|
|
1050
1081
|
const lockContextResult = await this.lockContext.getLockContext();
|
|
1051
1082
|
if (lockContextResult.failure) {
|
|
1052
1083
|
log.emit();
|
|
@@ -1057,15 +1088,15 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1057
1088
|
async () => {
|
|
1058
1089
|
if (!this.client) throw noClientError();
|
|
1059
1090
|
const { metadata } = this.getAuditData();
|
|
1060
|
-
const queries =
|
|
1061
|
-
(term) => buildQueryPayload(term, context)
|
|
1091
|
+
const queries = nonNullTerms.map(
|
|
1092
|
+
({ term }) => buildQueryPayload(term, context)
|
|
1062
1093
|
);
|
|
1063
1094
|
const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
|
|
1064
1095
|
queries,
|
|
1065
1096
|
serviceToken: ctsToken,
|
|
1066
1097
|
unverifiedContext: metadata
|
|
1067
1098
|
});
|
|
1068
|
-
return assembleResults(this.terms, encrypted);
|
|
1099
|
+
return assembleResults(this.terms.length, encrypted, nonNullTerms);
|
|
1069
1100
|
},
|
|
1070
1101
|
(error) => {
|
|
1071
1102
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1085,25 +1116,30 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1085
1116
|
var import_result2 = require("@byteslice/result");
|
|
1086
1117
|
var import_protect_ffi3 = require("@cipherstash/protect-ffi");
|
|
1087
1118
|
var createDecryptPayloads = (encryptedPayloads, lockContext) => {
|
|
1088
|
-
return encryptedPayloads.map(({ id, data }) => ({
|
|
1119
|
+
return encryptedPayloads.filter(({ data }) => data !== null).map(({ id, data }) => ({
|
|
1089
1120
|
id,
|
|
1090
1121
|
ciphertext: data,
|
|
1091
1122
|
...lockContext && { lockContext }
|
|
1092
1123
|
}));
|
|
1093
1124
|
};
|
|
1125
|
+
var createNullResult = (encryptedPayloads) => encryptedPayloads.map(({ id }) => ({ id, data: null }));
|
|
1094
1126
|
var mapDecryptedDataToResult = (encryptedPayloads, decryptedData) => {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1127
|
+
const result = new Array(encryptedPayloads.length);
|
|
1128
|
+
let decryptedIndex = 0;
|
|
1129
|
+
for (let i = 0; i < encryptedPayloads.length; i++) {
|
|
1130
|
+
if (encryptedPayloads[i].data === null) {
|
|
1131
|
+
result[i] = { id: encryptedPayloads[i].id, data: null };
|
|
1132
|
+
} else {
|
|
1133
|
+
const decryptResult = decryptedData[decryptedIndex];
|
|
1134
|
+
if ("error" in decryptResult) {
|
|
1135
|
+
result[i] = { id: encryptedPayloads[i].id, error: decryptResult.error };
|
|
1136
|
+
} else {
|
|
1137
|
+
result[i] = { id: encryptedPayloads[i].id, data: decryptResult.data };
|
|
1138
|
+
}
|
|
1139
|
+
decryptedIndex++;
|
|
1101
1140
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
data: decryptResult.data
|
|
1105
|
-
};
|
|
1106
|
-
});
|
|
1141
|
+
}
|
|
1142
|
+
return result;
|
|
1107
1143
|
};
|
|
1108
1144
|
var BulkDecryptOperation = class extends EncryptionOperation {
|
|
1109
1145
|
client;
|
|
@@ -1128,10 +1164,13 @@ var BulkDecryptOperation = class extends EncryptionOperation {
|
|
|
1128
1164
|
if (!this.client) throw noClientError();
|
|
1129
1165
|
if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
|
|
1130
1166
|
return [];
|
|
1131
|
-
const
|
|
1167
|
+
const nonNullPayloads = createDecryptPayloads(this.encryptedPayloads);
|
|
1168
|
+
if (nonNullPayloads.length === 0) {
|
|
1169
|
+
return createNullResult(this.encryptedPayloads);
|
|
1170
|
+
}
|
|
1132
1171
|
const { metadata } = this.getAuditData();
|
|
1133
1172
|
const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(this.client, {
|
|
1134
|
-
ciphertexts:
|
|
1173
|
+
ciphertexts: nonNullPayloads,
|
|
1135
1174
|
unverifiedContext: metadata
|
|
1136
1175
|
});
|
|
1137
1176
|
return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData);
|
|
@@ -1183,13 +1222,16 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1183
1222
|
if (context.failure) {
|
|
1184
1223
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1185
1224
|
}
|
|
1186
|
-
const
|
|
1225
|
+
const nonNullPayloads = createDecryptPayloads(
|
|
1187
1226
|
encryptedPayloads,
|
|
1188
1227
|
context.data.context
|
|
1189
1228
|
);
|
|
1229
|
+
if (nonNullPayloads.length === 0) {
|
|
1230
|
+
return createNullResult(encryptedPayloads);
|
|
1231
|
+
}
|
|
1190
1232
|
const { metadata } = this.getAuditData();
|
|
1191
1233
|
const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(client, {
|
|
1192
|
-
ciphertexts:
|
|
1234
|
+
ciphertexts: nonNullPayloads,
|
|
1193
1235
|
serviceToken: context.data.ctsToken,
|
|
1194
1236
|
unverifiedContext: metadata
|
|
1195
1237
|
});
|
|
@@ -1828,7 +1870,7 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1828
1870
|
var import_result4 = require("@byteslice/result");
|
|
1829
1871
|
var import_protect_ffi5 = require("@cipherstash/protect-ffi");
|
|
1830
1872
|
var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
1831
|
-
return plaintexts.map(({ id, plaintext }) => ({
|
|
1873
|
+
return plaintexts.filter(({ plaintext }) => plaintext !== null).map(({ id, plaintext }) => ({
|
|
1832
1874
|
id,
|
|
1833
1875
|
plaintext,
|
|
1834
1876
|
column: column.getName(),
|
|
@@ -1836,6 +1878,20 @@ var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
|
1836
1878
|
...lockContext && { lockContext }
|
|
1837
1879
|
}));
|
|
1838
1880
|
};
|
|
1881
|
+
var createNullResult2 = (plaintexts) => plaintexts.map(({ id }) => ({ id, data: null }));
|
|
1882
|
+
var mapEncryptedDataToResult = (plaintexts, encryptedData) => {
|
|
1883
|
+
const result = new Array(plaintexts.length);
|
|
1884
|
+
let encryptedIndex = 0;
|
|
1885
|
+
for (let i = 0; i < plaintexts.length; i++) {
|
|
1886
|
+
if (plaintexts[i].plaintext === null) {
|
|
1887
|
+
result[i] = { id: plaintexts[i].id, data: null };
|
|
1888
|
+
} else {
|
|
1889
|
+
result[i] = { id: plaintexts[i].id, data: encryptedData[encryptedIndex] };
|
|
1890
|
+
encryptedIndex++;
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
return result;
|
|
1894
|
+
};
|
|
1839
1895
|
var BulkEncryptOperation = class extends EncryptionOperation {
|
|
1840
1896
|
client;
|
|
1841
1897
|
plaintexts;
|
|
@@ -1868,20 +1924,20 @@ var BulkEncryptOperation = class extends EncryptionOperation {
|
|
|
1868
1924
|
if (!this.plaintexts || this.plaintexts.length === 0) {
|
|
1869
1925
|
return [];
|
|
1870
1926
|
}
|
|
1871
|
-
const
|
|
1927
|
+
const nonNullPayloads = createEncryptPayloads(
|
|
1872
1928
|
this.plaintexts,
|
|
1873
1929
|
this.column,
|
|
1874
1930
|
this.table
|
|
1875
1931
|
);
|
|
1932
|
+
if (nonNullPayloads.length === 0) {
|
|
1933
|
+
return createNullResult2(this.plaintexts);
|
|
1934
|
+
}
|
|
1876
1935
|
const { metadata } = this.getAuditData();
|
|
1877
1936
|
const encryptedData = await (0, import_protect_ffi5.encryptBulk)(this.client, {
|
|
1878
|
-
plaintexts:
|
|
1937
|
+
plaintexts: nonNullPayloads,
|
|
1879
1938
|
unverifiedContext: metadata
|
|
1880
1939
|
});
|
|
1881
|
-
return
|
|
1882
|
-
id: this.plaintexts[i].id,
|
|
1883
|
-
data
|
|
1884
|
-
}));
|
|
1940
|
+
return mapEncryptedDataToResult(this.plaintexts, encryptedData);
|
|
1885
1941
|
},
|
|
1886
1942
|
(error) => {
|
|
1887
1943
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1938,22 +1994,22 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1938
1994
|
if (context.failure) {
|
|
1939
1995
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1940
1996
|
}
|
|
1941
|
-
const
|
|
1997
|
+
const nonNullPayloads = createEncryptPayloads(
|
|
1942
1998
|
plaintexts,
|
|
1943
1999
|
column,
|
|
1944
2000
|
table,
|
|
1945
2001
|
context.data.context
|
|
1946
2002
|
);
|
|
2003
|
+
if (nonNullPayloads.length === 0) {
|
|
2004
|
+
return createNullResult2(plaintexts);
|
|
2005
|
+
}
|
|
1947
2006
|
const { metadata } = this.getAuditData();
|
|
1948
2007
|
const encryptedData = await (0, import_protect_ffi5.encryptBulk)(client, {
|
|
1949
|
-
plaintexts:
|
|
2008
|
+
plaintexts: nonNullPayloads,
|
|
1950
2009
|
serviceToken: context.data.ctsToken,
|
|
1951
2010
|
unverifiedContext: metadata
|
|
1952
2011
|
});
|
|
1953
|
-
return
|
|
1954
|
-
id: plaintexts[i].id,
|
|
1955
|
-
data
|
|
1956
|
-
}));
|
|
2012
|
+
return mapEncryptedDataToResult(plaintexts, encryptedData);
|
|
1957
2013
|
},
|
|
1958
2014
|
(error) => {
|
|
1959
2015
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -2083,6 +2139,10 @@ var import_result6 = require("@byteslice/result");
|
|
|
2083
2139
|
var import_protect_ffi6 = require("@cipherstash/protect-ffi");
|
|
2084
2140
|
var DecryptOperation = class extends EncryptionOperation {
|
|
2085
2141
|
client;
|
|
2142
|
+
// Internally widened to allow null so the runtime guard below can
|
|
2143
|
+
// short-circuit on legacy / manually-NULLed rows. The public
|
|
2144
|
+
// `Encryption.decrypt()` signature still rejects null at the type
|
|
2145
|
+
// layer; this is defense in depth for direct construction.
|
|
2086
2146
|
encryptedData;
|
|
2087
2147
|
constructor(client, encryptedData) {
|
|
2088
2148
|
super();
|
|
@@ -2103,6 +2163,9 @@ var DecryptOperation = class extends EncryptionOperation {
|
|
|
2103
2163
|
if (!this.client) {
|
|
2104
2164
|
throw noClientError();
|
|
2105
2165
|
}
|
|
2166
|
+
if (this.encryptedData === null) {
|
|
2167
|
+
return null;
|
|
2168
|
+
}
|
|
2106
2169
|
const { metadata } = this.getAuditData();
|
|
2107
2170
|
return await (0, import_protect_ffi6.decrypt)(this.client, {
|
|
2108
2171
|
ciphertext: this.encryptedData,
|
|
@@ -2153,6 +2216,9 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2153
2216
|
if (!client) {
|
|
2154
2217
|
throw noClientError();
|
|
2155
2218
|
}
|
|
2219
|
+
if (encryptedData === null) {
|
|
2220
|
+
return null;
|
|
2221
|
+
}
|
|
2156
2222
|
const { metadata } = this.getAuditData();
|
|
2157
2223
|
const context = await this.lockContext.getLockContext();
|
|
2158
2224
|
if (context.failure) {
|
|
@@ -2280,6 +2346,10 @@ var import_result8 = require("@byteslice/result");
|
|
|
2280
2346
|
var import_protect_ffi7 = require("@cipherstash/protect-ffi");
|
|
2281
2347
|
var EncryptOperation = class extends EncryptionOperation {
|
|
2282
2348
|
client;
|
|
2349
|
+
// Internally widened to allow null so the runtime guard below can
|
|
2350
|
+
// short-circuit. The public `Encryption.encrypt()` signature still
|
|
2351
|
+
// rejects null at the type layer; this is defense in depth for callers
|
|
2352
|
+
// that reach this class through casts or dynamic field walking.
|
|
2283
2353
|
plaintext;
|
|
2284
2354
|
column;
|
|
2285
2355
|
table;
|
|
@@ -2306,6 +2376,9 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
2306
2376
|
if (!this.client) {
|
|
2307
2377
|
throw noClientError();
|
|
2308
2378
|
}
|
|
2379
|
+
if (this.plaintext === null) {
|
|
2380
|
+
return null;
|
|
2381
|
+
}
|
|
2309
2382
|
if (typeof this.plaintext === "number" && Number.isNaN(this.plaintext)) {
|
|
2310
2383
|
throw new Error("[encryption]: Cannot encrypt NaN value");
|
|
2311
2384
|
}
|
|
@@ -2367,6 +2440,9 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2367
2440
|
if (!client) {
|
|
2368
2441
|
throw noClientError();
|
|
2369
2442
|
}
|
|
2443
|
+
if (plaintext === null) {
|
|
2444
|
+
return null;
|
|
2445
|
+
}
|
|
2370
2446
|
const { metadata } = this.getAuditData();
|
|
2371
2447
|
const context = await this.lockContext.getLockContext();
|
|
2372
2448
|
if (context.failure) {
|
|
@@ -2512,6 +2588,9 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2512
2588
|
this.plaintext = plaintext;
|
|
2513
2589
|
this.opts = opts;
|
|
2514
2590
|
}
|
|
2591
|
+
client;
|
|
2592
|
+
plaintext;
|
|
2593
|
+
opts;
|
|
2515
2594
|
withLockContext(lockContext) {
|
|
2516
2595
|
return new EncryptQueryOperationWithLockContext(
|
|
2517
2596
|
this.client,
|
|
@@ -2530,7 +2609,12 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2530
2609
|
queryType: this.opts.queryType,
|
|
2531
2610
|
lockContext: false
|
|
2532
2611
|
});
|
|
2533
|
-
|
|
2612
|
+
if (this.plaintext === null || this.plaintext === void 0) {
|
|
2613
|
+
log.emit();
|
|
2614
|
+
return { data: null };
|
|
2615
|
+
}
|
|
2616
|
+
const plaintext = this.plaintext;
|
|
2617
|
+
const validationError = validateNumericValue(plaintext);
|
|
2534
2618
|
if (validationError?.failure) {
|
|
2535
2619
|
log.emit();
|
|
2536
2620
|
return { failure: validationError.failure };
|
|
@@ -2542,15 +2626,15 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2542
2626
|
const { indexType, queryOp } = resolveIndexType(
|
|
2543
2627
|
this.opts.column,
|
|
2544
2628
|
this.opts.queryType,
|
|
2545
|
-
|
|
2629
|
+
plaintext
|
|
2546
2630
|
);
|
|
2547
2631
|
assertValueIndexCompatibility(
|
|
2548
|
-
|
|
2632
|
+
plaintext,
|
|
2549
2633
|
indexType,
|
|
2550
2634
|
this.opts.column.getName()
|
|
2551
2635
|
);
|
|
2552
2636
|
const encrypted = await (0, import_protect_ffi8.encryptQuery)(this.client, {
|
|
2553
|
-
plaintext
|
|
2637
|
+
plaintext,
|
|
2554
2638
|
column: this.opts.column.getName(),
|
|
2555
2639
|
table: this.opts.table.tableName,
|
|
2556
2640
|
indexType,
|
|
@@ -2584,6 +2668,10 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2584
2668
|
this.lockContext = lockContext;
|
|
2585
2669
|
this.auditMetadata = auditMetadata;
|
|
2586
2670
|
}
|
|
2671
|
+
client;
|
|
2672
|
+
plaintext;
|
|
2673
|
+
opts;
|
|
2674
|
+
lockContext;
|
|
2587
2675
|
async execute() {
|
|
2588
2676
|
const log = createRequestLogger();
|
|
2589
2677
|
log.set({
|
|
@@ -2593,7 +2681,12 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2593
2681
|
queryType: this.opts.queryType,
|
|
2594
2682
|
lockContext: true
|
|
2595
2683
|
});
|
|
2596
|
-
|
|
2684
|
+
if (this.plaintext === null || this.plaintext === void 0) {
|
|
2685
|
+
log.emit();
|
|
2686
|
+
return { data: null };
|
|
2687
|
+
}
|
|
2688
|
+
const plaintext = this.plaintext;
|
|
2689
|
+
const validationError = validateNumericValue(plaintext);
|
|
2597
2690
|
if (validationError?.failure) {
|
|
2598
2691
|
log.emit();
|
|
2599
2692
|
return { failure: validationError.failure };
|
|
@@ -2611,15 +2704,15 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2611
2704
|
const { indexType, queryOp } = resolveIndexType(
|
|
2612
2705
|
this.opts.column,
|
|
2613
2706
|
this.opts.queryType,
|
|
2614
|
-
|
|
2707
|
+
plaintext
|
|
2615
2708
|
);
|
|
2616
2709
|
assertValueIndexCompatibility(
|
|
2617
|
-
|
|
2710
|
+
plaintext,
|
|
2618
2711
|
indexType,
|
|
2619
2712
|
this.opts.column.getName()
|
|
2620
2713
|
);
|
|
2621
2714
|
const encrypted = await (0, import_protect_ffi8.encryptQuery)(this.client, {
|
|
2622
|
-
plaintext
|
|
2715
|
+
plaintext,
|
|
2623
2716
|
column: this.opts.column.getName(),
|
|
2624
2717
|
table: this.opts.table.tableName,
|
|
2625
2718
|
indexType,
|
|
@@ -2815,6 +2908,13 @@ var EncryptionClient = class {
|
|
|
2815
2908
|
* .withLockContext(lockContext)
|
|
2816
2909
|
* ```
|
|
2817
2910
|
*
|
|
2911
|
+
* @remarks
|
|
2912
|
+
* The public input type rejects null, but at runtime `decrypt` will
|
|
2913
|
+
* short-circuit and return null when given a null ciphertext
|
|
2914
|
+
* (defense in depth for legacy / manually-NULLed DB rows reached via
|
|
2915
|
+
* casts or dynamic field walking). The narrow return type holds for
|
|
2916
|
+
* any caller that respects the input contract.
|
|
2917
|
+
*
|
|
2818
2918
|
* @see {@link LockContext}
|
|
2819
2919
|
* @see {@link DecryptOperation}
|
|
2820
2920
|
*/
|