@cipherstash/stack 0.15.3 → 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 +60 -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-GNLU3I27.js → chunk-YWQXTZ5M.js} +4 -2
- package/dist/chunk-YWQXTZ5M.js.map +1 -0
- package/dist/{chunk-46S3YFRK.js → chunk-ZYOZHZMJ.js} +170 -54
- package/dist/chunk-ZYOZHZMJ.js.map +1 -0
- package/dist/{client-Dv60lAyy.d.ts → client-CIsfZ2zg.d.ts} +17 -22
- package/dist/{client-DQyqn0oT.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 +178 -52
- 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 +160 -52
- 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-DX3mGqoi.d.ts → types-public-BTxqjmtv.d.cts} +96 -81
- package/dist/{types-public-DX3mGqoi.d.cts → types-public-BTxqjmtv.d.ts} +96 -81
- 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 +16 -16
- package/dist/chunk-46S3YFRK.js.map +0 -1
- package/dist/chunk-4RNBI3UH.js.map +0 -1
- package/dist/chunk-6FD7OBGM.js.map +0 -1
- package/dist/chunk-GNLU3I27.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
|
}
|
|
@@ -750,7 +752,15 @@ var logger = {
|
|
|
750
752
|
// src/encryption/index.ts
|
|
751
753
|
var import_result11 = require("@byteslice/result");
|
|
752
754
|
var import_protect_ffi9 = require("@cipherstash/protect-ffi");
|
|
753
|
-
|
|
755
|
+
|
|
756
|
+
// ../../node_modules/.pnpm/uuid@14.0.0/node_modules/uuid/dist-node/regex.js
|
|
757
|
+
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
|
758
|
+
|
|
759
|
+
// ../../node_modules/.pnpm/uuid@14.0.0/node_modules/uuid/dist-node/validate.js
|
|
760
|
+
function validate(uuid) {
|
|
761
|
+
return typeof uuid === "string" && regex_default.test(uuid);
|
|
762
|
+
}
|
|
763
|
+
var validate_default = validate;
|
|
754
764
|
|
|
755
765
|
// src/encryption/helpers/index.ts
|
|
756
766
|
function encryptedToPgComposite(obj) {
|
|
@@ -944,6 +954,15 @@ var EncryptionOperation = class {
|
|
|
944
954
|
};
|
|
945
955
|
|
|
946
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
|
+
}
|
|
947
966
|
function buildQueryPayload(term, lockContext) {
|
|
948
967
|
assertValidNumericValue(term.value);
|
|
949
968
|
const { indexType, queryOp } = resolveIndexType(
|
|
@@ -964,10 +983,15 @@ function buildQueryPayload(term, lockContext) {
|
|
|
964
983
|
}
|
|
965
984
|
return payload;
|
|
966
985
|
}
|
|
967
|
-
function assembleResults(
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
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;
|
|
971
995
|
}
|
|
972
996
|
var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
973
997
|
constructor(client, terms) {
|
|
@@ -975,6 +999,8 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
975
999
|
this.client = client;
|
|
976
1000
|
this.terms = terms;
|
|
977
1001
|
}
|
|
1002
|
+
client;
|
|
1003
|
+
terms;
|
|
978
1004
|
withLockContext(lockContext) {
|
|
979
1005
|
return new BatchEncryptQueryOperationWithLockContext(
|
|
980
1006
|
this.client,
|
|
@@ -994,18 +1020,23 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
994
1020
|
log.emit();
|
|
995
1021
|
return { data: [] };
|
|
996
1022
|
}
|
|
1023
|
+
const { nonNullTerms } = filterNullTerms(this.terms);
|
|
1024
|
+
if (nonNullTerms.length === 0) {
|
|
1025
|
+
log.emit();
|
|
1026
|
+
return { data: this.terms.map(() => null) };
|
|
1027
|
+
}
|
|
997
1028
|
const result = await (0, import_result.withResult)(
|
|
998
1029
|
async () => {
|
|
999
1030
|
if (!this.client) throw noClientError();
|
|
1000
1031
|
const { metadata } = this.getAuditData();
|
|
1001
|
-
const queries =
|
|
1002
|
-
(term) => buildQueryPayload(term)
|
|
1032
|
+
const queries = nonNullTerms.map(
|
|
1033
|
+
({ term }) => buildQueryPayload(term)
|
|
1003
1034
|
);
|
|
1004
1035
|
const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
|
|
1005
1036
|
queries,
|
|
1006
1037
|
unverifiedContext: metadata
|
|
1007
1038
|
});
|
|
1008
|
-
return assembleResults(this.terms, encrypted);
|
|
1039
|
+
return assembleResults(this.terms.length, encrypted, nonNullTerms);
|
|
1009
1040
|
},
|
|
1010
1041
|
(error) => {
|
|
1011
1042
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1028,6 +1059,9 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1028
1059
|
this.lockContext = lockContext;
|
|
1029
1060
|
this.auditMetadata = auditMetadata;
|
|
1030
1061
|
}
|
|
1062
|
+
client;
|
|
1063
|
+
terms;
|
|
1064
|
+
lockContext;
|
|
1031
1065
|
async execute() {
|
|
1032
1066
|
const log = createRequestLogger();
|
|
1033
1067
|
log.set({
|
|
@@ -1039,6 +1073,11 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1039
1073
|
log.emit();
|
|
1040
1074
|
return { data: [] };
|
|
1041
1075
|
}
|
|
1076
|
+
const { nonNullTerms } = filterNullTerms(this.terms);
|
|
1077
|
+
if (nonNullTerms.length === 0) {
|
|
1078
|
+
log.emit();
|
|
1079
|
+
return { data: this.terms.map(() => null) };
|
|
1080
|
+
}
|
|
1042
1081
|
const lockContextResult = await this.lockContext.getLockContext();
|
|
1043
1082
|
if (lockContextResult.failure) {
|
|
1044
1083
|
log.emit();
|
|
@@ -1049,15 +1088,15 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1049
1088
|
async () => {
|
|
1050
1089
|
if (!this.client) throw noClientError();
|
|
1051
1090
|
const { metadata } = this.getAuditData();
|
|
1052
|
-
const queries =
|
|
1053
|
-
(term) => buildQueryPayload(term, context)
|
|
1091
|
+
const queries = nonNullTerms.map(
|
|
1092
|
+
({ term }) => buildQueryPayload(term, context)
|
|
1054
1093
|
);
|
|
1055
1094
|
const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
|
|
1056
1095
|
queries,
|
|
1057
1096
|
serviceToken: ctsToken,
|
|
1058
1097
|
unverifiedContext: metadata
|
|
1059
1098
|
});
|
|
1060
|
-
return assembleResults(this.terms, encrypted);
|
|
1099
|
+
return assembleResults(this.terms.length, encrypted, nonNullTerms);
|
|
1061
1100
|
},
|
|
1062
1101
|
(error) => {
|
|
1063
1102
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1077,25 +1116,30 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1077
1116
|
var import_result2 = require("@byteslice/result");
|
|
1078
1117
|
var import_protect_ffi3 = require("@cipherstash/protect-ffi");
|
|
1079
1118
|
var createDecryptPayloads = (encryptedPayloads, lockContext) => {
|
|
1080
|
-
return encryptedPayloads.map(({ id, data }) => ({
|
|
1119
|
+
return encryptedPayloads.filter(({ data }) => data !== null).map(({ id, data }) => ({
|
|
1081
1120
|
id,
|
|
1082
1121
|
ciphertext: data,
|
|
1083
1122
|
...lockContext && { lockContext }
|
|
1084
1123
|
}));
|
|
1085
1124
|
};
|
|
1125
|
+
var createNullResult = (encryptedPayloads) => encryptedPayloads.map(({ id }) => ({ id, data: null }));
|
|
1086
1126
|
var mapDecryptedDataToResult = (encryptedPayloads, decryptedData) => {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
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++;
|
|
1093
1140
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
data: decryptResult.data
|
|
1097
|
-
};
|
|
1098
|
-
});
|
|
1141
|
+
}
|
|
1142
|
+
return result;
|
|
1099
1143
|
};
|
|
1100
1144
|
var BulkDecryptOperation = class extends EncryptionOperation {
|
|
1101
1145
|
client;
|
|
@@ -1120,10 +1164,13 @@ var BulkDecryptOperation = class extends EncryptionOperation {
|
|
|
1120
1164
|
if (!this.client) throw noClientError();
|
|
1121
1165
|
if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
|
|
1122
1166
|
return [];
|
|
1123
|
-
const
|
|
1167
|
+
const nonNullPayloads = createDecryptPayloads(this.encryptedPayloads);
|
|
1168
|
+
if (nonNullPayloads.length === 0) {
|
|
1169
|
+
return createNullResult(this.encryptedPayloads);
|
|
1170
|
+
}
|
|
1124
1171
|
const { metadata } = this.getAuditData();
|
|
1125
1172
|
const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(this.client, {
|
|
1126
|
-
ciphertexts:
|
|
1173
|
+
ciphertexts: nonNullPayloads,
|
|
1127
1174
|
unverifiedContext: metadata
|
|
1128
1175
|
});
|
|
1129
1176
|
return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData);
|
|
@@ -1175,13 +1222,16 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1175
1222
|
if (context.failure) {
|
|
1176
1223
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1177
1224
|
}
|
|
1178
|
-
const
|
|
1225
|
+
const nonNullPayloads = createDecryptPayloads(
|
|
1179
1226
|
encryptedPayloads,
|
|
1180
1227
|
context.data.context
|
|
1181
1228
|
);
|
|
1229
|
+
if (nonNullPayloads.length === 0) {
|
|
1230
|
+
return createNullResult(encryptedPayloads);
|
|
1231
|
+
}
|
|
1182
1232
|
const { metadata } = this.getAuditData();
|
|
1183
1233
|
const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(client, {
|
|
1184
|
-
ciphertexts:
|
|
1234
|
+
ciphertexts: nonNullPayloads,
|
|
1185
1235
|
serviceToken: context.data.ctsToken,
|
|
1186
1236
|
unverifiedContext: metadata
|
|
1187
1237
|
});
|
|
@@ -1820,7 +1870,7 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1820
1870
|
var import_result4 = require("@byteslice/result");
|
|
1821
1871
|
var import_protect_ffi5 = require("@cipherstash/protect-ffi");
|
|
1822
1872
|
var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
1823
|
-
return plaintexts.map(({ id, plaintext }) => ({
|
|
1873
|
+
return plaintexts.filter(({ plaintext }) => plaintext !== null).map(({ id, plaintext }) => ({
|
|
1824
1874
|
id,
|
|
1825
1875
|
plaintext,
|
|
1826
1876
|
column: column.getName(),
|
|
@@ -1828,6 +1878,20 @@ var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
|
1828
1878
|
...lockContext && { lockContext }
|
|
1829
1879
|
}));
|
|
1830
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
|
+
};
|
|
1831
1895
|
var BulkEncryptOperation = class extends EncryptionOperation {
|
|
1832
1896
|
client;
|
|
1833
1897
|
plaintexts;
|
|
@@ -1860,20 +1924,20 @@ var BulkEncryptOperation = class extends EncryptionOperation {
|
|
|
1860
1924
|
if (!this.plaintexts || this.plaintexts.length === 0) {
|
|
1861
1925
|
return [];
|
|
1862
1926
|
}
|
|
1863
|
-
const
|
|
1927
|
+
const nonNullPayloads = createEncryptPayloads(
|
|
1864
1928
|
this.plaintexts,
|
|
1865
1929
|
this.column,
|
|
1866
1930
|
this.table
|
|
1867
1931
|
);
|
|
1932
|
+
if (nonNullPayloads.length === 0) {
|
|
1933
|
+
return createNullResult2(this.plaintexts);
|
|
1934
|
+
}
|
|
1868
1935
|
const { metadata } = this.getAuditData();
|
|
1869
1936
|
const encryptedData = await (0, import_protect_ffi5.encryptBulk)(this.client, {
|
|
1870
|
-
plaintexts:
|
|
1937
|
+
plaintexts: nonNullPayloads,
|
|
1871
1938
|
unverifiedContext: metadata
|
|
1872
1939
|
});
|
|
1873
|
-
return
|
|
1874
|
-
id: this.plaintexts[i].id,
|
|
1875
|
-
data
|
|
1876
|
-
}));
|
|
1940
|
+
return mapEncryptedDataToResult(this.plaintexts, encryptedData);
|
|
1877
1941
|
},
|
|
1878
1942
|
(error) => {
|
|
1879
1943
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1930,22 +1994,22 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1930
1994
|
if (context.failure) {
|
|
1931
1995
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1932
1996
|
}
|
|
1933
|
-
const
|
|
1997
|
+
const nonNullPayloads = createEncryptPayloads(
|
|
1934
1998
|
plaintexts,
|
|
1935
1999
|
column,
|
|
1936
2000
|
table,
|
|
1937
2001
|
context.data.context
|
|
1938
2002
|
);
|
|
2003
|
+
if (nonNullPayloads.length === 0) {
|
|
2004
|
+
return createNullResult2(plaintexts);
|
|
2005
|
+
}
|
|
1939
2006
|
const { metadata } = this.getAuditData();
|
|
1940
2007
|
const encryptedData = await (0, import_protect_ffi5.encryptBulk)(client, {
|
|
1941
|
-
plaintexts:
|
|
2008
|
+
plaintexts: nonNullPayloads,
|
|
1942
2009
|
serviceToken: context.data.ctsToken,
|
|
1943
2010
|
unverifiedContext: metadata
|
|
1944
2011
|
});
|
|
1945
|
-
return
|
|
1946
|
-
id: plaintexts[i].id,
|
|
1947
|
-
data
|
|
1948
|
-
}));
|
|
2012
|
+
return mapEncryptedDataToResult(plaintexts, encryptedData);
|
|
1949
2013
|
},
|
|
1950
2014
|
(error) => {
|
|
1951
2015
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -2075,6 +2139,10 @@ var import_result6 = require("@byteslice/result");
|
|
|
2075
2139
|
var import_protect_ffi6 = require("@cipherstash/protect-ffi");
|
|
2076
2140
|
var DecryptOperation = class extends EncryptionOperation {
|
|
2077
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.
|
|
2078
2146
|
encryptedData;
|
|
2079
2147
|
constructor(client, encryptedData) {
|
|
2080
2148
|
super();
|
|
@@ -2095,6 +2163,9 @@ var DecryptOperation = class extends EncryptionOperation {
|
|
|
2095
2163
|
if (!this.client) {
|
|
2096
2164
|
throw noClientError();
|
|
2097
2165
|
}
|
|
2166
|
+
if (this.encryptedData === null) {
|
|
2167
|
+
return null;
|
|
2168
|
+
}
|
|
2098
2169
|
const { metadata } = this.getAuditData();
|
|
2099
2170
|
return await (0, import_protect_ffi6.decrypt)(this.client, {
|
|
2100
2171
|
ciphertext: this.encryptedData,
|
|
@@ -2145,6 +2216,9 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2145
2216
|
if (!client) {
|
|
2146
2217
|
throw noClientError();
|
|
2147
2218
|
}
|
|
2219
|
+
if (encryptedData === null) {
|
|
2220
|
+
return null;
|
|
2221
|
+
}
|
|
2148
2222
|
const { metadata } = this.getAuditData();
|
|
2149
2223
|
const context = await this.lockContext.getLockContext();
|
|
2150
2224
|
if (context.failure) {
|
|
@@ -2272,6 +2346,10 @@ var import_result8 = require("@byteslice/result");
|
|
|
2272
2346
|
var import_protect_ffi7 = require("@cipherstash/protect-ffi");
|
|
2273
2347
|
var EncryptOperation = class extends EncryptionOperation {
|
|
2274
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.
|
|
2275
2353
|
plaintext;
|
|
2276
2354
|
column;
|
|
2277
2355
|
table;
|
|
@@ -2298,6 +2376,9 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
2298
2376
|
if (!this.client) {
|
|
2299
2377
|
throw noClientError();
|
|
2300
2378
|
}
|
|
2379
|
+
if (this.plaintext === null) {
|
|
2380
|
+
return null;
|
|
2381
|
+
}
|
|
2301
2382
|
if (typeof this.plaintext === "number" && Number.isNaN(this.plaintext)) {
|
|
2302
2383
|
throw new Error("[encryption]: Cannot encrypt NaN value");
|
|
2303
2384
|
}
|
|
@@ -2359,6 +2440,9 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2359
2440
|
if (!client) {
|
|
2360
2441
|
throw noClientError();
|
|
2361
2442
|
}
|
|
2443
|
+
if (plaintext === null) {
|
|
2444
|
+
return null;
|
|
2445
|
+
}
|
|
2362
2446
|
const { metadata } = this.getAuditData();
|
|
2363
2447
|
const context = await this.lockContext.getLockContext();
|
|
2364
2448
|
if (context.failure) {
|
|
@@ -2504,6 +2588,9 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2504
2588
|
this.plaintext = plaintext;
|
|
2505
2589
|
this.opts = opts;
|
|
2506
2590
|
}
|
|
2591
|
+
client;
|
|
2592
|
+
plaintext;
|
|
2593
|
+
opts;
|
|
2507
2594
|
withLockContext(lockContext) {
|
|
2508
2595
|
return new EncryptQueryOperationWithLockContext(
|
|
2509
2596
|
this.client,
|
|
@@ -2522,7 +2609,12 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2522
2609
|
queryType: this.opts.queryType,
|
|
2523
2610
|
lockContext: false
|
|
2524
2611
|
});
|
|
2525
|
-
|
|
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);
|
|
2526
2618
|
if (validationError?.failure) {
|
|
2527
2619
|
log.emit();
|
|
2528
2620
|
return { failure: validationError.failure };
|
|
@@ -2534,15 +2626,15 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2534
2626
|
const { indexType, queryOp } = resolveIndexType(
|
|
2535
2627
|
this.opts.column,
|
|
2536
2628
|
this.opts.queryType,
|
|
2537
|
-
|
|
2629
|
+
plaintext
|
|
2538
2630
|
);
|
|
2539
2631
|
assertValueIndexCompatibility(
|
|
2540
|
-
|
|
2632
|
+
plaintext,
|
|
2541
2633
|
indexType,
|
|
2542
2634
|
this.opts.column.getName()
|
|
2543
2635
|
);
|
|
2544
2636
|
const encrypted = await (0, import_protect_ffi8.encryptQuery)(this.client, {
|
|
2545
|
-
plaintext
|
|
2637
|
+
plaintext,
|
|
2546
2638
|
column: this.opts.column.getName(),
|
|
2547
2639
|
table: this.opts.table.tableName,
|
|
2548
2640
|
indexType,
|
|
@@ -2576,6 +2668,10 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2576
2668
|
this.lockContext = lockContext;
|
|
2577
2669
|
this.auditMetadata = auditMetadata;
|
|
2578
2670
|
}
|
|
2671
|
+
client;
|
|
2672
|
+
plaintext;
|
|
2673
|
+
opts;
|
|
2674
|
+
lockContext;
|
|
2579
2675
|
async execute() {
|
|
2580
2676
|
const log = createRequestLogger();
|
|
2581
2677
|
log.set({
|
|
@@ -2585,7 +2681,12 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2585
2681
|
queryType: this.opts.queryType,
|
|
2586
2682
|
lockContext: true
|
|
2587
2683
|
});
|
|
2588
|
-
|
|
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);
|
|
2589
2690
|
if (validationError?.failure) {
|
|
2590
2691
|
log.emit();
|
|
2591
2692
|
return { failure: validationError.failure };
|
|
@@ -2603,15 +2704,15 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2603
2704
|
const { indexType, queryOp } = resolveIndexType(
|
|
2604
2705
|
this.opts.column,
|
|
2605
2706
|
this.opts.queryType,
|
|
2606
|
-
|
|
2707
|
+
plaintext
|
|
2607
2708
|
);
|
|
2608
2709
|
assertValueIndexCompatibility(
|
|
2609
|
-
|
|
2710
|
+
plaintext,
|
|
2610
2711
|
indexType,
|
|
2611
2712
|
this.opts.column.getName()
|
|
2612
2713
|
);
|
|
2613
2714
|
const encrypted = await (0, import_protect_ffi8.encryptQuery)(this.client, {
|
|
2614
|
-
plaintext
|
|
2715
|
+
plaintext,
|
|
2615
2716
|
column: this.opts.column.getName(),
|
|
2616
2717
|
table: this.opts.table.tableName,
|
|
2617
2718
|
indexType,
|
|
@@ -2807,6 +2908,13 @@ var EncryptionClient = class {
|
|
|
2807
2908
|
* .withLockContext(lockContext)
|
|
2808
2909
|
* ```
|
|
2809
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
|
+
*
|
|
2810
2918
|
* @see {@link LockContext}
|
|
2811
2919
|
* @see {@link DecryptOperation}
|
|
2812
2920
|
*/
|
|
@@ -3068,7 +3176,7 @@ var Encryption = async (config) => {
|
|
|
3068
3176
|
"[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
|
|
3069
3177
|
);
|
|
3070
3178
|
}
|
|
3071
|
-
if (clientConfig?.keyset && "id" in clientConfig.keyset && !(
|
|
3179
|
+
if (clientConfig?.keyset && "id" in clientConfig.keyset && !validate_default(clientConfig.keyset.id)) {
|
|
3072
3180
|
throw new Error(
|
|
3073
3181
|
"[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
|
|
3074
3182
|
);
|