@forklaunch/core 3.1.0 → 3.2.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/bin/gateway-mock/routes/email.mjs +91 -4
- package/lib/http/emailClient.d.ts +46 -0
- 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 +303 -92
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +262 -54
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/middleware/request/enrichDetails.middleware.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/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 +150 -18
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +148 -18
- package/lib/persistence/index.mjs.map +1 -1
- package/package.json +10 -10
package/lib/http/index.js
CHANGED
|
@@ -63,6 +63,9 @@ __export(http_exports, {
|
|
|
63
63
|
VoiceClient: () => VoiceClient,
|
|
64
64
|
VoiceRequestError: () => VoiceRequestError,
|
|
65
65
|
WhatsAppRequestError: () => WhatsAppRequestError,
|
|
66
|
+
auditComplianceAccess: () => auditComplianceAccess,
|
|
67
|
+
auditEnabled: () => auditEnabled,
|
|
68
|
+
auditEventType: () => auditEventType,
|
|
66
69
|
createContext: () => createContext,
|
|
67
70
|
createEmailClient: () => createEmailClient,
|
|
68
71
|
createHmacToken: () => createHmacToken,
|
|
@@ -115,6 +118,7 @@ __export(http_exports, {
|
|
|
115
118
|
post: () => post,
|
|
116
119
|
put: () => put,
|
|
117
120
|
recordMetric: () => recordMetric,
|
|
121
|
+
recordRequestAudit: () => recordRequestAudit,
|
|
118
122
|
resetProcessHandlersForTesting: () => resetProcessHandlersForTesting,
|
|
119
123
|
signPlatformEvent: () => signPlatformEvent,
|
|
120
124
|
smsSegments: () => smsSegments,
|
|
@@ -123,6 +127,7 @@ __export(http_exports, {
|
|
|
123
127
|
typedAuthHandler: () => typedAuthHandler,
|
|
124
128
|
typedHandler: () => typedHandler,
|
|
125
129
|
validateEmailSendRequest: () => validateEmailSendRequest,
|
|
130
|
+
validateListUnsubscribe: () => validateListUnsubscribe,
|
|
126
131
|
validateSmsSend: () => validateSmsSend,
|
|
127
132
|
verifyPlatformEvent: () => verifyPlatformEvent,
|
|
128
133
|
voiceRequestProblem: () => voiceRequestProblem
|
|
@@ -151,7 +156,7 @@ function cors(corsOptions) {
|
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
// src/http/router/expressLikeRouter.ts
|
|
154
|
-
var
|
|
159
|
+
var import_common12 = require("@forklaunch/common");
|
|
155
160
|
|
|
156
161
|
// src/http/guards/hasPermissionChecks.ts
|
|
157
162
|
function hasPermissionChecks(maybePermissionedAuth) {
|
|
@@ -721,7 +726,7 @@ function discriminateResponseBodies(schemaValidator, responses) {
|
|
|
721
726
|
}
|
|
722
727
|
|
|
723
728
|
// src/http/router/routerSharedLogic.ts
|
|
724
|
-
var
|
|
729
|
+
var import_common11 = require("@forklaunch/common");
|
|
725
730
|
|
|
726
731
|
// src/http/guards/hasVersionedSchema.ts
|
|
727
732
|
function hasVersionedSchema(contractDetails) {
|
|
@@ -800,8 +805,8 @@ async function getCachedJwks(jwksPublicKeyUrl) {
|
|
|
800
805
|
return cachedJwks.value;
|
|
801
806
|
} else {
|
|
802
807
|
const jwksResponse = await fetch(jwksPublicKeyUrl);
|
|
803
|
-
const
|
|
804
|
-
if (!
|
|
808
|
+
const text2 = await jwksResponse.text();
|
|
809
|
+
if (!text2) {
|
|
805
810
|
if (cachedJwks.value) {
|
|
806
811
|
return cachedJwks.value;
|
|
807
812
|
}
|
|
@@ -809,7 +814,7 @@ async function getCachedJwks(jwksPublicKeyUrl) {
|
|
|
809
814
|
`JWKS endpoint returned empty response (status ${jwksResponse.status})`
|
|
810
815
|
);
|
|
811
816
|
}
|
|
812
|
-
const jwks = JSON.parse(
|
|
817
|
+
const jwks = JSON.parse(text2).keys;
|
|
813
818
|
cachedJwks.value = jwks;
|
|
814
819
|
cachedJwks.lastUpdated = /* @__PURE__ */ new Date();
|
|
815
820
|
cachedJwks.ttl = parseInt(
|
|
@@ -1271,7 +1276,164 @@ async function parseRequestAuth(req, res, next) {
|
|
|
1271
1276
|
}
|
|
1272
1277
|
|
|
1273
1278
|
// src/http/middleware/request/enrichDetails.middleware.ts
|
|
1279
|
+
var import_common9 = require("@forklaunch/common");
|
|
1280
|
+
|
|
1281
|
+
// src/http/telemetry/requestAudit.ts
|
|
1274
1282
|
var import_common8 = require("@forklaunch/common");
|
|
1283
|
+
|
|
1284
|
+
// src/persistence/encryptedType.ts
|
|
1285
|
+
var import_core = require("@mikro-orm/core");
|
|
1286
|
+
var import_node_async_hooks = require("async_hooks");
|
|
1287
|
+
var _tenantContext = new import_node_async_hooks.AsyncLocalStorage();
|
|
1288
|
+
|
|
1289
|
+
// src/persistence/complianceChanges.ts
|
|
1290
|
+
var LISTENERS = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.changeListeners")] ??= /* @__PURE__ */ new Set();
|
|
1291
|
+
function onComplianceChange(listener) {
|
|
1292
|
+
LISTENERS.add(listener);
|
|
1293
|
+
return () => LISTENERS.delete(listener);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// src/persistence/compliantField.ts
|
|
1297
|
+
var import_core2 = require("@mikro-orm/core");
|
|
1298
|
+
|
|
1299
|
+
// src/persistence/fieldEncryptor.ts
|
|
1300
|
+
var HKDF_SALT = Buffer.alloc(0);
|
|
1301
|
+
|
|
1302
|
+
// src/persistence/compliantField.ts
|
|
1303
|
+
var LISTENERS2 = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.listeners")] ??= /* @__PURE__ */ new Set();
|
|
1304
|
+
function onComplianceAccess(listener) {
|
|
1305
|
+
LISTENERS2.add(listener);
|
|
1306
|
+
return () => LISTENERS2.delete(listener);
|
|
1307
|
+
}
|
|
1308
|
+
var STATE = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.state")] ??= /* @__PURE__ */ new WeakMap();
|
|
1309
|
+
var SLOTS = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.slots")] ??= /* @__PURE__ */ new WeakMap();
|
|
1310
|
+
var LOADED_TENANTS = globalThis[/* @__PURE__ */ Symbol.for("forklaunch.compliance.loadedTenants")] ??= /* @__PURE__ */ new WeakMap();
|
|
1311
|
+
|
|
1312
|
+
// src/http/telemetry/auditLogger.ts
|
|
1313
|
+
var import_crypto3 = require("crypto");
|
|
1314
|
+
var AuditLogger = class {
|
|
1315
|
+
_otel;
|
|
1316
|
+
constructor(otel) {
|
|
1317
|
+
this._otel = otel;
|
|
1318
|
+
}
|
|
1319
|
+
append(entry) {
|
|
1320
|
+
try {
|
|
1321
|
+
this._otel.info(
|
|
1322
|
+
{
|
|
1323
|
+
"log.type": "audit",
|
|
1324
|
+
"audit.timestamp": entry.timestamp,
|
|
1325
|
+
"audit.userId": entry.userId ?? "",
|
|
1326
|
+
"audit.tenantId": entry.tenantId ?? "",
|
|
1327
|
+
"audit.route": entry.route,
|
|
1328
|
+
"audit.method": entry.method,
|
|
1329
|
+
"audit.bodyHash": entry.bodyHash,
|
|
1330
|
+
"audit.status": entry.status,
|
|
1331
|
+
"audit.duration": entry.duration,
|
|
1332
|
+
"audit.redactedFields": entry.redactedFields.join(","),
|
|
1333
|
+
"audit.eventType": entry.eventType,
|
|
1334
|
+
_meta: true
|
|
1335
|
+
},
|
|
1336
|
+
`audit:${entry.eventType} ${entry.method} ${entry.route} ${entry.status}`
|
|
1337
|
+
);
|
|
1338
|
+
} catch (error) {
|
|
1339
|
+
console.error("Failed to emit audit log via OTEL:", error);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
static hashBody(body) {
|
|
1343
|
+
if (body === void 0 || body === null || body === "") {
|
|
1344
|
+
return "";
|
|
1345
|
+
}
|
|
1346
|
+
return (0, import_crypto3.createHash)("sha256").update(body).digest("hex");
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
// src/http/telemetry/requestAudit.ts
|
|
1351
|
+
function auditEnabled() {
|
|
1352
|
+
return (0, import_common8.getEnvVar)("FORKLAUNCH_AUDIT") !== "off";
|
|
1353
|
+
}
|
|
1354
|
+
var loggers = /* @__PURE__ */ new WeakMap();
|
|
1355
|
+
function loggerFor(otel) {
|
|
1356
|
+
let logger2 = loggers.get(otel);
|
|
1357
|
+
if (!logger2) {
|
|
1358
|
+
logger2 = new AuditLogger(otel);
|
|
1359
|
+
loggers.set(otel, logger2);
|
|
1360
|
+
}
|
|
1361
|
+
return logger2;
|
|
1362
|
+
}
|
|
1363
|
+
function auditEventType(status) {
|
|
1364
|
+
if (status === 401) return "auth_failure";
|
|
1365
|
+
if (status === 403) return "rbac_deny";
|
|
1366
|
+
if (status === 429) return "rate_limit";
|
|
1367
|
+
return "http";
|
|
1368
|
+
}
|
|
1369
|
+
var text = (value) => typeof value === "string" && value ? value : null;
|
|
1370
|
+
function bodyText(body) {
|
|
1371
|
+
if (body == null || body === "") return void 0;
|
|
1372
|
+
if (typeof body === "string" || Buffer.isBuffer(body)) return String(body);
|
|
1373
|
+
try {
|
|
1374
|
+
return JSON.stringify(body);
|
|
1375
|
+
} catch {
|
|
1376
|
+
return void 0;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
function recordRequestAudit(otel, req, status, durationMs) {
|
|
1380
|
+
if (!otel || !auditEnabled()) return;
|
|
1381
|
+
const session = req.session && typeof req.session === "object" ? req.session : void 0;
|
|
1382
|
+
loggerFor(otel).append({
|
|
1383
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1384
|
+
userId: text(session?.sub) ?? text(session?.userId),
|
|
1385
|
+
tenantId: text(session?.activeOrganizationId) ?? text(session?.organizationId),
|
|
1386
|
+
route: req.originalPath ?? req.path ?? "unknown",
|
|
1387
|
+
method: req.method,
|
|
1388
|
+
bodyHash: AuditLogger.hashBody(bodyText(req.body)),
|
|
1389
|
+
status,
|
|
1390
|
+
duration: Math.max(0, Math.round(durationMs)),
|
|
1391
|
+
redactedFields: [],
|
|
1392
|
+
eventType: auditEventType(status)
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
var accessAudit;
|
|
1396
|
+
function auditComplianceAccess(otel) {
|
|
1397
|
+
if (!accessAudit && auditEnabled()) {
|
|
1398
|
+
const logger2 = loggerFor(otel);
|
|
1399
|
+
const remove = onComplianceAccess(
|
|
1400
|
+
(event) => logger2.append({
|
|
1401
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1402
|
+
userId: null,
|
|
1403
|
+
tenantId: event.tenantId || null,
|
|
1404
|
+
route: event.field,
|
|
1405
|
+
method: "READ",
|
|
1406
|
+
bodyHash: "",
|
|
1407
|
+
status: 0,
|
|
1408
|
+
duration: 0,
|
|
1409
|
+
redactedFields: [event.field],
|
|
1410
|
+
eventType: "data_access"
|
|
1411
|
+
})
|
|
1412
|
+
);
|
|
1413
|
+
const removeChanges = onComplianceChange(
|
|
1414
|
+
(event) => logger2.append({
|
|
1415
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1416
|
+
userId: null,
|
|
1417
|
+
tenantId: event.tenantId,
|
|
1418
|
+
route: `${event.entity}#${event.id}`,
|
|
1419
|
+
method: event.action.toUpperCase(),
|
|
1420
|
+
bodyHash: "",
|
|
1421
|
+
status: 0,
|
|
1422
|
+
duration: 0,
|
|
1423
|
+
redactedFields: event.sensitiveFields,
|
|
1424
|
+
eventType: "data_change"
|
|
1425
|
+
})
|
|
1426
|
+
);
|
|
1427
|
+
accessAudit = () => {
|
|
1428
|
+
remove();
|
|
1429
|
+
removeChanges();
|
|
1430
|
+
accessAudit = void 0;
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
return accessAudit ?? (() => void 0);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
// src/http/middleware/request/enrichDetails.middleware.ts
|
|
1275
1437
|
function enrichDetails(path, contractDetails, requestSchema, responseSchemas, openTelemetryCollector, globalOptions) {
|
|
1276
1438
|
return (req, res, next) => {
|
|
1277
1439
|
req.originalPath = path;
|
|
@@ -1282,12 +1444,20 @@ function enrichDetails(path, contractDetails, requestSchema, responseSchemas, op
|
|
|
1282
1444
|
req._globalOptions = globalOptions ?? (() => void 0);
|
|
1283
1445
|
req.context?.span?.setAttribute(ATTR_API_NAME, req.contractDetails?.name);
|
|
1284
1446
|
const startTime = process.hrtime();
|
|
1447
|
+
if (openTelemetryCollector) auditComplianceAccess(openTelemetryCollector);
|
|
1285
1448
|
res.on("finish", () => {
|
|
1449
|
+
const [auditSeconds, auditNanoseconds] = process.hrtime(startTime);
|
|
1450
|
+
recordRequestAudit(
|
|
1451
|
+
openTelemetryCollector,
|
|
1452
|
+
req,
|
|
1453
|
+
Number(res.statusCode),
|
|
1454
|
+
auditSeconds * 1e3 + auditNanoseconds / 1e6
|
|
1455
|
+
);
|
|
1286
1456
|
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
1287
1457
|
const durationMs = seconds + nanoseconds / 1e9;
|
|
1288
1458
|
httpServerDurationHistogram.record(durationMs, {
|
|
1289
|
-
[import_semantic_conventions.ATTR_SERVICE_NAME]: (0,
|
|
1290
|
-
[ATTR_APPLICATION_ID]: (0,
|
|
1459
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: (0, import_common9.getEnvVar)("OTEL_SERVICE_NAME") || "unknown",
|
|
1460
|
+
[ATTR_APPLICATION_ID]: (0, import_common9.getEnvVar)("OTEL_APPLICATION_ID"),
|
|
1291
1461
|
[ATTR_API_NAME]: req.contractDetails?.name || "unknown",
|
|
1292
1462
|
[import_semantic_conventions.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
|
1293
1463
|
[import_semantic_conventions.ATTR_HTTP_ROUTE]: req.originalPath || "unknown",
|
|
@@ -1299,7 +1469,7 @@ function enrichDetails(path, contractDetails, requestSchema, responseSchemas, op
|
|
|
1299
1469
|
}
|
|
1300
1470
|
|
|
1301
1471
|
// src/http/middleware/request/parse.middleware.ts
|
|
1302
|
-
var
|
|
1472
|
+
var import_common10 = require("@forklaunch/common");
|
|
1303
1473
|
var import_validator2 = require("@forklaunch/validator");
|
|
1304
1474
|
|
|
1305
1475
|
// src/http/guards/hasSend.ts
|
|
@@ -1328,7 +1498,7 @@ function parse(req, res, next) {
|
|
|
1328
1498
|
let parsedRequest;
|
|
1329
1499
|
let collectedParseErrors;
|
|
1330
1500
|
if (req.contractDetails.versions) {
|
|
1331
|
-
if ((0,
|
|
1501
|
+
if ((0, import_common10.isRecord)(req.requestSchema)) {
|
|
1332
1502
|
let runningParseErrors = "";
|
|
1333
1503
|
matchedVersions = [];
|
|
1334
1504
|
Object.entries(req.requestSchema).forEach(([version, schema]) => {
|
|
@@ -1559,13 +1729,13 @@ function compileRouteSchemas(contractDetails, schemaValidator) {
|
|
|
1559
1729
|
versionedContractDetails,
|
|
1560
1730
|
contractDetails.params
|
|
1561
1731
|
);
|
|
1562
|
-
if ((0,
|
|
1732
|
+
if ((0, import_common11.isRecord)(requestSchema)) {
|
|
1563
1733
|
requestSchema = {
|
|
1564
1734
|
...requestSchema,
|
|
1565
1735
|
[version]: versionedRequestSchema
|
|
1566
1736
|
};
|
|
1567
1737
|
}
|
|
1568
|
-
if ((0,
|
|
1738
|
+
if ((0, import_common11.isRecord)(responseSchemas)) {
|
|
1569
1739
|
responseSchemas = {
|
|
1570
1740
|
...responseSchemas,
|
|
1571
1741
|
[version]: versionedResponseSchemas
|
|
@@ -1919,8 +2089,8 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
1919
2089
|
...middlewares,
|
|
1920
2090
|
this.#parseAndRunControllerHandler(controllerHandler)
|
|
1921
2091
|
);
|
|
1922
|
-
(0,
|
|
1923
|
-
...this._fetchMap[(0,
|
|
2092
|
+
(0, import_common12.toRecord)(this._fetchMap)[(0, import_common12.sanitizePathSlashes)(`${this.basePath}${path}`)] = {
|
|
2093
|
+
...this._fetchMap[(0, import_common12.sanitizePathSlashes)(`${this.basePath}${path}`)] ?? {},
|
|
1924
2094
|
[method.toUpperCase()]: contractDetails.versions ? Object.fromEntries(
|
|
1925
2095
|
Object.keys(contractDetails.versions).map((version) => [
|
|
1926
2096
|
version,
|
|
@@ -1943,7 +2113,7 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
1943
2113
|
};
|
|
1944
2114
|
const contractDetailsName = contractDetails.name;
|
|
1945
2115
|
if (contractDetailsName) {
|
|
1946
|
-
(0,
|
|
2116
|
+
(0, import_common12.toRecord)(this.sdk)[(0, import_common12.toPrettyCamelCase)(contractDetailsName)] = contractDetails.versions ? Object.fromEntries(
|
|
1947
2117
|
Object.keys(contractDetails.versions).map((version) => [
|
|
1948
2118
|
version,
|
|
1949
2119
|
(req) => this.#localParamRequest(
|
|
@@ -2047,10 +2217,10 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
2047
2217
|
}
|
|
2048
2218
|
addRouterToSdk(router) {
|
|
2049
2219
|
Object.entries(router._fetchMap).map(
|
|
2050
|
-
([key, value]) => (0,
|
|
2220
|
+
([key, value]) => (0, import_common12.toRecord)(this._fetchMap)[(0, import_common12.sanitizePathSlashes)(`${this.basePath}${key}`)] = value
|
|
2051
2221
|
);
|
|
2052
|
-
const existingSdk = this.sdk[router.sdkName ?? (0,
|
|
2053
|
-
(0,
|
|
2222
|
+
const existingSdk = this.sdk[router.sdkName ?? (0, import_common12.toPrettyCamelCase)(router.basePath)];
|
|
2223
|
+
(0, import_common12.toRecord)(this.sdk)[router.sdkName ?? (0, import_common12.toPrettyCamelCase)(router.basePath)] = {
|
|
2054
2224
|
...typeof existingSdk === "object" ? existingSdk : {},
|
|
2055
2225
|
...router.sdk
|
|
2056
2226
|
};
|
|
@@ -2382,7 +2552,7 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
2382
2552
|
unpackSdks(sdks, path, routerUniquenessCache) {
|
|
2383
2553
|
Object.entries(sdks).forEach(([key, maybeHandler]) => {
|
|
2384
2554
|
if (isSdkHandler(maybeHandler)) {
|
|
2385
|
-
const cacheKey = (0,
|
|
2555
|
+
const cacheKey = (0, import_common12.hashString)((0, import_common12.safeStringify)(maybeHandler));
|
|
2386
2556
|
if (routerUniquenessCache.has(cacheKey)) {
|
|
2387
2557
|
throw new Error(`SDK handler ${key} is already registered`);
|
|
2388
2558
|
}
|
|
@@ -2489,7 +2659,7 @@ function isPortBound(port, host = "localhost") {
|
|
|
2489
2659
|
}
|
|
2490
2660
|
|
|
2491
2661
|
// src/http/generateHmacAuthHeaders.ts
|
|
2492
|
-
var
|
|
2662
|
+
var import_crypto4 = require("crypto");
|
|
2493
2663
|
function generateHmacAuthHeaders({
|
|
2494
2664
|
secretKey,
|
|
2495
2665
|
method,
|
|
@@ -2498,7 +2668,7 @@ function generateHmacAuthHeaders({
|
|
|
2498
2668
|
keyId = "default"
|
|
2499
2669
|
}) {
|
|
2500
2670
|
const timestamp = /* @__PURE__ */ new Date();
|
|
2501
|
-
const nonce = (0,
|
|
2671
|
+
const nonce = (0, import_crypto4.randomUUID)();
|
|
2502
2672
|
const signature = createHmacToken({
|
|
2503
2673
|
secretKey,
|
|
2504
2674
|
method,
|
|
@@ -2513,7 +2683,7 @@ function generateHmacAuthHeaders({
|
|
|
2513
2683
|
}
|
|
2514
2684
|
|
|
2515
2685
|
// src/http/instanceGateway.ts
|
|
2516
|
-
var
|
|
2686
|
+
var import_crypto5 = require("crypto");
|
|
2517
2687
|
var INSTANCE_GATEWAY_MOUNT = "/instance-gateway";
|
|
2518
2688
|
var PLATFORM_EVENT_KEY_ID = "platform";
|
|
2519
2689
|
var PLATFORM_EVENTS_PATH = "/platform-events";
|
|
@@ -2634,7 +2804,7 @@ function verifyPlatformEvent(request, options2 = {}) {
|
|
|
2634
2804
|
})
|
|
2635
2805
|
);
|
|
2636
2806
|
const received = Buffer.from(signature);
|
|
2637
|
-
if (expected.length !== received.length || !(0,
|
|
2807
|
+
if (expected.length !== received.length || !(0, import_crypto5.timingSafeEqual)(expected, received)) {
|
|
2638
2808
|
throw new PlatformEventVerificationError("Invalid signature");
|
|
2639
2809
|
}
|
|
2640
2810
|
for (const [seen, at] of seenEventNonces) {
|
|
@@ -2769,17 +2939,17 @@ async function readPreviewCatalog(response) {
|
|
|
2769
2939
|
if (!response.body) return invalidCatalog();
|
|
2770
2940
|
const reader = response.body.getReader();
|
|
2771
2941
|
const decoder = new TextDecoder();
|
|
2772
|
-
let
|
|
2942
|
+
let text2 = "", bytes = 0;
|
|
2773
2943
|
try {
|
|
2774
2944
|
for (; ; ) {
|
|
2775
2945
|
const { done, value } = await reader.read();
|
|
2776
2946
|
if (done) break;
|
|
2777
2947
|
bytes += value.byteLength;
|
|
2778
2948
|
if (bytes > 8192) return invalidCatalog();
|
|
2779
|
-
|
|
2949
|
+
text2 += decoder.decode(value, { stream: true });
|
|
2780
2950
|
}
|
|
2781
|
-
|
|
2782
|
-
return previewCatalog(JSON.parse(
|
|
2951
|
+
text2 += decoder.decode();
|
|
2952
|
+
return previewCatalog(JSON.parse(text2));
|
|
2783
2953
|
} catch {
|
|
2784
2954
|
return invalidCatalog();
|
|
2785
2955
|
} finally {
|
|
@@ -2835,10 +3005,16 @@ var EMAIL_LIMITS = {
|
|
|
2835
3005
|
maxSubjectLength: 998,
|
|
2836
3006
|
/** text + html, UTF-8 bytes. */
|
|
2837
3007
|
maxBodyBytes: 512 * 1024,
|
|
2838
|
-
maxTags: 10
|
|
3008
|
+
maxTags: 10,
|
|
3009
|
+
/** `listUnsubscribe.url`; keeps the header within SES's limit. */
|
|
3010
|
+
maxUnsubscribeUrlLength: 512
|
|
2839
3011
|
};
|
|
2840
3012
|
var ADDRESS = /^[^\s@<>()[\]\\,;:"]+@[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)+$/;
|
|
2841
3013
|
var TAG_PART = /^[A-Za-z0-9_-]{1,256}$/;
|
|
3014
|
+
var HEADER_SAFE = /^[\x21-\x7e]+$/;
|
|
3015
|
+
var URL_DELIMITERS = /[<>,"\\]/;
|
|
3016
|
+
var MAILBOX = /^[A-Za-z0-9._+-]+@[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)+$/;
|
|
3017
|
+
var UNSUBSCRIBE_FIELDS = /* @__PURE__ */ new Set(["url", "mailto", "oneClick"]);
|
|
2842
3018
|
function isEmailAddress(address) {
|
|
2843
3019
|
return typeof address === "string" && address.length <= EMAIL_LIMITS.maxAddressLength && ADDRESS.test(address);
|
|
2844
3020
|
}
|
|
@@ -2863,6 +3039,72 @@ function addresses(value, field) {
|
|
|
2863
3039
|
}
|
|
2864
3040
|
return list;
|
|
2865
3041
|
}
|
|
3042
|
+
function fail(problem) {
|
|
3043
|
+
refuse(`listUnsubscribe: ${problem}`);
|
|
3044
|
+
}
|
|
3045
|
+
function unsubscribeUrlProblem(url) {
|
|
3046
|
+
if (typeof url !== "string" || url === "") return "url must be a string";
|
|
3047
|
+
if (url.length > EMAIL_LIMITS.maxUnsubscribeUrlLength) {
|
|
3048
|
+
return `url is longer than ${EMAIL_LIMITS.maxUnsubscribeUrlLength} characters`;
|
|
3049
|
+
}
|
|
3050
|
+
if (!HEADER_SAFE.test(url)) {
|
|
3051
|
+
return "url must be printable ASCII with no spaces or line breaks; percent-encode anything else";
|
|
3052
|
+
}
|
|
3053
|
+
if (URL_DELIMITERS.test(url)) {
|
|
3054
|
+
return 'url must not contain < > , " or \\; percent-encode them';
|
|
3055
|
+
}
|
|
3056
|
+
let parsed;
|
|
3057
|
+
try {
|
|
3058
|
+
parsed = new URL(url);
|
|
3059
|
+
} catch {
|
|
3060
|
+
return "url is not a URL";
|
|
3061
|
+
}
|
|
3062
|
+
if (parsed.protocol !== "https:") return "url must be https";
|
|
3063
|
+
if (parsed.username || parsed.password) {
|
|
3064
|
+
return "url must not carry a user name or password";
|
|
3065
|
+
}
|
|
3066
|
+
return null;
|
|
3067
|
+
}
|
|
3068
|
+
function validateListUnsubscribe(value) {
|
|
3069
|
+
if (value === void 0 || value === null) return void 0;
|
|
3070
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
3071
|
+
fail("must be an object");
|
|
3072
|
+
}
|
|
3073
|
+
const unknownFields = Object.keys(value).filter(
|
|
3074
|
+
(key) => !UNSUBSCRIBE_FIELDS.has(key)
|
|
3075
|
+
);
|
|
3076
|
+
if (unknownFields.length) {
|
|
3077
|
+
fail(`unknown field ${unknownFields.map((k) => `'${k}'`).join(", ")}`);
|
|
3078
|
+
}
|
|
3079
|
+
const url = "url" in value ? value.url : void 0;
|
|
3080
|
+
const mailto = "mailto" in value ? value.mailto : void 0;
|
|
3081
|
+
const oneClick = "oneClick" in value ? value.oneClick : void 0;
|
|
3082
|
+
if (url === void 0 && mailto === void 0) {
|
|
3083
|
+
fail("needs a url or a mailto");
|
|
3084
|
+
}
|
|
3085
|
+
if (url !== void 0) {
|
|
3086
|
+
const problem = unsubscribeUrlProblem(url);
|
|
3087
|
+
if (problem) fail(problem);
|
|
3088
|
+
}
|
|
3089
|
+
if (mailto !== void 0 && (typeof mailto !== "string" || mailto.length > EMAIL_LIMITS.maxAddressLength || !MAILBOX.test(mailto))) {
|
|
3090
|
+
fail(
|
|
3091
|
+
`mailto: '${String(mailto).slice(0, 80)}' is not a plain mailbox (letters, digits, . _ + - before the @)`
|
|
3092
|
+
);
|
|
3093
|
+
}
|
|
3094
|
+
if (oneClick !== void 0 && typeof oneClick !== "boolean") {
|
|
3095
|
+
fail("oneClick must be true or false");
|
|
3096
|
+
}
|
|
3097
|
+
if (typeof url === "string") {
|
|
3098
|
+
return {
|
|
3099
|
+
url,
|
|
3100
|
+
...typeof mailto === "string" ? { mailto } : {},
|
|
3101
|
+
...oneClick === true ? { oneClick: true } : {}
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
if (oneClick === true) fail("oneClick needs a url (RFC 8058 posts to it)");
|
|
3105
|
+
if (typeof mailto === "string") return { mailto };
|
|
3106
|
+
return fail("needs a url or a mailto");
|
|
3107
|
+
}
|
|
2866
3108
|
function validateEmailSendRequest(request) {
|
|
2867
3109
|
const to = addresses(request.to, "to") ?? refuse("to is required");
|
|
2868
3110
|
const replyTo = addresses(request.replyTo, "replyTo");
|
|
@@ -2894,13 +3136,15 @@ function validateEmailSendRequest(request) {
|
|
|
2894
3136
|
refuse(`tag '${name}' is reserved`);
|
|
2895
3137
|
}
|
|
2896
3138
|
}
|
|
3139
|
+
const listUnsubscribe = validateListUnsubscribe(request.listUnsubscribe);
|
|
2897
3140
|
return {
|
|
2898
3141
|
to,
|
|
2899
3142
|
subject,
|
|
2900
3143
|
...request.text !== void 0 ? { text: request.text } : {},
|
|
2901
3144
|
...request.html !== void 0 ? { html: request.html } : {},
|
|
2902
3145
|
...replyTo ? { replyTo } : {},
|
|
2903
|
-
...names.length ? { tags } : {}
|
|
3146
|
+
...names.length ? { tags } : {},
|
|
3147
|
+
...listUnsubscribe ? { listUnsubscribe } : {}
|
|
2904
3148
|
};
|
|
2905
3149
|
}
|
|
2906
3150
|
function createEmailClient(options2 = {}) {
|
|
@@ -3209,8 +3453,8 @@ var VoiceClient = class {
|
|
|
3209
3453
|
async send(method, route, body) {
|
|
3210
3454
|
try {
|
|
3211
3455
|
const response = await this.transport.request(method, route, body);
|
|
3212
|
-
const
|
|
3213
|
-
return
|
|
3456
|
+
const text2 = await response.text();
|
|
3457
|
+
return text2 ? JSON.parse(text2) : void 0;
|
|
3214
3458
|
} catch (error) {
|
|
3215
3459
|
if (error instanceof InstanceGatewayRequestError) {
|
|
3216
3460
|
throw new VoiceRequestError(
|
|
@@ -4443,7 +4687,7 @@ var getCodeForStatus = (status) => {
|
|
|
4443
4687
|
var httpStatusCodes_default = HTTPStatuses;
|
|
4444
4688
|
|
|
4445
4689
|
// src/http/mcpGenerator/mcpGenerator.ts
|
|
4446
|
-
var
|
|
4690
|
+
var import_common13 = require("@forklaunch/common");
|
|
4447
4691
|
var import_zod = require("@forklaunch/validator/zod");
|
|
4448
4692
|
var import_fastmcp = require("fastmcp");
|
|
4449
4693
|
|
|
@@ -4578,7 +4822,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4578
4822
|
if (discriminatedBody) {
|
|
4579
4823
|
switch (discriminatedBody.parserType) {
|
|
4580
4824
|
case "json": {
|
|
4581
|
-
parsedBody = (0,
|
|
4825
|
+
parsedBody = (0, import_common13.safeStringify)(body);
|
|
4582
4826
|
break;
|
|
4583
4827
|
}
|
|
4584
4828
|
case "text": {
|
|
@@ -4586,12 +4830,12 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4586
4830
|
break;
|
|
4587
4831
|
}
|
|
4588
4832
|
case "file": {
|
|
4589
|
-
parsedBody = Buffer.from((0,
|
|
4833
|
+
parsedBody = Buffer.from((0, import_common13.safeStringify)(body));
|
|
4590
4834
|
break;
|
|
4591
4835
|
}
|
|
4592
4836
|
case "multipart": {
|
|
4593
4837
|
const formData = new FormData();
|
|
4594
|
-
if ((0,
|
|
4838
|
+
if ((0, import_common13.isRecord)(body)) {
|
|
4595
4839
|
for (const key in body) {
|
|
4596
4840
|
if (typeof body[key] === "string") {
|
|
4597
4841
|
if (schemaValidator.isInstanceOf(
|
|
@@ -4616,11 +4860,11 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4616
4860
|
break;
|
|
4617
4861
|
}
|
|
4618
4862
|
case "urlEncoded": {
|
|
4619
|
-
if ((0,
|
|
4863
|
+
if ((0, import_common13.isRecord)(body)) {
|
|
4620
4864
|
parsedBody = new URLSearchParams(
|
|
4621
4865
|
Object.entries(body).map(([key, value]) => [
|
|
4622
4866
|
key,
|
|
4623
|
-
(0,
|
|
4867
|
+
(0, import_common13.safeStringify)(value)
|
|
4624
4868
|
])
|
|
4625
4869
|
);
|
|
4626
4870
|
} else {
|
|
@@ -4629,8 +4873,8 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4629
4873
|
break;
|
|
4630
4874
|
}
|
|
4631
4875
|
default: {
|
|
4632
|
-
(0,
|
|
4633
|
-
parsedBody = (0,
|
|
4876
|
+
(0, import_common13.isNever)(discriminatedBody.parserType);
|
|
4877
|
+
parsedBody = (0, import_common13.safeStringify)(body);
|
|
4634
4878
|
break;
|
|
4635
4879
|
}
|
|
4636
4880
|
}
|
|
@@ -4639,7 +4883,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4639
4883
|
const queryString = new URLSearchParams(
|
|
4640
4884
|
Object.entries(query).map(([key, value]) => [
|
|
4641
4885
|
key,
|
|
4642
|
-
(0,
|
|
4886
|
+
(0, import_common13.safeStringify)(value)
|
|
4643
4887
|
])
|
|
4644
4888
|
).toString();
|
|
4645
4889
|
url += queryString ? `?${queryString}` : "";
|
|
@@ -4672,7 +4916,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4672
4916
|
content: [
|
|
4673
4917
|
{
|
|
4674
4918
|
type: "text",
|
|
4675
|
-
text: (0,
|
|
4919
|
+
text: (0, import_common13.safeStringify)(await response.json())
|
|
4676
4920
|
}
|
|
4677
4921
|
]
|
|
4678
4922
|
};
|
|
@@ -4827,20 +5071,20 @@ ${parseErrors.join("\n\n")}`
|
|
|
4827
5071
|
}
|
|
4828
5072
|
|
|
4829
5073
|
// src/http/middleware/response/enrichExpressLikeSend.middleware.ts
|
|
4830
|
-
var
|
|
5074
|
+
var import_common15 = require("@forklaunch/common");
|
|
4831
5075
|
var import_stream = require("stream");
|
|
4832
5076
|
|
|
4833
5077
|
// src/http/telemetry/recordMetric.ts
|
|
4834
|
-
var
|
|
5078
|
+
var import_common14 = require("@forklaunch/common");
|
|
4835
5079
|
var import_semantic_conventions4 = require("@opentelemetry/semantic-conventions");
|
|
4836
5080
|
function recordMetric(req, res) {
|
|
4837
5081
|
if (res.metricRecorded) {
|
|
4838
5082
|
return;
|
|
4839
5083
|
}
|
|
4840
|
-
const serviceName = (0,
|
|
5084
|
+
const serviceName = (0, import_common14.getEnvVar)("OTEL_SERVICE_NAME") || "unknown";
|
|
4841
5085
|
const attrs = {
|
|
4842
5086
|
[import_semantic_conventions4.ATTR_SERVICE_NAME]: serviceName,
|
|
4843
|
-
[ATTR_APPLICATION_ID]: (0,
|
|
5087
|
+
[ATTR_APPLICATION_ID]: (0, import_common14.getEnvVar)("OTEL_APPLICATION_ID"),
|
|
4844
5088
|
[ATTR_API_NAME]: req.contractDetails?.name,
|
|
4845
5089
|
[import_semantic_conventions4.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
|
4846
5090
|
[import_semantic_conventions4.ATTR_HTTP_ROUTE]: req.originalPath,
|
|
@@ -4888,15 +5132,15 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
|
4888
5132
|
`attachment; filename="${data.name}"`
|
|
4889
5133
|
);
|
|
4890
5134
|
}
|
|
4891
|
-
if ((0,
|
|
4892
|
-
import_stream.Readable.from((0,
|
|
5135
|
+
if ((0, import_common15.isNodeJsWriteableStream)(res)) {
|
|
5136
|
+
import_stream.Readable.from((0, import_common15.readableStreamToAsyncIterable)(data.stream())).pipe(res);
|
|
4893
5137
|
} else {
|
|
4894
5138
|
res.type("text/plain");
|
|
4895
5139
|
res.status(500);
|
|
4896
5140
|
originalSend.call(instance, "Not a NodeJS WritableStream");
|
|
4897
5141
|
errorSent = true;
|
|
4898
5142
|
}
|
|
4899
|
-
} else if ((0,
|
|
5143
|
+
} else if ((0, import_common15.isAsyncGenerator)(data)) {
|
|
4900
5144
|
let firstPass = true;
|
|
4901
5145
|
const transformer = new import_stream.Transform({
|
|
4902
5146
|
objectMode: true,
|
|
@@ -4920,7 +5164,7 @@ ${res.locals.errorMessage}`;
|
|
|
4920
5164
|
} else {
|
|
4921
5165
|
let data2 = "";
|
|
4922
5166
|
for (const [key, value] of Object.entries(chunk)) {
|
|
4923
|
-
data2 += `${key}: ${typeof value === "string" ? value : (0,
|
|
5167
|
+
data2 += `${key}: ${typeof value === "string" ? value : (0, import_common15.safeStringify)(value)}
|
|
4924
5168
|
`;
|
|
4925
5169
|
}
|
|
4926
5170
|
data2 += "\n";
|
|
@@ -4931,7 +5175,7 @@ ${res.locals.errorMessage}`;
|
|
|
4931
5175
|
} else if (!errorSent) {
|
|
4932
5176
|
let data2 = "";
|
|
4933
5177
|
for (const [key, value] of Object.entries(chunk)) {
|
|
4934
|
-
data2 += `${key}: ${typeof value === "string" ? value : (0,
|
|
5178
|
+
data2 += `${key}: ${typeof value === "string" ? value : (0, import_common15.safeStringify)(value)}
|
|
4935
5179
|
`;
|
|
4936
5180
|
}
|
|
4937
5181
|
data2 += "\n";
|
|
@@ -4939,7 +5183,7 @@ ${res.locals.errorMessage}`;
|
|
|
4939
5183
|
}
|
|
4940
5184
|
}
|
|
4941
5185
|
});
|
|
4942
|
-
if ((0,
|
|
5186
|
+
if ((0, import_common15.isNodeJsWriteableStream)(res)) {
|
|
4943
5187
|
import_stream.Readable.from(data).pipe(transformer).pipe(res);
|
|
4944
5188
|
} else {
|
|
4945
5189
|
res.type("text/plain");
|
|
@@ -4950,7 +5194,7 @@ ${res.locals.errorMessage}`;
|
|
|
4950
5194
|
} else {
|
|
4951
5195
|
const parserType = responseBodies?.[Number(res.statusCode)]?.parserType;
|
|
4952
5196
|
res.bodyData = data;
|
|
4953
|
-
if ((0,
|
|
5197
|
+
if ((0, import_common15.isRecord)(data)) {
|
|
4954
5198
|
switch (parserType) {
|
|
4955
5199
|
case "json":
|
|
4956
5200
|
res.bodyData = "json" in data ? data.json : data;
|
|
@@ -4971,7 +5215,7 @@ ${res.locals.errorMessage}`;
|
|
|
4971
5215
|
res.bodyData = data;
|
|
4972
5216
|
break;
|
|
4973
5217
|
default:
|
|
4974
|
-
(0,
|
|
5218
|
+
(0, import_common15.isNever)(parserType);
|
|
4975
5219
|
res.bodyData = data;
|
|
4976
5220
|
break;
|
|
4977
5221
|
}
|
|
@@ -5006,7 +5250,7 @@ ${res.locals.errorMessage}`;
|
|
|
5006
5250
|
}
|
|
5007
5251
|
|
|
5008
5252
|
// src/http/openApiV3Generator/openApiV3Generator.ts
|
|
5009
|
-
var
|
|
5253
|
+
var import_common16 = require("@forklaunch/common");
|
|
5010
5254
|
var OPENAPI_DEFAULT_VERSION = /* @__PURE__ */ Symbol("default");
|
|
5011
5255
|
function toUpperCase(str) {
|
|
5012
5256
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
@@ -5229,7 +5473,7 @@ function generateOpenApiSpecs(schemaValidator, serverUrls, serverDescriptions, a
|
|
|
5229
5473
|
].forEach(({ fullPath, router }) => {
|
|
5230
5474
|
const controllerName = transformBasePath(fullPath);
|
|
5231
5475
|
router.routes.forEach((route) => {
|
|
5232
|
-
const openApiPath = (0,
|
|
5476
|
+
const openApiPath = (0, import_common16.openApiCompliantPath)(
|
|
5233
5477
|
`${fullPath}${route.path === "/" ? "" : route.path}`
|
|
5234
5478
|
);
|
|
5235
5479
|
const { name, summary, params, versions, auth, options: options2 } = route.contractDetails;
|
|
@@ -5333,44 +5577,6 @@ function generateOpenApiSpecs(schemaValidator, serverUrls, serverDescriptions, a
|
|
|
5333
5577
|
);
|
|
5334
5578
|
}
|
|
5335
5579
|
|
|
5336
|
-
// src/http/telemetry/auditLogger.ts
|
|
5337
|
-
var import_crypto5 = require("crypto");
|
|
5338
|
-
var AuditLogger = class {
|
|
5339
|
-
_otel;
|
|
5340
|
-
constructor(otel) {
|
|
5341
|
-
this._otel = otel;
|
|
5342
|
-
}
|
|
5343
|
-
append(entry) {
|
|
5344
|
-
try {
|
|
5345
|
-
this._otel.info(
|
|
5346
|
-
{
|
|
5347
|
-
"log.type": "audit",
|
|
5348
|
-
"audit.timestamp": entry.timestamp,
|
|
5349
|
-
"audit.userId": entry.userId ?? "",
|
|
5350
|
-
"audit.tenantId": entry.tenantId ?? "",
|
|
5351
|
-
"audit.route": entry.route,
|
|
5352
|
-
"audit.method": entry.method,
|
|
5353
|
-
"audit.bodyHash": entry.bodyHash,
|
|
5354
|
-
"audit.status": entry.status,
|
|
5355
|
-
"audit.duration": entry.duration,
|
|
5356
|
-
"audit.redactedFields": entry.redactedFields.join(","),
|
|
5357
|
-
"audit.eventType": entry.eventType,
|
|
5358
|
-
_meta: true
|
|
5359
|
-
},
|
|
5360
|
-
`audit:${entry.eventType} ${entry.method} ${entry.route} ${entry.status}`
|
|
5361
|
-
);
|
|
5362
|
-
} catch (error) {
|
|
5363
|
-
console.error("Failed to emit audit log via OTEL:", error);
|
|
5364
|
-
}
|
|
5365
|
-
}
|
|
5366
|
-
static hashBody(body) {
|
|
5367
|
-
if (body === void 0 || body === null || body === "") {
|
|
5368
|
-
return "";
|
|
5369
|
-
}
|
|
5370
|
-
return (0, import_crypto5.createHash)("sha256").update(body).digest("hex");
|
|
5371
|
-
}
|
|
5372
|
-
};
|
|
5373
|
-
|
|
5374
5580
|
// src/http/telemetry/evaluateTelemetryOptions.ts
|
|
5375
5581
|
function evaluateTelemetryOptions(telemetryOptions) {
|
|
5376
5582
|
return {
|
|
@@ -5494,6 +5700,9 @@ var RateLimiter = class {
|
|
|
5494
5700
|
VoiceClient,
|
|
5495
5701
|
VoiceRequestError,
|
|
5496
5702
|
WhatsAppRequestError,
|
|
5703
|
+
auditComplianceAccess,
|
|
5704
|
+
auditEnabled,
|
|
5705
|
+
auditEventType,
|
|
5497
5706
|
createContext,
|
|
5498
5707
|
createEmailClient,
|
|
5499
5708
|
createHmacToken,
|
|
@@ -5546,6 +5755,7 @@ var RateLimiter = class {
|
|
|
5546
5755
|
post,
|
|
5547
5756
|
put,
|
|
5548
5757
|
recordMetric,
|
|
5758
|
+
recordRequestAudit,
|
|
5549
5759
|
resetProcessHandlersForTesting,
|
|
5550
5760
|
signPlatformEvent,
|
|
5551
5761
|
smsSegments,
|
|
@@ -5554,6 +5764,7 @@ var RateLimiter = class {
|
|
|
5554
5764
|
typedAuthHandler,
|
|
5555
5765
|
typedHandler,
|
|
5556
5766
|
validateEmailSendRequest,
|
|
5767
|
+
validateListUnsubscribe,
|
|
5557
5768
|
validateSmsSend,
|
|
5558
5769
|
verifyPlatformEvent,
|
|
5559
5770
|
voiceRequestProblem
|