@forklaunch/core 3.1.0 → 3.2.1
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/bin/gateway-mock/routes/email.mjs +91 -4
- package/lib/http/emailClient.d.ts +48 -1
- package/lib/http/emailClient.d.ts.map +1 -1
- package/lib/http/index.d.ts +1 -0
- package/lib/http/index.d.ts.map +1 -1
- package/lib/http/index.js +307 -96
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +266 -58
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/instanceGateway.d.ts +10 -6
- package/lib/http/instanceGateway.d.ts.map +1 -1
- package/lib/http/middleware/request/enrichDetails.middleware.d.ts.map +1 -1
- package/lib/http/modelGatewayClient.d.ts +13 -12
- package/lib/http/modelGatewayClient.d.ts.map +1 -1
- package/lib/http/smsClient.d.ts +2 -2
- package/lib/http/smsClient.d.ts.map +1 -1
- package/lib/http/telemetry/auditLogger.d.ts +5 -1
- package/lib/http/telemetry/auditLogger.d.ts.map +1 -1
- package/lib/http/telemetry/requestAudit.d.ts +30 -0
- package/lib/http/telemetry/requestAudit.d.ts.map +1 -0
- package/lib/http/voiceClient.d.ts +4 -4
- package/lib/http/voiceClient.d.ts.map +1 -1
- package/lib/http/whatsappClient.d.ts +5 -5
- package/lib/persistence/complianceChanges.d.ts +30 -0
- package/lib/persistence/complianceChanges.d.ts.map +1 -0
- package/lib/persistence/compliancePropertyBuilder.d.ts.map +1 -1
- package/lib/persistence/compliantField.d.ts +41 -8
- package/lib/persistence/compliantField.d.ts.map +1 -1
- package/lib/persistence/defineComplianceEntity.d.ts.map +1 -1
- package/lib/persistence/index.d.ts +2 -1
- package/lib/persistence/index.d.ts.map +1 -1
- package/lib/persistence/index.js +156 -19
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +154 -19
- package/lib/persistence/index.mjs.map +1 -1
- package/package.json +10 -10
package/lib/persistence/index.js
CHANGED
|
@@ -53,6 +53,7 @@ __export(persistence_exports, {
|
|
|
53
53
|
RetentionDuration: () => RetentionDuration,
|
|
54
54
|
RlsEventSubscriber: () => RlsEventSubscriber,
|
|
55
55
|
TENANT_FILTER_NAME: () => TENANT_FILTER_NAME,
|
|
56
|
+
TenantMismatchError: () => TenantMismatchError,
|
|
56
57
|
UnboundTenantError: () => UnboundTenantError,
|
|
57
58
|
asEncryptionSafe: () => asEncryptionSafe,
|
|
58
59
|
assertBindableTenantId: () => assertBindableTenantId,
|
|
@@ -81,6 +82,7 @@ __export(persistence_exports, {
|
|
|
81
82
|
isEncryptedCiphertext: () => isEncryptedCiphertext,
|
|
82
83
|
isEncryptedValue: () => isEncryptedValue,
|
|
83
84
|
onComplianceAccess: () => onComplianceAccess,
|
|
85
|
+
onComplianceChange: () => onComplianceChange,
|
|
84
86
|
parseDuration: () => parseDuration,
|
|
85
87
|
parseEncryptionKeyList: () => parseEncryptionKeyList,
|
|
86
88
|
reencryptEncryptedColumns: () => reencryptEncryptedColumns,
|
|
@@ -827,6 +829,22 @@ var LegacyCiphertextError = class extends Error {
|
|
|
827
829
|
var CompliantQueryError = class extends Error {
|
|
828
830
|
name = "CompliantQueryError";
|
|
829
831
|
};
|
|
832
|
+
var TenantMismatchError = class extends Error {
|
|
833
|
+
constructor(path, operation, ownerTenantId, boundTenantId) {
|
|
834
|
+
super(
|
|
835
|
+
`Cannot ${operation} ${path || "a compliant field"} under tenant '${boundTenantId}': it belongs to tenant '${ownerTenantId}', the tenant it was loaded or assigned under. Read it outside any encryption context, or inside the owning tenant's.`
|
|
836
|
+
);
|
|
837
|
+
this.path = path;
|
|
838
|
+
this.operation = operation;
|
|
839
|
+
this.ownerTenantId = ownerTenantId;
|
|
840
|
+
this.boundTenantId = boundTenantId;
|
|
841
|
+
}
|
|
842
|
+
path;
|
|
843
|
+
operation;
|
|
844
|
+
ownerTenantId;
|
|
845
|
+
boundTenantId;
|
|
846
|
+
name = "TenantMismatchError";
|
|
847
|
+
};
|
|
830
848
|
var MINT = /* @__PURE__ */ Symbol.for("forklaunch.compliance.mint");
|
|
831
849
|
var ANON_BRAND = /* @__PURE__ */ Symbol.for("forklaunch.compliance.anon");
|
|
832
850
|
var Anon = class {
|
|
@@ -907,10 +925,11 @@ var CompliantField = class _CompliantField {
|
|
|
907
925
|
Object.freeze(this);
|
|
908
926
|
}
|
|
909
927
|
/**
|
|
910
|
-
* @internal Wrap a plaintext value for `spec
|
|
911
|
-
*
|
|
928
|
+
* @internal Wrap a plaintext value for `spec`, owned by `tenant` (the one
|
|
929
|
+
* bound where it was assigned, if any). Applications assign plain values to
|
|
930
|
+
* the entity property instead.
|
|
912
931
|
*/
|
|
913
|
-
static fromPlain(value, spec) {
|
|
932
|
+
static fromPlain(value, spec, tenant) {
|
|
914
933
|
if (spec.enumValues) {
|
|
915
934
|
const values = spec.isArray && Array.isArray(value) ? value : [value];
|
|
916
935
|
for (const v of values) {
|
|
@@ -923,16 +942,22 @@ var CompliantField = class _CompliantField {
|
|
|
923
942
|
}
|
|
924
943
|
return new _CompliantField({
|
|
925
944
|
spec,
|
|
945
|
+
tenant,
|
|
926
946
|
hasPlain: true,
|
|
927
947
|
plain: value,
|
|
928
948
|
anon: computeAnon(spec.anon, value)
|
|
929
949
|
});
|
|
930
950
|
}
|
|
931
|
-
/**
|
|
932
|
-
|
|
951
|
+
/**
|
|
952
|
+
* @internal Wrap a stored value (any envelope, or legacy plaintext) loaded
|
|
953
|
+
* under `tenant`: the tenant bound during hydration, which is the loading
|
|
954
|
+
* entity manager's.
|
|
955
|
+
*/
|
|
956
|
+
static fromStored(stored, spec, index, tenant) {
|
|
933
957
|
if (!isEncryptedCiphertext(stored)) {
|
|
934
958
|
return new _CompliantField({
|
|
935
959
|
spec,
|
|
960
|
+
tenant,
|
|
936
961
|
hasPlain: true,
|
|
937
962
|
plain: deserializeFromEncryption(
|
|
938
963
|
stored,
|
|
@@ -944,6 +969,7 @@ var CompliantField = class _CompliantField {
|
|
|
944
969
|
}
|
|
945
970
|
return new _CompliantField({
|
|
946
971
|
spec,
|
|
972
|
+
tenant,
|
|
947
973
|
hasPlain: false,
|
|
948
974
|
sealed: stored,
|
|
949
975
|
anon: sealedAnon(stored) ?? void 0,
|
|
@@ -976,11 +1002,24 @@ var CompliantField = class _CompliantField {
|
|
|
976
1002
|
return readPlaintext(this, true);
|
|
977
1003
|
}
|
|
978
1004
|
};
|
|
1005
|
+
function tenantOf(state, operation) {
|
|
1006
|
+
const bound = getBoundTenantId();
|
|
1007
|
+
if (state.tenant === void 0) return requireBoundTenantId(operation);
|
|
1008
|
+
if (bound !== void 0 && bound !== state.tenant) {
|
|
1009
|
+
throw new TenantMismatchError(
|
|
1010
|
+
state.spec.path,
|
|
1011
|
+
operation,
|
|
1012
|
+
state.tenant,
|
|
1013
|
+
bound
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
return state.tenant;
|
|
1017
|
+
}
|
|
979
1018
|
function readPlaintext(field, report) {
|
|
980
1019
|
const state = stateOf(field);
|
|
981
1020
|
let tenantId = "";
|
|
982
1021
|
if (!state.hasPlain) {
|
|
983
|
-
tenantId =
|
|
1022
|
+
tenantId = tenantOf(state, "read");
|
|
984
1023
|
if (state.sealed === void 0) {
|
|
985
1024
|
throw new Error(
|
|
986
1025
|
`${state.spec.path} was not loaded: its ciphertext column was left out of the selection`
|
|
@@ -999,6 +1038,8 @@ function readPlaintext(field, report) {
|
|
|
999
1038
|
state.spec.isArray
|
|
1000
1039
|
);
|
|
1001
1040
|
state.hasPlain = true;
|
|
1041
|
+
} else if (state.tenant !== void 0) {
|
|
1042
|
+
tenantId = tenantOf(state, "read");
|
|
1002
1043
|
}
|
|
1003
1044
|
if (report) {
|
|
1004
1045
|
tenantId ||= getBoundTenantId() ?? "";
|
|
@@ -1026,10 +1067,11 @@ function sealedValueOf(field) {
|
|
|
1026
1067
|
return state.sealed;
|
|
1027
1068
|
}
|
|
1028
1069
|
if (!state.hasPlain) return state.sealed;
|
|
1029
|
-
|
|
1030
|
-
if (state.sealed !== void 0 && state.sealedTenant === tenantId) {
|
|
1070
|
+
if (state.sealed !== void 0 && state.sealedTenant === state.tenant) {
|
|
1031
1071
|
return state.sealed;
|
|
1032
1072
|
}
|
|
1073
|
+
const tenantId = tenantOf(state, "write");
|
|
1074
|
+
state.tenant = tenantId;
|
|
1033
1075
|
if (state.anon === void 0) {
|
|
1034
1076
|
state.anon = computeAnon(state.spec.anon, state.plain);
|
|
1035
1077
|
}
|
|
@@ -1048,9 +1090,12 @@ function normalizedForIndex(value, spec) {
|
|
|
1048
1090
|
return normalizeSerializedForIndex(serializeForEncryption(value), spec);
|
|
1049
1091
|
}
|
|
1050
1092
|
function blindIndexOfValue(value, spec) {
|
|
1093
|
+
return blindIndexUnder(value, spec, requireBoundTenantId("query"));
|
|
1094
|
+
}
|
|
1095
|
+
function blindIndexUnder(value, spec, tenantId) {
|
|
1051
1096
|
return requireEncryptor(spec.path).blindIndex(
|
|
1052
1097
|
normalizedForIndex(value, spec),
|
|
1053
|
-
|
|
1098
|
+
tenantId
|
|
1054
1099
|
);
|
|
1055
1100
|
}
|
|
1056
1101
|
function blindIndexOf(field) {
|
|
@@ -1059,7 +1104,7 @@ function blindIndexOf(field) {
|
|
|
1059
1104
|
if (!state.hasPlain && state.sealed === void 0) return state.index ?? null;
|
|
1060
1105
|
try {
|
|
1061
1106
|
const plain = state.hasPlain ? state.plain : readPlaintext(field, false);
|
|
1062
|
-
state.index =
|
|
1107
|
+
state.index = blindIndexUnder(plain, state.spec, tenantOf(state, "index"));
|
|
1063
1108
|
} catch {
|
|
1064
1109
|
return state.index ?? null;
|
|
1065
1110
|
}
|
|
@@ -1072,6 +1117,7 @@ function isPendingIndex(value) {
|
|
|
1072
1117
|
function pendingIndexValue(value) {
|
|
1073
1118
|
return value[PENDING];
|
|
1074
1119
|
}
|
|
1120
|
+
var COMPLIANT_RUNTIME_TYPE = "CompliantField";
|
|
1075
1121
|
var CompliantTypeBase = class extends import_core2.Type {
|
|
1076
1122
|
constructor(spec) {
|
|
1077
1123
|
super();
|
|
@@ -1082,7 +1128,7 @@ var CompliantTypeBase = class extends import_core2.Type {
|
|
|
1082
1128
|
return "text";
|
|
1083
1129
|
}
|
|
1084
1130
|
get runtimeType() {
|
|
1085
|
-
return
|
|
1131
|
+
return COMPLIANT_RUNTIME_TYPE;
|
|
1086
1132
|
}
|
|
1087
1133
|
ensureComparable() {
|
|
1088
1134
|
return false;
|
|
@@ -1093,7 +1139,7 @@ var CompliantTypeBase = class extends import_core2.Type {
|
|
|
1093
1139
|
};
|
|
1094
1140
|
var CompliantType = class extends CompliantTypeBase {
|
|
1095
1141
|
convertToDatabaseValue(value, _platform, context) {
|
|
1096
|
-
if (context?.fromQuery) {
|
|
1142
|
+
if (context?.fromQuery && context.mode !== "query-data") {
|
|
1097
1143
|
throw new CompliantQueryError(
|
|
1098
1144
|
`${this.spec.path} cannot be queried: declare it with .compliance('${this.spec.level}', { queryable: true }) to allow equality lookups`
|
|
1099
1145
|
);
|
|
@@ -1101,18 +1147,30 @@ var CompliantType = class extends CompliantTypeBase {
|
|
|
1101
1147
|
if (value === null || value === void 0) return null;
|
|
1102
1148
|
if (isCompliantField(value)) return sealedValueOf(value) ?? null;
|
|
1103
1149
|
if (isEncryptedCiphertext(value)) return value;
|
|
1104
|
-
return sealedValueOf(
|
|
1150
|
+
return sealedValueOf(
|
|
1151
|
+
CompliantField.fromPlain(value, this.spec, getBoundTenantId())
|
|
1152
|
+
) ?? null;
|
|
1105
1153
|
}
|
|
1106
1154
|
convertToJSValue(value) {
|
|
1107
1155
|
if (value === null || value === void 0) return value;
|
|
1108
1156
|
if (isCompliantField(value)) return value;
|
|
1109
|
-
return CompliantField.fromStored(
|
|
1157
|
+
return CompliantField.fromStored(
|
|
1158
|
+
String(value),
|
|
1159
|
+
this.spec,
|
|
1160
|
+
void 0,
|
|
1161
|
+
getBoundTenantId()
|
|
1162
|
+
);
|
|
1110
1163
|
}
|
|
1111
1164
|
};
|
|
1112
1165
|
var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["$eq", "$ne", "$in", "$nin"]);
|
|
1113
1166
|
var CompliantIndexType = class extends CompliantTypeBase {
|
|
1114
1167
|
convertToDatabaseValue(value, _platform, context) {
|
|
1115
1168
|
if (value === null || value === void 0) return null;
|
|
1169
|
+
if (context?.mode === "query-data") {
|
|
1170
|
+
throw new CompliantQueryError(
|
|
1171
|
+
`${this.spec.path} is queryable, so a bulk update (nativeUpdate, qb.update) cannot set it: its sealed value lives in a second column the update does not write. Load the entity, assign the value and flush.`
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1116
1174
|
if (context?.fromQuery) {
|
|
1117
1175
|
const key = context.key;
|
|
1118
1176
|
if (key !== void 0 && !EQUALITY_OPERATORS.has(String(key)) && !/^\d+$/.test(String(key))) {
|
|
@@ -1135,6 +1193,18 @@ function isCompliantType(type) {
|
|
|
1135
1193
|
return type instanceof CompliantType || type instanceof CompliantIndexType;
|
|
1136
1194
|
}
|
|
1137
1195
|
var SLOTS = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.slots")] ??= /* @__PURE__ */ new WeakMap();
|
|
1196
|
+
var LOADED_TENANTS = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.loadedTenants")] ??= /* @__PURE__ */ new WeakMap();
|
|
1197
|
+
function loadedTenantOf(entity, binding) {
|
|
1198
|
+
return LOADED_TENANTS.get(entity)?.[binding.property];
|
|
1199
|
+
}
|
|
1200
|
+
function recordLoadedTenant(entity, binding) {
|
|
1201
|
+
let tenants = LOADED_TENANTS.get(entity);
|
|
1202
|
+
if (!tenants) {
|
|
1203
|
+
tenants = {};
|
|
1204
|
+
LOADED_TENANTS.set(entity, tenants);
|
|
1205
|
+
}
|
|
1206
|
+
tenants[binding.property] = getBoundTenantId();
|
|
1207
|
+
}
|
|
1138
1208
|
function slotsOf(entity) {
|
|
1139
1209
|
let slots = SLOTS.get(entity);
|
|
1140
1210
|
if (!slots) {
|
|
@@ -1150,12 +1220,22 @@ function readProperty(entity, binding) {
|
|
|
1150
1220
|
const stored = slots[binding.sibling];
|
|
1151
1221
|
if (isPendingIndex(value)) {
|
|
1152
1222
|
const index = pendingIndexValue(value);
|
|
1153
|
-
const field = typeof stored === "string" ? CompliantField.fromStored(
|
|
1223
|
+
const field = typeof stored === "string" ? CompliantField.fromStored(
|
|
1224
|
+
stored,
|
|
1225
|
+
binding.spec,
|
|
1226
|
+
index,
|
|
1227
|
+
loadedTenantOf(entity, binding)
|
|
1228
|
+
) : CompliantField.fromIndexOnly(index, binding.spec);
|
|
1154
1229
|
slots[binding.property] = field;
|
|
1155
1230
|
return field;
|
|
1156
1231
|
}
|
|
1157
1232
|
if (value == null && typeof stored === "string") {
|
|
1158
|
-
const field = CompliantField.fromStored(
|
|
1233
|
+
const field = CompliantField.fromStored(
|
|
1234
|
+
stored,
|
|
1235
|
+
binding.spec,
|
|
1236
|
+
null,
|
|
1237
|
+
loadedTenantOf(entity, binding)
|
|
1238
|
+
);
|
|
1159
1239
|
slots[binding.property] = field;
|
|
1160
1240
|
return field;
|
|
1161
1241
|
}
|
|
@@ -1177,10 +1257,18 @@ function writeProperty(entity, binding, value) {
|
|
|
1177
1257
|
return;
|
|
1178
1258
|
}
|
|
1179
1259
|
if (isCompliantField(value)) {
|
|
1180
|
-
slots[binding.property] = sameRules(stateOf(value).spec, binding.spec) ? value : CompliantField.fromPlain(
|
|
1260
|
+
slots[binding.property] = sameRules(stateOf(value).spec, binding.spec) ? value : CompliantField.fromPlain(
|
|
1261
|
+
readPlaintext(value, false),
|
|
1262
|
+
binding.spec,
|
|
1263
|
+
stateOf(value).tenant ?? getBoundTenantId()
|
|
1264
|
+
);
|
|
1181
1265
|
return;
|
|
1182
1266
|
}
|
|
1183
|
-
slots[binding.property] = CompliantField.fromPlain(
|
|
1267
|
+
slots[binding.property] = CompliantField.fromPlain(
|
|
1268
|
+
value,
|
|
1269
|
+
binding.spec,
|
|
1270
|
+
getBoundTenantId()
|
|
1271
|
+
);
|
|
1184
1272
|
}
|
|
1185
1273
|
function installCompliantAccessors(prototype, bindings) {
|
|
1186
1274
|
installInspect(prototype, bindings);
|
|
@@ -1207,6 +1295,7 @@ function installCompliantAccessors(prototype, bindings) {
|
|
|
1207
1295
|
return sealedValueOf(field) ?? stored;
|
|
1208
1296
|
},
|
|
1209
1297
|
set(value) {
|
|
1298
|
+
recordLoadedTenant(this, binding);
|
|
1210
1299
|
slotsOf(this)[sibling] = value;
|
|
1211
1300
|
}
|
|
1212
1301
|
});
|
|
@@ -1315,7 +1404,7 @@ function wrapClassified(builder, level, complianceOptions) {
|
|
|
1315
1404
|
};
|
|
1316
1405
|
options.type = spec.queryable ? new CompliantIndexType(spec) : new CompliantType(spec);
|
|
1317
1406
|
options.columnType = "text";
|
|
1318
|
-
options.runtimeType =
|
|
1407
|
+
options.runtimeType = COMPLIANT_RUNTIME_TYPE;
|
|
1319
1408
|
options.accessor = true;
|
|
1320
1409
|
}
|
|
1321
1410
|
}
|
|
@@ -1419,6 +1508,47 @@ var fp = new Proxy(import_core3.p, {
|
|
|
1419
1508
|
|
|
1420
1509
|
// src/persistence/defineComplianceEntity.ts
|
|
1421
1510
|
var import_core4 = require("@mikro-orm/core");
|
|
1511
|
+
|
|
1512
|
+
// src/persistence/complianceChanges.ts
|
|
1513
|
+
var LISTENERS2 = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.changeListeners")] ??= /* @__PURE__ */ new Set();
|
|
1514
|
+
function onComplianceChange(listener) {
|
|
1515
|
+
LISTENERS2.add(listener);
|
|
1516
|
+
return () => LISTENERS2.delete(listener);
|
|
1517
|
+
}
|
|
1518
|
+
function emit(event) {
|
|
1519
|
+
for (const listener of LISTENERS2) {
|
|
1520
|
+
try {
|
|
1521
|
+
listener(event);
|
|
1522
|
+
} catch (error) {
|
|
1523
|
+
console.error("Compliance change listener failed:", error);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
function installComplianceChangeHooks(schema, entityName, levels) {
|
|
1528
|
+
const sensitive = new Set(
|
|
1529
|
+
[...levels].filter(([, level]) => level !== "none").map(([name]) => name)
|
|
1530
|
+
);
|
|
1531
|
+
if (!sensitive.size) return;
|
|
1532
|
+
const report = (action) => (args) => {
|
|
1533
|
+
if (!LISTENERS2.size) return;
|
|
1534
|
+
const entity = args.entity;
|
|
1535
|
+
const keys = args.meta?.primaryKeys ?? ["id"];
|
|
1536
|
+
const fields = action === "update" ? Object.keys(args.changeSet?.payload ?? {}) : action === "create" ? [...levels.keys()].filter((name) => entity[name] !== void 0) : [];
|
|
1537
|
+
emit({
|
|
1538
|
+
entity: entityName,
|
|
1539
|
+
id: keys.map((key) => String(entity[key] ?? "")).join(":"),
|
|
1540
|
+
action,
|
|
1541
|
+
fields,
|
|
1542
|
+
sensitiveFields: action === "delete" ? [...sensitive] : fields.filter((name) => sensitive.has(name)),
|
|
1543
|
+
tenantId: getBoundTenantId() ?? null
|
|
1544
|
+
});
|
|
1545
|
+
};
|
|
1546
|
+
schema.addHook("afterCreate", report("create"));
|
|
1547
|
+
schema.addHook("afterUpdate", report("update"));
|
|
1548
|
+
schema.addHook("afterDelete", report("delete"));
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
// src/persistence/defineComplianceEntity.ts
|
|
1422
1552
|
var naming = new import_core4.UnderscoreNamingStrategy();
|
|
1423
1553
|
function wireCompliantProperties(entityName, properties) {
|
|
1424
1554
|
const wired = {};
|
|
@@ -1498,6 +1628,11 @@ function defineComplianceEntity(meta) {
|
|
|
1498
1628
|
...meta,
|
|
1499
1629
|
properties: wired.properties
|
|
1500
1630
|
});
|
|
1631
|
+
installComplianceChangeHooks(
|
|
1632
|
+
schema,
|
|
1633
|
+
entityName,
|
|
1634
|
+
complianceFields
|
|
1635
|
+
);
|
|
1501
1636
|
if (wired.bindings.length > 0) {
|
|
1502
1637
|
const entityClass = schema.meta.class;
|
|
1503
1638
|
if (entityClass)
|
|
@@ -2080,6 +2215,7 @@ function rebind(result, target, proxy) {
|
|
|
2080
2215
|
RetentionDuration,
|
|
2081
2216
|
RlsEventSubscriber,
|
|
2082
2217
|
TENANT_FILTER_NAME,
|
|
2218
|
+
TenantMismatchError,
|
|
2083
2219
|
UnboundTenantError,
|
|
2084
2220
|
asEncryptionSafe,
|
|
2085
2221
|
assertBindableTenantId,
|
|
@@ -2108,6 +2244,7 @@ function rebind(result, target, proxy) {
|
|
|
2108
2244
|
isEncryptedCiphertext,
|
|
2109
2245
|
isEncryptedValue,
|
|
2110
2246
|
onComplianceAccess,
|
|
2247
|
+
onComplianceChange,
|
|
2111
2248
|
parseDuration,
|
|
2112
2249
|
parseEncryptionKeyList,
|
|
2113
2250
|
reencryptEncryptedColumns,
|