paygate-mcp 8.87.0 → 8.89.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/dist/server.d.ts.map +1 -1
- package/dist/server.js +95 -52
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAgB,eAAe,EAA0B,MAAM,MAAM,CAAC;AAI7E,OAAO,EAAE,aAAa,EAAkB,mBAAmB,EAAkB,MAAM,SAAS,CAAC;AAE7F,OAAO,EAAE,MAAM,EAAiC,MAAM,UAAU,CAAC;AASjE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,cAAc,EAAqD,MAAM,WAAW,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAS,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,eAAe,EAA6B,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAqB,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -111,6 +111,17 @@ function safeJsonParse(text) {
|
|
|
111
111
|
}
|
|
112
112
|
/** Max length for user-supplied string fields (names, reasons, messages, memos) */
|
|
113
113
|
const MAX_STRING_FIELD = 500;
|
|
114
|
+
/**
|
|
115
|
+
* Upper bounds for numeric admin inputs.
|
|
116
|
+
* Prevents absurd values that could cause issues in downstream systems,
|
|
117
|
+
* audit log bloat, or unexpected behavior in quota/credit arithmetic.
|
|
118
|
+
*/
|
|
119
|
+
const MAX_CREDITS = 1_000_000_000; // 1 billion credits
|
|
120
|
+
const MAX_QUOTA_LIMIT = 1_000_000_000; // 1 billion calls/credits per period
|
|
121
|
+
const MAX_SPENDING_LIMIT = 1_000_000_000; // 1 billion credits lifetime cap
|
|
122
|
+
const MAX_TOPUP_AMOUNT = 100_000_000; // 100 million credits per auto-topup
|
|
123
|
+
const MAX_TOPUP_THRESHOLD = 100_000_000; // 100 million credits threshold
|
|
124
|
+
const MAX_RATE_LIMIT = 100_000; // 100k requests per window
|
|
114
125
|
/** Truncate user-supplied strings to MAX_STRING_FIELD to prevent log injection and memory abuse. */
|
|
115
126
|
function sanitizeString(value, maxLen = MAX_STRING_FIELD) {
|
|
116
127
|
if (!value)
|
|
@@ -2080,11 +2091,12 @@ class PayGateServer {
|
|
|
2080
2091
|
}
|
|
2081
2092
|
}
|
|
2082
2093
|
const name = String(params.name || 'unnamed').slice(0, 200);
|
|
2083
|
-
const
|
|
2084
|
-
if (!Number.isFinite(
|
|
2094
|
+
const rawCredits = Math.floor(Number(params.credits ?? tpl?.credits ?? 100));
|
|
2095
|
+
if (!Number.isFinite(rawCredits) || rawCredits <= 0) {
|
|
2085
2096
|
this.sendError(res, 400, 'Credits must be a positive integer');
|
|
2086
2097
|
return;
|
|
2087
2098
|
}
|
|
2099
|
+
const credits = clampInt(rawCredits, 1, MAX_CREDITS);
|
|
2088
2100
|
// Calculate expiry: expiresIn (seconds) takes priority over expiresAt (ISO date), template TTL is fallback
|
|
2089
2101
|
let expiresAt = null;
|
|
2090
2102
|
const expiresInNum = Number(params.expiresIn);
|
|
@@ -2106,10 +2118,10 @@ class PayGateServer {
|
|
|
2106
2118
|
let quota = undefined;
|
|
2107
2119
|
if (params.quota) {
|
|
2108
2120
|
quota = {
|
|
2109
|
-
dailyCallLimit:
|
|
2110
|
-
monthlyCallLimit:
|
|
2111
|
-
dailyCreditLimit:
|
|
2112
|
-
monthlyCreditLimit:
|
|
2121
|
+
dailyCallLimit: clampInt(Number(params.quota.dailyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
2122
|
+
monthlyCallLimit: clampInt(Number(params.quota.monthlyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
2123
|
+
dailyCreditLimit: clampInt(Number(params.quota.dailyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
2124
|
+
monthlyCreditLimit: clampInt(Number(params.quota.monthlyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
2113
2125
|
};
|
|
2114
2126
|
}
|
|
2115
2127
|
else if (tpl?.quota) {
|
|
@@ -2211,10 +2223,12 @@ class PayGateServer {
|
|
|
2211
2223
|
res.end(JSON.stringify(result));
|
|
2212
2224
|
return;
|
|
2213
2225
|
}
|
|
2214
|
-
// Legacy: plain list with optional namespace
|
|
2226
|
+
// Legacy: plain list with optional namespace — cap at 500 to prevent memory exhaustion
|
|
2215
2227
|
const namespace = params.get('namespace') || undefined;
|
|
2228
|
+
const allKeysList = this.gate.store.listKeys(namespace);
|
|
2229
|
+
const cappedKeys = allKeysList.slice(0, 500);
|
|
2216
2230
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2217
|
-
res.end(JSON.stringify(
|
|
2231
|
+
res.end(JSON.stringify(cappedKeys, null, 2));
|
|
2218
2232
|
}
|
|
2219
2233
|
// ─── /topup — Add credits ───────────────────────────────────────────────────
|
|
2220
2234
|
async handleTopUp(req, res) {
|
|
@@ -2237,11 +2251,12 @@ class PayGateServer {
|
|
|
2237
2251
|
this.sendError(res, 400, 'Missing key or credits');
|
|
2238
2252
|
return;
|
|
2239
2253
|
}
|
|
2240
|
-
const
|
|
2241
|
-
if (!Number.isFinite(
|
|
2254
|
+
const rawCredits = Number(params.credits);
|
|
2255
|
+
if (!Number.isFinite(rawCredits) || rawCredits <= 0) {
|
|
2242
2256
|
this.sendError(res, 400, 'Credits must be a positive integer');
|
|
2243
2257
|
return;
|
|
2244
2258
|
}
|
|
2259
|
+
const credits = clampInt(rawCredits, 1, MAX_CREDITS);
|
|
2245
2260
|
// Resolve alias to actual key
|
|
2246
2261
|
const resolved = this.gate.store.resolveKey(params.key);
|
|
2247
2262
|
const actualKey = resolved ? resolved.key : params.key;
|
|
@@ -2297,11 +2312,12 @@ class PayGateServer {
|
|
|
2297
2312
|
this.sendError(res, 400, 'Cannot transfer credits to the same key');
|
|
2298
2313
|
return;
|
|
2299
2314
|
}
|
|
2300
|
-
const
|
|
2301
|
-
if (!Number.isFinite(
|
|
2315
|
+
const rawXferCredits = Number(params.credits);
|
|
2316
|
+
if (!Number.isFinite(rawXferCredits) || rawXferCredits <= 0) {
|
|
2302
2317
|
this.sendError(res, 400, 'Credits must be a positive integer');
|
|
2303
2318
|
return;
|
|
2304
2319
|
}
|
|
2320
|
+
const credits = clampInt(rawXferCredits, 1, MAX_CREDITS);
|
|
2305
2321
|
// Validate source key exists and has enough credits
|
|
2306
2322
|
const sourceRecord = this.gate.store.resolveKey(params.from);
|
|
2307
2323
|
if (!sourceRecord) {
|
|
@@ -2401,7 +2417,7 @@ class PayGateServer {
|
|
|
2401
2417
|
switch (op.action) {
|
|
2402
2418
|
case 'create': {
|
|
2403
2419
|
const name = String(op.name || 'unnamed').slice(0, 200);
|
|
2404
|
-
const credits =
|
|
2420
|
+
const credits = clampInt(Number(op.credits) || 100, 0, MAX_CREDITS);
|
|
2405
2421
|
if (credits <= 0) {
|
|
2406
2422
|
results.push({ index: i, action: 'create', success: false, error: 'Credits must be positive' });
|
|
2407
2423
|
break;
|
|
@@ -2426,7 +2442,8 @@ class PayGateServer {
|
|
|
2426
2442
|
}
|
|
2427
2443
|
case 'topup': {
|
|
2428
2444
|
const key = op.key;
|
|
2429
|
-
const
|
|
2445
|
+
const rawAmount = Number(op.credits);
|
|
2446
|
+
const amount = Number.isFinite(rawAmount) ? clampInt(rawAmount, 0, MAX_CREDITS) : NaN;
|
|
2430
2447
|
if (!key) {
|
|
2431
2448
|
results.push({ index: i, action: 'topup', success: false, error: 'Missing key' });
|
|
2432
2449
|
break;
|
|
@@ -2513,9 +2530,14 @@ class PayGateServer {
|
|
|
2513
2530
|
const namespace = params.get('namespace') || undefined;
|
|
2514
2531
|
const activeOnly = params.get('activeOnly') === 'true';
|
|
2515
2532
|
const format = params.get('format') || 'json';
|
|
2516
|
-
const
|
|
2517
|
-
|
|
2518
|
-
|
|
2533
|
+
const allKeys = this.gate.store.exportKeys({ namespace, activeOnly });
|
|
2534
|
+
// Enforce result cap to prevent memory exhaustion (default 1000, max 5000)
|
|
2535
|
+
const limit = params.has('limit') ? clampInt(parseInt(params.get('limit'), 10), 1, 5000, 1000) : 1000;
|
|
2536
|
+
const offset = params.has('offset') ? clampInt(parseInt(params.get('offset'), 10), 0, 100_000, 0) : 0;
|
|
2537
|
+
const totalKeys = allKeys.length;
|
|
2538
|
+
const keys = allKeys.slice(offset, offset + limit);
|
|
2539
|
+
this.audit.log('keys.exported', 'admin', `Exported ${keys.length} keys (of ${totalKeys} total)`, {
|
|
2540
|
+
count: keys.length, total: totalKeys, namespace: namespace || 'all', activeOnly,
|
|
2519
2541
|
});
|
|
2520
2542
|
if (format === 'csv') {
|
|
2521
2543
|
const headers = ['key', 'name', 'credits', 'totalSpent', 'totalCalls', 'createdAt', 'lastUsedAt', 'active', 'namespace', 'expiresAt', 'spendingLimit'];
|
|
@@ -2543,6 +2565,9 @@ class PayGateServer {
|
|
|
2543
2565
|
version: '1.0',
|
|
2544
2566
|
exportedAt: new Date().toISOString(),
|
|
2545
2567
|
count: keys.length,
|
|
2568
|
+
total: totalKeys,
|
|
2569
|
+
limit,
|
|
2570
|
+
offset,
|
|
2546
2571
|
keys,
|
|
2547
2572
|
}, null, 2));
|
|
2548
2573
|
}
|
|
@@ -3046,10 +3071,10 @@ class PayGateServer {
|
|
|
3046
3071
|
return;
|
|
3047
3072
|
}
|
|
3048
3073
|
const quota = {
|
|
3049
|
-
dailyCallLimit:
|
|
3050
|
-
monthlyCallLimit:
|
|
3051
|
-
dailyCreditLimit:
|
|
3052
|
-
monthlyCreditLimit:
|
|
3074
|
+
dailyCallLimit: clampInt(Number(params.dailyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
3075
|
+
monthlyCallLimit: clampInt(Number(params.monthlyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
3076
|
+
dailyCreditLimit: clampInt(Number(params.dailyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
3077
|
+
monthlyCreditLimit: clampInt(Number(params.monthlyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
3053
3078
|
};
|
|
3054
3079
|
const success = this.gate.store.setQuota(params.key, quota);
|
|
3055
3080
|
if (!success) {
|
|
@@ -3939,10 +3964,10 @@ class PayGateServer {
|
|
|
3939
3964
|
this.sendJson(res, 200, { autoTopup: null, message: 'Auto-topup disabled' });
|
|
3940
3965
|
return;
|
|
3941
3966
|
}
|
|
3942
|
-
// Validate params
|
|
3943
|
-
const threshold =
|
|
3944
|
-
const amount =
|
|
3945
|
-
const maxDaily =
|
|
3967
|
+
// Validate params (clamp to reasonable upper bounds)
|
|
3968
|
+
const threshold = clampInt(Number(params.threshold) || 0, 0, MAX_TOPUP_THRESHOLD);
|
|
3969
|
+
const amount = clampInt(Number(params.amount) || 0, 0, MAX_TOPUP_AMOUNT);
|
|
3970
|
+
const maxDaily = clampInt(Number(params.maxDaily) || 0, 0, MAX_TOPUP_AMOUNT * 10);
|
|
3946
3971
|
if (threshold <= 0) {
|
|
3947
3972
|
this.sendError(res, 400, 'threshold must be a positive integer');
|
|
3948
3973
|
return;
|
|
@@ -4037,7 +4062,7 @@ class PayGateServer {
|
|
|
4037
4062
|
this.sendError(res, 404, 'Key not found or inactive');
|
|
4038
4063
|
return;
|
|
4039
4064
|
}
|
|
4040
|
-
const limit =
|
|
4065
|
+
const limit = clampInt(Number(params.spendingLimit) || 0, 0, MAX_SPENDING_LIMIT);
|
|
4041
4066
|
record.spendingLimit = limit;
|
|
4042
4067
|
this.gate.store.save();
|
|
4043
4068
|
this.syncKeyMutation(params.key);
|
|
@@ -9155,13 +9180,14 @@ class PayGateServer {
|
|
|
9155
9180
|
this.sendError(res, 400, 'executeAt must be in the future');
|
|
9156
9181
|
return;
|
|
9157
9182
|
}
|
|
9158
|
-
// Topup requires credits param
|
|
9183
|
+
// Topup requires credits param (clamp to MAX_CREDITS)
|
|
9159
9184
|
if (params.action === 'topup') {
|
|
9160
9185
|
const credits = params.params?.credits;
|
|
9161
9186
|
if (!credits || typeof credits !== 'number' || credits <= 0) {
|
|
9162
9187
|
this.sendError(res, 400, 'topup action requires params.credits (positive number)');
|
|
9163
9188
|
return;
|
|
9164
9189
|
}
|
|
9190
|
+
params.params.credits = clampInt(credits, 1, MAX_CREDITS);
|
|
9165
9191
|
}
|
|
9166
9192
|
const record = this.gate.store.resolveKeyRaw(params.key);
|
|
9167
9193
|
if (!record) {
|
|
@@ -9399,6 +9425,8 @@ class PayGateServer {
|
|
|
9399
9425
|
this.sendError(res, 400, 'Missing or invalid credits (must be positive number)');
|
|
9400
9426
|
return;
|
|
9401
9427
|
}
|
|
9428
|
+
// Clamp credits to max bound
|
|
9429
|
+
params.credits = clampInt(params.credits, 1, MAX_CREDITS);
|
|
9402
9430
|
const record = this.gate.store.resolveKeyRaw(params.key);
|
|
9403
9431
|
if (!record) {
|
|
9404
9432
|
this.sendError(res, 404, 'Key not found');
|
|
@@ -9649,10 +9677,10 @@ class PayGateServer {
|
|
|
9649
9677
|
if (fileConfig.globalQuota !== undefined) {
|
|
9650
9678
|
const q = fileConfig.globalQuota;
|
|
9651
9679
|
patch.globalQuota = {
|
|
9652
|
-
dailyCallLimit:
|
|
9653
|
-
monthlyCallLimit:
|
|
9654
|
-
dailyCreditLimit:
|
|
9655
|
-
monthlyCreditLimit:
|
|
9680
|
+
dailyCallLimit: clampInt(Number(q.dailyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
9681
|
+
monthlyCallLimit: clampInt(Number(q.monthlyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
9682
|
+
dailyCreditLimit: clampInt(Number(q.dailyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
9683
|
+
monthlyCreditLimit: clampInt(Number(q.monthlyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
9656
9684
|
};
|
|
9657
9685
|
}
|
|
9658
9686
|
if (fileConfig.alertRules !== undefined) {
|
|
@@ -10078,11 +10106,16 @@ class PayGateServer {
|
|
|
10078
10106
|
const urlParts = req.url?.split('?') || [];
|
|
10079
10107
|
const params = new URLSearchParams(urlParts[1] || '');
|
|
10080
10108
|
const format = params.get('format') || 'json';
|
|
10109
|
+
// Enforce result cap to prevent memory exhaustion (default 1000, max 5000)
|
|
10110
|
+
const limit = params.has('limit') ? clampInt(parseInt(params.get('limit'), 10), 1, 5000, 1000) : 1000;
|
|
10111
|
+
const offset = params.has('offset') ? clampInt(parseInt(params.get('offset'), 10), 0, 100_000, 0) : 0;
|
|
10081
10112
|
if (format === 'csv') {
|
|
10082
10113
|
const csv = this.audit.exportCsv({
|
|
10083
10114
|
types: params.get('types')?.split(',').filter(Boolean),
|
|
10084
10115
|
since: params.get('since') || undefined,
|
|
10085
10116
|
until: params.get('until') || undefined,
|
|
10117
|
+
limit,
|
|
10118
|
+
offset,
|
|
10086
10119
|
});
|
|
10087
10120
|
res.writeHead(200, {
|
|
10088
10121
|
'Content-Type': 'text/csv',
|
|
@@ -10091,9 +10124,15 @@ class PayGateServer {
|
|
|
10091
10124
|
res.end(csv);
|
|
10092
10125
|
}
|
|
10093
10126
|
else {
|
|
10094
|
-
const
|
|
10127
|
+
const result = this.audit.query({
|
|
10128
|
+
types: params.get('types')?.split(',').filter(Boolean),
|
|
10129
|
+
since: params.get('since') || undefined,
|
|
10130
|
+
until: params.get('until') || undefined,
|
|
10131
|
+
limit,
|
|
10132
|
+
offset,
|
|
10133
|
+
});
|
|
10095
10134
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
10096
|
-
res.end(JSON.stringify({ count: events.length, events }, null, 2));
|
|
10135
|
+
res.end(JSON.stringify({ count: result.events.length, total: result.total, limit, offset, events: result.events }, null, 2));
|
|
10097
10136
|
}
|
|
10098
10137
|
}
|
|
10099
10138
|
// ─── /audit/stats — Audit log statistics ────────────────────────────────
|
|
@@ -10179,7 +10218,7 @@ class PayGateServer {
|
|
|
10179
10218
|
const team = this.teams.createTeam({
|
|
10180
10219
|
name: sanitizeString(params.name) || 'unnamed',
|
|
10181
10220
|
description: sanitizeString(params.description) || undefined,
|
|
10182
|
-
budget: params.budget,
|
|
10221
|
+
budget: params.budget ? clampInt(Number(params.budget), 0, MAX_CREDITS) : undefined,
|
|
10183
10222
|
quota: params.quota,
|
|
10184
10223
|
tags: params.tags,
|
|
10185
10224
|
});
|
|
@@ -10214,7 +10253,7 @@ class PayGateServer {
|
|
|
10214
10253
|
const success = this.teams.updateTeam(params.teamId, {
|
|
10215
10254
|
name: params.name ? sanitizeString(params.name) : undefined,
|
|
10216
10255
|
description: params.description !== undefined ? (sanitizeString(params.description) || undefined) : undefined,
|
|
10217
|
-
budget: params.budget,
|
|
10256
|
+
budget: params.budget !== undefined ? clampInt(Number(params.budget), 0, MAX_CREDITS) : undefined,
|
|
10218
10257
|
quota: params.quota,
|
|
10219
10258
|
tags: params.tags,
|
|
10220
10259
|
});
|
|
@@ -10520,17 +10559,17 @@ class PayGateServer {
|
|
|
10520
10559
|
description: sanitizeString(params.description) || undefined,
|
|
10521
10560
|
allowedTools: params.allowedTools,
|
|
10522
10561
|
deniedTools: params.deniedTools,
|
|
10523
|
-
rateLimitPerMin: params.rateLimitPerMin,
|
|
10562
|
+
rateLimitPerMin: params.rateLimitPerMin ? clampInt(Number(params.rateLimitPerMin), 0, MAX_RATE_LIMIT) : undefined,
|
|
10524
10563
|
toolPricing: params.toolPricing,
|
|
10525
10564
|
quota: params.quota ? {
|
|
10526
|
-
dailyCallLimit:
|
|
10527
|
-
monthlyCallLimit:
|
|
10528
|
-
dailyCreditLimit:
|
|
10529
|
-
monthlyCreditLimit:
|
|
10565
|
+
dailyCallLimit: clampInt(Number(params.quota.dailyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10566
|
+
monthlyCallLimit: clampInt(Number(params.quota.monthlyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10567
|
+
dailyCreditLimit: clampInt(Number(params.quota.dailyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10568
|
+
monthlyCreditLimit: clampInt(Number(params.quota.monthlyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10530
10569
|
} : undefined,
|
|
10531
10570
|
ipAllowlist: params.ipAllowlist,
|
|
10532
|
-
defaultCredits: params.defaultCredits,
|
|
10533
|
-
maxSpendingLimit: params.maxSpendingLimit,
|
|
10571
|
+
defaultCredits: params.defaultCredits ? clampInt(Number(params.defaultCredits), 0, MAX_CREDITS) : undefined,
|
|
10572
|
+
maxSpendingLimit: params.maxSpendingLimit ? clampInt(Number(params.maxSpendingLimit), 0, MAX_SPENDING_LIMIT) : undefined,
|
|
10534
10573
|
tags: params.tags,
|
|
10535
10574
|
});
|
|
10536
10575
|
this.audit.log('group.created', 'admin', `Group created: ${group.name}`, { groupId: group.id, name: group.name });
|
|
@@ -10570,17 +10609,17 @@ class PayGateServer {
|
|
|
10570
10609
|
description: params.description !== undefined ? (sanitizeString(params.description) || undefined) : undefined,
|
|
10571
10610
|
allowedTools: params.allowedTools,
|
|
10572
10611
|
deniedTools: params.deniedTools,
|
|
10573
|
-
rateLimitPerMin: params.rateLimitPerMin,
|
|
10612
|
+
rateLimitPerMin: params.rateLimitPerMin ? clampInt(Number(params.rateLimitPerMin), 0, MAX_RATE_LIMIT) : undefined,
|
|
10574
10613
|
toolPricing: params.toolPricing,
|
|
10575
10614
|
quota: params.quota === null ? null : params.quota ? {
|
|
10576
|
-
dailyCallLimit:
|
|
10577
|
-
monthlyCallLimit:
|
|
10578
|
-
dailyCreditLimit:
|
|
10579
|
-
monthlyCreditLimit:
|
|
10615
|
+
dailyCallLimit: clampInt(Number(params.quota.dailyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10616
|
+
monthlyCallLimit: clampInt(Number(params.quota.monthlyCallLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10617
|
+
dailyCreditLimit: clampInt(Number(params.quota.dailyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10618
|
+
monthlyCreditLimit: clampInt(Number(params.quota.monthlyCreditLimit) || 0, 0, MAX_QUOTA_LIMIT),
|
|
10580
10619
|
} : undefined,
|
|
10581
10620
|
ipAllowlist: params.ipAllowlist,
|
|
10582
|
-
defaultCredits: params.defaultCredits,
|
|
10583
|
-
maxSpendingLimit: params.maxSpendingLimit,
|
|
10621
|
+
defaultCredits: params.defaultCredits ? clampInt(Number(params.defaultCredits), 0, MAX_CREDITS) : undefined,
|
|
10622
|
+
maxSpendingLimit: params.maxSpendingLimit ? clampInt(Number(params.maxSpendingLimit), 0, MAX_SPENDING_LIMIT) : undefined,
|
|
10584
10623
|
tags: params.tags,
|
|
10585
10624
|
});
|
|
10586
10625
|
this.audit.log('group.updated', 'admin', `Group updated: ${group.name}`, { groupId: group.id });
|
|
@@ -11559,11 +11598,15 @@ class PayGateServer {
|
|
|
11559
11598
|
filtered = filtered.filter(e => new Date(e.timestamp).getTime() <= untilTime);
|
|
11560
11599
|
}
|
|
11561
11600
|
}
|
|
11562
|
-
// Return newest first
|
|
11601
|
+
// Return newest first, with result cap to prevent memory exhaustion
|
|
11563
11602
|
const sorted = [...filtered].reverse();
|
|
11603
|
+
const limit = params.has('limit') ? clampInt(parseInt(params.get('limit'), 10), 1, 5000, 1000) : 1000;
|
|
11604
|
+
const offset = params.has('offset') ? clampInt(parseInt(params.get('offset'), 10), 0, 100_000, 0) : 0;
|
|
11605
|
+
const totalFiltered = sorted.length;
|
|
11606
|
+
const page = sorted.slice(offset, offset + limit);
|
|
11564
11607
|
if (format === 'csv') {
|
|
11565
11608
|
const header = 'id,timestamp,tool,key,status,credits,durationMs,denyReason,requestId';
|
|
11566
|
-
const rows =
|
|
11609
|
+
const rows = page.map(e => {
|
|
11567
11610
|
const escapeCsv = (v) => {
|
|
11568
11611
|
if (v === undefined || v === null)
|
|
11569
11612
|
return '';
|
|
@@ -11597,7 +11640,7 @@ class PayGateServer {
|
|
|
11597
11640
|
'Content-Type': 'application/json',
|
|
11598
11641
|
'Content-Disposition': 'attachment; filename="paygate-requests.json"',
|
|
11599
11642
|
});
|
|
11600
|
-
res.end(JSON.stringify({ count:
|
|
11643
|
+
res.end(JSON.stringify({ count: page.length, total: totalFiltered, limit, offset, requests: page }, null, 2));
|
|
11601
11644
|
}
|
|
11602
11645
|
}
|
|
11603
11646
|
// ─── /tools/available — Per-key tool availability with pricing ──────────────
|