@digilogiclabs/platform-core 1.3.0 → 1.5.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/README.md +79 -3
- package/dist/{ConsoleEmail-hUDFsKoA.d.mts → ConsoleEmail-ubSVWgTa.d.mts} +187 -1
- package/dist/{ConsoleEmail-hUDFsKoA.d.ts → ConsoleEmail-ubSVWgTa.d.ts} +187 -1
- package/dist/index.d.mts +1583 -130
- package/dist/index.d.ts +1583 -130
- package/dist/index.js +1978 -169
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1922 -162
- package/dist/index.mjs.map +1 -1
- package/dist/migrate.js +3 -2
- package/dist/migrate.js.map +1 -1
- package/dist/security-headers.d.mts +75 -0
- package/dist/security-headers.d.ts +75 -0
- package/dist/security-headers.js +137 -0
- package/dist/security-headers.js.map +1 -0
- package/dist/security-headers.mjs +111 -0
- package/dist/security-headers.mjs.map +1 -0
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +196 -15
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +200 -14
- package/dist/testing.mjs.map +1 -1
- package/package.json +16 -11
package/dist/index.js
CHANGED
|
@@ -409,10 +409,11 @@ var init_IAI = __esm({
|
|
|
409
409
|
});
|
|
410
410
|
|
|
411
411
|
// src/interfaces/IRAG.ts
|
|
412
|
-
var ChunkingPresets, MemoryRAG;
|
|
412
|
+
var import_crypto13, ChunkingPresets, MemoryRAG;
|
|
413
413
|
var init_IRAG = __esm({
|
|
414
414
|
"src/interfaces/IRAG.ts"() {
|
|
415
415
|
"use strict";
|
|
416
|
+
import_crypto13 = require("crypto");
|
|
416
417
|
ChunkingPresets = {
|
|
417
418
|
default: {
|
|
418
419
|
strategy: "recursive",
|
|
@@ -538,7 +539,7 @@ var init_IRAG = __esm({
|
|
|
538
539
|
}
|
|
539
540
|
async ingestOne(collection, document, options) {
|
|
540
541
|
const startTime = Date.now();
|
|
541
|
-
const docId = `doc_${Date.now()}_${
|
|
542
|
+
const docId = `doc_${Date.now()}_${(0, import_crypto13.randomBytes)(4).toString("hex")}`;
|
|
542
543
|
const now = /* @__PURE__ */ new Date();
|
|
543
544
|
try {
|
|
544
545
|
const col = await this.getCollection(collection);
|
|
@@ -1107,10 +1108,11 @@ function toPoolConfig(config) {
|
|
|
1107
1108
|
}
|
|
1108
1109
|
return poolConfig;
|
|
1109
1110
|
}
|
|
1110
|
-
var PostgresDatabase, TransactionDatabase, PostgresQueryBuilder;
|
|
1111
|
+
var import_crypto22, PostgresDatabase, TransactionDatabase, PostgresQueryBuilder;
|
|
1111
1112
|
var init_PostgresDatabase = __esm({
|
|
1112
1113
|
"src/adapters/postgres/PostgresDatabase.ts"() {
|
|
1113
1114
|
"use strict";
|
|
1115
|
+
import_crypto22 = require("crypto");
|
|
1114
1116
|
PostgresDatabase = class _PostgresDatabase {
|
|
1115
1117
|
pool;
|
|
1116
1118
|
config;
|
|
@@ -1231,7 +1233,7 @@ var init_PostgresDatabase = __esm({
|
|
|
1231
1233
|
}
|
|
1232
1234
|
}
|
|
1233
1235
|
async transaction(fn) {
|
|
1234
|
-
const savepointName = `sp_${Date.now()}_${
|
|
1236
|
+
const savepointName = `sp_${Date.now()}_${(0, import_crypto22.randomBytes)(4).toString("hex")}`;
|
|
1235
1237
|
try {
|
|
1236
1238
|
await this.client.query(`SAVEPOINT ${savepointName}`);
|
|
1237
1239
|
const result = await fn(this);
|
|
@@ -1759,7 +1761,7 @@ var init_RedisCache = __esm({
|
|
|
1759
1761
|
* Create a RedisCache from configuration
|
|
1760
1762
|
*/
|
|
1761
1763
|
static async create(config) {
|
|
1762
|
-
const { default:
|
|
1764
|
+
const { default: Redis2 } = await import("ioredis");
|
|
1763
1765
|
let client;
|
|
1764
1766
|
if (config.cluster) {
|
|
1765
1767
|
const { Cluster } = await import("ioredis");
|
|
@@ -1772,7 +1774,7 @@ var init_RedisCache = __esm({
|
|
|
1772
1774
|
}
|
|
1773
1775
|
});
|
|
1774
1776
|
} else if (config.sentinel) {
|
|
1775
|
-
client = new
|
|
1777
|
+
client = new Redis2({
|
|
1776
1778
|
sentinels: config.sentinel.sentinels,
|
|
1777
1779
|
name: config.sentinel.name,
|
|
1778
1780
|
password: config.password,
|
|
@@ -1781,7 +1783,7 @@ var init_RedisCache = __esm({
|
|
|
1781
1783
|
});
|
|
1782
1784
|
} else {
|
|
1783
1785
|
const options = toIORedisOptions(config);
|
|
1784
|
-
client = typeof options === "string" ? new
|
|
1786
|
+
client = typeof options === "string" ? new Redis2(options) : new Redis2(options);
|
|
1785
1787
|
}
|
|
1786
1788
|
if (!config.lazyConnect) {
|
|
1787
1789
|
await new Promise((resolve, reject) => {
|
|
@@ -1915,9 +1917,9 @@ var init_RedisCache = __esm({
|
|
|
1915
1917
|
}
|
|
1916
1918
|
async subscribe(channel, callback) {
|
|
1917
1919
|
if (!this.subscriberClient) {
|
|
1918
|
-
const { default:
|
|
1920
|
+
const { default: Redis2 } = await import("ioredis");
|
|
1919
1921
|
const options = toIORedisOptions(this.config);
|
|
1920
|
-
this.subscriberClient = typeof options === "string" ? new
|
|
1922
|
+
this.subscriberClient = typeof options === "string" ? new Redis2(options) : new Redis2(options);
|
|
1921
1923
|
this.subscriberClient.on("message", (ch, message) => {
|
|
1922
1924
|
const callbacks = this.subscriptions.get(ch);
|
|
1923
1925
|
if (callbacks) {
|
|
@@ -5470,11 +5472,12 @@ __export(PineconeRAG_exports, {
|
|
|
5470
5472
|
function createPineconeRAG(config) {
|
|
5471
5473
|
return new PineconeRAG(config);
|
|
5472
5474
|
}
|
|
5473
|
-
var PineconeRAG;
|
|
5475
|
+
var import_crypto23, PineconeRAG;
|
|
5474
5476
|
var init_PineconeRAG = __esm({
|
|
5475
5477
|
"src/adapters/pinecone/PineconeRAG.ts"() {
|
|
5476
5478
|
"use strict";
|
|
5477
5479
|
init_IRAG();
|
|
5480
|
+
import_crypto23 = require("crypto");
|
|
5478
5481
|
PineconeRAG = class {
|
|
5479
5482
|
client = null;
|
|
5480
5483
|
index = null;
|
|
@@ -5624,7 +5627,7 @@ var init_PineconeRAG = __esm({
|
|
|
5624
5627
|
throw new Error(`Collection ${collection} not found`);
|
|
5625
5628
|
}
|
|
5626
5629
|
const now = /* @__PURE__ */ new Date();
|
|
5627
|
-
const documentId = `doc_${Date.now()}_${
|
|
5630
|
+
const documentId = `doc_${Date.now()}_${(0, import_crypto23.randomBytes)(4).toString("hex")}`;
|
|
5628
5631
|
const doc = {
|
|
5629
5632
|
id: documentId,
|
|
5630
5633
|
source: document.source,
|
|
@@ -6191,11 +6194,12 @@ __export(WeaviateRAG_exports, {
|
|
|
6191
6194
|
function createWeaviateRAG(config) {
|
|
6192
6195
|
return new WeaviateRAG(config);
|
|
6193
6196
|
}
|
|
6194
|
-
var WeaviateRAG;
|
|
6197
|
+
var import_crypto24, WeaviateRAG;
|
|
6195
6198
|
var init_WeaviateRAG = __esm({
|
|
6196
6199
|
"src/adapters/weaviate/WeaviateRAG.ts"() {
|
|
6197
6200
|
"use strict";
|
|
6198
6201
|
init_IRAG();
|
|
6202
|
+
import_crypto24 = require("crypto");
|
|
6199
6203
|
WeaviateRAG = class {
|
|
6200
6204
|
client = null;
|
|
6201
6205
|
config;
|
|
@@ -6382,7 +6386,7 @@ var init_WeaviateRAG = __esm({
|
|
|
6382
6386
|
const client = await this.getClient();
|
|
6383
6387
|
const className = this.getClassName(collection);
|
|
6384
6388
|
const now = /* @__PURE__ */ new Date();
|
|
6385
|
-
const documentId = `doc_${Date.now()}_${
|
|
6389
|
+
const documentId = `doc_${Date.now()}_${(0, import_crypto24.randomBytes)(4).toString("hex")}`;
|
|
6386
6390
|
const doc = {
|
|
6387
6391
|
id: documentId,
|
|
6388
6392
|
source: document.source,
|
|
@@ -6957,6 +6961,175 @@ var init_WeaviateRAG = __esm({
|
|
|
6957
6961
|
}
|
|
6958
6962
|
});
|
|
6959
6963
|
|
|
6964
|
+
// src/adapters/node-crypto/NodeCrypto.ts
|
|
6965
|
+
var NodeCrypto_exports = {};
|
|
6966
|
+
__export(NodeCrypto_exports, {
|
|
6967
|
+
NodeCrypto: () => NodeCrypto
|
|
6968
|
+
});
|
|
6969
|
+
var import_crypto25, NodeCrypto;
|
|
6970
|
+
var init_NodeCrypto = __esm({
|
|
6971
|
+
"src/adapters/node-crypto/NodeCrypto.ts"() {
|
|
6972
|
+
"use strict";
|
|
6973
|
+
import_crypto25 = require("crypto");
|
|
6974
|
+
NodeCrypto = class {
|
|
6975
|
+
masterKey;
|
|
6976
|
+
hmacKey;
|
|
6977
|
+
keys = /* @__PURE__ */ new Map();
|
|
6978
|
+
activeKeyId;
|
|
6979
|
+
keyCounter = 0;
|
|
6980
|
+
constructor(config) {
|
|
6981
|
+
if (!config.masterKey || config.masterKey.length < 64) {
|
|
6982
|
+
throw new Error(
|
|
6983
|
+
"NodeCrypto requires a 256-bit master key (64 hex characters)"
|
|
6984
|
+
);
|
|
6985
|
+
}
|
|
6986
|
+
this.masterKey = Buffer.from(config.masterKey, "hex");
|
|
6987
|
+
this.hmacKey = config.hmacKey ? Buffer.from(config.hmacKey, "hex") : Buffer.from((0, import_crypto25.hkdfSync)("sha256", this.masterKey, "", "hmac-key", 32));
|
|
6988
|
+
const keyId = this.generateKeyId();
|
|
6989
|
+
const dek = this.deriveDEK(keyId);
|
|
6990
|
+
this.keys.set(keyId, {
|
|
6991
|
+
id: keyId,
|
|
6992
|
+
dek,
|
|
6993
|
+
status: "active",
|
|
6994
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
6995
|
+
});
|
|
6996
|
+
this.activeKeyId = keyId;
|
|
6997
|
+
}
|
|
6998
|
+
async encrypt(plaintext, options) {
|
|
6999
|
+
const keyId = options?.keyId || this.activeKeyId;
|
|
7000
|
+
const stored = this.keys.get(keyId);
|
|
7001
|
+
if (!stored) {
|
|
7002
|
+
throw new Error(`Key not found: ${keyId}`);
|
|
7003
|
+
}
|
|
7004
|
+
if (stored.status === "retired") {
|
|
7005
|
+
throw new Error(`Key is retired and cannot encrypt: ${keyId}`);
|
|
7006
|
+
}
|
|
7007
|
+
if (stored.status === "decrypt-only" && !options?.keyId) {
|
|
7008
|
+
throw new Error(`Key is decrypt-only: ${keyId}`);
|
|
7009
|
+
}
|
|
7010
|
+
const iv = (0, import_crypto25.randomBytes)(12);
|
|
7011
|
+
const cipher = (0, import_crypto25.createCipheriv)("aes-256-gcm", stored.dek, iv);
|
|
7012
|
+
if (options?.aad) {
|
|
7013
|
+
cipher.setAAD(Buffer.from(options.aad, "utf8"));
|
|
7014
|
+
}
|
|
7015
|
+
const encrypted = Buffer.concat([
|
|
7016
|
+
cipher.update(plaintext, "utf8"),
|
|
7017
|
+
cipher.final()
|
|
7018
|
+
]);
|
|
7019
|
+
const tag = cipher.getAuthTag();
|
|
7020
|
+
return {
|
|
7021
|
+
ciphertext: encrypted.toString("base64"),
|
|
7022
|
+
iv: iv.toString("base64"),
|
|
7023
|
+
tag: tag.toString("base64"),
|
|
7024
|
+
keyId,
|
|
7025
|
+
algorithm: "aes-256-gcm",
|
|
7026
|
+
version: 1
|
|
7027
|
+
};
|
|
7028
|
+
}
|
|
7029
|
+
async decrypt(field, options) {
|
|
7030
|
+
const stored = this.keys.get(field.keyId);
|
|
7031
|
+
if (!stored) {
|
|
7032
|
+
throw new Error(`Key not found: ${field.keyId}`);
|
|
7033
|
+
}
|
|
7034
|
+
if (stored.status === "retired") {
|
|
7035
|
+
throw new Error(`Key is retired and cannot decrypt: ${field.keyId}`);
|
|
7036
|
+
}
|
|
7037
|
+
const decipher = (0, import_crypto25.createDecipheriv)(
|
|
7038
|
+
"aes-256-gcm",
|
|
7039
|
+
stored.dek,
|
|
7040
|
+
Buffer.from(field.iv, "base64")
|
|
7041
|
+
);
|
|
7042
|
+
decipher.setAuthTag(Buffer.from(field.tag, "base64"));
|
|
7043
|
+
if (options?.aad) {
|
|
7044
|
+
decipher.setAAD(Buffer.from(options.aad, "utf8"));
|
|
7045
|
+
}
|
|
7046
|
+
const decrypted = Buffer.concat([
|
|
7047
|
+
decipher.update(Buffer.from(field.ciphertext, "base64")),
|
|
7048
|
+
decipher.final()
|
|
7049
|
+
]);
|
|
7050
|
+
return decrypted.toString("utf8");
|
|
7051
|
+
}
|
|
7052
|
+
async encryptDeterministic(plaintext, options) {
|
|
7053
|
+
const hash = await this.computeHash(plaintext);
|
|
7054
|
+
const encrypted = await this.encrypt(plaintext, options);
|
|
7055
|
+
return { hash, encrypted };
|
|
7056
|
+
}
|
|
7057
|
+
async computeHash(plaintext) {
|
|
7058
|
+
return (0, import_crypto25.createHmac)("sha256", this.hmacKey).update(plaintext, "utf8").digest("hex");
|
|
7059
|
+
}
|
|
7060
|
+
async encryptBatch(fields, options) {
|
|
7061
|
+
const result = {};
|
|
7062
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
7063
|
+
result[key] = await this.encrypt(value, options);
|
|
7064
|
+
}
|
|
7065
|
+
return result;
|
|
7066
|
+
}
|
|
7067
|
+
async decryptBatch(fields, options) {
|
|
7068
|
+
const result = {};
|
|
7069
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
7070
|
+
result[key] = await this.decrypt(value, options);
|
|
7071
|
+
}
|
|
7072
|
+
return result;
|
|
7073
|
+
}
|
|
7074
|
+
async rotateKey() {
|
|
7075
|
+
const previousKeyId = this.activeKeyId;
|
|
7076
|
+
const currentKey = this.keys.get(previousKeyId);
|
|
7077
|
+
if (currentKey) {
|
|
7078
|
+
currentKey.status = "decrypt-only";
|
|
7079
|
+
}
|
|
7080
|
+
const newKeyId = this.generateKeyId();
|
|
7081
|
+
const dek = this.deriveDEK(newKeyId);
|
|
7082
|
+
this.keys.set(newKeyId, {
|
|
7083
|
+
id: newKeyId,
|
|
7084
|
+
dek,
|
|
7085
|
+
status: "active",
|
|
7086
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
7087
|
+
});
|
|
7088
|
+
this.activeKeyId = newKeyId;
|
|
7089
|
+
return { newKeyId, previousKeyId };
|
|
7090
|
+
}
|
|
7091
|
+
async reEncrypt(field, options) {
|
|
7092
|
+
const plaintext = await this.decrypt(field);
|
|
7093
|
+
return this.encrypt(plaintext, options);
|
|
7094
|
+
}
|
|
7095
|
+
async listKeys() {
|
|
7096
|
+
return Array.from(this.keys.values()).map((k) => ({
|
|
7097
|
+
keyId: k.id,
|
|
7098
|
+
createdAt: k.createdAt,
|
|
7099
|
+
status: k.status
|
|
7100
|
+
}));
|
|
7101
|
+
}
|
|
7102
|
+
async getActiveKeyId() {
|
|
7103
|
+
return this.activeKeyId;
|
|
7104
|
+
}
|
|
7105
|
+
async healthCheck() {
|
|
7106
|
+
try {
|
|
7107
|
+
const testPlain = "health-check-" + (0, import_crypto25.randomBytes)(4).toString("hex");
|
|
7108
|
+
const encrypted = await this.encrypt(testPlain);
|
|
7109
|
+
const decrypted = await this.decrypt(encrypted);
|
|
7110
|
+
return decrypted === testPlain;
|
|
7111
|
+
} catch {
|
|
7112
|
+
return false;
|
|
7113
|
+
}
|
|
7114
|
+
}
|
|
7115
|
+
/**
|
|
7116
|
+
* Derive a Data Encryption Key from the master key using HKDF.
|
|
7117
|
+
*/
|
|
7118
|
+
deriveDEK(keyId) {
|
|
7119
|
+
return Buffer.from(
|
|
7120
|
+
(0, import_crypto25.hkdfSync)("sha256", this.masterKey, keyId, "dek-derivation", 32)
|
|
7121
|
+
);
|
|
7122
|
+
}
|
|
7123
|
+
generateKeyId() {
|
|
7124
|
+
this.keyCounter++;
|
|
7125
|
+
const timestamp = Date.now().toString(36);
|
|
7126
|
+
const random = (0, import_crypto25.randomBytes)(4).toString("hex");
|
|
7127
|
+
return `dek_${timestamp}_${random}_${this.keyCounter}`;
|
|
7128
|
+
}
|
|
7129
|
+
};
|
|
7130
|
+
}
|
|
7131
|
+
});
|
|
7132
|
+
|
|
6960
7133
|
// src/index.ts
|
|
6961
7134
|
var src_exports = {};
|
|
6962
7135
|
__export(src_exports, {
|
|
@@ -6981,9 +7154,11 @@ __export(src_exports, {
|
|
|
6981
7154
|
CircuitBreakerRegistry: () => CircuitBreakerRegistry,
|
|
6982
7155
|
CircuitOpenError: () => CircuitOpenError,
|
|
6983
7156
|
CommonApiErrors: () => CommonApiErrors,
|
|
7157
|
+
CommonRateLimits: () => CommonRateLimits,
|
|
6984
7158
|
ConsoleEmail: () => ConsoleEmail,
|
|
6985
7159
|
ConsoleLogger: () => ConsoleLogger,
|
|
6986
7160
|
CronPresets: () => CronPresets,
|
|
7161
|
+
CryptoConfigSchema: () => CryptoConfigSchema,
|
|
6987
7162
|
DEFAULT_BULKHEAD_OPTIONS: () => DEFAULT_BULKHEAD_OPTIONS,
|
|
6988
7163
|
DEFAULT_CIRCUIT_BREAKER_OPTIONS: () => DEFAULT_CIRCUIT_BREAKER_OPTIONS,
|
|
6989
7164
|
DEFAULT_RETRY_OPTIONS: () => DEFAULT_RETRY_OPTIONS,
|
|
@@ -6996,17 +7171,21 @@ __export(src_exports, {
|
|
|
6996
7171
|
DatabaseNotification: () => DatabaseNotification,
|
|
6997
7172
|
DatabasePromptStore: () => DatabasePromptStore,
|
|
6998
7173
|
DatabaseProviderSchema: () => DatabaseProviderSchema,
|
|
7174
|
+
DateRangeSchema: () => DateRangeSchema,
|
|
6999
7175
|
DefaultTimeouts: () => DefaultTimeouts,
|
|
7000
7176
|
EmailConfigSchema: () => EmailConfigSchema,
|
|
7001
7177
|
EmailProviderSchema: () => EmailProviderSchema,
|
|
7178
|
+
EmailSchema: () => EmailSchema,
|
|
7002
7179
|
EnvSecrets: () => EnvSecrets,
|
|
7003
7180
|
FallbackStrategies: () => FallbackStrategies,
|
|
7004
7181
|
GenericOIDCAuthSSO: () => GenericOIDCAuthSSO,
|
|
7005
7182
|
GoogleAIAdapter: () => GoogleAIAdapter,
|
|
7006
7183
|
HTML_TAG_PATTERN: () => HTML_TAG_PATTERN,
|
|
7007
7184
|
HttpWebhook: () => HttpWebhook,
|
|
7185
|
+
KEYCLOAK_DEFAULT_ROLES: () => KEYCLOAK_DEFAULT_ROLES,
|
|
7008
7186
|
LogLevelSchema: () => LogLevelSchema,
|
|
7009
7187
|
LoggingConfigSchema: () => LoggingConfigSchema,
|
|
7188
|
+
LoginSchema: () => LoginSchema,
|
|
7010
7189
|
MemoryAI: () => MemoryAI,
|
|
7011
7190
|
MemoryAIUsage: () => MemoryAIUsage,
|
|
7012
7191
|
MemoryAuditLog: () => MemoryAuditLog,
|
|
@@ -7015,6 +7194,7 @@ __export(src_exports, {
|
|
|
7015
7194
|
MemoryBilling: () => MemoryBilling,
|
|
7016
7195
|
MemoryCache: () => MemoryCache,
|
|
7017
7196
|
MemoryCompliance: () => MemoryCompliance,
|
|
7197
|
+
MemoryCrypto: () => MemoryCrypto,
|
|
7018
7198
|
MemoryDatabase: () => MemoryDatabase,
|
|
7019
7199
|
MemoryDevPortal: () => MemoryDevPortal,
|
|
7020
7200
|
MemoryDevice: () => MemoryDevice,
|
|
@@ -7036,6 +7216,7 @@ __export(src_exports, {
|
|
|
7036
7216
|
MetricsConfigSchema: () => MetricsConfigSchema,
|
|
7037
7217
|
MiddlewareConfigSchema: () => MiddlewareConfigSchema,
|
|
7038
7218
|
Migrator: () => Migrator,
|
|
7219
|
+
NodeCrypto: () => NodeCrypto,
|
|
7039
7220
|
NoopLogger: () => NoopLogger,
|
|
7040
7221
|
NoopMetrics: () => NoopMetrics,
|
|
7041
7222
|
NoopTracing: () => NoopTracing,
|
|
@@ -7043,7 +7224,11 @@ __export(src_exports, {
|
|
|
7043
7224
|
ObservabilityConfigSchema: () => ObservabilityConfigSchema,
|
|
7044
7225
|
OpenAIAdapter: () => OpenAIAdapter,
|
|
7045
7226
|
PG_ERROR_MAP: () => PG_ERROR_MAP,
|
|
7227
|
+
PaginationSchema: () => PaginationSchema,
|
|
7228
|
+
PasswordSchema: () => PasswordSchema,
|
|
7046
7229
|
PaymentErrorMessages: () => PaymentErrorMessages,
|
|
7230
|
+
PersonNameSchema: () => PersonNameSchema,
|
|
7231
|
+
PhoneSchema: () => PhoneSchema,
|
|
7047
7232
|
PineconeRAG: () => PineconeRAG,
|
|
7048
7233
|
PlatformConfigSchema: () => PlatformConfigSchema,
|
|
7049
7234
|
PostgresDatabase: () => PostgresDatabase,
|
|
@@ -7063,7 +7248,14 @@ __export(src_exports, {
|
|
|
7063
7248
|
RetryPredicates: () => RetryPredicates,
|
|
7064
7249
|
S3Storage: () => S3Storage,
|
|
7065
7250
|
SQL: () => SQL,
|
|
7251
|
+
SearchQuerySchema: () => SearchQuerySchema,
|
|
7252
|
+
SecurityConfigSchema: () => SecurityConfigSchema,
|
|
7253
|
+
SecurityHeaderPresets: () => SecurityHeaderPresets,
|
|
7254
|
+
SignupSchema: () => SignupSchema,
|
|
7255
|
+
SlugSchema: () => SlugSchema,
|
|
7066
7256
|
SmtpEmail: () => SmtpEmail,
|
|
7257
|
+
StandardAuditActions: () => StandardAuditActions,
|
|
7258
|
+
StandardRateLimitPresets: () => StandardRateLimitPresets,
|
|
7067
7259
|
StorageConfigSchema: () => StorageConfigSchema,
|
|
7068
7260
|
StorageProviderSchema: () => StorageProviderSchema,
|
|
7069
7261
|
StripePayment: () => StripePayment,
|
|
@@ -7079,16 +7271,32 @@ __export(src_exports, {
|
|
|
7079
7271
|
UpstashCache: () => UpstashCache,
|
|
7080
7272
|
WeaviateRAG: () => WeaviateRAG,
|
|
7081
7273
|
WebhookEventTypes: () => WebhookEventTypes,
|
|
7274
|
+
WrapperPresets: () => WrapperPresets,
|
|
7275
|
+
buildAllowlist: () => buildAllowlist,
|
|
7276
|
+
buildAuthCookies: () => buildAuthCookies,
|
|
7277
|
+
buildErrorBody: () => buildErrorBody,
|
|
7278
|
+
buildKeycloakCallbacks: () => buildKeycloakCallbacks,
|
|
7082
7279
|
buildPagination: () => buildPagination,
|
|
7280
|
+
buildRateLimitHeaders: () => buildRateLimitHeaders,
|
|
7281
|
+
buildRateLimitResponseHeaders: () => buildRateLimitResponseHeaders,
|
|
7282
|
+
buildRedirectCallback: () => buildRedirectCallback,
|
|
7283
|
+
buildTokenRefreshParams: () => buildTokenRefreshParams,
|
|
7083
7284
|
calculateBackoff: () => calculateBackoff,
|
|
7084
7285
|
calculateRetryDelay: () => calculateRetryDelay,
|
|
7286
|
+
checkEnvVars: () => checkEnvVars,
|
|
7287
|
+
checkRateLimit: () => checkRateLimit,
|
|
7085
7288
|
classifyError: () => classifyError,
|
|
7289
|
+
closeSharedRedis: () => closeSharedRedis,
|
|
7086
7290
|
composeHookRegistries: () => composeHookRegistries,
|
|
7291
|
+
constantTimeEqual: () => constantTimeEqual,
|
|
7087
7292
|
containsHtml: () => containsHtml,
|
|
7088
7293
|
containsUrls: () => containsUrls,
|
|
7089
7294
|
correlationContext: () => correlationContext,
|
|
7090
7295
|
createAIError: () => createAIError,
|
|
7091
7296
|
createAnthropicAdapter: () => createAnthropicAdapter,
|
|
7297
|
+
createAppLogger: () => createAppLogger,
|
|
7298
|
+
createAuditActor: () => createAuditActor,
|
|
7299
|
+
createAuditLogger: () => createAuditLogger,
|
|
7092
7300
|
createAuthError: () => createAuthError,
|
|
7093
7301
|
createBulkhead: () => createBulkhead,
|
|
7094
7302
|
createCacheMiddleware: () => createCacheMiddleware,
|
|
@@ -7099,6 +7307,7 @@ __export(src_exports, {
|
|
|
7099
7307
|
createErrorReport: () => createErrorReport,
|
|
7100
7308
|
createExpressHealthHandlers: () => createExpressHealthHandlers,
|
|
7101
7309
|
createExpressMetricsHandler: () => createExpressMetricsHandler,
|
|
7310
|
+
createFeatureFlags: () => createFeatureFlags,
|
|
7102
7311
|
createGoogleAIAdapter: () => createGoogleAIAdapter,
|
|
7103
7312
|
createHealthEndpoints: () => createHealthEndpoints,
|
|
7104
7313
|
createHealthServer: () => createHealthServer,
|
|
@@ -7106,6 +7315,7 @@ __export(src_exports, {
|
|
|
7106
7315
|
createIpKeyGenerator: () => createIpKeyGenerator,
|
|
7107
7316
|
createJobContext: () => createJobContext,
|
|
7108
7317
|
createLoggingMiddleware: () => createLoggingMiddleware,
|
|
7318
|
+
createMemoryRateLimitStore: () => createMemoryRateLimitStore,
|
|
7109
7319
|
createMetricsEndpoint: () => createMetricsEndpoint,
|
|
7110
7320
|
createMetricsMiddleware: () => createMetricsMiddleware,
|
|
7111
7321
|
createMetricsServer: () => createMetricsServer,
|
|
@@ -7119,8 +7329,10 @@ __export(src_exports, {
|
|
|
7119
7329
|
createPlatform: () => createPlatform,
|
|
7120
7330
|
createPlatformAsync: () => createPlatformAsync,
|
|
7121
7331
|
createRateLimitMiddleware: () => createRateLimitMiddleware,
|
|
7332
|
+
createRedisClient: () => createRedisClient,
|
|
7122
7333
|
createRequestContext: () => createRequestContext,
|
|
7123
7334
|
createRequestIdMiddleware: () => createRequestIdMiddleware,
|
|
7335
|
+
createSafeTextSchema: () => createSafeTextSchema,
|
|
7124
7336
|
createScopedMetrics: () => createScopedMetrics,
|
|
7125
7337
|
createSlowQueryMiddleware: () => createSlowQueryMiddleware,
|
|
7126
7338
|
createSsoOidcConfigsTable: () => createSsoOidcConfigsTable,
|
|
@@ -7137,8 +7349,13 @@ __export(src_exports, {
|
|
|
7137
7349
|
defangUrl: () => defangUrl,
|
|
7138
7350
|
defineMigration: () => defineMigration,
|
|
7139
7351
|
describeCron: () => describeCron,
|
|
7352
|
+
detectStage: () => detectStage,
|
|
7140
7353
|
enterpriseMigrations: () => enterpriseMigrations,
|
|
7141
7354
|
escapeHtml: () => escapeHtml,
|
|
7355
|
+
extractAuditIp: () => extractAuditIp,
|
|
7356
|
+
extractAuditRequestId: () => extractAuditRequestId,
|
|
7357
|
+
extractAuditUserAgent: () => extractAuditUserAgent,
|
|
7358
|
+
extractClientIp: () => extractClientIp,
|
|
7142
7359
|
filterChannelsByPreferences: () => filterChannelsByPreferences,
|
|
7143
7360
|
formatAmount: () => formatAmount,
|
|
7144
7361
|
generateAuditId: () => generateAuditId,
|
|
@@ -7152,40 +7369,62 @@ __export(src_exports, {
|
|
|
7152
7369
|
generatePaymentId: () => generatePaymentId,
|
|
7153
7370
|
generateScheduleId: () => generateScheduleId,
|
|
7154
7371
|
generateSecureToken: () => generateSecureToken,
|
|
7372
|
+
generateSecurityHeaders: () => generateSecurityHeaders,
|
|
7155
7373
|
generateVersion: () => generateVersion,
|
|
7156
7374
|
generateWebhookId: () => generateWebhookId,
|
|
7157
7375
|
generateWebhookSecret: () => generateWebhookSecret,
|
|
7376
|
+
getBoolEnv: () => getBoolEnv,
|
|
7158
7377
|
getContext: () => getContext,
|
|
7159
|
-
getCorrelationId: () =>
|
|
7378
|
+
getCorrelationId: () => getCorrelationId2,
|
|
7160
7379
|
getDefaultConfig: () => getDefaultConfig,
|
|
7380
|
+
getEndSessionEndpoint: () => getEndSessionEndpoint,
|
|
7161
7381
|
getEnterpriseMigrations: () => getEnterpriseMigrations,
|
|
7382
|
+
getEnvSummary: () => getEnvSummary,
|
|
7383
|
+
getIntEnv: () => getIntEnv,
|
|
7162
7384
|
getLogMeta: () => getLogMeta,
|
|
7163
7385
|
getNextCronRun: () => getNextCronRun,
|
|
7386
|
+
getOptionalEnv: () => getOptionalEnv,
|
|
7387
|
+
getRateLimitStatus: () => getRateLimitStatus,
|
|
7164
7388
|
getRequestId: () => getRequestId,
|
|
7389
|
+
getRequiredEnv: () => getRequiredEnv,
|
|
7390
|
+
getSharedRedis: () => getSharedRedis,
|
|
7165
7391
|
getTenantId: () => getTenantId,
|
|
7392
|
+
getTokenEndpoint: () => getTokenEndpoint,
|
|
7166
7393
|
getTraceId: () => getTraceId,
|
|
7167
7394
|
getUserId: () => getUserId,
|
|
7395
|
+
hasAllRoles: () => hasAllRoles,
|
|
7396
|
+
hasAnyRole: () => hasAnyRole,
|
|
7397
|
+
hasRole: () => hasRole,
|
|
7168
7398
|
isAIError: () => isAIError,
|
|
7399
|
+
isAllowlisted: () => isAllowlisted,
|
|
7169
7400
|
isApiError: () => isApiError,
|
|
7170
7401
|
isAuthError: () => isAuthError,
|
|
7171
7402
|
isInContext: () => isInContext,
|
|
7172
7403
|
isInQuietHours: () => isInQuietHours,
|
|
7173
7404
|
isPaymentError: () => isPaymentError,
|
|
7405
|
+
isTokenExpired: () => isTokenExpired,
|
|
7174
7406
|
isValidCron: () => isValidCron,
|
|
7175
7407
|
loadConfig: () => loadConfig,
|
|
7176
7408
|
matchAction: () => matchAction,
|
|
7177
7409
|
matchEventType: () => matchEventType,
|
|
7410
|
+
parseKeycloakRoles: () => parseKeycloakRoles,
|
|
7178
7411
|
raceTimeout: () => raceTimeout,
|
|
7412
|
+
refreshKeycloakToken: () => refreshKeycloakToken,
|
|
7413
|
+
resetRateLimitForKey: () => resetRateLimitForKey,
|
|
7414
|
+
resolveIdentifier: () => resolveIdentifier,
|
|
7415
|
+
resolveRateLimitIdentifier: () => resolveRateLimitIdentifier,
|
|
7179
7416
|
retryable: () => retryable,
|
|
7180
7417
|
runWithContext: () => runWithContext,
|
|
7181
7418
|
runWithContextAsync: () => runWithContextAsync,
|
|
7182
7419
|
safeValidateConfig: () => safeValidateConfig,
|
|
7420
|
+
sanitizeApiError: () => sanitizeApiError,
|
|
7183
7421
|
sanitizeForEmail: () => sanitizeForEmail,
|
|
7184
7422
|
sqlMigration: () => sqlMigration,
|
|
7185
7423
|
stripHtml: () => stripHtml,
|
|
7186
7424
|
timedHealthCheck: () => timedHealthCheck,
|
|
7187
7425
|
toHealthCheckResult: () => toHealthCheckResult,
|
|
7188
7426
|
validateConfig: () => validateConfig,
|
|
7427
|
+
validateEnvVars: () => validateEnvVars,
|
|
7189
7428
|
withCorrelation: () => withCorrelation,
|
|
7190
7429
|
withCorrelationAsync: () => withCorrelationAsync,
|
|
7191
7430
|
withFallback: () => withFallback,
|
|
@@ -7199,6 +7438,7 @@ __export(src_exports, {
|
|
|
7199
7438
|
module.exports = __toCommonJS(src_exports);
|
|
7200
7439
|
|
|
7201
7440
|
// src/interfaces/IQueue.ts
|
|
7441
|
+
var import_crypto = require("crypto");
|
|
7202
7442
|
function calculateBackoff(attempt, options) {
|
|
7203
7443
|
if (options.type === "fixed") {
|
|
7204
7444
|
return options.delay;
|
|
@@ -7209,7 +7449,7 @@ function calculateBackoff(attempt, options) {
|
|
|
7209
7449
|
}
|
|
7210
7450
|
function generateJobId() {
|
|
7211
7451
|
const timestamp = Date.now().toString(36);
|
|
7212
|
-
const random =
|
|
7452
|
+
const random = (0, import_crypto.randomBytes)(4).toString("hex");
|
|
7213
7453
|
return `job_${timestamp}_${random}`;
|
|
7214
7454
|
}
|
|
7215
7455
|
|
|
@@ -7560,6 +7800,7 @@ function createScopedMetrics(metrics, prefix, defaultTags = {}) {
|
|
|
7560
7800
|
}
|
|
7561
7801
|
|
|
7562
7802
|
// src/interfaces/ISecrets.ts
|
|
7803
|
+
var import_crypto2 = require("crypto");
|
|
7563
7804
|
var EnvSecrets = class {
|
|
7564
7805
|
prefix;
|
|
7565
7806
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -7760,12 +8001,7 @@ var MemorySecrets = class {
|
|
|
7760
8001
|
return true;
|
|
7761
8002
|
}
|
|
7762
8003
|
generateSecureValue(length = 32) {
|
|
7763
|
-
|
|
7764
|
-
let result = "";
|
|
7765
|
-
for (let i = 0; i < length; i++) {
|
|
7766
|
-
result += chars[Math.floor(Math.random() * chars.length)];
|
|
7767
|
-
}
|
|
7768
|
-
return result;
|
|
8004
|
+
return (0, import_crypto2.randomBytes)(length).toString("base64url").slice(0, length);
|
|
7769
8005
|
}
|
|
7770
8006
|
/**
|
|
7771
8007
|
* Clear all secrets (for testing)
|
|
@@ -7783,6 +8019,7 @@ var MemorySecrets = class {
|
|
|
7783
8019
|
};
|
|
7784
8020
|
|
|
7785
8021
|
// src/interfaces/ITracing.ts
|
|
8022
|
+
var import_crypto3 = require("crypto");
|
|
7786
8023
|
var MemorySpan = class {
|
|
7787
8024
|
name;
|
|
7788
8025
|
context;
|
|
@@ -7802,7 +8039,7 @@ var MemorySpan = class {
|
|
|
7802
8039
|
};
|
|
7803
8040
|
}
|
|
7804
8041
|
generateSpanId() {
|
|
7805
|
-
return
|
|
8042
|
+
return (0, import_crypto3.randomBytes)(8).toString("hex");
|
|
7806
8043
|
}
|
|
7807
8044
|
setAttribute(key, value) {
|
|
7808
8045
|
this._attributes[key] = value;
|
|
@@ -7862,7 +8099,7 @@ var MemoryTracing = class {
|
|
|
7862
8099
|
this.traceId = this.generateTraceId();
|
|
7863
8100
|
}
|
|
7864
8101
|
generateTraceId() {
|
|
7865
|
-
return
|
|
8102
|
+
return (0, import_crypto3.randomBytes)(16).toString("hex");
|
|
7866
8103
|
}
|
|
7867
8104
|
startSpan(name, options) {
|
|
7868
8105
|
const span = new MemorySpan(
|
|
@@ -8015,9 +8252,10 @@ var NoopTracing = class {
|
|
|
8015
8252
|
};
|
|
8016
8253
|
|
|
8017
8254
|
// src/interfaces/IErrorReporter.ts
|
|
8255
|
+
var import_crypto4 = require("crypto");
|
|
8018
8256
|
function generateErrorId() {
|
|
8019
8257
|
const timestamp = Date.now().toString(36);
|
|
8020
|
-
const random =
|
|
8258
|
+
const random = (0, import_crypto4.randomBytes)(4).toString("hex");
|
|
8021
8259
|
return `err_${timestamp}_${random}`;
|
|
8022
8260
|
}
|
|
8023
8261
|
function generateFingerprint(error) {
|
|
@@ -8061,9 +8299,10 @@ function createErrorReport(error, context, options) {
|
|
|
8061
8299
|
}
|
|
8062
8300
|
|
|
8063
8301
|
// src/interfaces/IAuditLog.ts
|
|
8302
|
+
var import_crypto5 = require("crypto");
|
|
8064
8303
|
function generateAuditId() {
|
|
8065
8304
|
const timestamp = Date.now().toString(36);
|
|
8066
|
-
const random =
|
|
8305
|
+
const random = (0, import_crypto5.randomBytes)(4).toString("hex");
|
|
8067
8306
|
return `aud_${timestamp}${random}`;
|
|
8068
8307
|
}
|
|
8069
8308
|
function generateChecksum(event) {
|
|
@@ -8229,9 +8468,10 @@ var AuditEvents = {
|
|
|
8229
8468
|
};
|
|
8230
8469
|
|
|
8231
8470
|
// src/interfaces/IScheduler.ts
|
|
8471
|
+
var import_crypto6 = require("crypto");
|
|
8232
8472
|
function generateScheduleId() {
|
|
8233
8473
|
const timestamp = Date.now().toString(36);
|
|
8234
|
-
const random =
|
|
8474
|
+
const random = (0, import_crypto6.randomBytes)(4).toString("hex");
|
|
8235
8475
|
return `sch_${timestamp}${random}`;
|
|
8236
8476
|
}
|
|
8237
8477
|
function getNextCronRun(cron, after = /* @__PURE__ */ new Date(), timezone) {
|
|
@@ -8290,28 +8530,24 @@ function describeCron(cron) {
|
|
|
8290
8530
|
}
|
|
8291
8531
|
|
|
8292
8532
|
// src/interfaces/IWebhook.ts
|
|
8533
|
+
var import_crypto7 = require("crypto");
|
|
8293
8534
|
function generateWebhookId() {
|
|
8294
8535
|
const timestamp = Date.now().toString(36);
|
|
8295
|
-
const random =
|
|
8536
|
+
const random = (0, import_crypto7.randomBytes)(6).toString("hex");
|
|
8296
8537
|
return `wh_${timestamp}${random}`;
|
|
8297
8538
|
}
|
|
8298
8539
|
function generateDeliveryId() {
|
|
8299
8540
|
const timestamp = Date.now().toString(36);
|
|
8300
|
-
const random =
|
|
8541
|
+
const random = (0, import_crypto7.randomBytes)(6).toString("hex");
|
|
8301
8542
|
return `del_${timestamp}${random}`;
|
|
8302
8543
|
}
|
|
8303
8544
|
function generateEventId() {
|
|
8304
8545
|
const timestamp = Date.now().toString(36);
|
|
8305
|
-
const random =
|
|
8546
|
+
const random = (0, import_crypto7.randomBytes)(6).toString("hex");
|
|
8306
8547
|
return `evt_${timestamp}${random}`;
|
|
8307
8548
|
}
|
|
8308
8549
|
function generateWebhookSecret(length = 32) {
|
|
8309
|
-
|
|
8310
|
-
let secret = "whsec_";
|
|
8311
|
-
for (let i = 0; i < length; i++) {
|
|
8312
|
-
secret += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
8313
|
-
}
|
|
8314
|
-
return secret;
|
|
8550
|
+
return `whsec_${(0, import_crypto7.randomBytes)(length).toString("base64url").slice(0, length)}`;
|
|
8315
8551
|
}
|
|
8316
8552
|
function matchEventType(eventType, pattern) {
|
|
8317
8553
|
if (eventType === pattern || pattern === "*" || pattern === "**") {
|
|
@@ -8388,9 +8624,10 @@ var WebhookEventTypes = {
|
|
|
8388
8624
|
};
|
|
8389
8625
|
|
|
8390
8626
|
// src/interfaces/INotification.ts
|
|
8627
|
+
var import_crypto8 = require("crypto");
|
|
8391
8628
|
function generateNotificationId() {
|
|
8392
8629
|
const timestamp = Date.now().toString(36);
|
|
8393
|
-
const random =
|
|
8630
|
+
const random = (0, import_crypto8.randomBytes)(4).toString("hex");
|
|
8394
8631
|
return `notif_${timestamp}${random}`;
|
|
8395
8632
|
}
|
|
8396
8633
|
function isInQuietHours(preferences) {
|
|
@@ -8880,6 +9117,7 @@ var MemoryAuth = class {
|
|
|
8880
9117
|
};
|
|
8881
9118
|
|
|
8882
9119
|
// src/interfaces/IPayment.ts
|
|
9120
|
+
var import_crypto9 = require("crypto");
|
|
8883
9121
|
function createPaymentError(code, message, originalError) {
|
|
8884
9122
|
return { code, message, originalError };
|
|
8885
9123
|
}
|
|
@@ -8911,7 +9149,7 @@ function formatAmount(amount, currency, locale = "en-US") {
|
|
|
8911
9149
|
}
|
|
8912
9150
|
function generatePaymentId(prefix = "pi") {
|
|
8913
9151
|
const timestamp = Date.now().toString(36);
|
|
8914
|
-
const random =
|
|
9152
|
+
const random = (0, import_crypto9.randomBytes)(8).toString("hex");
|
|
8915
9153
|
return `${prefix}_${timestamp}${random}`;
|
|
8916
9154
|
}
|
|
8917
9155
|
var MemoryPayment = class {
|
|
@@ -8969,7 +9207,7 @@ var MemoryPayment = class {
|
|
|
8969
9207
|
amount: options.amount,
|
|
8970
9208
|
currency: options.currency,
|
|
8971
9209
|
status: options.paymentMethodId ? "requires_confirmation" : "requires_payment_method",
|
|
8972
|
-
clientSecret: `${id}_secret_${
|
|
9210
|
+
clientSecret: `${id}_secret_${(0, import_crypto9.randomBytes)(16).toString("base64url")}`,
|
|
8973
9211
|
metadata: options.metadata,
|
|
8974
9212
|
description: options.description,
|
|
8975
9213
|
receiptEmail: options.receiptEmail,
|
|
@@ -9284,6 +9522,7 @@ var MemoryPayment = class {
|
|
|
9284
9522
|
};
|
|
9285
9523
|
|
|
9286
9524
|
// src/interfaces/IAuthSSO.ts
|
|
9525
|
+
var import_crypto10 = require("crypto");
|
|
9287
9526
|
var MemoryAuthSSO = class {
|
|
9288
9527
|
samlConfigs = /* @__PURE__ */ new Map();
|
|
9289
9528
|
oidcConfigs = /* @__PURE__ */ new Map();
|
|
@@ -9315,7 +9554,7 @@ var MemoryAuthSSO = class {
|
|
|
9315
9554
|
if (!config) {
|
|
9316
9555
|
throw new Error("SAML not configured for tenant");
|
|
9317
9556
|
}
|
|
9318
|
-
const id = `_${
|
|
9557
|
+
const id = `_${(0, import_crypto10.randomBytes)(8).toString("hex")}`;
|
|
9319
9558
|
return {
|
|
9320
9559
|
id,
|
|
9321
9560
|
redirectUrl: `${config.ssoUrl}?SAMLRequest=mock_request&RelayState=${options.relayState ?? ""}`,
|
|
@@ -9327,7 +9566,7 @@ var MemoryAuthSSO = class {
|
|
|
9327
9566
|
}
|
|
9328
9567
|
async processSamlResponse(_samlResponse, _relayState) {
|
|
9329
9568
|
const user = {
|
|
9330
|
-
id: `saml_${
|
|
9569
|
+
id: `saml_${(0, import_crypto10.randomBytes)(8).toString("hex")}`,
|
|
9331
9570
|
email: "saml.user@example.com",
|
|
9332
9571
|
emailVerified: true,
|
|
9333
9572
|
metadata: { ssoProvider: "saml" },
|
|
@@ -9337,7 +9576,7 @@ var MemoryAuthSSO = class {
|
|
|
9337
9576
|
success: true,
|
|
9338
9577
|
user,
|
|
9339
9578
|
session: {
|
|
9340
|
-
accessToken: `saml_token_${
|
|
9579
|
+
accessToken: `saml_token_${(0, import_crypto10.randomBytes)(8).toString("hex")}`,
|
|
9341
9580
|
expiresAt: new Date(Date.now() + 36e5),
|
|
9342
9581
|
user
|
|
9343
9582
|
},
|
|
@@ -9374,8 +9613,8 @@ var MemoryAuthSSO = class {
|
|
|
9374
9613
|
}
|
|
9375
9614
|
// OIDC Authentication
|
|
9376
9615
|
async initiateOidcLogin(options) {
|
|
9377
|
-
const state = options.state ??
|
|
9378
|
-
const nonce =
|
|
9616
|
+
const state = options.state ?? (0, import_crypto10.randomBytes)(8).toString("hex");
|
|
9617
|
+
const nonce = (0, import_crypto10.randomBytes)(8).toString("hex");
|
|
9379
9618
|
return {
|
|
9380
9619
|
state,
|
|
9381
9620
|
redirectUrl: `https://idp.example.com/authorize?client_id=mock&redirect_uri=${encodeURIComponent(options.redirectUri)}&state=${state}`,
|
|
@@ -9386,7 +9625,7 @@ var MemoryAuthSSO = class {
|
|
|
9386
9625
|
}
|
|
9387
9626
|
async processOidcCallback(_code, _state, _codeVerifier) {
|
|
9388
9627
|
const user = {
|
|
9389
|
-
id: `oidc_${
|
|
9628
|
+
id: `oidc_${(0, import_crypto10.randomBytes)(8).toString("hex")}`,
|
|
9390
9629
|
email: "oidc.user@example.com",
|
|
9391
9630
|
emailVerified: true,
|
|
9392
9631
|
metadata: { ssoProvider: "oidc" },
|
|
@@ -9396,7 +9635,7 @@ var MemoryAuthSSO = class {
|
|
|
9396
9635
|
success: true,
|
|
9397
9636
|
user,
|
|
9398
9637
|
session: {
|
|
9399
|
-
accessToken: `oidc_token_${
|
|
9638
|
+
accessToken: `oidc_token_${(0, import_crypto10.randomBytes)(8).toString("hex")}`,
|
|
9400
9639
|
expiresAt: new Date(Date.now() + 36e5),
|
|
9401
9640
|
user
|
|
9402
9641
|
},
|
|
@@ -9405,7 +9644,7 @@ var MemoryAuthSSO = class {
|
|
|
9405
9644
|
}
|
|
9406
9645
|
async refreshOidcTokens(_refreshToken, _tenantId) {
|
|
9407
9646
|
return {
|
|
9408
|
-
accessToken: `refreshed_token_${
|
|
9647
|
+
accessToken: `refreshed_token_${(0, import_crypto10.randomBytes)(8).toString("hex")}`,
|
|
9409
9648
|
expiresIn: 3600
|
|
9410
9649
|
};
|
|
9411
9650
|
}
|
|
@@ -9435,7 +9674,7 @@ var MemoryAuthSSO = class {
|
|
|
9435
9674
|
}
|
|
9436
9675
|
// SCIM
|
|
9437
9676
|
async configureScim(config) {
|
|
9438
|
-
const token = `scim_token_${
|
|
9677
|
+
const token = `scim_token_${(0, import_crypto10.randomBytes)(8).toString("hex")}`;
|
|
9439
9678
|
this.scimConfigs.set(config.tenantId, { ...config, bearerToken: token });
|
|
9440
9679
|
return { bearerToken: token };
|
|
9441
9680
|
}
|
|
@@ -9448,7 +9687,7 @@ var MemoryAuthSSO = class {
|
|
|
9448
9687
|
async regenerateScimToken(tenantId) {
|
|
9449
9688
|
const config = this.scimConfigs.get(tenantId);
|
|
9450
9689
|
if (!config) throw new Error("SCIM not configured");
|
|
9451
|
-
const token = `scim_token_${
|
|
9690
|
+
const token = `scim_token_${(0, import_crypto10.randomBytes)(8).toString("hex")}`;
|
|
9452
9691
|
config.bearerToken = token;
|
|
9453
9692
|
return { bearerToken: token };
|
|
9454
9693
|
}
|
|
@@ -9457,7 +9696,7 @@ var MemoryAuthSSO = class {
|
|
|
9457
9696
|
}
|
|
9458
9697
|
// Domain Verification
|
|
9459
9698
|
async initiateDomainVerification(tenantId, domain) {
|
|
9460
|
-
const token = `dll-verify-${
|
|
9699
|
+
const token = `dll-verify-${(0, import_crypto10.randomBytes)(8).toString("hex")}`;
|
|
9461
9700
|
this.pendingVerifications.set(`${tenantId}:${domain}`, { domain, token });
|
|
9462
9701
|
return {
|
|
9463
9702
|
verificationMethod: "dns_txt",
|
|
@@ -9523,6 +9762,7 @@ var MemoryAuthSSO = class {
|
|
|
9523
9762
|
};
|
|
9524
9763
|
|
|
9525
9764
|
// src/interfaces/ITenant.ts
|
|
9765
|
+
var import_crypto11 = require("crypto");
|
|
9526
9766
|
var tenantContextStorage = /* @__PURE__ */ new Map();
|
|
9527
9767
|
var contextIdCounter = 0;
|
|
9528
9768
|
var currentContextId = null;
|
|
@@ -9590,7 +9830,7 @@ var MemoryTenant = class {
|
|
|
9590
9830
|
// Tenant CRUD
|
|
9591
9831
|
async createTenant(options) {
|
|
9592
9832
|
const tenant = {
|
|
9593
|
-
id: `tenant_${
|
|
9833
|
+
id: `tenant_${(0, import_crypto11.randomBytes)(8).toString("hex")}`,
|
|
9594
9834
|
slug: options.slug,
|
|
9595
9835
|
name: options.name,
|
|
9596
9836
|
status: "active",
|
|
@@ -9711,7 +9951,7 @@ var MemoryTenant = class {
|
|
|
9711
9951
|
}
|
|
9712
9952
|
async addMember(tenantId, userId, role) {
|
|
9713
9953
|
const member = {
|
|
9714
|
-
id: `member_${
|
|
9954
|
+
id: `member_${(0, import_crypto11.randomBytes)(8).toString("hex")}`,
|
|
9715
9955
|
tenantId,
|
|
9716
9956
|
userId,
|
|
9717
9957
|
role,
|
|
@@ -9752,12 +9992,12 @@ var MemoryTenant = class {
|
|
|
9752
9992
|
}
|
|
9753
9993
|
async inviteMember(tenantId, options) {
|
|
9754
9994
|
const invitation = {
|
|
9755
|
-
id: `inv_${
|
|
9995
|
+
id: `inv_${(0, import_crypto11.randomBytes)(8).toString("hex")}`,
|
|
9756
9996
|
tenantId,
|
|
9757
9997
|
email: options.email,
|
|
9758
9998
|
role: options.role,
|
|
9759
9999
|
invitedBy: "system",
|
|
9760
|
-
token:
|
|
10000
|
+
token: (0, import_crypto11.randomBytes)(16).toString("base64url"),
|
|
9761
10001
|
status: "pending",
|
|
9762
10002
|
createdAt: /* @__PURE__ */ new Date(),
|
|
9763
10003
|
expiresAt: new Date(
|
|
@@ -9918,6 +10158,7 @@ var MemoryTenant = class {
|
|
|
9918
10158
|
init_IAI();
|
|
9919
10159
|
|
|
9920
10160
|
// src/interfaces/IPromptStore.ts
|
|
10161
|
+
var import_crypto12 = require("crypto");
|
|
9921
10162
|
var MemoryPromptStore = class {
|
|
9922
10163
|
// userId -> variantId
|
|
9923
10164
|
constructor(config = {}) {
|
|
@@ -9933,7 +10174,7 @@ var MemoryPromptStore = class {
|
|
|
9933
10174
|
// Prompt CRUD
|
|
9934
10175
|
// ─────────────────────────────────────────────────────────────
|
|
9935
10176
|
async create(prompt) {
|
|
9936
|
-
const id = `prompt_${Date.now()}_${
|
|
10177
|
+
const id = `prompt_${Date.now()}_${(0, import_crypto12.randomBytes)(4).toString("hex")}`;
|
|
9937
10178
|
const now = /* @__PURE__ */ new Date();
|
|
9938
10179
|
const newPrompt = {
|
|
9939
10180
|
...prompt,
|
|
@@ -9948,7 +10189,7 @@ var MemoryPromptStore = class {
|
|
|
9948
10189
|
this.prompts.set(id, newPrompt);
|
|
9949
10190
|
this.prompts.set(prompt.slug, newPrompt);
|
|
9950
10191
|
const version = {
|
|
9951
|
-
id: `pv_${Date.now()}_${
|
|
10192
|
+
id: `pv_${Date.now()}_${(0, import_crypto12.randomBytes)(4).toString("hex")}`,
|
|
9952
10193
|
promptId: id,
|
|
9953
10194
|
version: 1,
|
|
9954
10195
|
content: prompt.content,
|
|
@@ -9983,7 +10224,7 @@ var MemoryPromptStore = class {
|
|
|
9983
10224
|
latestVersion.isLatest = false;
|
|
9984
10225
|
}
|
|
9985
10226
|
const newVersion = {
|
|
9986
|
-
id: `pv_${Date.now()}_${
|
|
10227
|
+
id: `pv_${Date.now()}_${(0, import_crypto12.randomBytes)(4).toString("hex")}`,
|
|
9987
10228
|
promptId: prompt.id,
|
|
9988
10229
|
version: versions.length + 1,
|
|
9989
10230
|
content: updates.content,
|
|
@@ -10228,7 +10469,7 @@ ${v2.content}`;
|
|
|
10228
10469
|
// A/B Testing
|
|
10229
10470
|
// ─────────────────────────────────────────────────────────────
|
|
10230
10471
|
async createExperiment(experiment) {
|
|
10231
|
-
const id = `exp_${Date.now()}_${
|
|
10472
|
+
const id = `exp_${Date.now()}_${(0, import_crypto12.randomBytes)(4).toString("hex")}`;
|
|
10232
10473
|
const now = /* @__PURE__ */ new Date();
|
|
10233
10474
|
const newExperiment = {
|
|
10234
10475
|
...experiment,
|
|
@@ -10305,7 +10546,7 @@ ${v2.content}`;
|
|
|
10305
10546
|
// Prompt Chains
|
|
10306
10547
|
// ─────────────────────────────────────────────────────────────
|
|
10307
10548
|
async createChain(chain) {
|
|
10308
|
-
const id = `chain_${Date.now()}_${
|
|
10549
|
+
const id = `chain_${Date.now()}_${(0, import_crypto12.randomBytes)(4).toString("hex")}`;
|
|
10309
10550
|
const now = /* @__PURE__ */ new Date();
|
|
10310
10551
|
const newChain = {
|
|
10311
10552
|
...chain,
|
|
@@ -10396,7 +10637,7 @@ ${v2.content}`;
|
|
|
10396
10637
|
async recordUsage(record) {
|
|
10397
10638
|
const usageRecord = {
|
|
10398
10639
|
...record,
|
|
10399
|
-
id: `usage_${Date.now()}_${
|
|
10640
|
+
id: `usage_${Date.now()}_${(0, import_crypto12.randomBytes)(4).toString("hex")}`,
|
|
10400
10641
|
createdAt: /* @__PURE__ */ new Date()
|
|
10401
10642
|
};
|
|
10402
10643
|
if (this.config.trackUsage !== false) {
|
|
@@ -10500,6 +10741,7 @@ ${v2.content}`;
|
|
|
10500
10741
|
init_IRAG();
|
|
10501
10742
|
|
|
10502
10743
|
// src/interfaces/IAIUsage.ts
|
|
10744
|
+
var import_crypto14 = require("crypto");
|
|
10503
10745
|
var MemoryAIUsage = class {
|
|
10504
10746
|
constructor(config = {}) {
|
|
10505
10747
|
this.config = config;
|
|
@@ -10533,7 +10775,7 @@ var MemoryAIUsage = class {
|
|
|
10533
10775
|
async record(record) {
|
|
10534
10776
|
const newRecord = {
|
|
10535
10777
|
...record,
|
|
10536
|
-
id: `usage_${Date.now()}_${
|
|
10778
|
+
id: `usage_${Date.now()}_${(0, import_crypto14.randomBytes)(4).toString("hex")}`,
|
|
10537
10779
|
createdAt: /* @__PURE__ */ new Date()
|
|
10538
10780
|
};
|
|
10539
10781
|
this.records.push(newRecord);
|
|
@@ -10614,7 +10856,7 @@ var MemoryAIUsage = class {
|
|
|
10614
10856
|
const period = this.getPeriodBounds(quota.period, /* @__PURE__ */ new Date());
|
|
10615
10857
|
const newQuota = {
|
|
10616
10858
|
...quota,
|
|
10617
|
-
id: existingQuota?.id || `quota_${Date.now()}_${
|
|
10859
|
+
id: existingQuota?.id || `quota_${Date.now()}_${(0, import_crypto14.randomBytes)(4).toString("hex")}`,
|
|
10618
10860
|
used: existingQuota?.used || 0,
|
|
10619
10861
|
periodStart: period.start,
|
|
10620
10862
|
periodEnd: period.end
|
|
@@ -10708,7 +10950,7 @@ var MemoryAIUsage = class {
|
|
|
10708
10950
|
const period = this.getPeriodBounds(budget.period, /* @__PURE__ */ new Date());
|
|
10709
10951
|
const newBudget = {
|
|
10710
10952
|
...budget,
|
|
10711
|
-
id: existingBudget?.id || `budget_${Date.now()}_${
|
|
10953
|
+
id: existingBudget?.id || `budget_${Date.now()}_${(0, import_crypto14.randomBytes)(4).toString("hex")}`,
|
|
10712
10954
|
spent: existingBudget?.spent || 0,
|
|
10713
10955
|
periodStart: period.start,
|
|
10714
10956
|
periodEnd: period.end
|
|
@@ -10972,7 +11214,7 @@ var MemoryAIUsage = class {
|
|
|
10972
11214
|
const items = Array.from(itemsMap.values());
|
|
10973
11215
|
const subtotal = items.reduce((sum, item) => sum + item.costUsd, 0);
|
|
10974
11216
|
const invoice = {
|
|
10975
|
-
id: `inv_${Date.now()}_${
|
|
11217
|
+
id: `inv_${Date.now()}_${(0, import_crypto14.randomBytes)(4).toString("hex")}`,
|
|
10976
11218
|
tenantId,
|
|
10977
11219
|
periodStart,
|
|
10978
11220
|
periodEnd,
|
|
@@ -11185,7 +11427,7 @@ var MemoryAIUsage = class {
|
|
|
11185
11427
|
);
|
|
11186
11428
|
if (existingAlert) return;
|
|
11187
11429
|
this.alerts.push({
|
|
11188
|
-
id: `alert_${Date.now()}_${
|
|
11430
|
+
id: `alert_${Date.now()}_${(0, import_crypto14.randomBytes)(4).toString("hex")}`,
|
|
11189
11431
|
tenantId,
|
|
11190
11432
|
type,
|
|
11191
11433
|
severity,
|
|
@@ -11314,6 +11556,7 @@ var MemoryAIUsage = class {
|
|
|
11314
11556
|
};
|
|
11315
11557
|
|
|
11316
11558
|
// src/interfaces/IDevice.ts
|
|
11559
|
+
var import_crypto15 = require("crypto");
|
|
11317
11560
|
var MemoryDevice = class {
|
|
11318
11561
|
constructor(config = {}) {
|
|
11319
11562
|
this.config = config;
|
|
@@ -11338,7 +11581,7 @@ var MemoryDevice = class {
|
|
|
11338
11581
|
const now = /* @__PURE__ */ new Date();
|
|
11339
11582
|
const newDevice = {
|
|
11340
11583
|
...device,
|
|
11341
|
-
id: `dev_${Date.now()}_${
|
|
11584
|
+
id: `dev_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`,
|
|
11342
11585
|
status: "active",
|
|
11343
11586
|
connectionState: "disconnected",
|
|
11344
11587
|
tags: device.tags || [],
|
|
@@ -11461,7 +11704,7 @@ var MemoryDevice = class {
|
|
|
11461
11704
|
// Provisioning
|
|
11462
11705
|
// ─────────────────────────────────────────────────────────────
|
|
11463
11706
|
async provision(request) {
|
|
11464
|
-
const id = `prov_${Date.now()}_${
|
|
11707
|
+
const id = `prov_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`;
|
|
11465
11708
|
const newRequest = {
|
|
11466
11709
|
...request,
|
|
11467
11710
|
id,
|
|
@@ -11473,7 +11716,7 @@ var MemoryDevice = class {
|
|
|
11473
11716
|
const result = {
|
|
11474
11717
|
credentials: {
|
|
11475
11718
|
type: request.config.authMethod || "token",
|
|
11476
|
-
token: `tok_${Date.now()}_${
|
|
11719
|
+
token: `tok_${Date.now()}_${(0, import_crypto15.randomBytes)(16).toString("hex")}`
|
|
11477
11720
|
},
|
|
11478
11721
|
endpoint: "mqtt://localhost:1883",
|
|
11479
11722
|
mqttBroker: "mqtt://localhost:1883"
|
|
@@ -11516,7 +11759,7 @@ var MemoryDevice = class {
|
|
|
11516
11759
|
}
|
|
11517
11760
|
}
|
|
11518
11761
|
async generateRegistrationCode(deviceType, tenantId, expiresInHours = 24) {
|
|
11519
|
-
const code = `REG_${
|
|
11762
|
+
const code = `REG_${(0, import_crypto15.randomBytes)(4).toString("hex").toUpperCase()}`;
|
|
11520
11763
|
this.registrationCodes.set(code, {
|
|
11521
11764
|
deviceType,
|
|
11522
11765
|
tenantId,
|
|
@@ -11616,7 +11859,7 @@ var MemoryDevice = class {
|
|
|
11616
11859
|
async ingestTelemetry(message) {
|
|
11617
11860
|
const newMessage = {
|
|
11618
11861
|
...message,
|
|
11619
|
-
id: `tel_${Date.now()}_${
|
|
11862
|
+
id: `tel_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`,
|
|
11620
11863
|
receivedAt: /* @__PURE__ */ new Date()
|
|
11621
11864
|
};
|
|
11622
11865
|
if (this.config.storeTelemetry !== false) {
|
|
@@ -11696,7 +11939,7 @@ var MemoryDevice = class {
|
|
|
11696
11939
|
// ─────────────────────────────────────────────────────────────
|
|
11697
11940
|
async sendCommand(deviceId, name, payload, options) {
|
|
11698
11941
|
const command = {
|
|
11699
|
-
id: `cmd_${Date.now()}_${
|
|
11942
|
+
id: `cmd_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`,
|
|
11700
11943
|
deviceId,
|
|
11701
11944
|
name,
|
|
11702
11945
|
payload,
|
|
@@ -11759,7 +12002,7 @@ var MemoryDevice = class {
|
|
|
11759
12002
|
async createFirmware(firmware) {
|
|
11760
12003
|
const newFirmware = {
|
|
11761
12004
|
...firmware,
|
|
11762
|
-
id: `fw_${Date.now()}_${
|
|
12005
|
+
id: `fw_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`,
|
|
11763
12006
|
status: "draft",
|
|
11764
12007
|
createdAt: /* @__PURE__ */ new Date()
|
|
11765
12008
|
};
|
|
@@ -11811,7 +12054,7 @@ var MemoryDevice = class {
|
|
|
11811
12054
|
throw new Error(`Firmware not found: ${firmwareVersionId}`);
|
|
11812
12055
|
}
|
|
11813
12056
|
const update = {
|
|
11814
|
-
id: `upd_${Date.now()}_${
|
|
12057
|
+
id: `upd_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`,
|
|
11815
12058
|
deviceId,
|
|
11816
12059
|
firmwareVersionId,
|
|
11817
12060
|
targetVersion: firmware.version,
|
|
@@ -11865,7 +12108,7 @@ var MemoryDevice = class {
|
|
|
11865
12108
|
const now = /* @__PURE__ */ new Date();
|
|
11866
12109
|
const newGroup = {
|
|
11867
12110
|
...group,
|
|
11868
|
-
id: `grp_${Date.now()}_${
|
|
12111
|
+
id: `grp_${Date.now()}_${(0, import_crypto15.randomBytes)(4).toString("hex")}`,
|
|
11869
12112
|
deviceCount: 0,
|
|
11870
12113
|
tags: group.tags || [],
|
|
11871
12114
|
attributes: group.attributes || {},
|
|
@@ -11985,6 +12228,7 @@ var MemoryDevice = class {
|
|
|
11985
12228
|
};
|
|
11986
12229
|
|
|
11987
12230
|
// src/interfaces/IBilling.ts
|
|
12231
|
+
var import_crypto16 = require("crypto");
|
|
11988
12232
|
var MemoryBilling = class {
|
|
11989
12233
|
constructor(config = {}) {
|
|
11990
12234
|
this.config = config;
|
|
@@ -12005,7 +12249,7 @@ var MemoryBilling = class {
|
|
|
12005
12249
|
async createProduct(product) {
|
|
12006
12250
|
const newProduct = {
|
|
12007
12251
|
...product,
|
|
12008
|
-
id: `prod_${Date.now()}_${
|
|
12252
|
+
id: `prod_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12009
12253
|
features: product.features || [],
|
|
12010
12254
|
metadata: product.metadata || {},
|
|
12011
12255
|
createdAt: /* @__PURE__ */ new Date(),
|
|
@@ -12033,7 +12277,7 @@ var MemoryBilling = class {
|
|
|
12033
12277
|
async createPrice(price) {
|
|
12034
12278
|
const newPrice = {
|
|
12035
12279
|
...price,
|
|
12036
|
-
id: `price_${Date.now()}_${
|
|
12280
|
+
id: `price_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12037
12281
|
metadata: price.metadata || {},
|
|
12038
12282
|
createdAt: /* @__PURE__ */ new Date(),
|
|
12039
12283
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -12064,7 +12308,7 @@ var MemoryBilling = class {
|
|
|
12064
12308
|
async createMeter(meter) {
|
|
12065
12309
|
const newMeter = {
|
|
12066
12310
|
...meter,
|
|
12067
|
-
id: `meter_${Date.now()}_${
|
|
12311
|
+
id: `meter_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12068
12312
|
createdAt: /* @__PURE__ */ new Date(),
|
|
12069
12313
|
updatedAt: /* @__PURE__ */ new Date()
|
|
12070
12314
|
};
|
|
@@ -12098,13 +12342,13 @@ var MemoryBilling = class {
|
|
|
12098
12342
|
const trialDays = options.trialDays ?? price.trialDays ?? 0;
|
|
12099
12343
|
const periodEnd = this.addPeriod(now, price.billingPeriod);
|
|
12100
12344
|
const subscription = {
|
|
12101
|
-
id: `sub_${Date.now()}_${
|
|
12345
|
+
id: `sub_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12102
12346
|
customerId: options.customerId,
|
|
12103
12347
|
tenantId: options.tenantId,
|
|
12104
12348
|
status: trialDays > 0 ? "trialing" : "active",
|
|
12105
12349
|
items: [
|
|
12106
12350
|
{
|
|
12107
|
-
id: `si_${Date.now()}_${
|
|
12351
|
+
id: `si_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12108
12352
|
priceId: options.priceId,
|
|
12109
12353
|
quantity: options.quantity || 1
|
|
12110
12354
|
}
|
|
@@ -12195,7 +12439,7 @@ var MemoryBilling = class {
|
|
|
12195
12439
|
const sub = await this.getSubscription(subscriptionId);
|
|
12196
12440
|
if (!sub) throw new Error(`Subscription not found: ${subscriptionId}`);
|
|
12197
12441
|
sub.items.push({
|
|
12198
|
-
id: `si_${Date.now()}_${
|
|
12442
|
+
id: `si_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12199
12443
|
priceId,
|
|
12200
12444
|
quantity: quantity || 1
|
|
12201
12445
|
});
|
|
@@ -12247,7 +12491,7 @@ var MemoryBilling = class {
|
|
|
12247
12491
|
if (existing) return existing;
|
|
12248
12492
|
}
|
|
12249
12493
|
const event = {
|
|
12250
|
-
id: `ue_${Date.now()}_${
|
|
12494
|
+
id: `ue_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12251
12495
|
subscriptionId,
|
|
12252
12496
|
customerId: sub.customerId,
|
|
12253
12497
|
meterId: meter.id,
|
|
@@ -12318,7 +12562,7 @@ var MemoryBilling = class {
|
|
|
12318
12562
|
if (price) {
|
|
12319
12563
|
const unitAmount = price.unitAmount || 0;
|
|
12320
12564
|
lineItems.push({
|
|
12321
|
-
id: `ii_${Date.now()}_${
|
|
12565
|
+
id: `ii_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12322
12566
|
priceId: item.priceId,
|
|
12323
12567
|
description: price.name,
|
|
12324
12568
|
quantity: item.quantity,
|
|
@@ -12333,7 +12577,7 @@ var MemoryBilling = class {
|
|
|
12333
12577
|
const usageSummary = await this.getUsageSummary(subscriptionId);
|
|
12334
12578
|
for (const usage of usageSummary) {
|
|
12335
12579
|
lineItems.push({
|
|
12336
|
-
id: `ii_${Date.now()}_${
|
|
12580
|
+
id: `ii_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12337
12581
|
description: `${usage.meterName}: ${usage.total} ${usage.unit}`,
|
|
12338
12582
|
quantity: usage.total,
|
|
12339
12583
|
unitAmount: usage.cost / usage.total,
|
|
@@ -12356,7 +12600,7 @@ var MemoryBilling = class {
|
|
|
12356
12600
|
const tax = (subtotal - discount) * (taxRate / 100);
|
|
12357
12601
|
const total = subtotal - discount + tax;
|
|
12358
12602
|
const invoice = {
|
|
12359
|
-
id: `inv_${Date.now()}_${
|
|
12603
|
+
id: `inv_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12360
12604
|
customerId: sub.customerId,
|
|
12361
12605
|
subscriptionId,
|
|
12362
12606
|
tenantId: sub.tenantId,
|
|
@@ -12387,14 +12631,14 @@ var MemoryBilling = class {
|
|
|
12387
12631
|
async createInvoice(options) {
|
|
12388
12632
|
const lineItems = options.lineItems.map((item) => ({
|
|
12389
12633
|
...item,
|
|
12390
|
-
id: `ii_${Date.now()}_${
|
|
12634
|
+
id: `ii_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`
|
|
12391
12635
|
}));
|
|
12392
12636
|
const subtotal = lineItems.reduce((sum, item) => sum + item.amount, 0);
|
|
12393
12637
|
const taxRate = this.config.defaultTaxRate || 0;
|
|
12394
12638
|
const tax = subtotal * (taxRate / 100);
|
|
12395
12639
|
const total = subtotal + tax;
|
|
12396
12640
|
const invoice = {
|
|
12397
|
-
id: `inv_${Date.now()}_${
|
|
12641
|
+
id: `inv_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12398
12642
|
customerId: options.customerId,
|
|
12399
12643
|
tenantId: options.tenantId,
|
|
12400
12644
|
number: `${this.config.invoiceNumberPrefix || "INV-"}${++this.invoiceCounter}`,
|
|
@@ -12483,7 +12727,7 @@ var MemoryBilling = class {
|
|
|
12483
12727
|
async createDunningConfig(config) {
|
|
12484
12728
|
const newConfig = {
|
|
12485
12729
|
...config,
|
|
12486
|
-
id: `dun_${Date.now()}_${
|
|
12730
|
+
id: `dun_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12487
12731
|
createdAt: /* @__PURE__ */ new Date(),
|
|
12488
12732
|
updatedAt: /* @__PURE__ */ new Date()
|
|
12489
12733
|
};
|
|
@@ -12509,7 +12753,7 @@ var MemoryBilling = class {
|
|
|
12509
12753
|
const invoice = await this.getInvoice(invoiceId);
|
|
12510
12754
|
if (!invoice) throw new Error(`Invoice not found: ${invoiceId}`);
|
|
12511
12755
|
const attempt = {
|
|
12512
|
-
id: `da_${Date.now()}_${
|
|
12756
|
+
id: `da_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12513
12757
|
invoiceId,
|
|
12514
12758
|
attemptNumber: invoice.attemptCount + 1,
|
|
12515
12759
|
action: "retry_payment",
|
|
@@ -12541,7 +12785,7 @@ var MemoryBilling = class {
|
|
|
12541
12785
|
balance.updatedAt = /* @__PURE__ */ new Date();
|
|
12542
12786
|
this.creditBalances.set(customerId, balance);
|
|
12543
12787
|
const transaction = {
|
|
12544
|
-
id: `ct_${Date.now()}_${
|
|
12788
|
+
id: `ct_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12545
12789
|
customerId,
|
|
12546
12790
|
type: options?.type || "manual",
|
|
12547
12791
|
amount,
|
|
@@ -12566,7 +12810,7 @@ var MemoryBilling = class {
|
|
|
12566
12810
|
balance.updatedAt = /* @__PURE__ */ new Date();
|
|
12567
12811
|
this.creditBalances.set(customerId, balance);
|
|
12568
12812
|
const transaction = {
|
|
12569
|
-
id: `ct_${Date.now()}_${
|
|
12813
|
+
id: `ct_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12570
12814
|
customerId,
|
|
12571
12815
|
type: "manual",
|
|
12572
12816
|
amount: -amount,
|
|
@@ -12590,7 +12834,7 @@ var MemoryBilling = class {
|
|
|
12590
12834
|
async createCoupon(coupon) {
|
|
12591
12835
|
const newCoupon = {
|
|
12592
12836
|
...coupon,
|
|
12593
|
-
id: `coup_${Date.now()}_${
|
|
12837
|
+
id: `coup_${Date.now()}_${(0, import_crypto16.randomBytes)(4).toString("hex")}`,
|
|
12594
12838
|
timesRedeemed: 0,
|
|
12595
12839
|
createdAt: /* @__PURE__ */ new Date(),
|
|
12596
12840
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -12826,6 +13070,7 @@ var MemoryBilling = class {
|
|
|
12826
13070
|
};
|
|
12827
13071
|
|
|
12828
13072
|
// src/interfaces/IDevPortal.ts
|
|
13073
|
+
var import_crypto17 = require("crypto");
|
|
12829
13074
|
var MemoryDevPortal = class {
|
|
12830
13075
|
constructor(config = {}) {
|
|
12831
13076
|
this.config = config;
|
|
@@ -12838,8 +13083,9 @@ var MemoryDevPortal = class {
|
|
|
12838
13083
|
usageRecords = [];
|
|
12839
13084
|
// API Key Management
|
|
12840
13085
|
async createApiKey(options, userId) {
|
|
12841
|
-
const
|
|
12842
|
-
const
|
|
13086
|
+
const { randomBytes: randomBytes37, createHash: createHash2 } = await import("crypto");
|
|
13087
|
+
const id = `key_${Date.now()}_${randomBytes37(8).toString("hex")}`;
|
|
13088
|
+
const secret = `sk_${options.type}_${randomBytes37(24).toString("base64url")}`;
|
|
12843
13089
|
const prefix = secret.substring(0, 12);
|
|
12844
13090
|
const key = {
|
|
12845
13091
|
id,
|
|
@@ -12926,7 +13172,7 @@ var MemoryDevPortal = class {
|
|
|
12926
13172
|
// API Documentation
|
|
12927
13173
|
async generateDocumentation(endpoints, config) {
|
|
12928
13174
|
const doc = {
|
|
12929
|
-
id: `doc_${Date.now()}_${
|
|
13175
|
+
id: `doc_${Date.now()}_${(0, import_crypto17.randomBytes)(4).toString("hex")}`,
|
|
12930
13176
|
title: config.title,
|
|
12931
13177
|
version: config.version,
|
|
12932
13178
|
baseUrl: config.baseUrl,
|
|
@@ -12982,7 +13228,7 @@ var MemoryDevPortal = class {
|
|
|
12982
13228
|
if (!doc) throw new Error(`Documentation not found: ${docId}`);
|
|
12983
13229
|
const newEndpoint = {
|
|
12984
13230
|
...endpoint,
|
|
12985
|
-
id: `ep_${Date.now()}_${
|
|
13231
|
+
id: `ep_${Date.now()}_${(0, import_crypto17.randomBytes)(4).toString("hex")}`
|
|
12986
13232
|
};
|
|
12987
13233
|
doc.endpoints.push(newEndpoint);
|
|
12988
13234
|
return newEndpoint;
|
|
@@ -13078,7 +13324,7 @@ SDK for ${documentation.title}`,
|
|
|
13078
13324
|
});
|
|
13079
13325
|
}
|
|
13080
13326
|
const sdk = {
|
|
13081
|
-
id: `sdk_${Date.now()}_${
|
|
13327
|
+
id: `sdk_${Date.now()}_${(0, import_crypto17.randomBytes)(4).toString("hex")}`,
|
|
13082
13328
|
language: config.language,
|
|
13083
13329
|
packageName: config.packageName,
|
|
13084
13330
|
version: config.version,
|
|
@@ -13105,7 +13351,7 @@ SDK for ${documentation.title}`,
|
|
|
13105
13351
|
}
|
|
13106
13352
|
// Sandbox / Playground
|
|
13107
13353
|
async createSandbox(options, userId) {
|
|
13108
|
-
const id = `sandbox_${Date.now()}_${
|
|
13354
|
+
const id = `sandbox_${Date.now()}_${(0, import_crypto17.randomBytes)(4).toString("hex")}`;
|
|
13109
13355
|
const lifetimeHours = options.lifetimeHours || this.config.sandboxDefaultLifetimeHours || 24;
|
|
13110
13356
|
const sandbox = {
|
|
13111
13357
|
id,
|
|
@@ -13114,7 +13360,7 @@ SDK for ${documentation.title}`,
|
|
|
13114
13360
|
tenantId: options.tenantId,
|
|
13115
13361
|
status: "active",
|
|
13116
13362
|
baseUrl: `https://sandbox-${id}.example.com`,
|
|
13117
|
-
apiKey: `sandbox_${
|
|
13363
|
+
apiKey: `sandbox_${(0, import_crypto17.randomBytes)(8).toString("hex")}`,
|
|
13118
13364
|
seedDataLoaded: options.seedData || [],
|
|
13119
13365
|
config: options.config || {},
|
|
13120
13366
|
limits: {
|
|
@@ -13251,7 +13497,7 @@ SDK for ${documentation.title}`,
|
|
|
13251
13497
|
}
|
|
13252
13498
|
// Webhook Testing
|
|
13253
13499
|
async createWebhookTestEndpoint(userId, maxEvents = 100) {
|
|
13254
|
-
const id = `wh_test_${Date.now()}_${
|
|
13500
|
+
const id = `wh_test_${Date.now()}_${(0, import_crypto17.randomBytes)(4).toString("hex")}`;
|
|
13255
13501
|
const endpoint = {
|
|
13256
13502
|
id,
|
|
13257
13503
|
url: `https://webhook-test.example.com/${id}`,
|
|
@@ -13288,18 +13534,13 @@ SDK for ${documentation.title}`,
|
|
|
13288
13534
|
statusCode: 200,
|
|
13289
13535
|
headers: { "content-type": "application/json" },
|
|
13290
13536
|
body: { received: true },
|
|
13291
|
-
latencyMs:
|
|
13537
|
+
latencyMs: 0
|
|
13292
13538
|
};
|
|
13293
13539
|
}
|
|
13294
13540
|
// Private helpers
|
|
13295
13541
|
hashKey(key) {
|
|
13296
|
-
|
|
13297
|
-
|
|
13298
|
-
const char = key.charCodeAt(i);
|
|
13299
|
-
hash = (hash << 5) - hash + char;
|
|
13300
|
-
hash = hash & hash;
|
|
13301
|
-
}
|
|
13302
|
-
return `hashed_${Math.abs(hash).toString(36)}`;
|
|
13542
|
+
const { createHash: createHash2 } = require("crypto");
|
|
13543
|
+
return createHash2("sha256").update(key).digest("hex");
|
|
13303
13544
|
}
|
|
13304
13545
|
endpointsToOpenApiPaths(endpoints) {
|
|
13305
13546
|
const paths = {};
|
|
@@ -13391,6 +13632,7 @@ class ApiClient:
|
|
|
13391
13632
|
};
|
|
13392
13633
|
|
|
13393
13634
|
// src/interfaces/ICompliance.ts
|
|
13635
|
+
var import_crypto18 = require("crypto");
|
|
13394
13636
|
var MemoryCompliance = class {
|
|
13395
13637
|
constructor(config = {}) {
|
|
13396
13638
|
this.config = config;
|
|
@@ -13407,13 +13649,13 @@ var MemoryCompliance = class {
|
|
|
13407
13649
|
breaches = /* @__PURE__ */ new Map();
|
|
13408
13650
|
// DSAR Management
|
|
13409
13651
|
async createDsar(options) {
|
|
13410
|
-
const id = `dsar_${Date.now()}_${
|
|
13652
|
+
const id = `dsar_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13411
13653
|
const dsar = {
|
|
13412
13654
|
id,
|
|
13413
13655
|
type: options.type,
|
|
13414
13656
|
subjectId: options.subjectId || options.subjectEmail,
|
|
13415
13657
|
subjectEmail: options.subjectEmail,
|
|
13416
|
-
verificationToken: `verify_${
|
|
13658
|
+
verificationToken: `verify_${(0, import_crypto18.randomBytes)(8).toString("hex")}`,
|
|
13417
13659
|
verified: false,
|
|
13418
13660
|
status: "pending_verification",
|
|
13419
13661
|
tenantId: options.tenantId,
|
|
@@ -13464,7 +13706,7 @@ var MemoryCompliance = class {
|
|
|
13464
13706
|
dsar.updatedAt = /* @__PURE__ */ new Date();
|
|
13465
13707
|
if (notes) {
|
|
13466
13708
|
dsar.notes.push({
|
|
13467
|
-
id: `note_${Date.now()}_${
|
|
13709
|
+
id: `note_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`,
|
|
13468
13710
|
content: notes,
|
|
13469
13711
|
authorId: "system",
|
|
13470
13712
|
createdAt: /* @__PURE__ */ new Date()
|
|
@@ -13476,7 +13718,7 @@ var MemoryCompliance = class {
|
|
|
13476
13718
|
const dsar = await this.getDsar(dsarId);
|
|
13477
13719
|
if (!dsar) throw new Error(`DSAR not found: ${dsarId}`);
|
|
13478
13720
|
const note = {
|
|
13479
|
-
id: `note_${Date.now()}_${
|
|
13721
|
+
id: `note_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`,
|
|
13480
13722
|
content,
|
|
13481
13723
|
authorId,
|
|
13482
13724
|
createdAt: /* @__PURE__ */ new Date()
|
|
@@ -13490,7 +13732,7 @@ var MemoryCompliance = class {
|
|
|
13490
13732
|
if (!dsar) throw new Error(`DSAR not found: ${dsarId}`);
|
|
13491
13733
|
const att = {
|
|
13492
13734
|
...attachment,
|
|
13493
|
-
id: `att_${Date.now()}_${
|
|
13735
|
+
id: `att_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`,
|
|
13494
13736
|
createdAt: /* @__PURE__ */ new Date()
|
|
13495
13737
|
};
|
|
13496
13738
|
dsar.attachments.push(att);
|
|
@@ -13531,7 +13773,7 @@ var MemoryCompliance = class {
|
|
|
13531
13773
|
}
|
|
13532
13774
|
// Consent Management
|
|
13533
13775
|
async recordConsent(options) {
|
|
13534
|
-
const id = `consent_${Date.now()}_${
|
|
13776
|
+
const id = `consent_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13535
13777
|
const consent = {
|
|
13536
13778
|
id,
|
|
13537
13779
|
subjectId: options.subjectId,
|
|
@@ -13606,7 +13848,7 @@ var MemoryCompliance = class {
|
|
|
13606
13848
|
}
|
|
13607
13849
|
// Retention Policies
|
|
13608
13850
|
async createRetentionPolicy(policy) {
|
|
13609
|
-
const id = `rp_${Date.now()}_${
|
|
13851
|
+
const id = `rp_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13610
13852
|
const newPolicy = {
|
|
13611
13853
|
...policy,
|
|
13612
13854
|
id,
|
|
@@ -13639,7 +13881,7 @@ var MemoryCompliance = class {
|
|
|
13639
13881
|
if (!policy) throw new Error(`Policy not found: ${policyId}`);
|
|
13640
13882
|
const startedAt = /* @__PURE__ */ new Date();
|
|
13641
13883
|
const execution = {
|
|
13642
|
-
id: `re_${Date.now()}_${
|
|
13884
|
+
id: `re_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`,
|
|
13643
13885
|
policyId,
|
|
13644
13886
|
recordsProcessed: 100,
|
|
13645
13887
|
recordsAffected: 15,
|
|
@@ -13658,7 +13900,7 @@ var MemoryCompliance = class {
|
|
|
13658
13900
|
}
|
|
13659
13901
|
// Data Inventory
|
|
13660
13902
|
async addDataInventoryItem(item) {
|
|
13661
|
-
const id = `di_${Date.now()}_${
|
|
13903
|
+
const id = `di_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13662
13904
|
const newItem = {
|
|
13663
13905
|
...item,
|
|
13664
13906
|
id,
|
|
@@ -13719,7 +13961,7 @@ var MemoryCompliance = class {
|
|
|
13719
13961
|
}
|
|
13720
13962
|
// Audit Evidence
|
|
13721
13963
|
async addEvidence(evidence) {
|
|
13722
|
-
const id = `ev_${Date.now()}_${
|
|
13964
|
+
const id = `ev_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13723
13965
|
const newEvidence = {
|
|
13724
13966
|
...evidence,
|
|
13725
13967
|
id,
|
|
@@ -13795,7 +14037,7 @@ var MemoryCompliance = class {
|
|
|
13795
14037
|
}
|
|
13796
14038
|
// PIAs
|
|
13797
14039
|
async createPia(pia) {
|
|
13798
|
-
const id = `pia_${Date.now()}_${
|
|
14040
|
+
const id = `pia_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13799
14041
|
const newPia = {
|
|
13800
14042
|
...pia,
|
|
13801
14043
|
id,
|
|
@@ -13827,7 +14069,7 @@ var MemoryCompliance = class {
|
|
|
13827
14069
|
if (!pia) throw new Error(`PIA not found: ${piaId}`);
|
|
13828
14070
|
const newRisk = {
|
|
13829
14071
|
...risk,
|
|
13830
|
-
id: `risk_${Date.now()}_${
|
|
14072
|
+
id: `risk_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`
|
|
13831
14073
|
};
|
|
13832
14074
|
pia.risks.push(newRisk);
|
|
13833
14075
|
pia.updatedAt = /* @__PURE__ */ new Date();
|
|
@@ -13838,7 +14080,7 @@ var MemoryCompliance = class {
|
|
|
13838
14080
|
if (!pia) throw new Error(`PIA not found: ${piaId}`);
|
|
13839
14081
|
const newMitigation = {
|
|
13840
14082
|
...mitigation,
|
|
13841
|
-
id: `mit_${Date.now()}_${
|
|
14083
|
+
id: `mit_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`
|
|
13842
14084
|
};
|
|
13843
14085
|
pia.mitigations.push(newMitigation);
|
|
13844
14086
|
pia.updatedAt = /* @__PURE__ */ new Date();
|
|
@@ -13875,7 +14117,7 @@ var MemoryCompliance = class {
|
|
|
13875
14117
|
(c) => c.status === "non_compliant"
|
|
13876
14118
|
).length;
|
|
13877
14119
|
const report = {
|
|
13878
|
-
id: `report_${Date.now()}_${
|
|
14120
|
+
id: `report_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`,
|
|
13879
14121
|
title: `${framework.toUpperCase()} Compliance Report`,
|
|
13880
14122
|
framework,
|
|
13881
14123
|
period,
|
|
@@ -13926,7 +14168,7 @@ var MemoryCompliance = class {
|
|
|
13926
14168
|
}
|
|
13927
14169
|
// Breach Management
|
|
13928
14170
|
async recordBreach(breach) {
|
|
13929
|
-
const id = `breach_${Date.now()}_${
|
|
14171
|
+
const id = `breach_${Date.now()}_${(0, import_crypto18.randomBytes)(4).toString("hex")}`;
|
|
13930
14172
|
const newBreach = {
|
|
13931
14173
|
...breach,
|
|
13932
14174
|
id,
|
|
@@ -14165,6 +14407,27 @@ var RAGConfigSchema = import_zod.z.object({
|
|
|
14165
14407
|
message: "Pinecone requires apiKey and indexName; Weaviate requires host"
|
|
14166
14408
|
}
|
|
14167
14409
|
);
|
|
14410
|
+
var CryptoConfigSchema = import_zod.z.object({
|
|
14411
|
+
enabled: import_zod.z.boolean().default(false).describe("Enable field-level encryption"),
|
|
14412
|
+
masterKey: import_zod.z.string().optional().describe("256-bit master key as hex (64 chars). Required when enabled."),
|
|
14413
|
+
hmacKey: import_zod.z.string().optional().describe(
|
|
14414
|
+
"HMAC key for deterministic hashing (derived from master key if not provided)"
|
|
14415
|
+
)
|
|
14416
|
+
}).refine(
|
|
14417
|
+
(data) => {
|
|
14418
|
+
if (data.enabled) {
|
|
14419
|
+
return data.masterKey && data.masterKey.length >= 64;
|
|
14420
|
+
}
|
|
14421
|
+
return true;
|
|
14422
|
+
},
|
|
14423
|
+
{
|
|
14424
|
+
message: "Crypto requires a 256-bit master key (64 hex characters) when enabled"
|
|
14425
|
+
}
|
|
14426
|
+
);
|
|
14427
|
+
var SecurityConfigSchema = import_zod.z.object({
|
|
14428
|
+
enforceTls: import_zod.z.boolean().default(true).describe("Enforce TLS for production connections"),
|
|
14429
|
+
tlsWarnOnly: import_zod.z.boolean().default(false).describe("Warn instead of throwing when TLS is missing in production")
|
|
14430
|
+
});
|
|
14168
14431
|
var RetryConfigSchema = import_zod.z.object({
|
|
14169
14432
|
enabled: import_zod.z.boolean().default(true).describe("Enable retry for failed operations"),
|
|
14170
14433
|
maxAttempts: import_zod.z.number().int().min(1).max(10).default(3).describe("Maximum retry attempts"),
|
|
@@ -14254,6 +14517,10 @@ var PlatformConfigSchema = import_zod.z.object({
|
|
|
14254
14517
|
// AI configurations
|
|
14255
14518
|
ai: AIConfigSchema.default({ enabled: false }),
|
|
14256
14519
|
rag: RAGConfigSchema.default({ enabled: false }),
|
|
14520
|
+
// Crypto configuration
|
|
14521
|
+
crypto: CryptoConfigSchema.default({ enabled: false }),
|
|
14522
|
+
// Security configuration
|
|
14523
|
+
security: SecurityConfigSchema.default({}),
|
|
14257
14524
|
// Resilience configuration
|
|
14258
14525
|
resilience: ResilienceConfigSchema.default({}),
|
|
14259
14526
|
// Observability configuration
|
|
@@ -14331,6 +14598,15 @@ function loadConfig() {
|
|
|
14331
14598
|
embeddingApiKey: process.env.EMBEDDING_API_KEY || process.env.OPENAI_API_KEY,
|
|
14332
14599
|
embeddingModel: process.env.EMBEDDING_MODEL
|
|
14333
14600
|
},
|
|
14601
|
+
crypto: {
|
|
14602
|
+
enabled: process.env.CRYPTO_ENABLED === "true",
|
|
14603
|
+
masterKey: process.env.CRYPTO_MASTER_KEY,
|
|
14604
|
+
hmacKey: process.env.CRYPTO_HMAC_KEY
|
|
14605
|
+
},
|
|
14606
|
+
security: {
|
|
14607
|
+
enforceTls: process.env.SECURITY_ENFORCE_TLS !== "false",
|
|
14608
|
+
tlsWarnOnly: process.env.SECURITY_TLS_WARN_ONLY === "true"
|
|
14609
|
+
},
|
|
14334
14610
|
resilience: {
|
|
14335
14611
|
retry: {
|
|
14336
14612
|
enabled: process.env.RESILIENCE_RETRY_ENABLED !== "false",
|
|
@@ -14737,13 +15013,14 @@ var MemoryEmail = class {
|
|
|
14737
15013
|
|
|
14738
15014
|
// src/context/CorrelationContext.ts
|
|
14739
15015
|
var import_async_hooks = require("async_hooks");
|
|
15016
|
+
var import_crypto19 = require("crypto");
|
|
14740
15017
|
var CorrelationContextManager = class {
|
|
14741
15018
|
storage = new import_async_hooks.AsyncLocalStorage();
|
|
14742
15019
|
idGenerator;
|
|
14743
15020
|
constructor() {
|
|
14744
15021
|
this.idGenerator = () => {
|
|
14745
15022
|
const timestamp = Date.now().toString(36);
|
|
14746
|
-
const random =
|
|
15023
|
+
const random = (0, import_crypto19.randomBytes)(4).toString("hex");
|
|
14747
15024
|
return `${timestamp}-${random}`;
|
|
14748
15025
|
};
|
|
14749
15026
|
}
|
|
@@ -15373,10 +15650,11 @@ var MemoryQueue = class {
|
|
|
15373
15650
|
};
|
|
15374
15651
|
|
|
15375
15652
|
// src/adapters/console/ConsoleEmail.ts
|
|
15653
|
+
var import_crypto20 = require("crypto");
|
|
15376
15654
|
var ConsoleEmail = class {
|
|
15377
15655
|
sentEmails = [];
|
|
15378
15656
|
async send(message) {
|
|
15379
|
-
const id = `console_${Date.now()}_${
|
|
15657
|
+
const id = `console_${Date.now()}_${(0, import_crypto20.randomBytes)(4).toString("hex")}`;
|
|
15380
15658
|
console.log("\n" + "=".repeat(60));
|
|
15381
15659
|
console.log("\u{1F4E7} EMAIL SENT (Console Adapter)");
|
|
15382
15660
|
console.log("=".repeat(60));
|
|
@@ -15453,6 +15731,147 @@ var ConsoleEmail = class {
|
|
|
15453
15731
|
// src/factory.ts
|
|
15454
15732
|
init_IAI();
|
|
15455
15733
|
init_IRAG();
|
|
15734
|
+
|
|
15735
|
+
// src/adapters/memory/MemoryCrypto.ts
|
|
15736
|
+
var import_crypto21 = require("crypto");
|
|
15737
|
+
var MemoryCrypto = class {
|
|
15738
|
+
keys = /* @__PURE__ */ new Map();
|
|
15739
|
+
activeKeyId;
|
|
15740
|
+
hmacKey;
|
|
15741
|
+
constructor(options) {
|
|
15742
|
+
const masterKeyBuf = options?.masterKey ? Buffer.from(options.masterKey, "hex") : (0, import_crypto21.randomBytes)(32);
|
|
15743
|
+
this.hmacKey = options?.hmacKey ? Buffer.from(options.hmacKey, "hex") : (0, import_crypto21.randomBytes)(32);
|
|
15744
|
+
const keyId = this.generateKeyId();
|
|
15745
|
+
this.keys.set(keyId, {
|
|
15746
|
+
id: keyId,
|
|
15747
|
+
key: masterKeyBuf,
|
|
15748
|
+
status: "active",
|
|
15749
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
15750
|
+
});
|
|
15751
|
+
this.activeKeyId = keyId;
|
|
15752
|
+
}
|
|
15753
|
+
async encrypt(plaintext, options) {
|
|
15754
|
+
const keyId = options?.keyId || this.activeKeyId;
|
|
15755
|
+
const stored = this.keys.get(keyId);
|
|
15756
|
+
if (!stored) {
|
|
15757
|
+
throw new Error(`Key not found: ${keyId}`);
|
|
15758
|
+
}
|
|
15759
|
+
if (stored.status === "retired") {
|
|
15760
|
+
throw new Error(`Key is retired: ${keyId}`);
|
|
15761
|
+
}
|
|
15762
|
+
if (stored.status === "decrypt-only" && !options?.keyId) {
|
|
15763
|
+
throw new Error(`Key is decrypt-only: ${keyId}`);
|
|
15764
|
+
}
|
|
15765
|
+
const iv = (0, import_crypto21.randomBytes)(12);
|
|
15766
|
+
const cipher = (0, import_crypto21.createCipheriv)("aes-256-gcm", stored.key, iv);
|
|
15767
|
+
if (options?.aad) {
|
|
15768
|
+
cipher.setAAD(Buffer.from(options.aad, "utf8"));
|
|
15769
|
+
}
|
|
15770
|
+
const encrypted = Buffer.concat([
|
|
15771
|
+
cipher.update(plaintext, "utf8"),
|
|
15772
|
+
cipher.final()
|
|
15773
|
+
]);
|
|
15774
|
+
const tag = cipher.getAuthTag();
|
|
15775
|
+
return {
|
|
15776
|
+
ciphertext: encrypted.toString("base64"),
|
|
15777
|
+
iv: iv.toString("base64"),
|
|
15778
|
+
tag: tag.toString("base64"),
|
|
15779
|
+
keyId,
|
|
15780
|
+
algorithm: "aes-256-gcm",
|
|
15781
|
+
version: 1
|
|
15782
|
+
};
|
|
15783
|
+
}
|
|
15784
|
+
async decrypt(field, options) {
|
|
15785
|
+
const stored = this.keys.get(field.keyId);
|
|
15786
|
+
if (!stored) {
|
|
15787
|
+
throw new Error(`Key not found: ${field.keyId}`);
|
|
15788
|
+
}
|
|
15789
|
+
if (stored.status === "retired") {
|
|
15790
|
+
throw new Error(`Key is retired and cannot decrypt: ${field.keyId}`);
|
|
15791
|
+
}
|
|
15792
|
+
const decipher = (0, import_crypto21.createDecipheriv)(
|
|
15793
|
+
"aes-256-gcm",
|
|
15794
|
+
stored.key,
|
|
15795
|
+
Buffer.from(field.iv, "base64")
|
|
15796
|
+
);
|
|
15797
|
+
decipher.setAuthTag(Buffer.from(field.tag, "base64"));
|
|
15798
|
+
if (options?.aad) {
|
|
15799
|
+
decipher.setAAD(Buffer.from(options.aad, "utf8"));
|
|
15800
|
+
}
|
|
15801
|
+
const decrypted = Buffer.concat([
|
|
15802
|
+
decipher.update(Buffer.from(field.ciphertext, "base64")),
|
|
15803
|
+
decipher.final()
|
|
15804
|
+
]);
|
|
15805
|
+
return decrypted.toString("utf8");
|
|
15806
|
+
}
|
|
15807
|
+
async encryptDeterministic(plaintext, options) {
|
|
15808
|
+
const hash = await this.computeHash(plaintext);
|
|
15809
|
+
const encrypted = await this.encrypt(plaintext, options);
|
|
15810
|
+
return { hash, encrypted };
|
|
15811
|
+
}
|
|
15812
|
+
async computeHash(plaintext) {
|
|
15813
|
+
return (0, import_crypto21.createHmac)("sha256", this.hmacKey).update(plaintext, "utf8").digest("hex");
|
|
15814
|
+
}
|
|
15815
|
+
async encryptBatch(fields, options) {
|
|
15816
|
+
const result = {};
|
|
15817
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
15818
|
+
result[key] = await this.encrypt(value, options);
|
|
15819
|
+
}
|
|
15820
|
+
return result;
|
|
15821
|
+
}
|
|
15822
|
+
async decryptBatch(fields, options) {
|
|
15823
|
+
const result = {};
|
|
15824
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
15825
|
+
result[key] = await this.decrypt(value, options);
|
|
15826
|
+
}
|
|
15827
|
+
return result;
|
|
15828
|
+
}
|
|
15829
|
+
async rotateKey() {
|
|
15830
|
+
const previousKeyId = this.activeKeyId;
|
|
15831
|
+
const currentKey = this.keys.get(previousKeyId);
|
|
15832
|
+
if (currentKey) {
|
|
15833
|
+
currentKey.status = "decrypt-only";
|
|
15834
|
+
}
|
|
15835
|
+
const newKeyId = this.generateKeyId();
|
|
15836
|
+
this.keys.set(newKeyId, {
|
|
15837
|
+
id: newKeyId,
|
|
15838
|
+
key: (0, import_crypto21.randomBytes)(32),
|
|
15839
|
+
status: "active",
|
|
15840
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
15841
|
+
});
|
|
15842
|
+
this.activeKeyId = newKeyId;
|
|
15843
|
+
return { newKeyId, previousKeyId };
|
|
15844
|
+
}
|
|
15845
|
+
async reEncrypt(field, options) {
|
|
15846
|
+
const plaintext = await this.decrypt(field);
|
|
15847
|
+
return this.encrypt(plaintext, options);
|
|
15848
|
+
}
|
|
15849
|
+
async listKeys() {
|
|
15850
|
+
return Array.from(this.keys.values()).map((k) => ({
|
|
15851
|
+
keyId: k.id,
|
|
15852
|
+
createdAt: k.createdAt,
|
|
15853
|
+
status: k.status
|
|
15854
|
+
}));
|
|
15855
|
+
}
|
|
15856
|
+
async getActiveKeyId() {
|
|
15857
|
+
return this.activeKeyId;
|
|
15858
|
+
}
|
|
15859
|
+
async healthCheck() {
|
|
15860
|
+
try {
|
|
15861
|
+
const testPlain = "health-check-test";
|
|
15862
|
+
const encrypted = await this.encrypt(testPlain);
|
|
15863
|
+
const decrypted = await this.decrypt(encrypted);
|
|
15864
|
+
return decrypted === testPlain;
|
|
15865
|
+
} catch {
|
|
15866
|
+
return false;
|
|
15867
|
+
}
|
|
15868
|
+
}
|
|
15869
|
+
generateKeyId() {
|
|
15870
|
+
return `key_${(0, import_crypto21.randomBytes)(8).toString("hex")}`;
|
|
15871
|
+
}
|
|
15872
|
+
};
|
|
15873
|
+
|
|
15874
|
+
// src/factory.ts
|
|
15456
15875
|
async function createDatabaseAdapter(config) {
|
|
15457
15876
|
switch (config.database.provider) {
|
|
15458
15877
|
case "postgres": {
|
|
@@ -15508,9 +15927,9 @@ async function createCacheAdapter(config) {
|
|
|
15508
15927
|
"Upstash requires UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN environment variables"
|
|
15509
15928
|
);
|
|
15510
15929
|
}
|
|
15511
|
-
const { Redis } = await import("@upstash/redis");
|
|
15930
|
+
const { Redis: Redis2 } = await import("@upstash/redis");
|
|
15512
15931
|
const { UpstashCache: UpstashCache2 } = await Promise.resolve().then(() => (init_UpstashCache(), UpstashCache_exports));
|
|
15513
|
-
const client = new
|
|
15932
|
+
const client = new Redis2({
|
|
15514
15933
|
url: config.cache.upstashUrl,
|
|
15515
15934
|
token: config.cache.upstashToken
|
|
15516
15935
|
});
|
|
@@ -15753,16 +16172,73 @@ async function createRAGAdapter(config, ai) {
|
|
|
15753
16172
|
return new MemoryRAG();
|
|
15754
16173
|
}
|
|
15755
16174
|
}
|
|
16175
|
+
async function createCryptoAdapter(config) {
|
|
16176
|
+
if (!config.crypto.enabled) {
|
|
16177
|
+
return null;
|
|
16178
|
+
}
|
|
16179
|
+
if (config.crypto.masterKey && config.crypto.masterKey.length >= 64) {
|
|
16180
|
+
const { NodeCrypto: NodeCrypto2 } = await Promise.resolve().then(() => (init_NodeCrypto(), NodeCrypto_exports));
|
|
16181
|
+
return new NodeCrypto2({
|
|
16182
|
+
masterKey: config.crypto.masterKey,
|
|
16183
|
+
hmacKey: config.crypto.hmacKey
|
|
16184
|
+
});
|
|
16185
|
+
}
|
|
16186
|
+
return new MemoryCrypto();
|
|
16187
|
+
}
|
|
16188
|
+
function validateTlsSecurity(config) {
|
|
16189
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
16190
|
+
if (!isProduction || !config.security.enforceTls) {
|
|
16191
|
+
return;
|
|
16192
|
+
}
|
|
16193
|
+
const warnings = [];
|
|
16194
|
+
if (config.database.provider === "postgres") {
|
|
16195
|
+
const connStr = config.database.connectionString || config.database.url || "";
|
|
16196
|
+
const hasSSL = config.database.ssl || connStr.includes("sslmode=require") || connStr.includes("sslmode=verify");
|
|
16197
|
+
if (!hasSSL) {
|
|
16198
|
+
warnings.push(
|
|
16199
|
+
"PostgreSQL: TLS/SSL not configured. Set database.ssl=true or add sslmode=require to connection string."
|
|
16200
|
+
);
|
|
16201
|
+
}
|
|
16202
|
+
}
|
|
16203
|
+
if (config.cache.provider === "redis") {
|
|
16204
|
+
const url = config.cache.url || "";
|
|
16205
|
+
if (url && !url.startsWith("rediss://")) {
|
|
16206
|
+
warnings.push(
|
|
16207
|
+
"Redis: Connection URL uses redis:// instead of rediss:// (TLS). Consider enabling TLS."
|
|
16208
|
+
);
|
|
16209
|
+
}
|
|
16210
|
+
}
|
|
16211
|
+
if (config.email.provider === "smtp") {
|
|
16212
|
+
if (!config.email.secure) {
|
|
16213
|
+
warnings.push(
|
|
16214
|
+
"SMTP: secure=false in production. Set email.secure=true for TLS."
|
|
16215
|
+
);
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
if (warnings.length > 0) {
|
|
16219
|
+
const message = `[Security] TLS warnings in production:
|
|
16220
|
+
- ${warnings.join("\n - ")}`;
|
|
16221
|
+
if (config.security.tlsWarnOnly) {
|
|
16222
|
+
console.warn(message);
|
|
16223
|
+
} else {
|
|
16224
|
+
throw new Error(message);
|
|
16225
|
+
}
|
|
16226
|
+
}
|
|
16227
|
+
}
|
|
15756
16228
|
async function createPlatformAsync(config) {
|
|
15757
16229
|
const finalConfig = config ? deepMerge(loadConfig(), config) : loadConfig();
|
|
15758
|
-
|
|
15759
|
-
|
|
15760
|
-
|
|
15761
|
-
|
|
15762
|
-
|
|
15763
|
-
|
|
15764
|
-
|
|
15765
|
-
|
|
16230
|
+
validateTlsSecurity(finalConfig);
|
|
16231
|
+
const [db, cache, storage, email, queue, tracing, crypto2] = await Promise.all(
|
|
16232
|
+
[
|
|
16233
|
+
createDatabaseAdapter(finalConfig),
|
|
16234
|
+
createCacheAdapter(finalConfig),
|
|
16235
|
+
createStorageAdapter(finalConfig),
|
|
16236
|
+
createEmailAdapter(finalConfig),
|
|
16237
|
+
createQueueAdapter(finalConfig),
|
|
16238
|
+
createTracingAdapter(finalConfig),
|
|
16239
|
+
createCryptoAdapter(finalConfig)
|
|
16240
|
+
]
|
|
16241
|
+
);
|
|
15766
16242
|
const logger = createLogger(finalConfig);
|
|
15767
16243
|
const metrics = createMetrics(finalConfig);
|
|
15768
16244
|
const ai = await createAIAdapter(finalConfig);
|
|
@@ -15777,7 +16253,8 @@ async function createPlatformAsync(config) {
|
|
|
15777
16253
|
metrics,
|
|
15778
16254
|
tracing,
|
|
15779
16255
|
ai,
|
|
15780
|
-
rag
|
|
16256
|
+
rag,
|
|
16257
|
+
crypto2
|
|
15781
16258
|
);
|
|
15782
16259
|
}
|
|
15783
16260
|
function createPlatform(config) {
|
|
@@ -15798,6 +16275,7 @@ function createPlatform(config) {
|
|
|
15798
16275
|
const tracing = finalConfig.observability.tracing.provider === "memory" ? new MemoryTracing() : new NoopTracing();
|
|
15799
16276
|
const ai = finalConfig.ai.enabled ? new MemoryAI() : null;
|
|
15800
16277
|
const rag = finalConfig.rag.enabled ? new MemoryRAG() : null;
|
|
16278
|
+
const crypto2 = finalConfig.crypto.enabled ? new MemoryCrypto() : null;
|
|
15801
16279
|
return createPlatformFromAdapters(
|
|
15802
16280
|
db,
|
|
15803
16281
|
cache,
|
|
@@ -15808,10 +16286,11 @@ function createPlatform(config) {
|
|
|
15808
16286
|
metrics,
|
|
15809
16287
|
tracing,
|
|
15810
16288
|
ai,
|
|
15811
|
-
rag
|
|
16289
|
+
rag,
|
|
16290
|
+
crypto2
|
|
15812
16291
|
);
|
|
15813
16292
|
}
|
|
15814
|
-
function createPlatformFromAdapters(db, cache, storage, email, queue, logger, metrics, tracing, ai, rag) {
|
|
16293
|
+
function createPlatformFromAdapters(db, cache, storage, email, queue, logger, metrics, tracing, ai, rag, crypto2) {
|
|
15815
16294
|
const platform = {
|
|
15816
16295
|
db,
|
|
15817
16296
|
cache,
|
|
@@ -15865,6 +16344,9 @@ function createPlatformFromAdapters(db, cache, storage, email, queue, logger, me
|
|
|
15865
16344
|
if (rag) {
|
|
15866
16345
|
platform.rag = rag;
|
|
15867
16346
|
}
|
|
16347
|
+
if (crypto2) {
|
|
16348
|
+
platform.crypto = crypto2;
|
|
16349
|
+
}
|
|
15868
16350
|
return platform;
|
|
15869
16351
|
}
|
|
15870
16352
|
function deepMerge(target, source) {
|
|
@@ -15887,11 +16369,11 @@ function deepMerge(target, source) {
|
|
|
15887
16369
|
}
|
|
15888
16370
|
|
|
15889
16371
|
// src/middleware/chain.ts
|
|
15890
|
-
var
|
|
16372
|
+
var import_crypto26 = require("crypto");
|
|
15891
16373
|
function createMiddlewareChain(options = {}) {
|
|
15892
16374
|
const middlewares = [];
|
|
15893
16375
|
const logger = options.logger ?? new NoopLogger();
|
|
15894
|
-
const generateCorrelationId = options.generateCorrelationId ?? (() => (0,
|
|
16376
|
+
const generateCorrelationId = options.generateCorrelationId ?? (() => (0, import_crypto26.randomUUID)());
|
|
15895
16377
|
function sortMiddleware() {
|
|
15896
16378
|
middlewares.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
|
15897
16379
|
}
|
|
@@ -16008,7 +16490,7 @@ function createMiddlewareContext(service, operation, args, logger, options = {})
|
|
|
16008
16490
|
args,
|
|
16009
16491
|
logger,
|
|
16010
16492
|
startTime: Date.now(),
|
|
16011
|
-
correlationId: options.correlationId ?? (0,
|
|
16493
|
+
correlationId: options.correlationId ?? (0, import_crypto26.randomUUID)(),
|
|
16012
16494
|
tenantId: options.tenantId
|
|
16013
16495
|
};
|
|
16014
16496
|
}
|
|
@@ -17336,6 +17818,7 @@ var FallbackStrategies = {
|
|
|
17336
17818
|
};
|
|
17337
17819
|
|
|
17338
17820
|
// src/security.ts
|
|
17821
|
+
var import_crypto27 = require("crypto");
|
|
17339
17822
|
var URL_PROTOCOL_PATTERN = /(https?:\/\/|ftp:\/\/|www\.)\S+/i;
|
|
17340
17823
|
var URL_DOMAIN_PATTERN = /\b[\w.-]+\.(com|net|org|io|co|dev|app|xyz|info|biz|me|us|uk|edu|gov)\b/i;
|
|
17341
17824
|
var HTML_TAG_PATTERN = /<[^>]*>/;
|
|
@@ -17360,6 +17843,144 @@ function defangUrl(str) {
|
|
|
17360
17843
|
function sanitizeForEmail(str) {
|
|
17361
17844
|
return escapeHtml(str);
|
|
17362
17845
|
}
|
|
17846
|
+
function constantTimeEqual(a, b) {
|
|
17847
|
+
try {
|
|
17848
|
+
const aBuf = Buffer.from(a, "utf-8");
|
|
17849
|
+
const bBuf = Buffer.from(b, "utf-8");
|
|
17850
|
+
if (aBuf.length !== bBuf.length) return false;
|
|
17851
|
+
return (0, import_crypto27.timingSafeEqual)(aBuf, bBuf);
|
|
17852
|
+
} catch {
|
|
17853
|
+
return false;
|
|
17854
|
+
}
|
|
17855
|
+
}
|
|
17856
|
+
function sanitizeApiError(error, statusCode, isDevelopment = false) {
|
|
17857
|
+
if (statusCode >= 400 && statusCode < 500) {
|
|
17858
|
+
const message = error instanceof Error ? error.message : String(error || "Bad request");
|
|
17859
|
+
return { message };
|
|
17860
|
+
}
|
|
17861
|
+
const result = {
|
|
17862
|
+
message: "An internal error occurred. Please try again later.",
|
|
17863
|
+
code: "INTERNAL_ERROR"
|
|
17864
|
+
};
|
|
17865
|
+
if (isDevelopment && error instanceof Error) {
|
|
17866
|
+
result.stack = error.stack;
|
|
17867
|
+
}
|
|
17868
|
+
return result;
|
|
17869
|
+
}
|
|
17870
|
+
function getCorrelationId2(headers) {
|
|
17871
|
+
const get = typeof headers === "function" ? headers : (name) => {
|
|
17872
|
+
const val = headers[name] ?? headers[name.toLowerCase()];
|
|
17873
|
+
return Array.isArray(val) ? val[0] : val;
|
|
17874
|
+
};
|
|
17875
|
+
return get("x-request-id") || get("X-Request-ID") || get("x-correlation-id") || get("X-Correlation-ID") || crypto.randomUUID();
|
|
17876
|
+
}
|
|
17877
|
+
|
|
17878
|
+
// src/security-headers.ts
|
|
17879
|
+
var SecurityHeaderPresets = {
|
|
17880
|
+
/** Minimal: basic headers only, no CSP */
|
|
17881
|
+
minimal: {
|
|
17882
|
+
csp: false,
|
|
17883
|
+
hsts: false
|
|
17884
|
+
},
|
|
17885
|
+
/** Standard: full CSP + HSTS for most apps */
|
|
17886
|
+
standard: {
|
|
17887
|
+
csp: true,
|
|
17888
|
+
hsts: true,
|
|
17889
|
+
frameOptions: "DENY"
|
|
17890
|
+
},
|
|
17891
|
+
/** Strict: deny all permissions, strict CSP, no frame embedding */
|
|
17892
|
+
strict: {
|
|
17893
|
+
csp: true,
|
|
17894
|
+
hsts: true,
|
|
17895
|
+
hstsMaxAge: 63072e3,
|
|
17896
|
+
// 2 years
|
|
17897
|
+
frameOptions: "DENY"
|
|
17898
|
+
}
|
|
17899
|
+
};
|
|
17900
|
+
function generateSecurityHeaders(config = {}) {
|
|
17901
|
+
const isProduction = config.isProduction ?? process.env.NODE_ENV === "production";
|
|
17902
|
+
const frameOptions = config.frameOptions ?? "DENY";
|
|
17903
|
+
const enableCsp = config.csp ?? true;
|
|
17904
|
+
const enableHsts = config.hsts ?? true;
|
|
17905
|
+
const hstsMaxAge = config.hstsMaxAge ?? 31536e3;
|
|
17906
|
+
const baseHeaders = [
|
|
17907
|
+
{ key: "X-Frame-Options", value: frameOptions },
|
|
17908
|
+
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
17909
|
+
// Modern browsers use CSP, not XSS-Protection. Value '0' disables the
|
|
17910
|
+
// legacy filter which can itself introduce vulnerabilities.
|
|
17911
|
+
{ key: "X-XSS-Protection", value: "0" },
|
|
17912
|
+
{
|
|
17913
|
+
key: "Referrer-Policy",
|
|
17914
|
+
value: "strict-origin-when-cross-origin"
|
|
17915
|
+
},
|
|
17916
|
+
{
|
|
17917
|
+
key: "Permissions-Policy",
|
|
17918
|
+
value: "camera=(), microphone=(), geolocation=()"
|
|
17919
|
+
}
|
|
17920
|
+
];
|
|
17921
|
+
const entries = [
|
|
17922
|
+
{ source: "/:path*", headers: baseHeaders }
|
|
17923
|
+
];
|
|
17924
|
+
if (isProduction) {
|
|
17925
|
+
const prodHeaders = [];
|
|
17926
|
+
if (enableHsts) {
|
|
17927
|
+
prodHeaders.push({
|
|
17928
|
+
key: "Strict-Transport-Security",
|
|
17929
|
+
value: `max-age=${hstsMaxAge}; includeSubDomains`
|
|
17930
|
+
});
|
|
17931
|
+
}
|
|
17932
|
+
if (enableCsp) {
|
|
17933
|
+
const csp = buildCsp(config);
|
|
17934
|
+
prodHeaders.push({ key: "Content-Security-Policy", value: csp });
|
|
17935
|
+
}
|
|
17936
|
+
if (prodHeaders.length > 0) {
|
|
17937
|
+
entries.push({ source: "/:path*", headers: prodHeaders });
|
|
17938
|
+
}
|
|
17939
|
+
}
|
|
17940
|
+
return entries;
|
|
17941
|
+
}
|
|
17942
|
+
function buildCsp(config) {
|
|
17943
|
+
const scriptSrc = [
|
|
17944
|
+
"'self'",
|
|
17945
|
+
"'unsafe-inline'",
|
|
17946
|
+
"'unsafe-eval'",
|
|
17947
|
+
...config.cspScriptSrc ?? []
|
|
17948
|
+
];
|
|
17949
|
+
const styleSrc = [
|
|
17950
|
+
"'self'",
|
|
17951
|
+
"'unsafe-inline'",
|
|
17952
|
+
"https://fonts.googleapis.com",
|
|
17953
|
+
...config.cspStyleSrc ?? []
|
|
17954
|
+
];
|
|
17955
|
+
const imgSrc = [
|
|
17956
|
+
"'self'",
|
|
17957
|
+
"data:",
|
|
17958
|
+
"https:",
|
|
17959
|
+
"blob:",
|
|
17960
|
+
...config.cspImgSrc ?? []
|
|
17961
|
+
];
|
|
17962
|
+
const fontSrc = ["'self'", "data:", "https://fonts.gstatic.com"];
|
|
17963
|
+
const connectSrc = ["'self'", ...config.cspConnectSrc ?? []];
|
|
17964
|
+
const frameSrc = [...config.cspFrameSrc ?? []];
|
|
17965
|
+
const directives = [
|
|
17966
|
+
`default-src 'self'`,
|
|
17967
|
+
`script-src ${scriptSrc.join(" ")}`,
|
|
17968
|
+
`style-src ${styleSrc.join(" ")}`,
|
|
17969
|
+
`img-src ${imgSrc.join(" ")}`,
|
|
17970
|
+
`font-src ${fontSrc.join(" ")}`,
|
|
17971
|
+
`connect-src ${connectSrc.join(" ")}`
|
|
17972
|
+
];
|
|
17973
|
+
if (frameSrc.length > 0) {
|
|
17974
|
+
directives.push(`frame-src ${frameSrc.join(" ")}`);
|
|
17975
|
+
}
|
|
17976
|
+
directives.push(
|
|
17977
|
+
`object-src 'none'`,
|
|
17978
|
+
`base-uri 'self'`,
|
|
17979
|
+
`form-action 'self'`,
|
|
17980
|
+
`frame-ancestors 'none'`
|
|
17981
|
+
);
|
|
17982
|
+
return directives.join("; ");
|
|
17983
|
+
}
|
|
17363
17984
|
|
|
17364
17985
|
// src/api.ts
|
|
17365
17986
|
var ApiErrorCode = {
|
|
@@ -17486,6 +18107,850 @@ function buildPagination(page, limit, total) {
|
|
|
17486
18107
|
};
|
|
17487
18108
|
}
|
|
17488
18109
|
|
|
18110
|
+
// src/auth/keycloak.ts
|
|
18111
|
+
var KEYCLOAK_DEFAULT_ROLES = [
|
|
18112
|
+
"offline_access",
|
|
18113
|
+
"uma_authorization"
|
|
18114
|
+
];
|
|
18115
|
+
function parseKeycloakRoles(accessToken, additionalDefaultRoles = []) {
|
|
18116
|
+
if (!accessToken) return [];
|
|
18117
|
+
try {
|
|
18118
|
+
const parts = accessToken.split(".");
|
|
18119
|
+
if (parts.length !== 3) return [];
|
|
18120
|
+
const payload = parts[1];
|
|
18121
|
+
const decoded = JSON.parse(atob(payload));
|
|
18122
|
+
const realmRoles = decoded.realm_roles ?? decoded.realm_access?.roles;
|
|
18123
|
+
if (!Array.isArray(realmRoles)) return [];
|
|
18124
|
+
const filterSet = /* @__PURE__ */ new Set([
|
|
18125
|
+
...KEYCLOAK_DEFAULT_ROLES,
|
|
18126
|
+
...additionalDefaultRoles
|
|
18127
|
+
]);
|
|
18128
|
+
return realmRoles.filter(
|
|
18129
|
+
(role) => typeof role === "string" && !filterSet.has(role)
|
|
18130
|
+
);
|
|
18131
|
+
} catch {
|
|
18132
|
+
return [];
|
|
18133
|
+
}
|
|
18134
|
+
}
|
|
18135
|
+
function hasRole(roles, role) {
|
|
18136
|
+
return roles?.includes(role) ?? false;
|
|
18137
|
+
}
|
|
18138
|
+
function hasAnyRole(roles, requiredRoles) {
|
|
18139
|
+
if (!roles || roles.length === 0) return false;
|
|
18140
|
+
return requiredRoles.some((role) => roles.includes(role));
|
|
18141
|
+
}
|
|
18142
|
+
function hasAllRoles(roles, requiredRoles) {
|
|
18143
|
+
if (!roles || roles.length === 0) return false;
|
|
18144
|
+
return requiredRoles.every((role) => roles.includes(role));
|
|
18145
|
+
}
|
|
18146
|
+
function isTokenExpired(expiresAt, bufferMs = 6e4) {
|
|
18147
|
+
if (!expiresAt) return true;
|
|
18148
|
+
return Date.now() >= expiresAt - bufferMs;
|
|
18149
|
+
}
|
|
18150
|
+
function buildTokenRefreshParams(config, refreshToken) {
|
|
18151
|
+
return new URLSearchParams({
|
|
18152
|
+
grant_type: "refresh_token",
|
|
18153
|
+
client_id: config.clientId,
|
|
18154
|
+
client_secret: config.clientSecret,
|
|
18155
|
+
refresh_token: refreshToken
|
|
18156
|
+
});
|
|
18157
|
+
}
|
|
18158
|
+
function getTokenEndpoint(issuer) {
|
|
18159
|
+
const base = issuer.endsWith("/") ? issuer.slice(0, -1) : issuer;
|
|
18160
|
+
return `${base}/protocol/openid-connect/token`;
|
|
18161
|
+
}
|
|
18162
|
+
function getEndSessionEndpoint(issuer) {
|
|
18163
|
+
const base = issuer.endsWith("/") ? issuer.slice(0, -1) : issuer;
|
|
18164
|
+
return `${base}/protocol/openid-connect/logout`;
|
|
18165
|
+
}
|
|
18166
|
+
async function refreshKeycloakToken(config, refreshToken, additionalDefaultRoles) {
|
|
18167
|
+
try {
|
|
18168
|
+
const endpoint = getTokenEndpoint(config.issuer);
|
|
18169
|
+
const params = buildTokenRefreshParams(config, refreshToken);
|
|
18170
|
+
const response = await fetch(endpoint, {
|
|
18171
|
+
method: "POST",
|
|
18172
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
18173
|
+
body: params
|
|
18174
|
+
});
|
|
18175
|
+
if (!response.ok) {
|
|
18176
|
+
const body = await response.text().catch(() => "");
|
|
18177
|
+
return {
|
|
18178
|
+
ok: false,
|
|
18179
|
+
error: `Token refresh failed: HTTP ${response.status} - ${body}`
|
|
18180
|
+
};
|
|
18181
|
+
}
|
|
18182
|
+
const data = await response.json();
|
|
18183
|
+
return {
|
|
18184
|
+
ok: true,
|
|
18185
|
+
tokens: {
|
|
18186
|
+
accessToken: data.access_token,
|
|
18187
|
+
refreshToken: data.refresh_token ?? refreshToken,
|
|
18188
|
+
idToken: data.id_token,
|
|
18189
|
+
expiresAt: Date.now() + data.expires_in * 1e3,
|
|
18190
|
+
roles: parseKeycloakRoles(data.access_token, additionalDefaultRoles)
|
|
18191
|
+
}
|
|
18192
|
+
};
|
|
18193
|
+
} catch (error) {
|
|
18194
|
+
return {
|
|
18195
|
+
ok: false,
|
|
18196
|
+
error: error instanceof Error ? error.message : "Token refresh failed"
|
|
18197
|
+
};
|
|
18198
|
+
}
|
|
18199
|
+
}
|
|
18200
|
+
|
|
18201
|
+
// src/auth/nextjs-keycloak.ts
|
|
18202
|
+
function buildAuthCookies(config = {}) {
|
|
18203
|
+
const { domain, sessionToken = true, callbackUrl = true } = config;
|
|
18204
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
18205
|
+
const cookieDomain = isProduction ? domain : void 0;
|
|
18206
|
+
const baseOptions = {
|
|
18207
|
+
httpOnly: true,
|
|
18208
|
+
sameSite: "lax",
|
|
18209
|
+
path: "/",
|
|
18210
|
+
secure: isProduction,
|
|
18211
|
+
domain: cookieDomain
|
|
18212
|
+
};
|
|
18213
|
+
const cookies = {
|
|
18214
|
+
pkceCodeVerifier: {
|
|
18215
|
+
name: "authjs.pkce.code_verifier",
|
|
18216
|
+
options: { ...baseOptions }
|
|
18217
|
+
},
|
|
18218
|
+
state: {
|
|
18219
|
+
name: "authjs.state",
|
|
18220
|
+
options: { ...baseOptions }
|
|
18221
|
+
}
|
|
18222
|
+
};
|
|
18223
|
+
if (sessionToken) {
|
|
18224
|
+
cookies.sessionToken = {
|
|
18225
|
+
name: isProduction ? "__Secure-authjs.session-token" : "authjs.session-token",
|
|
18226
|
+
options: { ...baseOptions }
|
|
18227
|
+
};
|
|
18228
|
+
}
|
|
18229
|
+
if (callbackUrl) {
|
|
18230
|
+
cookies.callbackUrl = {
|
|
18231
|
+
name: isProduction ? "__Secure-authjs.callback-url" : "authjs.callback-url",
|
|
18232
|
+
options: { ...baseOptions }
|
|
18233
|
+
};
|
|
18234
|
+
}
|
|
18235
|
+
return cookies;
|
|
18236
|
+
}
|
|
18237
|
+
function buildRedirectCallback(config = {}) {
|
|
18238
|
+
const { allowWwwVariant = false } = config;
|
|
18239
|
+
return async ({ url, baseUrl }) => {
|
|
18240
|
+
if (url.startsWith("/")) return `${baseUrl}${url}`;
|
|
18241
|
+
try {
|
|
18242
|
+
if (new URL(url).origin === baseUrl) return url;
|
|
18243
|
+
} catch {
|
|
18244
|
+
return baseUrl;
|
|
18245
|
+
}
|
|
18246
|
+
if (allowWwwVariant) {
|
|
18247
|
+
try {
|
|
18248
|
+
const urlHost = new URL(url).hostname;
|
|
18249
|
+
const baseHost = new URL(baseUrl).hostname;
|
|
18250
|
+
if (urlHost === `www.${baseHost}` || baseHost === `www.${urlHost}`) {
|
|
18251
|
+
return url;
|
|
18252
|
+
}
|
|
18253
|
+
} catch {
|
|
18254
|
+
}
|
|
18255
|
+
}
|
|
18256
|
+
return baseUrl;
|
|
18257
|
+
};
|
|
18258
|
+
}
|
|
18259
|
+
function buildKeycloakCallbacks(config) {
|
|
18260
|
+
const {
|
|
18261
|
+
issuer,
|
|
18262
|
+
clientId,
|
|
18263
|
+
clientSecret,
|
|
18264
|
+
defaultRoles = [],
|
|
18265
|
+
debug = process.env.NODE_ENV === "development"
|
|
18266
|
+
} = config;
|
|
18267
|
+
const kcConfig = { issuer, clientId, clientSecret };
|
|
18268
|
+
function log(message, meta) {
|
|
18269
|
+
if (debug) {
|
|
18270
|
+
console.log(`[Auth] ${message}`, meta ? JSON.stringify(meta) : "");
|
|
18271
|
+
}
|
|
18272
|
+
}
|
|
18273
|
+
return {
|
|
18274
|
+
/**
|
|
18275
|
+
* JWT callback — stores Keycloak tokens and handles refresh.
|
|
18276
|
+
*
|
|
18277
|
+
* Compatible with Auth.js v5 JWT callback signature.
|
|
18278
|
+
*/
|
|
18279
|
+
async jwt({
|
|
18280
|
+
token,
|
|
18281
|
+
user,
|
|
18282
|
+
account
|
|
18283
|
+
}) {
|
|
18284
|
+
if (user) {
|
|
18285
|
+
token.id = token.sub ?? user.id;
|
|
18286
|
+
}
|
|
18287
|
+
if (account?.provider === "keycloak") {
|
|
18288
|
+
token.accessToken = account.access_token;
|
|
18289
|
+
token.refreshToken = account.refresh_token;
|
|
18290
|
+
token.idToken = account.id_token;
|
|
18291
|
+
token.roles = parseKeycloakRoles(
|
|
18292
|
+
account.access_token,
|
|
18293
|
+
defaultRoles
|
|
18294
|
+
);
|
|
18295
|
+
token.accessTokenExpires = account.expires_at ? account.expires_at * 1e3 : Date.now() + 3e5;
|
|
18296
|
+
return token;
|
|
18297
|
+
}
|
|
18298
|
+
if (!isTokenExpired(token.accessTokenExpires)) {
|
|
18299
|
+
return token;
|
|
18300
|
+
}
|
|
18301
|
+
if (token.refreshToken) {
|
|
18302
|
+
log("Token expired, attempting refresh...");
|
|
18303
|
+
const result = await refreshKeycloakToken(
|
|
18304
|
+
kcConfig,
|
|
18305
|
+
token.refreshToken,
|
|
18306
|
+
defaultRoles
|
|
18307
|
+
);
|
|
18308
|
+
if (result.ok) {
|
|
18309
|
+
token.accessToken = result.tokens.accessToken;
|
|
18310
|
+
token.idToken = result.tokens.idToken ?? token.idToken;
|
|
18311
|
+
token.refreshToken = result.tokens.refreshToken ?? token.refreshToken;
|
|
18312
|
+
token.accessTokenExpires = result.tokens.expiresAt;
|
|
18313
|
+
token.roles = result.tokens.roles;
|
|
18314
|
+
delete token.error;
|
|
18315
|
+
log("Token refreshed OK");
|
|
18316
|
+
return token;
|
|
18317
|
+
}
|
|
18318
|
+
log("Token refresh failed", { error: result.error });
|
|
18319
|
+
return { ...token, error: "RefreshTokenError" };
|
|
18320
|
+
}
|
|
18321
|
+
log("Token expired but no refresh token available");
|
|
18322
|
+
return { ...token, error: "RefreshTokenError" };
|
|
18323
|
+
},
|
|
18324
|
+
/**
|
|
18325
|
+
* Session callback — maps JWT fields to the session object.
|
|
18326
|
+
*
|
|
18327
|
+
* Compatible with Auth.js v5 session callback signature.
|
|
18328
|
+
*/
|
|
18329
|
+
async session({
|
|
18330
|
+
session,
|
|
18331
|
+
token
|
|
18332
|
+
}) {
|
|
18333
|
+
const user = session.user;
|
|
18334
|
+
if (user) {
|
|
18335
|
+
user.id = token.id || token.sub;
|
|
18336
|
+
user.roles = token.roles || [];
|
|
18337
|
+
}
|
|
18338
|
+
session.idToken = token.idToken;
|
|
18339
|
+
session.accessToken = token.accessToken;
|
|
18340
|
+
if (token.error) {
|
|
18341
|
+
session.error = token.error;
|
|
18342
|
+
}
|
|
18343
|
+
return session;
|
|
18344
|
+
}
|
|
18345
|
+
};
|
|
18346
|
+
}
|
|
18347
|
+
|
|
18348
|
+
// src/auth/api-security.ts
|
|
18349
|
+
var StandardRateLimitPresets = {
|
|
18350
|
+
/** General API: 100/min, 200/min authenticated */
|
|
18351
|
+
apiGeneral: {
|
|
18352
|
+
limit: 100,
|
|
18353
|
+
windowSeconds: 60,
|
|
18354
|
+
authenticatedLimit: 200
|
|
18355
|
+
},
|
|
18356
|
+
/** Admin operations: 100/min (admins are trusted) */
|
|
18357
|
+
adminAction: {
|
|
18358
|
+
limit: 100,
|
|
18359
|
+
windowSeconds: 60
|
|
18360
|
+
},
|
|
18361
|
+
/** AI/expensive operations: 20/hour, 50/hour authenticated */
|
|
18362
|
+
aiRequest: {
|
|
18363
|
+
limit: 20,
|
|
18364
|
+
windowSeconds: 3600,
|
|
18365
|
+
authenticatedLimit: 50
|
|
18366
|
+
},
|
|
18367
|
+
/** Auth attempts: 5/15min with 15min block */
|
|
18368
|
+
authAttempt: {
|
|
18369
|
+
limit: 5,
|
|
18370
|
+
windowSeconds: 900,
|
|
18371
|
+
blockDurationSeconds: 900
|
|
18372
|
+
},
|
|
18373
|
+
/** Contact/public forms: 10/hour */
|
|
18374
|
+
publicForm: {
|
|
18375
|
+
limit: 10,
|
|
18376
|
+
windowSeconds: 3600,
|
|
18377
|
+
blockDurationSeconds: 1800
|
|
18378
|
+
},
|
|
18379
|
+
/** Checkout/billing: 10/hour with 1hr block */
|
|
18380
|
+
checkout: {
|
|
18381
|
+
limit: 10,
|
|
18382
|
+
windowSeconds: 3600,
|
|
18383
|
+
blockDurationSeconds: 3600
|
|
18384
|
+
}
|
|
18385
|
+
};
|
|
18386
|
+
function resolveRateLimitIdentifier(session, clientIp) {
|
|
18387
|
+
if (session?.user?.id) {
|
|
18388
|
+
return { identifier: `user:${session.user.id}`, isAuthenticated: true };
|
|
18389
|
+
}
|
|
18390
|
+
if (session?.user?.email) {
|
|
18391
|
+
return {
|
|
18392
|
+
identifier: `email:${session.user.email}`,
|
|
18393
|
+
isAuthenticated: true
|
|
18394
|
+
};
|
|
18395
|
+
}
|
|
18396
|
+
return { identifier: `ip:${clientIp}`, isAuthenticated: false };
|
|
18397
|
+
}
|
|
18398
|
+
function extractClientIp(getHeader) {
|
|
18399
|
+
return getHeader("cf-connecting-ip") || getHeader("x-real-ip") || getHeader("x-forwarded-for")?.split(",")[0]?.trim() || "unknown";
|
|
18400
|
+
}
|
|
18401
|
+
function buildRateLimitHeaders(limit, remaining, resetAtMs) {
|
|
18402
|
+
return {
|
|
18403
|
+
"X-RateLimit-Limit": String(limit),
|
|
18404
|
+
"X-RateLimit-Remaining": String(Math.max(0, remaining)),
|
|
18405
|
+
"X-RateLimit-Reset": String(Math.ceil(resetAtMs / 1e3))
|
|
18406
|
+
};
|
|
18407
|
+
}
|
|
18408
|
+
function buildErrorBody(error, extra) {
|
|
18409
|
+
return { error, ...extra };
|
|
18410
|
+
}
|
|
18411
|
+
var WrapperPresets = {
|
|
18412
|
+
/** Public route: no auth, rate limited */
|
|
18413
|
+
public: {
|
|
18414
|
+
requireAuth: false,
|
|
18415
|
+
requireAdmin: false,
|
|
18416
|
+
rateLimit: "apiGeneral"
|
|
18417
|
+
},
|
|
18418
|
+
/** Authenticated route: requires session */
|
|
18419
|
+
authenticated: {
|
|
18420
|
+
requireAuth: true,
|
|
18421
|
+
requireAdmin: false,
|
|
18422
|
+
rateLimit: "apiGeneral"
|
|
18423
|
+
},
|
|
18424
|
+
/** Admin route: requires session with admin role */
|
|
18425
|
+
admin: {
|
|
18426
|
+
requireAuth: true,
|
|
18427
|
+
requireAdmin: true,
|
|
18428
|
+
rateLimit: "adminAction"
|
|
18429
|
+
},
|
|
18430
|
+
/** Legacy admin: accepts session OR bearer token */
|
|
18431
|
+
legacyAdmin: {
|
|
18432
|
+
requireAuth: true,
|
|
18433
|
+
requireAdmin: true,
|
|
18434
|
+
allowBearerToken: true,
|
|
18435
|
+
rateLimit: "adminAction"
|
|
18436
|
+
},
|
|
18437
|
+
/** AI/expensive: requires auth, strict rate limit */
|
|
18438
|
+
ai: {
|
|
18439
|
+
requireAuth: true,
|
|
18440
|
+
requireAdmin: false,
|
|
18441
|
+
rateLimit: "aiRequest"
|
|
18442
|
+
},
|
|
18443
|
+
/** Cron: no rate limit, admin-level access */
|
|
18444
|
+
cron: {
|
|
18445
|
+
requireAuth: true,
|
|
18446
|
+
requireAdmin: false,
|
|
18447
|
+
skipRateLimit: true,
|
|
18448
|
+
skipAudit: false
|
|
18449
|
+
}
|
|
18450
|
+
};
|
|
18451
|
+
|
|
18452
|
+
// src/auth/schemas.ts
|
|
18453
|
+
var import_zod2 = require("zod");
|
|
18454
|
+
var EmailSchema = import_zod2.z.string().trim().toLowerCase().email("Invalid email address");
|
|
18455
|
+
var PasswordSchema = import_zod2.z.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters");
|
|
18456
|
+
var SlugSchema = import_zod2.z.string().min(1, "Slug is required").max(100, "Slug must be less than 100 characters").regex(
|
|
18457
|
+
/^[a-z0-9-]+$/,
|
|
18458
|
+
"Slug can only contain lowercase letters, numbers, and hyphens"
|
|
18459
|
+
);
|
|
18460
|
+
var PhoneSchema = import_zod2.z.string().regex(/^[\d\s()+.\-]{7,20}$/, "Invalid phone number format");
|
|
18461
|
+
var PersonNameSchema = import_zod2.z.string().min(2, "Name must be at least 2 characters").max(100, "Name must be less than 100 characters").regex(
|
|
18462
|
+
/^[a-zA-Z\s\-']+$/,
|
|
18463
|
+
"Name can only contain letters, spaces, hyphens and apostrophes"
|
|
18464
|
+
);
|
|
18465
|
+
function createSafeTextSchema(options) {
|
|
18466
|
+
const {
|
|
18467
|
+
min,
|
|
18468
|
+
max,
|
|
18469
|
+
allowHtml = false,
|
|
18470
|
+
allowUrls = false,
|
|
18471
|
+
fieldName = "Text"
|
|
18472
|
+
} = options ?? {};
|
|
18473
|
+
let schema = import_zod2.z.string();
|
|
18474
|
+
if (min !== void 0)
|
|
18475
|
+
schema = schema.min(min, `${fieldName} must be at least ${min} characters`);
|
|
18476
|
+
if (max !== void 0)
|
|
18477
|
+
schema = schema.max(
|
|
18478
|
+
max,
|
|
18479
|
+
`${fieldName} must be less than ${max} characters`
|
|
18480
|
+
);
|
|
18481
|
+
if (!allowHtml && !allowUrls) {
|
|
18482
|
+
return schema.refine((val) => !HTML_TAG_PATTERN.test(val), "HTML tags are not allowed").refine(
|
|
18483
|
+
(val) => !URL_PROTOCOL_PATTERN.test(val),
|
|
18484
|
+
"Links are not allowed for security reasons"
|
|
18485
|
+
).refine(
|
|
18486
|
+
(val) => !URL_DOMAIN_PATTERN.test(val),
|
|
18487
|
+
"Links are not allowed for security reasons"
|
|
18488
|
+
);
|
|
18489
|
+
}
|
|
18490
|
+
if (!allowHtml) {
|
|
18491
|
+
return schema.refine(
|
|
18492
|
+
(val) => !HTML_TAG_PATTERN.test(val),
|
|
18493
|
+
"HTML tags are not allowed"
|
|
18494
|
+
);
|
|
18495
|
+
}
|
|
18496
|
+
if (!allowUrls) {
|
|
18497
|
+
return schema.refine(
|
|
18498
|
+
(val) => !URL_PROTOCOL_PATTERN.test(val),
|
|
18499
|
+
"Links are not allowed for security reasons"
|
|
18500
|
+
).refine(
|
|
18501
|
+
(val) => !URL_DOMAIN_PATTERN.test(val),
|
|
18502
|
+
"Links are not allowed for security reasons"
|
|
18503
|
+
);
|
|
18504
|
+
}
|
|
18505
|
+
return schema;
|
|
18506
|
+
}
|
|
18507
|
+
var PaginationSchema = import_zod2.z.object({
|
|
18508
|
+
page: import_zod2.z.coerce.number().int().positive().default(1),
|
|
18509
|
+
limit: import_zod2.z.coerce.number().int().positive().max(100).default(20),
|
|
18510
|
+
sortBy: import_zod2.z.string().optional(),
|
|
18511
|
+
sortOrder: import_zod2.z.enum(["asc", "desc"]).default("desc")
|
|
18512
|
+
});
|
|
18513
|
+
var DateRangeSchema = import_zod2.z.object({
|
|
18514
|
+
startDate: import_zod2.z.string().datetime(),
|
|
18515
|
+
endDate: import_zod2.z.string().datetime()
|
|
18516
|
+
}).refine((data) => new Date(data.startDate) <= new Date(data.endDate), {
|
|
18517
|
+
message: "Start date must be before end date"
|
|
18518
|
+
});
|
|
18519
|
+
var SearchQuerySchema = import_zod2.z.object({
|
|
18520
|
+
query: import_zod2.z.string().min(1).max(200).trim(),
|
|
18521
|
+
page: import_zod2.z.coerce.number().int().positive().default(1),
|
|
18522
|
+
limit: import_zod2.z.coerce.number().int().positive().max(50).default(10)
|
|
18523
|
+
});
|
|
18524
|
+
var LoginSchema = import_zod2.z.object({
|
|
18525
|
+
email: EmailSchema,
|
|
18526
|
+
password: PasswordSchema
|
|
18527
|
+
});
|
|
18528
|
+
var SignupSchema = import_zod2.z.object({
|
|
18529
|
+
email: EmailSchema,
|
|
18530
|
+
password: PasswordSchema,
|
|
18531
|
+
name: import_zod2.z.string().min(2).max(100).optional()
|
|
18532
|
+
});
|
|
18533
|
+
|
|
18534
|
+
// src/auth/feature-flags.ts
|
|
18535
|
+
function detectStage() {
|
|
18536
|
+
const stage = process.env.DEPLOYMENT_STAGE;
|
|
18537
|
+
if (stage === "staging" || stage === "preview") return stage;
|
|
18538
|
+
if (process.env.NODE_ENV === "production") return "production";
|
|
18539
|
+
return "development";
|
|
18540
|
+
}
|
|
18541
|
+
function resolveFlagValue(value) {
|
|
18542
|
+
if (typeof value === "boolean") return value;
|
|
18543
|
+
const envValue = process.env[value.envVar];
|
|
18544
|
+
if (envValue === void 0 || envValue === "") {
|
|
18545
|
+
return value.default ?? false;
|
|
18546
|
+
}
|
|
18547
|
+
return envValue === "true" || envValue === "1";
|
|
18548
|
+
}
|
|
18549
|
+
function createFeatureFlags(definitions) {
|
|
18550
|
+
return {
|
|
18551
|
+
/**
|
|
18552
|
+
* Resolve all flags for the current environment.
|
|
18553
|
+
* Call this once at startup or per-request for dynamic flags.
|
|
18554
|
+
*/
|
|
18555
|
+
resolve(stage) {
|
|
18556
|
+
const currentStage = stage ?? detectStage();
|
|
18557
|
+
const resolved = {};
|
|
18558
|
+
for (const [key, def] of Object.entries(definitions)) {
|
|
18559
|
+
const stageKey = currentStage === "preview" ? "staging" : currentStage;
|
|
18560
|
+
resolved[key] = resolveFlagValue(def[stageKey]);
|
|
18561
|
+
}
|
|
18562
|
+
return resolved;
|
|
18563
|
+
},
|
|
18564
|
+
/**
|
|
18565
|
+
* Check if a single flag is enabled.
|
|
18566
|
+
*/
|
|
18567
|
+
isEnabled(flag, stage) {
|
|
18568
|
+
const currentStage = stage ?? detectStage();
|
|
18569
|
+
const def = definitions[flag];
|
|
18570
|
+
const stageKey = currentStage === "preview" ? "staging" : currentStage;
|
|
18571
|
+
return resolveFlagValue(def[stageKey]);
|
|
18572
|
+
},
|
|
18573
|
+
/**
|
|
18574
|
+
* Get the flag definitions (for introspection/admin UI).
|
|
18575
|
+
*/
|
|
18576
|
+
definitions
|
|
18577
|
+
};
|
|
18578
|
+
}
|
|
18579
|
+
function buildAllowlist(config) {
|
|
18580
|
+
const fromEnv = config.envVar ? process.env[config.envVar]?.split(",").map((e) => e.trim().toLowerCase()).filter(Boolean) ?? [] : [];
|
|
18581
|
+
const fallback = config.fallback?.map((e) => e.toLowerCase()) ?? [];
|
|
18582
|
+
return [.../* @__PURE__ */ new Set([...fromEnv, ...fallback])];
|
|
18583
|
+
}
|
|
18584
|
+
function isAllowlisted(email, allowlist) {
|
|
18585
|
+
return allowlist.includes(email.toLowerCase());
|
|
18586
|
+
}
|
|
18587
|
+
|
|
18588
|
+
// src/auth/rate-limiter.ts
|
|
18589
|
+
var CommonRateLimits = {
|
|
18590
|
+
/** General API: 100/min, 200/min authenticated */
|
|
18591
|
+
apiGeneral: {
|
|
18592
|
+
limit: 100,
|
|
18593
|
+
windowSeconds: 60,
|
|
18594
|
+
authenticatedLimit: 200
|
|
18595
|
+
},
|
|
18596
|
+
/** Admin actions: 100/min */
|
|
18597
|
+
adminAction: {
|
|
18598
|
+
limit: 100,
|
|
18599
|
+
windowSeconds: 60
|
|
18600
|
+
},
|
|
18601
|
+
/** Auth attempts: 10/15min with 30min block */
|
|
18602
|
+
authAttempt: {
|
|
18603
|
+
limit: 10,
|
|
18604
|
+
windowSeconds: 900,
|
|
18605
|
+
blockDurationSeconds: 1800
|
|
18606
|
+
},
|
|
18607
|
+
/** AI/expensive requests: 20/hour, 50/hour authenticated */
|
|
18608
|
+
aiRequest: {
|
|
18609
|
+
limit: 20,
|
|
18610
|
+
windowSeconds: 3600,
|
|
18611
|
+
authenticatedLimit: 50
|
|
18612
|
+
},
|
|
18613
|
+
/** Public form submissions: 5/hour with 1hr block */
|
|
18614
|
+
publicForm: {
|
|
18615
|
+
limit: 5,
|
|
18616
|
+
windowSeconds: 3600,
|
|
18617
|
+
blockDurationSeconds: 3600
|
|
18618
|
+
},
|
|
18619
|
+
/** Checkout/billing: 10/hour with 1hr block */
|
|
18620
|
+
checkout: {
|
|
18621
|
+
limit: 10,
|
|
18622
|
+
windowSeconds: 3600,
|
|
18623
|
+
blockDurationSeconds: 3600
|
|
18624
|
+
}
|
|
18625
|
+
};
|
|
18626
|
+
function createMemoryRateLimitStore() {
|
|
18627
|
+
const windows = /* @__PURE__ */ new Map();
|
|
18628
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
18629
|
+
const cleanupInterval = setInterval(() => {
|
|
18630
|
+
const now = Date.now();
|
|
18631
|
+
for (const [key, entry] of windows) {
|
|
18632
|
+
if (entry.expiresAt < now) windows.delete(key);
|
|
18633
|
+
}
|
|
18634
|
+
for (const [key, expiry] of blocks) {
|
|
18635
|
+
if (expiry < now) blocks.delete(key);
|
|
18636
|
+
}
|
|
18637
|
+
}, 60 * 1e3);
|
|
18638
|
+
if (cleanupInterval.unref) {
|
|
18639
|
+
cleanupInterval.unref();
|
|
18640
|
+
}
|
|
18641
|
+
return {
|
|
18642
|
+
async increment(key, windowMs, now) {
|
|
18643
|
+
const windowStart = now - windowMs;
|
|
18644
|
+
let entry = windows.get(key);
|
|
18645
|
+
if (!entry) {
|
|
18646
|
+
entry = { timestamps: [], expiresAt: now + windowMs + 6e4 };
|
|
18647
|
+
windows.set(key, entry);
|
|
18648
|
+
}
|
|
18649
|
+
entry.timestamps = entry.timestamps.filter((t) => t > windowStart);
|
|
18650
|
+
entry.timestamps.push(now);
|
|
18651
|
+
entry.expiresAt = now + windowMs + 6e4;
|
|
18652
|
+
return { count: entry.timestamps.length };
|
|
18653
|
+
},
|
|
18654
|
+
async isBlocked(key) {
|
|
18655
|
+
const expiry = blocks.get(key);
|
|
18656
|
+
if (!expiry || expiry < Date.now()) {
|
|
18657
|
+
blocks.delete(key);
|
|
18658
|
+
return { blocked: false, ttlMs: 0 };
|
|
18659
|
+
}
|
|
18660
|
+
return { blocked: true, ttlMs: expiry - Date.now() };
|
|
18661
|
+
},
|
|
18662
|
+
async setBlock(key, durationSeconds) {
|
|
18663
|
+
blocks.set(key, Date.now() + durationSeconds * 1e3);
|
|
18664
|
+
},
|
|
18665
|
+
async reset(key) {
|
|
18666
|
+
windows.delete(key);
|
|
18667
|
+
blocks.delete(`block:${key}`);
|
|
18668
|
+
blocks.delete(key);
|
|
18669
|
+
}
|
|
18670
|
+
};
|
|
18671
|
+
}
|
|
18672
|
+
var defaultStore;
|
|
18673
|
+
function getDefaultStore() {
|
|
18674
|
+
if (!defaultStore) {
|
|
18675
|
+
defaultStore = createMemoryRateLimitStore();
|
|
18676
|
+
}
|
|
18677
|
+
return defaultStore;
|
|
18678
|
+
}
|
|
18679
|
+
async function checkRateLimit(operation, identifier, rule, options = {}) {
|
|
18680
|
+
const store = options.store ?? getDefaultStore();
|
|
18681
|
+
const limit = options.isAuthenticated && rule.authenticatedLimit ? rule.authenticatedLimit : rule.limit;
|
|
18682
|
+
const now = Date.now();
|
|
18683
|
+
const windowMs = rule.windowSeconds * 1e3;
|
|
18684
|
+
const resetAt = now + windowMs;
|
|
18685
|
+
const key = `ratelimit:${operation}:${identifier}`;
|
|
18686
|
+
const blockKey = `ratelimit:block:${operation}:${identifier}`;
|
|
18687
|
+
try {
|
|
18688
|
+
if (rule.blockDurationSeconds) {
|
|
18689
|
+
const blockStatus = await store.isBlocked(blockKey);
|
|
18690
|
+
if (blockStatus.blocked) {
|
|
18691
|
+
return {
|
|
18692
|
+
allowed: false,
|
|
18693
|
+
remaining: 0,
|
|
18694
|
+
resetAt: now + blockStatus.ttlMs,
|
|
18695
|
+
current: limit + 1,
|
|
18696
|
+
limit,
|
|
18697
|
+
retryAfterSeconds: Math.ceil(blockStatus.ttlMs / 1e3)
|
|
18698
|
+
};
|
|
18699
|
+
}
|
|
18700
|
+
}
|
|
18701
|
+
const { count } = await store.increment(key, windowMs, now);
|
|
18702
|
+
if (count > limit) {
|
|
18703
|
+
options.logger?.warn("Rate limit exceeded", {
|
|
18704
|
+
operation,
|
|
18705
|
+
identifier,
|
|
18706
|
+
current: count,
|
|
18707
|
+
limit
|
|
18708
|
+
});
|
|
18709
|
+
if (rule.blockDurationSeconds) {
|
|
18710
|
+
await store.setBlock(blockKey, rule.blockDurationSeconds);
|
|
18711
|
+
}
|
|
18712
|
+
return {
|
|
18713
|
+
allowed: false,
|
|
18714
|
+
remaining: 0,
|
|
18715
|
+
resetAt,
|
|
18716
|
+
current: count,
|
|
18717
|
+
limit,
|
|
18718
|
+
retryAfterSeconds: Math.ceil(windowMs / 1e3)
|
|
18719
|
+
};
|
|
18720
|
+
}
|
|
18721
|
+
return {
|
|
18722
|
+
allowed: true,
|
|
18723
|
+
remaining: limit - count,
|
|
18724
|
+
resetAt,
|
|
18725
|
+
current: count,
|
|
18726
|
+
limit,
|
|
18727
|
+
retryAfterSeconds: 0
|
|
18728
|
+
};
|
|
18729
|
+
} catch (error) {
|
|
18730
|
+
options.logger?.error("Rate limit check failed, allowing request", {
|
|
18731
|
+
error: error instanceof Error ? error.message : String(error),
|
|
18732
|
+
operation,
|
|
18733
|
+
identifier
|
|
18734
|
+
});
|
|
18735
|
+
return {
|
|
18736
|
+
allowed: true,
|
|
18737
|
+
remaining: limit,
|
|
18738
|
+
resetAt,
|
|
18739
|
+
current: 0,
|
|
18740
|
+
limit,
|
|
18741
|
+
retryAfterSeconds: 0
|
|
18742
|
+
};
|
|
18743
|
+
}
|
|
18744
|
+
}
|
|
18745
|
+
async function getRateLimitStatus(operation, identifier, rule, store) {
|
|
18746
|
+
const s = store ?? getDefaultStore();
|
|
18747
|
+
const key = `ratelimit:${operation}:${identifier}`;
|
|
18748
|
+
const now = Date.now();
|
|
18749
|
+
const windowMs = rule.windowSeconds * 1e3;
|
|
18750
|
+
try {
|
|
18751
|
+
const { count } = await s.increment(key, windowMs, now);
|
|
18752
|
+
return {
|
|
18753
|
+
allowed: count <= rule.limit,
|
|
18754
|
+
remaining: Math.max(0, rule.limit - count),
|
|
18755
|
+
resetAt: now + windowMs,
|
|
18756
|
+
current: count,
|
|
18757
|
+
limit: rule.limit,
|
|
18758
|
+
retryAfterSeconds: count > rule.limit ? Math.ceil(windowMs / 1e3) : 0
|
|
18759
|
+
};
|
|
18760
|
+
} catch {
|
|
18761
|
+
return null;
|
|
18762
|
+
}
|
|
18763
|
+
}
|
|
18764
|
+
async function resetRateLimitForKey(operation, identifier, store) {
|
|
18765
|
+
const s = store ?? getDefaultStore();
|
|
18766
|
+
const key = `ratelimit:${operation}:${identifier}`;
|
|
18767
|
+
const blockKey = `ratelimit:block:${operation}:${identifier}`;
|
|
18768
|
+
await s.reset(key);
|
|
18769
|
+
await s.reset(blockKey);
|
|
18770
|
+
}
|
|
18771
|
+
function buildRateLimitResponseHeaders(result) {
|
|
18772
|
+
const headers = {
|
|
18773
|
+
"X-RateLimit-Limit": String(result.limit),
|
|
18774
|
+
"X-RateLimit-Remaining": String(result.remaining),
|
|
18775
|
+
"X-RateLimit-Reset": String(Math.ceil(result.resetAt / 1e3))
|
|
18776
|
+
};
|
|
18777
|
+
if (!result.allowed) {
|
|
18778
|
+
headers["Retry-After"] = String(result.retryAfterSeconds);
|
|
18779
|
+
}
|
|
18780
|
+
return headers;
|
|
18781
|
+
}
|
|
18782
|
+
function resolveIdentifier(session, clientIp) {
|
|
18783
|
+
if (session?.user?.id) {
|
|
18784
|
+
return { identifier: `user:${session.user.id}`, isAuthenticated: true };
|
|
18785
|
+
}
|
|
18786
|
+
if (session?.user?.email) {
|
|
18787
|
+
return {
|
|
18788
|
+
identifier: `email:${session.user.email}`,
|
|
18789
|
+
isAuthenticated: true
|
|
18790
|
+
};
|
|
18791
|
+
}
|
|
18792
|
+
return { identifier: `ip:${clientIp ?? "unknown"}`, isAuthenticated: false };
|
|
18793
|
+
}
|
|
18794
|
+
|
|
18795
|
+
// src/auth/audit.ts
|
|
18796
|
+
var StandardAuditActions = {
|
|
18797
|
+
// Authentication
|
|
18798
|
+
LOGIN_SUCCESS: "auth.login.success",
|
|
18799
|
+
LOGIN_FAILURE: "auth.login.failure",
|
|
18800
|
+
LOGOUT: "auth.logout",
|
|
18801
|
+
SESSION_REFRESH: "auth.session.refresh",
|
|
18802
|
+
PASSWORD_CHANGE: "auth.password.change",
|
|
18803
|
+
PASSWORD_RESET: "auth.password.reset",
|
|
18804
|
+
// Billing
|
|
18805
|
+
CHECKOUT_START: "billing.checkout.start",
|
|
18806
|
+
CHECKOUT_COMPLETE: "billing.checkout.complete",
|
|
18807
|
+
SUBSCRIPTION_CREATE: "billing.subscription.create",
|
|
18808
|
+
SUBSCRIPTION_CANCEL: "billing.subscription.cancel",
|
|
18809
|
+
SUBSCRIPTION_UPDATE: "billing.subscription.update",
|
|
18810
|
+
PAYMENT_FAILED: "billing.payment.failed",
|
|
18811
|
+
// Admin
|
|
18812
|
+
ADMIN_LOGIN: "admin.login",
|
|
18813
|
+
ADMIN_USER_VIEW: "admin.user.view",
|
|
18814
|
+
ADMIN_USER_UPDATE: "admin.user.update",
|
|
18815
|
+
ADMIN_CONFIG_CHANGE: "admin.config.change",
|
|
18816
|
+
// Security Events
|
|
18817
|
+
RATE_LIMIT_EXCEEDED: "security.rate_limit.exceeded",
|
|
18818
|
+
INVALID_INPUT: "security.input.invalid",
|
|
18819
|
+
UNAUTHORIZED_ACCESS: "security.access.unauthorized",
|
|
18820
|
+
OWNERSHIP_VIOLATION: "security.ownership.violation",
|
|
18821
|
+
WEBHOOK_SIGNATURE_INVALID: "security.webhook.signature_invalid",
|
|
18822
|
+
// Data
|
|
18823
|
+
DATA_EXPORT: "data.export",
|
|
18824
|
+
DATA_DELETE: "data.delete",
|
|
18825
|
+
DATA_UPDATE: "data.update"
|
|
18826
|
+
};
|
|
18827
|
+
function extractAuditIp(request) {
|
|
18828
|
+
if (!request) return void 0;
|
|
18829
|
+
const headers = [
|
|
18830
|
+
"cf-connecting-ip",
|
|
18831
|
+
// Cloudflare
|
|
18832
|
+
"x-real-ip",
|
|
18833
|
+
// Nginx
|
|
18834
|
+
"x-forwarded-for",
|
|
18835
|
+
// Standard proxy
|
|
18836
|
+
"x-client-ip"
|
|
18837
|
+
// Apache
|
|
18838
|
+
];
|
|
18839
|
+
for (const header of headers) {
|
|
18840
|
+
const value = request.headers.get(header);
|
|
18841
|
+
if (value) {
|
|
18842
|
+
return value.split(",")[0]?.trim();
|
|
18843
|
+
}
|
|
18844
|
+
}
|
|
18845
|
+
return void 0;
|
|
18846
|
+
}
|
|
18847
|
+
function extractAuditUserAgent(request) {
|
|
18848
|
+
return request?.headers.get("user-agent") ?? void 0;
|
|
18849
|
+
}
|
|
18850
|
+
function extractAuditRequestId(request) {
|
|
18851
|
+
return request?.headers.get("x-request-id") ?? crypto.randomUUID();
|
|
18852
|
+
}
|
|
18853
|
+
function createAuditActor(session) {
|
|
18854
|
+
if (!session?.user) {
|
|
18855
|
+
return { id: "anonymous", type: "anonymous" };
|
|
18856
|
+
}
|
|
18857
|
+
return {
|
|
18858
|
+
id: session.user.id ?? session.user.email ?? "unknown",
|
|
18859
|
+
email: session.user.email ?? void 0,
|
|
18860
|
+
type: "user"
|
|
18861
|
+
};
|
|
18862
|
+
}
|
|
18863
|
+
var defaultLogger = {
|
|
18864
|
+
info: (msg, meta) => console.log(msg, meta ? JSON.stringify(meta) : ""),
|
|
18865
|
+
warn: (msg, meta) => console.warn(msg, meta ? JSON.stringify(meta) : ""),
|
|
18866
|
+
error: (msg, meta) => console.error(msg, meta ? JSON.stringify(meta) : "")
|
|
18867
|
+
};
|
|
18868
|
+
function createAuditLogger(options = {}) {
|
|
18869
|
+
const { persist, logger = defaultLogger } = options;
|
|
18870
|
+
async function log(event, request) {
|
|
18871
|
+
const record = {
|
|
18872
|
+
id: crypto.randomUUID(),
|
|
18873
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18874
|
+
ip: extractAuditIp(request),
|
|
18875
|
+
userAgent: extractAuditUserAgent(request),
|
|
18876
|
+
requestId: extractAuditRequestId(request),
|
|
18877
|
+
...event
|
|
18878
|
+
};
|
|
18879
|
+
const logFn = event.outcome === "failure" || event.outcome === "blocked" ? logger.warn : logger.info;
|
|
18880
|
+
logFn(`[AUDIT] ${event.action}`, {
|
|
18881
|
+
auditId: record.id,
|
|
18882
|
+
actor: record.actor,
|
|
18883
|
+
action: record.action,
|
|
18884
|
+
resource: record.resource,
|
|
18885
|
+
outcome: record.outcome,
|
|
18886
|
+
ip: record.ip,
|
|
18887
|
+
metadata: record.metadata,
|
|
18888
|
+
reason: record.reason
|
|
18889
|
+
});
|
|
18890
|
+
if (persist) {
|
|
18891
|
+
try {
|
|
18892
|
+
await persist(record);
|
|
18893
|
+
} catch (error) {
|
|
18894
|
+
logger.error("Failed to persist audit log", {
|
|
18895
|
+
error: error instanceof Error ? error.message : String(error),
|
|
18896
|
+
auditId: record.id
|
|
18897
|
+
});
|
|
18898
|
+
}
|
|
18899
|
+
}
|
|
18900
|
+
return record;
|
|
18901
|
+
}
|
|
18902
|
+
function createTimedAudit(event, request) {
|
|
18903
|
+
const startTime = Date.now();
|
|
18904
|
+
return {
|
|
18905
|
+
success: async (metadata) => {
|
|
18906
|
+
return log(
|
|
18907
|
+
{
|
|
18908
|
+
...event,
|
|
18909
|
+
outcome: "success",
|
|
18910
|
+
metadata: {
|
|
18911
|
+
...event.metadata,
|
|
18912
|
+
...metadata,
|
|
18913
|
+
durationMs: Date.now() - startTime
|
|
18914
|
+
}
|
|
18915
|
+
},
|
|
18916
|
+
request
|
|
18917
|
+
);
|
|
18918
|
+
},
|
|
18919
|
+
failure: async (reason, metadata) => {
|
|
18920
|
+
return log(
|
|
18921
|
+
{
|
|
18922
|
+
...event,
|
|
18923
|
+
outcome: "failure",
|
|
18924
|
+
reason,
|
|
18925
|
+
metadata: {
|
|
18926
|
+
...event.metadata,
|
|
18927
|
+
...metadata,
|
|
18928
|
+
durationMs: Date.now() - startTime
|
|
18929
|
+
}
|
|
18930
|
+
},
|
|
18931
|
+
request
|
|
18932
|
+
);
|
|
18933
|
+
},
|
|
18934
|
+
blocked: async (reason, metadata) => {
|
|
18935
|
+
return log(
|
|
18936
|
+
{
|
|
18937
|
+
...event,
|
|
18938
|
+
outcome: "blocked",
|
|
18939
|
+
reason,
|
|
18940
|
+
metadata: {
|
|
18941
|
+
...event.metadata,
|
|
18942
|
+
...metadata,
|
|
18943
|
+
durationMs: Date.now() - startTime
|
|
18944
|
+
}
|
|
18945
|
+
},
|
|
18946
|
+
request
|
|
18947
|
+
);
|
|
18948
|
+
}
|
|
18949
|
+
};
|
|
18950
|
+
}
|
|
18951
|
+
return { log, createTimedAudit };
|
|
18952
|
+
}
|
|
18953
|
+
|
|
17489
18954
|
// src/http/health.ts
|
|
17490
18955
|
function createHealthEndpoints(platform, options = {}) {
|
|
17491
18956
|
const {
|
|
@@ -18564,7 +20029,7 @@ var MemoryAuditLog = class {
|
|
|
18564
20029
|
};
|
|
18565
20030
|
|
|
18566
20031
|
// src/adapters/memory/MemoryWebhook.ts
|
|
18567
|
-
var
|
|
20032
|
+
var import_crypto28 = require("crypto");
|
|
18568
20033
|
var MemoryWebhook = class {
|
|
18569
20034
|
endpoints = /* @__PURE__ */ new Map();
|
|
18570
20035
|
deliveries = /* @__PURE__ */ new Map();
|
|
@@ -18846,7 +20311,7 @@ var MemoryWebhook = class {
|
|
|
18846
20311
|
config.secret,
|
|
18847
20312
|
algorithm
|
|
18848
20313
|
);
|
|
18849
|
-
const providedSig = signature.replace(/^(sha256=|sha512
|
|
20314
|
+
const providedSig = signature.replace(/^(sha256=|sha512=)/, "");
|
|
18850
20315
|
if (providedSig !== expectedSignature) {
|
|
18851
20316
|
return { valid: false, error: "Invalid signature" };
|
|
18852
20317
|
}
|
|
@@ -18951,7 +20416,7 @@ var MemoryWebhook = class {
|
|
|
18951
20416
|
this.deliveries.set(delivery.id, delivery);
|
|
18952
20417
|
}
|
|
18953
20418
|
async executeDelivery(endpoint, event, attemptNumber) {
|
|
18954
|
-
const attemptId = `att_${Date.now().toString(36)}${
|
|
20419
|
+
const attemptId = `att_${Date.now().toString(36)}${(0, import_crypto28.randomBytes)(4).toString("hex")}`;
|
|
18955
20420
|
const startTime = Date.now();
|
|
18956
20421
|
if (this.config.simulatedDelay > 0) {
|
|
18957
20422
|
await new Promise(
|
|
@@ -19005,7 +20470,7 @@ var MemoryWebhook = class {
|
|
|
19005
20470
|
this.endpoints.set(endpoint.id, endpoint);
|
|
19006
20471
|
}
|
|
19007
20472
|
computeSignature(payload, secret, algorithm) {
|
|
19008
|
-
return (0,
|
|
20473
|
+
return (0, import_crypto28.createHmac)(algorithm, secret).update(payload).digest("hex");
|
|
19009
20474
|
}
|
|
19010
20475
|
};
|
|
19011
20476
|
|
|
@@ -19356,6 +20821,7 @@ var MemoryNotification = class {
|
|
|
19356
20821
|
};
|
|
19357
20822
|
|
|
19358
20823
|
// src/adapters/memory/MemoryScheduler.ts
|
|
20824
|
+
var import_crypto29 = require("crypto");
|
|
19359
20825
|
var MemoryScheduler = class {
|
|
19360
20826
|
config;
|
|
19361
20827
|
schedules = /* @__PURE__ */ new Map();
|
|
@@ -19639,7 +21105,7 @@ var MemoryScheduler = class {
|
|
|
19639
21105
|
}
|
|
19640
21106
|
}
|
|
19641
21107
|
async executeSchedule(schedule) {
|
|
19642
|
-
const executionId = `exec_${Date.now().toString(36)}${
|
|
21108
|
+
const executionId = `exec_${Date.now().toString(36)}${(0, import_crypto29.randomBytes)(4).toString("hex")}`;
|
|
19643
21109
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19644
21110
|
const execution = {
|
|
19645
21111
|
id: executionId,
|
|
@@ -20119,6 +21585,7 @@ CREATE INDEX IF NOT EXISTS idx_${tableName}_trace_id ON ${tableName}((context->>
|
|
|
20119
21585
|
};
|
|
20120
21586
|
|
|
20121
21587
|
// src/adapters/database/DatabaseErrorReporter.ts
|
|
21588
|
+
var import_crypto30 = require("crypto");
|
|
20122
21589
|
var DatabaseErrorReporter = class {
|
|
20123
21590
|
db;
|
|
20124
21591
|
errorsTable;
|
|
@@ -20413,7 +21880,7 @@ CREATE INDEX IF NOT EXISTS idx_${breadcrumbsTable}_error ON ${breadcrumbsTable}(
|
|
|
20413
21880
|
if (report.breadcrumbs && report.breadcrumbs.length > 0) {
|
|
20414
21881
|
for (const crumb of report.breadcrumbs) {
|
|
20415
21882
|
await this.db.from(this.breadcrumbsTable).insert({
|
|
20416
|
-
id: `bc_${Date.now().toString(36)}${
|
|
21883
|
+
id: `bc_${Date.now().toString(36)}${(0, import_crypto30.randomBytes)(4).toString("hex")}`,
|
|
20417
21884
|
error_id: report.id,
|
|
20418
21885
|
category: crumb.category,
|
|
20419
21886
|
message: crumb.message,
|
|
@@ -20453,6 +21920,7 @@ CREATE INDEX IF NOT EXISTS idx_${breadcrumbsTable}_error ON ${breadcrumbsTable}(
|
|
|
20453
21920
|
};
|
|
20454
21921
|
|
|
20455
21922
|
// src/adapters/database/DatabasePromptStore.ts
|
|
21923
|
+
var import_crypto31 = require("crypto");
|
|
20456
21924
|
var DatabasePromptStore = class {
|
|
20457
21925
|
db;
|
|
20458
21926
|
cache;
|
|
@@ -20592,7 +22060,7 @@ CREATE INDEX IF NOT EXISTS idx_${tablePrefix}usage_experiment ON ${tablePrefix}p
|
|
|
20592
22060
|
// Prompt CRUD
|
|
20593
22061
|
// ═══════════════════════════════════════════════════════════════
|
|
20594
22062
|
async create(prompt) {
|
|
20595
|
-
const id = `prompt_${Date.now()}_${
|
|
22063
|
+
const id = `prompt_${Date.now()}_${(0, import_crypto31.randomBytes)(4).toString("hex")}`;
|
|
20596
22064
|
const now = /* @__PURE__ */ new Date();
|
|
20597
22065
|
const newPrompt = {
|
|
20598
22066
|
...prompt,
|
|
@@ -20620,7 +22088,7 @@ CREATE INDEX IF NOT EXISTS idx_${tablePrefix}usage_experiment ON ${tablePrefix}p
|
|
|
20620
22088
|
created_by: newPrompt.createdBy,
|
|
20621
22089
|
updated_by: newPrompt.updatedBy
|
|
20622
22090
|
}).execute();
|
|
20623
|
-
const versionId = `pv_${Date.now()}_${
|
|
22091
|
+
const versionId = `pv_${Date.now()}_${(0, import_crypto31.randomBytes)(4).toString("hex")}`;
|
|
20624
22092
|
await this.db.from(this.versionsTable).insert({
|
|
20625
22093
|
id: versionId,
|
|
20626
22094
|
prompt_id: id,
|
|
@@ -20689,7 +22157,7 @@ CREATE INDEX IF NOT EXISTS idx_${tablePrefix}usage_experiment ON ${tablePrefix}p
|
|
|
20689
22157
|
await this.db.from(this.versionsTable).update({ is_latest: false }).where("prompt_id", "=", prompt.id).execute();
|
|
20690
22158
|
const versionsResult = await this.db.from(this.versionsTable).where("prompt_id", "=", prompt.id).execute();
|
|
20691
22159
|
const newVersionNum = versionsResult.data.length + 1;
|
|
20692
|
-
const versionId = `pv_${Date.now()}_${
|
|
22160
|
+
const versionId = `pv_${Date.now()}_${(0, import_crypto31.randomBytes)(4).toString("hex")}`;
|
|
20693
22161
|
await this.db.from(this.versionsTable).insert({
|
|
20694
22162
|
id: versionId,
|
|
20695
22163
|
prompt_id: prompt.id,
|
|
@@ -20944,7 +22412,7 @@ ${v2.content}`;
|
|
|
20944
22412
|
// A/B Testing
|
|
20945
22413
|
// ═══════════════════════════════════════════════════════════════
|
|
20946
22414
|
async createExperiment(experiment) {
|
|
20947
|
-
const id = `exp_${Date.now()}_${
|
|
22415
|
+
const id = `exp_${Date.now()}_${(0, import_crypto31.randomBytes)(4).toString("hex")}`;
|
|
20948
22416
|
const now = /* @__PURE__ */ new Date();
|
|
20949
22417
|
const newExperiment = {
|
|
20950
22418
|
...experiment,
|
|
@@ -21058,7 +22526,7 @@ ${v2.content}`;
|
|
|
21058
22526
|
// Prompt Chains
|
|
21059
22527
|
// ═══════════════════════════════════════════════════════════════
|
|
21060
22528
|
async createChain(chain) {
|
|
21061
|
-
const id = `chain_${Date.now()}_${
|
|
22529
|
+
const id = `chain_${Date.now()}_${(0, import_crypto31.randomBytes)(4).toString("hex")}`;
|
|
21062
22530
|
const now = /* @__PURE__ */ new Date();
|
|
21063
22531
|
const newChain = {
|
|
21064
22532
|
...chain,
|
|
@@ -21156,7 +22624,7 @@ ${v2.content}`;
|
|
|
21156
22624
|
// Usage & Analytics
|
|
21157
22625
|
// ═══════════════════════════════════════════════════════════════
|
|
21158
22626
|
async recordUsage(record) {
|
|
21159
|
-
const id = `usage_${Date.now()}_${
|
|
22627
|
+
const id = `usage_${Date.now()}_${(0, import_crypto31.randomBytes)(4).toString("hex")}`;
|
|
21160
22628
|
const now = /* @__PURE__ */ new Date();
|
|
21161
22629
|
const usageRecord = {
|
|
21162
22630
|
...record,
|
|
@@ -21342,8 +22810,9 @@ ${v2.content}`;
|
|
|
21342
22810
|
};
|
|
21343
22811
|
|
|
21344
22812
|
// src/adapters/database/DatabaseCompliance.ts
|
|
22813
|
+
var import_crypto32 = require("crypto");
|
|
21345
22814
|
function generateId(prefix) {
|
|
21346
|
-
return `${prefix}_${Date.now()}_${
|
|
22815
|
+
return `${prefix}_${Date.now()}_${(0, import_crypto32.randomBytes)(4).toString("hex")}`;
|
|
21347
22816
|
}
|
|
21348
22817
|
function toDate(value) {
|
|
21349
22818
|
return value ? new Date(value) : void 0;
|
|
@@ -21534,7 +23003,7 @@ var DatabaseCompliance = class {
|
|
|
21534
23003
|
async createDsar(options) {
|
|
21535
23004
|
const id = generateId("dsar");
|
|
21536
23005
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21537
|
-
const verificationToken = `verify_${
|
|
23006
|
+
const verificationToken = `verify_${(0, import_crypto32.randomBytes)(16).toString("hex")}`;
|
|
21538
23007
|
const result = await this.db.from("compliance_dsars").insert({
|
|
21539
23008
|
id,
|
|
21540
23009
|
type: options.type,
|
|
@@ -22473,6 +23942,7 @@ var DatabaseCompliance = class {
|
|
|
22473
23942
|
};
|
|
22474
23943
|
|
|
22475
23944
|
// src/adapters/database/DatabaseAIUsage.ts
|
|
23945
|
+
var import_crypto33 = require("crypto");
|
|
22476
23946
|
var DatabaseAIUsage = class {
|
|
22477
23947
|
db;
|
|
22478
23948
|
config;
|
|
@@ -22486,7 +23956,7 @@ var DatabaseAIUsage = class {
|
|
|
22486
23956
|
// Usage Recording
|
|
22487
23957
|
// ─────────────────────────────────────────────────────────────
|
|
22488
23958
|
async record(record) {
|
|
22489
|
-
const id = `usage_${Date.now()}_${
|
|
23959
|
+
const id = `usage_${Date.now()}_${(0, import_crypto33.randomBytes)(4).toString("hex")}`;
|
|
22490
23960
|
const now = /* @__PURE__ */ new Date();
|
|
22491
23961
|
await this.db.from(`${this.prefix}records`).insert({
|
|
22492
23962
|
id,
|
|
@@ -22593,7 +24063,7 @@ var DatabaseAIUsage = class {
|
|
|
22593
24063
|
quota.category
|
|
22594
24064
|
);
|
|
22595
24065
|
const period = this.getPeriodBounds(quota.period, /* @__PURE__ */ new Date());
|
|
22596
|
-
const id = existing?.id || `quota_${Date.now()}_${
|
|
24066
|
+
const id = existing?.id || `quota_${Date.now()}_${(0, import_crypto33.randomBytes)(4).toString("hex")}`;
|
|
22597
24067
|
const data = {
|
|
22598
24068
|
id,
|
|
22599
24069
|
tenant_id: quota.tenantId,
|
|
@@ -22730,7 +24200,7 @@ var DatabaseAIUsage = class {
|
|
|
22730
24200
|
existingResult.data[0]
|
|
22731
24201
|
) : null;
|
|
22732
24202
|
const period = this.getPeriodBounds(budget.period, /* @__PURE__ */ new Date());
|
|
22733
|
-
const id = existing?.id || `budget_${Date.now()}_${
|
|
24203
|
+
const id = existing?.id || `budget_${Date.now()}_${(0, import_crypto33.randomBytes)(4).toString("hex")}`;
|
|
22734
24204
|
const data = {
|
|
22735
24205
|
id,
|
|
22736
24206
|
tenant_id: budget.tenantId,
|
|
@@ -23029,7 +24499,7 @@ var DatabaseAIUsage = class {
|
|
|
23029
24499
|
}
|
|
23030
24500
|
const items = Array.from(itemsMap.values());
|
|
23031
24501
|
const subtotal = items.reduce((sum, item) => sum + item.costUsd, 0);
|
|
23032
|
-
const id = `inv_${Date.now()}_${
|
|
24502
|
+
const id = `inv_${Date.now()}_${(0, import_crypto33.randomBytes)(4).toString("hex")}`;
|
|
23033
24503
|
const now = /* @__PURE__ */ new Date();
|
|
23034
24504
|
await this.db.from(`${this.prefix}invoices`).insert({
|
|
23035
24505
|
id,
|
|
@@ -23251,7 +24721,7 @@ var DatabaseAIUsage = class {
|
|
|
23251
24721
|
}
|
|
23252
24722
|
}
|
|
23253
24723
|
async createAlert(tenantId, type, severity, message, metadata) {
|
|
23254
|
-
const id = `alert_${Date.now()}_${
|
|
24724
|
+
const id = `alert_${Date.now()}_${(0, import_crypto33.randomBytes)(4).toString("hex")}`;
|
|
23255
24725
|
await this.db.from(`${this.prefix}alerts`).insert({
|
|
23256
24726
|
id,
|
|
23257
24727
|
tenant_id: tenantId,
|
|
@@ -23457,6 +24927,7 @@ var DatabaseAIUsage = class {
|
|
|
23457
24927
|
};
|
|
23458
24928
|
|
|
23459
24929
|
// src/adapters/database/DatabaseNotification.ts
|
|
24930
|
+
var import_crypto34 = require("crypto");
|
|
23460
24931
|
var DatabaseNotification = class {
|
|
23461
24932
|
db;
|
|
23462
24933
|
email;
|
|
@@ -23694,7 +25165,7 @@ var DatabaseNotification = class {
|
|
|
23694
25165
|
// PUSH SUBSCRIPTIONS
|
|
23695
25166
|
// ═══════════════════════════════════════════════════════════════
|
|
23696
25167
|
async registerPushSubscription(userId, subscription) {
|
|
23697
|
-
const id = `push_${Date.now()}_${
|
|
25168
|
+
const id = `push_${Date.now()}_${(0, import_crypto34.randomBytes)(4).toString("hex")}`;
|
|
23698
25169
|
const existing = await this.db.from(`${this.prefix}push_subscriptions`).where("user_id", "=", userId).where("endpoint", "=", subscription.endpoint).execute();
|
|
23699
25170
|
if (existing.data && existing.data.length > 0) {
|
|
23700
25171
|
await this.db.from(`${this.prefix}push_subscriptions`).where("user_id", "=", userId).where("endpoint", "=", subscription.endpoint).update({
|
|
@@ -23792,7 +25263,7 @@ var DatabaseNotification = class {
|
|
|
23792
25263
|
// TOPICS
|
|
23793
25264
|
// ═══════════════════════════════════════════════════════════════
|
|
23794
25265
|
async subscribeToTopic(userId, topic) {
|
|
23795
|
-
const id = `topic_${Date.now()}_${
|
|
25266
|
+
const id = `topic_${Date.now()}_${(0, import_crypto34.randomBytes)(4).toString("hex")}`;
|
|
23796
25267
|
const existing = await this.db.from(`${this.prefix}notification_topic_subs`).where("user_id", "=", userId).where("topic", "=", topic).execute();
|
|
23797
25268
|
if (!existing.data || existing.data.length === 0) {
|
|
23798
25269
|
await this.db.from(`${this.prefix}notification_topic_subs`).insert({
|
|
@@ -23873,7 +25344,7 @@ var DatabaseNotification = class {
|
|
|
23873
25344
|
// PRIVATE HELPERS
|
|
23874
25345
|
// ═══════════════════════════════════════════════════════════════
|
|
23875
25346
|
async logDelivery(notificationId, channel, status, messageId, error) {
|
|
23876
|
-
const id = `del_${Date.now()}_${
|
|
25347
|
+
const id = `del_${Date.now()}_${(0, import_crypto34.randomBytes)(4).toString("hex")}`;
|
|
23877
25348
|
try {
|
|
23878
25349
|
await this.db.from(`${this.prefix}notification_delivery_log`).insert({
|
|
23879
25350
|
id,
|
|
@@ -23935,6 +25406,7 @@ var DatabaseNotification = class {
|
|
|
23935
25406
|
};
|
|
23936
25407
|
|
|
23937
25408
|
// src/adapters/database/DatabaseBilling.ts
|
|
25409
|
+
var import_crypto35 = require("crypto");
|
|
23938
25410
|
var DatabaseBilling = class {
|
|
23939
25411
|
db;
|
|
23940
25412
|
prefix;
|
|
@@ -23957,7 +25429,7 @@ var DatabaseBilling = class {
|
|
|
23957
25429
|
return `${this.prefix}${name}`;
|
|
23958
25430
|
}
|
|
23959
25431
|
generateId(prefix) {
|
|
23960
|
-
return `${prefix}_${Date.now()}_${
|
|
25432
|
+
return `${prefix}_${Date.now()}_${(0, import_crypto35.randomBytes)(4).toString("hex")}`;
|
|
23961
25433
|
}
|
|
23962
25434
|
// ─────────────────────────────────────────────────────────────
|
|
23963
25435
|
// Product & Price Management
|
|
@@ -25455,6 +26927,7 @@ var DatabaseBilling = class {
|
|
|
25455
26927
|
};
|
|
25456
26928
|
|
|
25457
26929
|
// src/adapters/scheduler/QueueScheduler.ts
|
|
26930
|
+
var import_crypto36 = require("crypto");
|
|
25458
26931
|
var QueueScheduler = class {
|
|
25459
26932
|
queue;
|
|
25460
26933
|
db;
|
|
@@ -25870,7 +27343,7 @@ CREATE INDEX IF NOT EXISTS idx_${executionsTable}_started ON ${executionsTable}(
|
|
|
25870
27343
|
}
|
|
25871
27344
|
}
|
|
25872
27345
|
async executeSchedule(schedule) {
|
|
25873
|
-
const executionId = `exec_${Date.now().toString(36)}${
|
|
27346
|
+
const executionId = `exec_${Date.now().toString(36)}${(0, import_crypto36.randomBytes)(4).toString("hex")}`;
|
|
25874
27347
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25875
27348
|
const execution = {
|
|
25876
27349
|
id: executionId,
|
|
@@ -26033,7 +27506,7 @@ CREATE INDEX IF NOT EXISTS idx_${executionsTable}_started ON ${executionsTable}(
|
|
|
26033
27506
|
};
|
|
26034
27507
|
|
|
26035
27508
|
// src/adapters/webhook/HttpWebhook.ts
|
|
26036
|
-
var
|
|
27509
|
+
var import_crypto37 = require("crypto");
|
|
26037
27510
|
var HttpWebhook = class {
|
|
26038
27511
|
db;
|
|
26039
27512
|
queue;
|
|
@@ -26375,14 +27848,14 @@ var HttpWebhook = class {
|
|
|
26375
27848
|
config.secret,
|
|
26376
27849
|
algorithm
|
|
26377
27850
|
);
|
|
26378
|
-
const providedSig = signature.replace(/^(sha256=|sha512
|
|
27851
|
+
const providedSig = signature.replace(/^(sha256=|sha512=)/, "");
|
|
26379
27852
|
try {
|
|
26380
27853
|
const providedBuffer = Buffer.from(providedSig, "hex");
|
|
26381
27854
|
const expectedBuffer = Buffer.from(expectedSignature, "hex");
|
|
26382
27855
|
if (providedBuffer.length !== expectedBuffer.length) {
|
|
26383
27856
|
return { valid: false, error: "Invalid signature" };
|
|
26384
27857
|
}
|
|
26385
|
-
if (!(0,
|
|
27858
|
+
if (!(0, import_crypto37.timingSafeEqual)(providedBuffer, expectedBuffer)) {
|
|
26386
27859
|
return { valid: false, error: "Invalid signature" };
|
|
26387
27860
|
}
|
|
26388
27861
|
} catch {
|
|
@@ -26631,7 +28104,7 @@ CREATE INDEX IF NOT EXISTS idx_${attemptsTable}_delivery ON ${attemptsTable}(del
|
|
|
26631
28104
|
await this.saveDelivery(delivery);
|
|
26632
28105
|
}
|
|
26633
28106
|
async executeDelivery(endpoint, event, attemptNumber) {
|
|
26634
|
-
const attemptId = `att_${Date.now().toString(36)}${
|
|
28107
|
+
const attemptId = `att_${Date.now().toString(36)}${(0, import_crypto37.randomBytes)(4).toString("hex")}`;
|
|
26635
28108
|
const startTime = Date.now();
|
|
26636
28109
|
const payloadStr = JSON.stringify(event);
|
|
26637
28110
|
const signature = this.computeSignature(
|
|
@@ -26735,7 +28208,7 @@ CREATE INDEX IF NOT EXISTS idx_${attemptsTable}_delivery ON ${attemptsTable}(del
|
|
|
26735
28208
|
await this.saveEndpoint(endpoint);
|
|
26736
28209
|
}
|
|
26737
28210
|
computeSignature(payload, secret, algorithm) {
|
|
26738
|
-
return (0,
|
|
28211
|
+
return (0, import_crypto37.createHmac)(algorithm, secret).update(payload).digest("hex");
|
|
26739
28212
|
}
|
|
26740
28213
|
endpointToRow(endpoint) {
|
|
26741
28214
|
return {
|
|
@@ -28057,6 +29530,9 @@ init_PineconeRAG();
|
|
|
28057
29530
|
// src/adapters/weaviate/index.ts
|
|
28058
29531
|
init_WeaviateRAG();
|
|
28059
29532
|
|
|
29533
|
+
// src/index.ts
|
|
29534
|
+
init_NodeCrypto();
|
|
29535
|
+
|
|
28060
29536
|
// src/adapters/oidc/GenericOIDCAuthSSO.ts
|
|
28061
29537
|
function generateRandomString(length) {
|
|
28062
29538
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
@@ -28650,6 +30126,7 @@ var GenericOIDCAuthSSO = class {
|
|
|
28650
30126
|
};
|
|
28651
30127
|
|
|
28652
30128
|
// src/adapters/postgres-tenant/PostgresTenant.ts
|
|
30129
|
+
var import_crypto38 = require("crypto");
|
|
28653
30130
|
var tenantContextMap = /* @__PURE__ */ new Map();
|
|
28654
30131
|
var contextIdCounter2 = 0;
|
|
28655
30132
|
var currentContextId2 = null;
|
|
@@ -29431,7 +30908,273 @@ var PostgresTenant = class {
|
|
|
29431
30908
|
}
|
|
29432
30909
|
};
|
|
29433
30910
|
function generateId2() {
|
|
29434
|
-
return
|
|
30911
|
+
return (0, import_crypto38.randomBytes)(8).toString("hex") + Date.now().toString(36);
|
|
30912
|
+
}
|
|
30913
|
+
|
|
30914
|
+
// src/env.ts
|
|
30915
|
+
function getRequiredEnv(key) {
|
|
30916
|
+
const value = process.env[key];
|
|
30917
|
+
if (!value) {
|
|
30918
|
+
throw new Error(`Missing required environment variable: ${key}`);
|
|
30919
|
+
}
|
|
30920
|
+
return value;
|
|
30921
|
+
}
|
|
30922
|
+
function getOptionalEnv(key, defaultValue) {
|
|
30923
|
+
return process.env[key] || defaultValue;
|
|
30924
|
+
}
|
|
30925
|
+
function getBoolEnv(key, defaultValue = false) {
|
|
30926
|
+
const value = process.env[key];
|
|
30927
|
+
if (value === void 0 || value === "") return defaultValue;
|
|
30928
|
+
return value === "true" || value === "1";
|
|
30929
|
+
}
|
|
30930
|
+
function getIntEnv(key, defaultValue) {
|
|
30931
|
+
const value = process.env[key];
|
|
30932
|
+
if (value === void 0 || value === "") return defaultValue;
|
|
30933
|
+
const parsed = parseInt(value, 10);
|
|
30934
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
30935
|
+
}
|
|
30936
|
+
function validateEnvVars(config) {
|
|
30937
|
+
const result = checkEnvVars(config);
|
|
30938
|
+
if (!result.valid) {
|
|
30939
|
+
const lines = [];
|
|
30940
|
+
if (result.missing.length > 0) {
|
|
30941
|
+
lines.push(
|
|
30942
|
+
"Missing required environment variables:",
|
|
30943
|
+
...result.missing.map((v) => ` - ${v}`)
|
|
30944
|
+
);
|
|
30945
|
+
}
|
|
30946
|
+
if (result.missingOneOf.length > 0) {
|
|
30947
|
+
for (const group of result.missingOneOf) {
|
|
30948
|
+
lines.push(`Missing one of: ${group.join(" | ")}`);
|
|
30949
|
+
}
|
|
30950
|
+
}
|
|
30951
|
+
if (result.invalid.length > 0) {
|
|
30952
|
+
lines.push(
|
|
30953
|
+
"Invalid environment variables:",
|
|
30954
|
+
...result.invalid.map((v) => ` - ${v.key}: ${v.reason}`)
|
|
30955
|
+
);
|
|
30956
|
+
}
|
|
30957
|
+
throw new Error(lines.join("\n"));
|
|
30958
|
+
}
|
|
30959
|
+
}
|
|
30960
|
+
function checkEnvVars(config) {
|
|
30961
|
+
const missing = [];
|
|
30962
|
+
const invalid = [];
|
|
30963
|
+
const missingOneOf = [];
|
|
30964
|
+
if (config.required) {
|
|
30965
|
+
for (const key of config.required) {
|
|
30966
|
+
if (!process.env[key]) {
|
|
30967
|
+
missing.push(key);
|
|
30968
|
+
}
|
|
30969
|
+
}
|
|
30970
|
+
}
|
|
30971
|
+
if (config.requireOneOf) {
|
|
30972
|
+
for (const group of config.requireOneOf) {
|
|
30973
|
+
const hasAny = group.some((key) => !!process.env[key]);
|
|
30974
|
+
if (!hasAny) {
|
|
30975
|
+
missingOneOf.push(group);
|
|
30976
|
+
}
|
|
30977
|
+
}
|
|
30978
|
+
}
|
|
30979
|
+
if (config.validators) {
|
|
30980
|
+
for (const [key, validator] of Object.entries(config.validators)) {
|
|
30981
|
+
const value = process.env[key];
|
|
30982
|
+
if (value) {
|
|
30983
|
+
const result = validator(value);
|
|
30984
|
+
if (result !== true) {
|
|
30985
|
+
invalid.push({ key, reason: result });
|
|
30986
|
+
}
|
|
30987
|
+
}
|
|
30988
|
+
}
|
|
30989
|
+
}
|
|
30990
|
+
return {
|
|
30991
|
+
valid: missing.length === 0 && invalid.length === 0 && missingOneOf.length === 0,
|
|
30992
|
+
missing,
|
|
30993
|
+
invalid,
|
|
30994
|
+
missingOneOf
|
|
30995
|
+
};
|
|
30996
|
+
}
|
|
30997
|
+
function getEnvSummary(keys) {
|
|
30998
|
+
const summary = {};
|
|
30999
|
+
for (const key of keys) {
|
|
31000
|
+
summary[key] = !!process.env[key];
|
|
31001
|
+
}
|
|
31002
|
+
return summary;
|
|
31003
|
+
}
|
|
31004
|
+
|
|
31005
|
+
// src/app-logger.ts
|
|
31006
|
+
var LEVEL_PRIORITY2 = {
|
|
31007
|
+
debug: 0,
|
|
31008
|
+
info: 1,
|
|
31009
|
+
warn: 2,
|
|
31010
|
+
error: 3
|
|
31011
|
+
};
|
|
31012
|
+
function defaultOutput(level, message, context) {
|
|
31013
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
31014
|
+
if (isProduction) {
|
|
31015
|
+
const entry = { level, message, ...context };
|
|
31016
|
+
const method = level === "error" ? "error" : level === "warn" ? "warn" : "log";
|
|
31017
|
+
console[method](JSON.stringify(entry));
|
|
31018
|
+
} else {
|
|
31019
|
+
const prefix = `[${level.toUpperCase()}]`;
|
|
31020
|
+
const ctx = Object.keys(context).length > 0 ? " " + JSON.stringify(context) : "";
|
|
31021
|
+
const method = level === "error" ? "error" : level === "warn" ? "warn" : level === "debug" ? "debug" : "log";
|
|
31022
|
+
console[method](`${prefix} ${message}${ctx}`);
|
|
31023
|
+
}
|
|
31024
|
+
}
|
|
31025
|
+
var AppLoggerImpl = class _AppLoggerImpl {
|
|
31026
|
+
baseContext;
|
|
31027
|
+
minLevelPriority;
|
|
31028
|
+
outputFn;
|
|
31029
|
+
onErrorFn;
|
|
31030
|
+
constructor(baseContext, options) {
|
|
31031
|
+
this.baseContext = baseContext;
|
|
31032
|
+
this.minLevelPriority = LEVEL_PRIORITY2[options.minLevel] ?? 0;
|
|
31033
|
+
this.outputFn = options.output;
|
|
31034
|
+
this.onErrorFn = options.onError;
|
|
31035
|
+
}
|
|
31036
|
+
log(level, message, context) {
|
|
31037
|
+
if ((LEVEL_PRIORITY2[level] ?? 0) < this.minLevelPriority) return;
|
|
31038
|
+
const merged = {
|
|
31039
|
+
...this.baseContext,
|
|
31040
|
+
...context,
|
|
31041
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
31042
|
+
};
|
|
31043
|
+
this.outputFn(level, message, merged);
|
|
31044
|
+
}
|
|
31045
|
+
debug(message, context) {
|
|
31046
|
+
this.log("debug", message, context);
|
|
31047
|
+
}
|
|
31048
|
+
info(message, context) {
|
|
31049
|
+
this.log("info", message, context);
|
|
31050
|
+
}
|
|
31051
|
+
warn(message, context) {
|
|
31052
|
+
this.log("warn", message, context);
|
|
31053
|
+
}
|
|
31054
|
+
error(message, context) {
|
|
31055
|
+
this.log("error", message, context);
|
|
31056
|
+
if (this.onErrorFn) {
|
|
31057
|
+
try {
|
|
31058
|
+
this.onErrorFn(message, { ...this.baseContext, ...context });
|
|
31059
|
+
} catch {
|
|
31060
|
+
}
|
|
31061
|
+
}
|
|
31062
|
+
}
|
|
31063
|
+
child(context) {
|
|
31064
|
+
return new _AppLoggerImpl(
|
|
31065
|
+
{ ...this.baseContext, ...context },
|
|
31066
|
+
{
|
|
31067
|
+
minLevel: Object.entries(LEVEL_PRIORITY2).find(
|
|
31068
|
+
([, v]) => v === this.minLevelPriority
|
|
31069
|
+
)?.[0] ?? "debug",
|
|
31070
|
+
output: this.outputFn,
|
|
31071
|
+
onError: this.onErrorFn
|
|
31072
|
+
}
|
|
31073
|
+
);
|
|
31074
|
+
}
|
|
31075
|
+
forRequest(request, operation) {
|
|
31076
|
+
const requestId = request.headers.get("x-request-id") ?? request.headers.get("x-correlation-id") ?? crypto.randomUUID();
|
|
31077
|
+
let path;
|
|
31078
|
+
try {
|
|
31079
|
+
path = new URL(request.url).pathname;
|
|
31080
|
+
} catch {
|
|
31081
|
+
path = request.url;
|
|
31082
|
+
}
|
|
31083
|
+
return this.child({
|
|
31084
|
+
requestId,
|
|
31085
|
+
operation,
|
|
31086
|
+
method: request.method,
|
|
31087
|
+
path
|
|
31088
|
+
});
|
|
31089
|
+
}
|
|
31090
|
+
forJob(jobType, jobId, context) {
|
|
31091
|
+
return this.child({ jobType, jobId, ...context });
|
|
31092
|
+
}
|
|
31093
|
+
async timed(operation, fn, context) {
|
|
31094
|
+
const opLogger = this.child({ operation, ...context });
|
|
31095
|
+
opLogger.debug("Operation started");
|
|
31096
|
+
const start = Date.now();
|
|
31097
|
+
try {
|
|
31098
|
+
const result = await fn();
|
|
31099
|
+
opLogger.info("Operation completed", {
|
|
31100
|
+
durationMs: Date.now() - start
|
|
31101
|
+
});
|
|
31102
|
+
return result;
|
|
31103
|
+
} catch (error) {
|
|
31104
|
+
opLogger.error("Operation failed", {
|
|
31105
|
+
durationMs: Date.now() - start,
|
|
31106
|
+
error: error instanceof Error ? error.message : String(error)
|
|
31107
|
+
});
|
|
31108
|
+
throw error;
|
|
31109
|
+
}
|
|
31110
|
+
}
|
|
31111
|
+
};
|
|
31112
|
+
function createAppLogger(options) {
|
|
31113
|
+
const {
|
|
31114
|
+
service,
|
|
31115
|
+
minLevel = process.env.NODE_ENV === "production" ? "info" : "debug",
|
|
31116
|
+
output = defaultOutput,
|
|
31117
|
+
onError
|
|
31118
|
+
} = options;
|
|
31119
|
+
return new AppLoggerImpl({ service }, { minLevel, output, onError });
|
|
31120
|
+
}
|
|
31121
|
+
|
|
31122
|
+
// src/redis-client.ts
|
|
31123
|
+
var import_ioredis = __toESM(require("ioredis"));
|
|
31124
|
+
function createRedisClient(options) {
|
|
31125
|
+
const {
|
|
31126
|
+
url,
|
|
31127
|
+
keyPrefix,
|
|
31128
|
+
maxRetries = 3,
|
|
31129
|
+
lazyConnect = true,
|
|
31130
|
+
silent = false
|
|
31131
|
+
} = options;
|
|
31132
|
+
const logger = options.logger ?? {
|
|
31133
|
+
error: console.error
|
|
31134
|
+
};
|
|
31135
|
+
const client = new import_ioredis.default(url, {
|
|
31136
|
+
keyPrefix,
|
|
31137
|
+
maxRetriesPerRequest: maxRetries,
|
|
31138
|
+
retryStrategy(times) {
|
|
31139
|
+
if (times > maxRetries) return null;
|
|
31140
|
+
return Math.min(times * 200, 2e3);
|
|
31141
|
+
},
|
|
31142
|
+
lazyConnect
|
|
31143
|
+
});
|
|
31144
|
+
if (!silent) {
|
|
31145
|
+
client.on("error", (err) => {
|
|
31146
|
+
logger.error("[redis] Connection error", { message: err.message });
|
|
31147
|
+
});
|
|
31148
|
+
if (logger.info) {
|
|
31149
|
+
const logInfo = logger.info;
|
|
31150
|
+
client.on("connect", () => {
|
|
31151
|
+
logInfo("[redis] Connected");
|
|
31152
|
+
});
|
|
31153
|
+
}
|
|
31154
|
+
}
|
|
31155
|
+
if (lazyConnect) {
|
|
31156
|
+
client.connect().catch(() => {
|
|
31157
|
+
});
|
|
31158
|
+
}
|
|
31159
|
+
return client;
|
|
31160
|
+
}
|
|
31161
|
+
var sharedClient = null;
|
|
31162
|
+
function getSharedRedis() {
|
|
31163
|
+
if (sharedClient) return sharedClient;
|
|
31164
|
+
const url = process.env.REDIS_URL;
|
|
31165
|
+
if (!url) return null;
|
|
31166
|
+
sharedClient = createRedisClient({
|
|
31167
|
+
url,
|
|
31168
|
+
keyPrefix: process.env.REDIS_KEY_PREFIX,
|
|
31169
|
+
silent: process.env.NODE_ENV === "test"
|
|
31170
|
+
});
|
|
31171
|
+
return sharedClient;
|
|
31172
|
+
}
|
|
31173
|
+
async function closeSharedRedis() {
|
|
31174
|
+
if (sharedClient) {
|
|
31175
|
+
await sharedClient.quit();
|
|
31176
|
+
sharedClient = null;
|
|
31177
|
+
}
|
|
29435
31178
|
}
|
|
29436
31179
|
|
|
29437
31180
|
// src/migrations/Migrator.ts
|
|
@@ -30211,9 +31954,11 @@ function getEnterpriseMigrations(features) {
|
|
|
30211
31954
|
CircuitBreakerRegistry,
|
|
30212
31955
|
CircuitOpenError,
|
|
30213
31956
|
CommonApiErrors,
|
|
31957
|
+
CommonRateLimits,
|
|
30214
31958
|
ConsoleEmail,
|
|
30215
31959
|
ConsoleLogger,
|
|
30216
31960
|
CronPresets,
|
|
31961
|
+
CryptoConfigSchema,
|
|
30217
31962
|
DEFAULT_BULKHEAD_OPTIONS,
|
|
30218
31963
|
DEFAULT_CIRCUIT_BREAKER_OPTIONS,
|
|
30219
31964
|
DEFAULT_RETRY_OPTIONS,
|
|
@@ -30226,17 +31971,21 @@ function getEnterpriseMigrations(features) {
|
|
|
30226
31971
|
DatabaseNotification,
|
|
30227
31972
|
DatabasePromptStore,
|
|
30228
31973
|
DatabaseProviderSchema,
|
|
31974
|
+
DateRangeSchema,
|
|
30229
31975
|
DefaultTimeouts,
|
|
30230
31976
|
EmailConfigSchema,
|
|
30231
31977
|
EmailProviderSchema,
|
|
31978
|
+
EmailSchema,
|
|
30232
31979
|
EnvSecrets,
|
|
30233
31980
|
FallbackStrategies,
|
|
30234
31981
|
GenericOIDCAuthSSO,
|
|
30235
31982
|
GoogleAIAdapter,
|
|
30236
31983
|
HTML_TAG_PATTERN,
|
|
30237
31984
|
HttpWebhook,
|
|
31985
|
+
KEYCLOAK_DEFAULT_ROLES,
|
|
30238
31986
|
LogLevelSchema,
|
|
30239
31987
|
LoggingConfigSchema,
|
|
31988
|
+
LoginSchema,
|
|
30240
31989
|
MemoryAI,
|
|
30241
31990
|
MemoryAIUsage,
|
|
30242
31991
|
MemoryAuditLog,
|
|
@@ -30245,6 +31994,7 @@ function getEnterpriseMigrations(features) {
|
|
|
30245
31994
|
MemoryBilling,
|
|
30246
31995
|
MemoryCache,
|
|
30247
31996
|
MemoryCompliance,
|
|
31997
|
+
MemoryCrypto,
|
|
30248
31998
|
MemoryDatabase,
|
|
30249
31999
|
MemoryDevPortal,
|
|
30250
32000
|
MemoryDevice,
|
|
@@ -30266,6 +32016,7 @@ function getEnterpriseMigrations(features) {
|
|
|
30266
32016
|
MetricsConfigSchema,
|
|
30267
32017
|
MiddlewareConfigSchema,
|
|
30268
32018
|
Migrator,
|
|
32019
|
+
NodeCrypto,
|
|
30269
32020
|
NoopLogger,
|
|
30270
32021
|
NoopMetrics,
|
|
30271
32022
|
NoopTracing,
|
|
@@ -30273,7 +32024,11 @@ function getEnterpriseMigrations(features) {
|
|
|
30273
32024
|
ObservabilityConfigSchema,
|
|
30274
32025
|
OpenAIAdapter,
|
|
30275
32026
|
PG_ERROR_MAP,
|
|
32027
|
+
PaginationSchema,
|
|
32028
|
+
PasswordSchema,
|
|
30276
32029
|
PaymentErrorMessages,
|
|
32030
|
+
PersonNameSchema,
|
|
32031
|
+
PhoneSchema,
|
|
30277
32032
|
PineconeRAG,
|
|
30278
32033
|
PlatformConfigSchema,
|
|
30279
32034
|
PostgresDatabase,
|
|
@@ -30293,7 +32048,14 @@ function getEnterpriseMigrations(features) {
|
|
|
30293
32048
|
RetryPredicates,
|
|
30294
32049
|
S3Storage,
|
|
30295
32050
|
SQL,
|
|
32051
|
+
SearchQuerySchema,
|
|
32052
|
+
SecurityConfigSchema,
|
|
32053
|
+
SecurityHeaderPresets,
|
|
32054
|
+
SignupSchema,
|
|
32055
|
+
SlugSchema,
|
|
30296
32056
|
SmtpEmail,
|
|
32057
|
+
StandardAuditActions,
|
|
32058
|
+
StandardRateLimitPresets,
|
|
30297
32059
|
StorageConfigSchema,
|
|
30298
32060
|
StorageProviderSchema,
|
|
30299
32061
|
StripePayment,
|
|
@@ -30309,16 +32071,32 @@ function getEnterpriseMigrations(features) {
|
|
|
30309
32071
|
UpstashCache,
|
|
30310
32072
|
WeaviateRAG,
|
|
30311
32073
|
WebhookEventTypes,
|
|
32074
|
+
WrapperPresets,
|
|
32075
|
+
buildAllowlist,
|
|
32076
|
+
buildAuthCookies,
|
|
32077
|
+
buildErrorBody,
|
|
32078
|
+
buildKeycloakCallbacks,
|
|
30312
32079
|
buildPagination,
|
|
32080
|
+
buildRateLimitHeaders,
|
|
32081
|
+
buildRateLimitResponseHeaders,
|
|
32082
|
+
buildRedirectCallback,
|
|
32083
|
+
buildTokenRefreshParams,
|
|
30313
32084
|
calculateBackoff,
|
|
30314
32085
|
calculateRetryDelay,
|
|
32086
|
+
checkEnvVars,
|
|
32087
|
+
checkRateLimit,
|
|
30315
32088
|
classifyError,
|
|
32089
|
+
closeSharedRedis,
|
|
30316
32090
|
composeHookRegistries,
|
|
32091
|
+
constantTimeEqual,
|
|
30317
32092
|
containsHtml,
|
|
30318
32093
|
containsUrls,
|
|
30319
32094
|
correlationContext,
|
|
30320
32095
|
createAIError,
|
|
30321
32096
|
createAnthropicAdapter,
|
|
32097
|
+
createAppLogger,
|
|
32098
|
+
createAuditActor,
|
|
32099
|
+
createAuditLogger,
|
|
30322
32100
|
createAuthError,
|
|
30323
32101
|
createBulkhead,
|
|
30324
32102
|
createCacheMiddleware,
|
|
@@ -30329,6 +32107,7 @@ function getEnterpriseMigrations(features) {
|
|
|
30329
32107
|
createErrorReport,
|
|
30330
32108
|
createExpressHealthHandlers,
|
|
30331
32109
|
createExpressMetricsHandler,
|
|
32110
|
+
createFeatureFlags,
|
|
30332
32111
|
createGoogleAIAdapter,
|
|
30333
32112
|
createHealthEndpoints,
|
|
30334
32113
|
createHealthServer,
|
|
@@ -30336,6 +32115,7 @@ function getEnterpriseMigrations(features) {
|
|
|
30336
32115
|
createIpKeyGenerator,
|
|
30337
32116
|
createJobContext,
|
|
30338
32117
|
createLoggingMiddleware,
|
|
32118
|
+
createMemoryRateLimitStore,
|
|
30339
32119
|
createMetricsEndpoint,
|
|
30340
32120
|
createMetricsMiddleware,
|
|
30341
32121
|
createMetricsServer,
|
|
@@ -30349,8 +32129,10 @@ function getEnterpriseMigrations(features) {
|
|
|
30349
32129
|
createPlatform,
|
|
30350
32130
|
createPlatformAsync,
|
|
30351
32131
|
createRateLimitMiddleware,
|
|
32132
|
+
createRedisClient,
|
|
30352
32133
|
createRequestContext,
|
|
30353
32134
|
createRequestIdMiddleware,
|
|
32135
|
+
createSafeTextSchema,
|
|
30354
32136
|
createScopedMetrics,
|
|
30355
32137
|
createSlowQueryMiddleware,
|
|
30356
32138
|
createSsoOidcConfigsTable,
|
|
@@ -30367,8 +32149,13 @@ function getEnterpriseMigrations(features) {
|
|
|
30367
32149
|
defangUrl,
|
|
30368
32150
|
defineMigration,
|
|
30369
32151
|
describeCron,
|
|
32152
|
+
detectStage,
|
|
30370
32153
|
enterpriseMigrations,
|
|
30371
32154
|
escapeHtml,
|
|
32155
|
+
extractAuditIp,
|
|
32156
|
+
extractAuditRequestId,
|
|
32157
|
+
extractAuditUserAgent,
|
|
32158
|
+
extractClientIp,
|
|
30372
32159
|
filterChannelsByPreferences,
|
|
30373
32160
|
formatAmount,
|
|
30374
32161
|
generateAuditId,
|
|
@@ -30382,40 +32169,62 @@ function getEnterpriseMigrations(features) {
|
|
|
30382
32169
|
generatePaymentId,
|
|
30383
32170
|
generateScheduleId,
|
|
30384
32171
|
generateSecureToken,
|
|
32172
|
+
generateSecurityHeaders,
|
|
30385
32173
|
generateVersion,
|
|
30386
32174
|
generateWebhookId,
|
|
30387
32175
|
generateWebhookSecret,
|
|
32176
|
+
getBoolEnv,
|
|
30388
32177
|
getContext,
|
|
30389
32178
|
getCorrelationId,
|
|
30390
32179
|
getDefaultConfig,
|
|
32180
|
+
getEndSessionEndpoint,
|
|
30391
32181
|
getEnterpriseMigrations,
|
|
32182
|
+
getEnvSummary,
|
|
32183
|
+
getIntEnv,
|
|
30392
32184
|
getLogMeta,
|
|
30393
32185
|
getNextCronRun,
|
|
32186
|
+
getOptionalEnv,
|
|
32187
|
+
getRateLimitStatus,
|
|
30394
32188
|
getRequestId,
|
|
32189
|
+
getRequiredEnv,
|
|
32190
|
+
getSharedRedis,
|
|
30395
32191
|
getTenantId,
|
|
32192
|
+
getTokenEndpoint,
|
|
30396
32193
|
getTraceId,
|
|
30397
32194
|
getUserId,
|
|
32195
|
+
hasAllRoles,
|
|
32196
|
+
hasAnyRole,
|
|
32197
|
+
hasRole,
|
|
30398
32198
|
isAIError,
|
|
32199
|
+
isAllowlisted,
|
|
30399
32200
|
isApiError,
|
|
30400
32201
|
isAuthError,
|
|
30401
32202
|
isInContext,
|
|
30402
32203
|
isInQuietHours,
|
|
30403
32204
|
isPaymentError,
|
|
32205
|
+
isTokenExpired,
|
|
30404
32206
|
isValidCron,
|
|
30405
32207
|
loadConfig,
|
|
30406
32208
|
matchAction,
|
|
30407
32209
|
matchEventType,
|
|
32210
|
+
parseKeycloakRoles,
|
|
30408
32211
|
raceTimeout,
|
|
32212
|
+
refreshKeycloakToken,
|
|
32213
|
+
resetRateLimitForKey,
|
|
32214
|
+
resolveIdentifier,
|
|
32215
|
+
resolveRateLimitIdentifier,
|
|
30409
32216
|
retryable,
|
|
30410
32217
|
runWithContext,
|
|
30411
32218
|
runWithContextAsync,
|
|
30412
32219
|
safeValidateConfig,
|
|
32220
|
+
sanitizeApiError,
|
|
30413
32221
|
sanitizeForEmail,
|
|
30414
32222
|
sqlMigration,
|
|
30415
32223
|
stripHtml,
|
|
30416
32224
|
timedHealthCheck,
|
|
30417
32225
|
toHealthCheckResult,
|
|
30418
32226
|
validateConfig,
|
|
32227
|
+
validateEnvVars,
|
|
30419
32228
|
withCorrelation,
|
|
30420
32229
|
withCorrelationAsync,
|
|
30421
32230
|
withFallback,
|