paygate-mcp 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/dist/audit.d.ts +1 -1
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/key-templates.d.ts +80 -0
- package/dist/key-templates.d.ts.map +1 -0
- package/dist/key-templates.js +129 -0
- package/dist/key-templates.js.map +1 -0
- package/dist/server.d.ts +6 -5
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +129 -13
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,6 +78,7 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
78
78
|
- **Webhook Pause/Resume** — `POST /webhooks/pause` and `POST /webhooks/resume` temporarily halt webhook delivery during maintenance — events are buffered (not lost) and flushed on resume, with pause state visible in `/webhooks/stats`
|
|
79
79
|
- **Key Aliases** — `POST /keys/alias` assigns human-readable aliases (e.g. `my-service`, `prod-backend`) to API keys — use aliases in any admin endpoint (topup, revoke, suspend, resume, clone, transfer, usage) instead of opaque key IDs, with uniqueness enforcement, format validation, state file persistence, and audit trail
|
|
80
80
|
- **Key Expiry Scanner** — Proactive background scanner that detects expiring API keys before they expire — configurable scan interval and notification thresholds (default: 7d, 24h, 1h), de-duplicated `key.expiry_warning` webhook events, audit trail, `GET /keys/expiring?within=86400` query endpoint, and graceful shutdown
|
|
81
|
+
- **Key Templates** — Named templates for API key creation — define reusable presets (credits, ACL, quotas, IP, tags, namespace, expiry TTL, spending limit, auto-topup) and create keys with `template: "free-tier"` — explicit params override template defaults, CRUD admin API, Prometheus gauge, file persistence, max 100 templates
|
|
81
82
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
82
83
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
83
84
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -361,6 +362,9 @@ A real-time admin UI for managing keys, viewing usage, and monitoring tool calls
|
|
|
361
362
|
| `/webhooks/resume` | POST | `X-Admin-Key` | Resume webhook delivery and flush buffered events |
|
|
362
363
|
| `/keys/alias` | POST | `X-Admin-Key` | Set or clear a human-readable alias for an API key |
|
|
363
364
|
| `/keys/expiring` | GET | `X-Admin-Key` | List keys expiring within a time window (`?within=86400` seconds) |
|
|
365
|
+
| `/keys/templates` | GET | `X-Admin-Key` | List all key templates |
|
|
366
|
+
| `/keys/templates` | POST | `X-Admin-Key` | Create or update a key template |
|
|
367
|
+
| `/keys/templates/delete` | POST | `X-Admin-Key` | Delete a key template |
|
|
364
368
|
| `/config/reload` | POST | `X-Admin-Key` | Hot-reload config file (pricing, rate limits, webhooks, quotas) |
|
|
365
369
|
| `/health` | GET | None | Health check (status, uptime, version, in-flight, Redis/webhook status) |
|
|
366
370
|
| `/` | GET | None | Root endpoint (endpoint list) |
|
|
@@ -1277,6 +1281,56 @@ Configure the scanner in your config file:
|
|
|
1277
1281
|
| Audit | `key.expiry_warning` event logged for every notification |
|
|
1278
1282
|
| Endpoint | `GET /keys/expiring?within=N` lists keys expiring within N seconds (default: 86400) |
|
|
1279
1283
|
|
|
1284
|
+
### Key Templates
|
|
1285
|
+
|
|
1286
|
+
Named templates for API key creation. Define reusable presets and create keys with `template: "free-tier"`:
|
|
1287
|
+
|
|
1288
|
+
```bash
|
|
1289
|
+
# Create a template
|
|
1290
|
+
curl -X POST http://localhost:3402/keys/templates \
|
|
1291
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY" \
|
|
1292
|
+
-d '{
|
|
1293
|
+
"name": "free-tier",
|
|
1294
|
+
"description": "Free plan with basic access",
|
|
1295
|
+
"credits": 50,
|
|
1296
|
+
"allowedTools": ["search", "read"],
|
|
1297
|
+
"deniedTools": ["admin"],
|
|
1298
|
+
"tags": {"plan": "free"},
|
|
1299
|
+
"namespace": "public",
|
|
1300
|
+
"expiryTtlSeconds": 2592000,
|
|
1301
|
+
"spendingLimit": 200
|
|
1302
|
+
}'
|
|
1303
|
+
|
|
1304
|
+
# List all templates
|
|
1305
|
+
curl http://localhost:3402/keys/templates \
|
|
1306
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
1307
|
+
|
|
1308
|
+
# Create a key from template (inherits all defaults)
|
|
1309
|
+
curl -X POST http://localhost:3402/keys \
|
|
1310
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY" \
|
|
1311
|
+
-d '{"name": "new-user", "template": "free-tier"}'
|
|
1312
|
+
|
|
1313
|
+
# Create a key from template with overrides
|
|
1314
|
+
curl -X POST http://localhost:3402/keys \
|
|
1315
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY" \
|
|
1316
|
+
-d '{"name": "vip-user", "template": "free-tier", "credits": 500, "tags": {"plan": "vip"}}'
|
|
1317
|
+
|
|
1318
|
+
# Delete a template
|
|
1319
|
+
curl -X POST http://localhost:3402/keys/templates/delete \
|
|
1320
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY" \
|
|
1321
|
+
-d '{"name": "free-tier"}'
|
|
1322
|
+
```
|
|
1323
|
+
|
|
1324
|
+
| Feature | Details |
|
|
1325
|
+
|---------|---------|
|
|
1326
|
+
| Fields | credits, allowedTools, deniedTools, quota, ipAllowlist, spendingLimit, tags, namespace, expiryTtlSeconds, autoTopup |
|
|
1327
|
+
| Override | Explicit params in `POST /keys` always override template defaults |
|
|
1328
|
+
| TTL | `expiryTtlSeconds` sets expiry relative to key creation time (0 = never) |
|
|
1329
|
+
| Limit | Max 100 templates per server |
|
|
1330
|
+
| Persistence | `-templates.json` alongside state file, survives restarts |
|
|
1331
|
+
| Audit | `template.created`, `template.updated`, `template.deleted` events |
|
|
1332
|
+
| Prometheus | `paygate_templates_total` gauge tracks template count |
|
|
1333
|
+
|
|
1280
1334
|
### IP Allowlisting
|
|
1281
1335
|
|
|
1282
1336
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/audit.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* session lifecycle, and admin operations. Ring buffer with configurable
|
|
6
6
|
* max size and age-based retention. Zero external dependencies.
|
|
7
7
|
*/
|
|
8
|
-
export type AuditEventType = 'key.created' | 'key.revoked' | 'key.suspended' | 'key.resumed' | 'key.cloned' | 'key.rotated' | 'key.topup' | 'key.acl_updated' | 'key.expiry_updated' | 'key.quota_updated' | 'key.tags_updated' | 'key.ip_updated' | 'key.limit_updated' | 'gate.allow' | 'gate.deny' | 'session.created' | 'session.destroyed' | 'oauth.client_registered' | 'oauth.token_issued' | 'oauth.token_revoked' | 'team.created' | 'team.updated' | 'team.deleted' | 'team.key_assigned' | 'team.key_removed' | 'admin.auth_failed' | 'admin.alerts_configured' | 'webhook.dead_letter_cleared' | 'webhook.replayed' | 'webhook.test' | 'webhook.pause' | 'webhook.resume' | 'key.alias_set' | 'key.expiry_warning' | 'token.created' | 'token.revoked' | 'billing.refund' | 'key.auto_topup_configured' | 'key.auto_topped_up' | 'admin_key.created' | 'admin_key.revoked' | 'group.created' | 'group.updated' | 'group.deleted' | 'group.key_assigned' | 'group.key_removed' | 'key.credits_transferred' | 'keys.exported' | 'keys.imported' | 'webhook_filter.created' | 'webhook_filter.updated' | 'webhook_filter.deleted' | 'config.reloaded';
|
|
8
|
+
export type AuditEventType = 'key.created' | 'key.revoked' | 'key.suspended' | 'key.resumed' | 'key.cloned' | 'key.rotated' | 'key.topup' | 'key.acl_updated' | 'key.expiry_updated' | 'key.quota_updated' | 'key.tags_updated' | 'key.ip_updated' | 'key.limit_updated' | 'gate.allow' | 'gate.deny' | 'session.created' | 'session.destroyed' | 'oauth.client_registered' | 'oauth.token_issued' | 'oauth.token_revoked' | 'team.created' | 'team.updated' | 'team.deleted' | 'team.key_assigned' | 'team.key_removed' | 'admin.auth_failed' | 'admin.alerts_configured' | 'webhook.dead_letter_cleared' | 'webhook.replayed' | 'webhook.test' | 'webhook.pause' | 'webhook.resume' | 'key.alias_set' | 'key.expiry_warning' | 'template.created' | 'template.updated' | 'template.deleted' | 'token.created' | 'token.revoked' | 'billing.refund' | 'key.auto_topup_configured' | 'key.auto_topped_up' | 'admin_key.created' | 'admin_key.revoked' | 'group.created' | 'group.updated' | 'group.deleted' | 'group.key_assigned' | 'group.key_removed' | 'key.credits_transferred' | 'keys.exported' | 'keys.imported' | 'webhook_filter.created' | 'webhook_filter.updated' | 'webhook_filter.deleted' | 'config.reloaded';
|
|
9
9
|
export interface AuditEvent {
|
|
10
10
|
/** Monotonically increasing ID */
|
|
11
11
|
id: number;
|
package/dist/audit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
|
package/dist/audit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KeyTemplateManager — Named templates for API key creation.
|
|
3
|
+
*
|
|
4
|
+
* Templates define reusable presets for key creation (credits, ACL, quotas, etc.).
|
|
5
|
+
* Instead of passing all options every time, use `template: "free-tier"` in POST /keys.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - CRUD: create, update, list, get, delete templates
|
|
9
|
+
* - File persistence (-templates.json alongside state file)
|
|
10
|
+
* - Templates define: credits, allowedTools, deniedTools, quota, ipAllowlist,
|
|
11
|
+
* spendingLimit, tags, namespace, expiryTtlSeconds, autoTopup
|
|
12
|
+
* - Max 100 templates
|
|
13
|
+
*/
|
|
14
|
+
import { QuotaConfig } from './types';
|
|
15
|
+
export interface KeyTemplate {
|
|
16
|
+
/** Unique template name (alphanumeric, hyphens, underscores, 1-50 chars) */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Human-readable description */
|
|
19
|
+
description: string;
|
|
20
|
+
/** Initial credits for keys created from this template */
|
|
21
|
+
credits: number;
|
|
22
|
+
/** Whitelist: only these tools are accessible. Empty = all tools allowed. */
|
|
23
|
+
allowedTools: string[];
|
|
24
|
+
/** Blacklist: these tools are always denied. */
|
|
25
|
+
deniedTools: string[];
|
|
26
|
+
/** Per-key quota overrides. Undefined = use global defaults. */
|
|
27
|
+
quota?: QuotaConfig;
|
|
28
|
+
/** IP allowlist. Empty = all IPs allowed. */
|
|
29
|
+
ipAllowlist: string[];
|
|
30
|
+
/** Max total credits this key can spend. 0 = unlimited. */
|
|
31
|
+
spendingLimit: number;
|
|
32
|
+
/** Arbitrary key-value metadata tags. */
|
|
33
|
+
tags: Record<string, string>;
|
|
34
|
+
/** Namespace for multi-tenant isolation. */
|
|
35
|
+
namespace: string;
|
|
36
|
+
/** TTL in seconds from creation. 0 = never expires. */
|
|
37
|
+
expiryTtlSeconds: number;
|
|
38
|
+
/** Auto-topup configuration. Undefined = disabled. */
|
|
39
|
+
autoTopup?: {
|
|
40
|
+
threshold: number;
|
|
41
|
+
amount: number;
|
|
42
|
+
maxDaily: number;
|
|
43
|
+
};
|
|
44
|
+
/** ISO timestamp when template was created */
|
|
45
|
+
createdAt: string;
|
|
46
|
+
/** ISO timestamp of last update */
|
|
47
|
+
updatedAt: string;
|
|
48
|
+
}
|
|
49
|
+
export declare class KeyTemplateManager {
|
|
50
|
+
private templates;
|
|
51
|
+
private readonly filePath;
|
|
52
|
+
constructor(filePath?: string);
|
|
53
|
+
/**
|
|
54
|
+
* Create or update a template.
|
|
55
|
+
*/
|
|
56
|
+
set(name: string, data: Partial<Omit<KeyTemplate, 'name' | 'createdAt' | 'updatedAt'>>): {
|
|
57
|
+
success: boolean;
|
|
58
|
+
error?: string;
|
|
59
|
+
template?: KeyTemplate;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Get a template by name.
|
|
63
|
+
*/
|
|
64
|
+
get(name: string): KeyTemplate | null;
|
|
65
|
+
/**
|
|
66
|
+
* Delete a template.
|
|
67
|
+
*/
|
|
68
|
+
delete(name: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* List all templates.
|
|
71
|
+
*/
|
|
72
|
+
list(): KeyTemplate[];
|
|
73
|
+
/**
|
|
74
|
+
* Get template count.
|
|
75
|
+
*/
|
|
76
|
+
get count(): number;
|
|
77
|
+
private saveToFile;
|
|
78
|
+
private loadFromFile;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=key-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-templates.d.ts","sourceRoot":"","sources":["../src/key-templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAItC,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gDAAgD;IAChD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gEAAgE;IAChE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,gBAAgB,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,SAAS,CAAC,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;gBAE7B,QAAQ,CAAC,EAAE,MAAM;IAO7B;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE;IAqCrJ;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAIrC;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAM7B;;OAEG;IACH,IAAI,IAAI,WAAW,EAAE;IAIrB;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAID,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,YAAY;CAgBrB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* KeyTemplateManager — Named templates for API key creation.
|
|
4
|
+
*
|
|
5
|
+
* Templates define reusable presets for key creation (credits, ACL, quotas, etc.).
|
|
6
|
+
* Instead of passing all options every time, use `template: "free-tier"` in POST /keys.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - CRUD: create, update, list, get, delete templates
|
|
10
|
+
* - File persistence (-templates.json alongside state file)
|
|
11
|
+
* - Templates define: credits, allowedTools, deniedTools, quota, ipAllowlist,
|
|
12
|
+
* spendingLimit, tags, namespace, expiryTtlSeconds, autoTopup
|
|
13
|
+
* - Max 100 templates
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.KeyTemplateManager = void 0;
|
|
17
|
+
const fs_1 = require("fs");
|
|
18
|
+
const path_1 = require("path");
|
|
19
|
+
// ─── Manager Class ────────────────────────────────────────────────────────────
|
|
20
|
+
const MAX_TEMPLATES = 100;
|
|
21
|
+
class KeyTemplateManager {
|
|
22
|
+
templates = new Map();
|
|
23
|
+
filePath;
|
|
24
|
+
constructor(filePath) {
|
|
25
|
+
this.filePath = filePath || null;
|
|
26
|
+
if (this.filePath) {
|
|
27
|
+
this.loadFromFile();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create or update a template.
|
|
32
|
+
*/
|
|
33
|
+
set(name, data) {
|
|
34
|
+
// Validate name
|
|
35
|
+
const sanitized = name.trim().slice(0, 50);
|
|
36
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(sanitized)) {
|
|
37
|
+
return { success: false, error: 'Template name must contain only letters, numbers, hyphens, and underscores' };
|
|
38
|
+
}
|
|
39
|
+
const existing = this.templates.get(sanitized);
|
|
40
|
+
const now = new Date().toISOString();
|
|
41
|
+
const template = {
|
|
42
|
+
name: sanitized,
|
|
43
|
+
description: String(data.description || existing?.description || '').slice(0, 500),
|
|
44
|
+
credits: Math.max(0, Math.floor(Number(data.credits ?? existing?.credits ?? 100))),
|
|
45
|
+
allowedTools: Array.isArray(data.allowedTools) ? data.allowedTools.filter(t => typeof t === 'string').slice(0, 100) : (existing?.allowedTools || []),
|
|
46
|
+
deniedTools: Array.isArray(data.deniedTools) ? data.deniedTools.filter(t => typeof t === 'string').slice(0, 100) : (existing?.deniedTools || []),
|
|
47
|
+
quota: data.quota !== undefined ? data.quota : existing?.quota,
|
|
48
|
+
ipAllowlist: Array.isArray(data.ipAllowlist) ? data.ipAllowlist.filter(t => typeof t === 'string').slice(0, 100) : (existing?.ipAllowlist || []),
|
|
49
|
+
spendingLimit: Math.max(0, Number(data.spendingLimit ?? existing?.spendingLimit ?? 0)),
|
|
50
|
+
tags: typeof data.tags === 'object' && data.tags !== null ? data.tags : (existing?.tags || {}),
|
|
51
|
+
namespace: String(data.namespace || existing?.namespace || 'default').trim().toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 50) || 'default',
|
|
52
|
+
expiryTtlSeconds: Math.max(0, Math.floor(Number(data.expiryTtlSeconds ?? existing?.expiryTtlSeconds ?? 0))),
|
|
53
|
+
autoTopup: data.autoTopup !== undefined ? data.autoTopup : existing?.autoTopup,
|
|
54
|
+
createdAt: existing?.createdAt || now,
|
|
55
|
+
updatedAt: now,
|
|
56
|
+
};
|
|
57
|
+
// Check limit (only for new templates)
|
|
58
|
+
if (!existing && this.templates.size >= MAX_TEMPLATES) {
|
|
59
|
+
return { success: false, error: `Maximum ${MAX_TEMPLATES} templates reached` };
|
|
60
|
+
}
|
|
61
|
+
this.templates.set(sanitized, template);
|
|
62
|
+
this.saveToFile();
|
|
63
|
+
return { success: true, template };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get a template by name.
|
|
67
|
+
*/
|
|
68
|
+
get(name) {
|
|
69
|
+
return this.templates.get(name) || null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Delete a template.
|
|
73
|
+
*/
|
|
74
|
+
delete(name) {
|
|
75
|
+
const existed = this.templates.delete(name);
|
|
76
|
+
if (existed)
|
|
77
|
+
this.saveToFile();
|
|
78
|
+
return existed;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* List all templates.
|
|
82
|
+
*/
|
|
83
|
+
list() {
|
|
84
|
+
return Array.from(this.templates.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get template count.
|
|
88
|
+
*/
|
|
89
|
+
get count() {
|
|
90
|
+
return this.templates.size;
|
|
91
|
+
}
|
|
92
|
+
// ─── File Persistence ──────────────────────────────────────────────────────
|
|
93
|
+
saveToFile() {
|
|
94
|
+
if (!this.filePath)
|
|
95
|
+
return;
|
|
96
|
+
const data = Array.from(this.templates.entries());
|
|
97
|
+
const json = JSON.stringify(data, null, 2);
|
|
98
|
+
const tmpPath = this.filePath + '.tmp';
|
|
99
|
+
try {
|
|
100
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(this.filePath), { recursive: true });
|
|
101
|
+
(0, fs_1.writeFileSync)(tmpPath, json, 'utf-8');
|
|
102
|
+
(0, fs_1.renameSync)(tmpPath, this.filePath);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
console.error(`[paygate] Failed to save templates: ${err.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
loadFromFile() {
|
|
109
|
+
if (!this.filePath || !(0, fs_1.existsSync)(this.filePath))
|
|
110
|
+
return;
|
|
111
|
+
try {
|
|
112
|
+
const json = (0, fs_1.readFileSync)(this.filePath, 'utf-8');
|
|
113
|
+
const data = JSON.parse(json);
|
|
114
|
+
if (!Array.isArray(data))
|
|
115
|
+
return;
|
|
116
|
+
for (const [name, template] of data) {
|
|
117
|
+
if (name && template && typeof template.name === 'string') {
|
|
118
|
+
this.templates.set(name, template);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
console.log(`[paygate] Loaded ${this.templates.size} template(s) from ${this.filePath}`);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
console.error(`[paygate] Failed to load templates: ${err.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.KeyTemplateManager = KeyTemplateManager;
|
|
129
|
+
//# sourceMappingURL=key-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-templates.js","sourceRoot":"","sources":["../src/key-templates.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { AdminKeyManager } from './admin-keys';
|
|
|
31
31
|
import { PluginManager, PayGatePlugin } from './plugin';
|
|
32
32
|
import { KeyGroupManager } from './groups';
|
|
33
33
|
import { ExpiryScanner } from './expiry-scanner';
|
|
34
|
+
import { KeyTemplateManager } from './key-templates';
|
|
34
35
|
/** Union type for both proxy backends */
|
|
35
36
|
type ProxyBackend = McpProxy | HttpMcpProxy;
|
|
36
37
|
export declare class PayGateServer {
|
|
@@ -71,6 +72,8 @@ export declare class PayGateServer {
|
|
|
71
72
|
readonly groups: KeyGroupManager;
|
|
72
73
|
/** Background key expiry scanner */
|
|
73
74
|
readonly expiryScanner: ExpiryScanner;
|
|
75
|
+
/** Key template manager for reusable key presets */
|
|
76
|
+
readonly templates: KeyTemplateManager;
|
|
74
77
|
/** Server start time (ms since epoch) */
|
|
75
78
|
private readonly startedAt;
|
|
76
79
|
/** Whether the server is draining (shutting down gracefully) */
|
|
@@ -214,11 +217,9 @@ export declare class PayGateServer {
|
|
|
214
217
|
private handleListAdminKeys;
|
|
215
218
|
private handleCreateAdminKey;
|
|
216
219
|
private handleRevokeAdminKey;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
* Fire-and-forget: errors logged, never thrown.
|
|
221
|
-
*/
|
|
220
|
+
private handleListTemplates;
|
|
221
|
+
private handleCreateTemplate;
|
|
222
|
+
private handleDeleteTemplate;
|
|
222
223
|
/**
|
|
223
224
|
* Route admin webhook events through the WebhookRouter (for filter rules) or direct emitter.
|
|
224
225
|
*/
|
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;AAKH,OAAO,EAAE,aAAa,EAAkB,mBAAmB,EAAkB,MAAM,SAAS,CAAC;AAU7F,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,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,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;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -84,6 +84,7 @@ const admin_keys_1 = require("./admin-keys");
|
|
|
84
84
|
const plugin_1 = require("./plugin");
|
|
85
85
|
const groups_1 = require("./groups");
|
|
86
86
|
const expiry_scanner_1 = require("./expiry-scanner");
|
|
87
|
+
const key_templates_1 = require("./key-templates");
|
|
87
88
|
/** Max request body size: 1MB */
|
|
88
89
|
const MAX_BODY_SIZE = 1_048_576;
|
|
89
90
|
class PayGateServer {
|
|
@@ -124,6 +125,8 @@ class PayGateServer {
|
|
|
124
125
|
groups;
|
|
125
126
|
/** Background key expiry scanner */
|
|
126
127
|
expiryScanner;
|
|
128
|
+
/** Key template manager for reusable key presets */
|
|
129
|
+
templates;
|
|
127
130
|
/** Server start time (ms since epoch) */
|
|
128
131
|
startedAt = Date.now();
|
|
129
132
|
/** Whether the server is draining (shutting down gracefully) */
|
|
@@ -260,6 +263,12 @@ class PayGateServer {
|
|
|
260
263
|
thresholdSeconds: warning.thresholdSeconds,
|
|
261
264
|
});
|
|
262
265
|
};
|
|
266
|
+
// Key template manager for reusable key creation presets
|
|
267
|
+
const templatesStatePath = statePath ? statePath.replace(/\.json$/, '-templates.json') : undefined;
|
|
268
|
+
this.templates = new key_templates_1.KeyTemplateManager(templatesStatePath);
|
|
269
|
+
this.metrics.registerGauge('paygate_templates_total', 'Number of key templates', () => {
|
|
270
|
+
return this.templates.count;
|
|
271
|
+
});
|
|
263
272
|
// Scoped token manager (uses bootstrap admin key as signing secret, padded to min length)
|
|
264
273
|
const tokenSecret = this.bootstrapAdminKey.length >= 8
|
|
265
274
|
? this.bootstrapAdminKey
|
|
@@ -409,6 +418,14 @@ class PayGateServer {
|
|
|
409
418
|
return this.handleKeyUsage(req, res);
|
|
410
419
|
case '/keys/expiring':
|
|
411
420
|
return this.handleKeysExpiring(req, res);
|
|
421
|
+
case '/keys/templates':
|
|
422
|
+
if (req.method === 'GET')
|
|
423
|
+
return this.handleListTemplates(req, res);
|
|
424
|
+
if (req.method === 'POST')
|
|
425
|
+
return this.handleCreateTemplate(req, res);
|
|
426
|
+
break;
|
|
427
|
+
case '/keys/templates/delete':
|
|
428
|
+
return this.handleDeleteTemplate(req, res);
|
|
412
429
|
case '/topup':
|
|
413
430
|
return this.handleTopUp(req, res);
|
|
414
431
|
case '/keys/transfer':
|
|
@@ -934,6 +951,8 @@ class PayGateServer {
|
|
|
934
951
|
autoTopup: 'POST /keys/auto-topup — Configure auto-topup for a key (requires X-Admin-Key)',
|
|
935
952
|
keyUsage: 'GET /keys/usage?key=... — Per-key usage breakdown (requires X-Admin-Key)',
|
|
936
953
|
keysExpiring: 'GET /keys/expiring?within=86400 — List keys expiring within N seconds (requires X-Admin-Key)',
|
|
954
|
+
keyTemplates: 'GET /keys/templates — List key templates + POST to create/update (requires X-Admin-Key)',
|
|
955
|
+
deleteTemplate: 'POST /keys/templates/delete — Delete a key template (requires X-Admin-Key)',
|
|
937
956
|
pricing: 'GET /pricing — Tool pricing breakdown (public)',
|
|
938
957
|
mcpPayment: 'GET /.well-known/mcp-payment — Payment metadata (SEP-2007)',
|
|
939
958
|
audit: 'GET /audit — Query audit log (requires X-Admin-Key)',
|
|
@@ -1045,14 +1064,24 @@ class PayGateServer {
|
|
|
1045
1064
|
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
1046
1065
|
return;
|
|
1047
1066
|
}
|
|
1067
|
+
// Resolve template defaults (explicit params override template values)
|
|
1068
|
+
let tpl = null;
|
|
1069
|
+
if (params.template) {
|
|
1070
|
+
tpl = this.templates.get(params.template);
|
|
1071
|
+
if (!tpl) {
|
|
1072
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1073
|
+
res.end(JSON.stringify({ error: `Template "${params.template}" not found` }));
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1048
1077
|
const name = String(params.name || 'unnamed').slice(0, 200);
|
|
1049
|
-
const credits = Math.max(0, Math.floor(Number(params.credits
|
|
1078
|
+
const credits = Math.max(0, Math.floor(Number(params.credits ?? tpl?.credits ?? 100)));
|
|
1050
1079
|
if (credits <= 0) {
|
|
1051
1080
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1052
1081
|
res.end(JSON.stringify({ error: 'Credits must be a positive integer' }));
|
|
1053
1082
|
return;
|
|
1054
1083
|
}
|
|
1055
|
-
// Calculate expiry: expiresIn (seconds) takes priority over expiresAt (ISO date)
|
|
1084
|
+
// Calculate expiry: expiresIn (seconds) takes priority over expiresAt (ISO date), template TTL is fallback
|
|
1056
1085
|
let expiresAt = null;
|
|
1057
1086
|
if (params.expiresIn && Number(params.expiresIn) > 0) {
|
|
1058
1087
|
expiresAt = new Date(Date.now() + Number(params.expiresIn) * 1000).toISOString();
|
|
@@ -1060,7 +1089,10 @@ class PayGateServer {
|
|
|
1060
1089
|
else if (params.expiresAt) {
|
|
1061
1090
|
expiresAt = String(params.expiresAt);
|
|
1062
1091
|
}
|
|
1063
|
-
|
|
1092
|
+
else if (tpl && tpl.expiryTtlSeconds > 0) {
|
|
1093
|
+
expiresAt = new Date(Date.now() + tpl.expiryTtlSeconds * 1000).toISOString();
|
|
1094
|
+
}
|
|
1095
|
+
// Parse quota: explicit params > template > undefined
|
|
1064
1096
|
let quota = undefined;
|
|
1065
1097
|
if (params.quota) {
|
|
1066
1098
|
quota = {
|
|
@@ -1070,15 +1102,28 @@ class PayGateServer {
|
|
|
1070
1102
|
monthlyCreditLimit: Math.max(0, Math.floor(Number(params.quota.monthlyCreditLimit) || 0)),
|
|
1071
1103
|
};
|
|
1072
1104
|
}
|
|
1105
|
+
else if (tpl?.quota) {
|
|
1106
|
+
quota = { ...tpl.quota };
|
|
1107
|
+
}
|
|
1073
1108
|
const record = this.gate.store.createKey(name, credits, {
|
|
1074
|
-
allowedTools: params.allowedTools,
|
|
1075
|
-
deniedTools: params.deniedTools,
|
|
1109
|
+
allowedTools: params.allowedTools || (tpl ? [...tpl.allowedTools] : undefined),
|
|
1110
|
+
deniedTools: params.deniedTools || (tpl ? [...tpl.deniedTools] : undefined),
|
|
1076
1111
|
expiresAt,
|
|
1077
1112
|
quota,
|
|
1078
|
-
tags: params.tags,
|
|
1079
|
-
ipAllowlist: params.ipAllowlist,
|
|
1080
|
-
namespace: params.namespace,
|
|
1113
|
+
tags: params.tags || (tpl ? { ...tpl.tags } : undefined),
|
|
1114
|
+
ipAllowlist: params.ipAllowlist || (tpl ? [...tpl.ipAllowlist] : undefined),
|
|
1115
|
+
namespace: params.namespace || tpl?.namespace,
|
|
1081
1116
|
});
|
|
1117
|
+
// Apply template spending limit if not explicitly set
|
|
1118
|
+
if (tpl && tpl.spendingLimit > 0 && record.spendingLimit === 0) {
|
|
1119
|
+
record.spendingLimit = tpl.spendingLimit;
|
|
1120
|
+
this.gate.store.save();
|
|
1121
|
+
}
|
|
1122
|
+
// Apply template auto-topup if not explicitly configured
|
|
1123
|
+
if (tpl?.autoTopup && !record.autoTopup) {
|
|
1124
|
+
record.autoTopup = { ...tpl.autoTopup };
|
|
1125
|
+
this.gate.store.save();
|
|
1126
|
+
}
|
|
1082
1127
|
// Sync new key to Redis (if configured)
|
|
1083
1128
|
if (this.redisSync) {
|
|
1084
1129
|
this.redisSync.saveKey(record).catch(() => { });
|
|
@@ -4264,11 +4309,82 @@ class PayGateServer {
|
|
|
4264
4309
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
4265
4310
|
res.end(JSON.stringify({ revoked: true }));
|
|
4266
4311
|
}
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4312
|
+
// ─── /keys/templates — CRUD ────────────────────────────────────────────────
|
|
4313
|
+
handleListTemplates(req, res) {
|
|
4314
|
+
if (!this.checkAdmin(req, res))
|
|
4315
|
+
return;
|
|
4316
|
+
const templates = this.templates.list();
|
|
4317
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
4318
|
+
res.end(JSON.stringify({ total: templates.length, templates }));
|
|
4319
|
+
}
|
|
4320
|
+
async handleCreateTemplate(req, res) {
|
|
4321
|
+
if (!this.checkAdmin(req, res, 'admin'))
|
|
4322
|
+
return;
|
|
4323
|
+
const body = await this.readBody(req);
|
|
4324
|
+
let params;
|
|
4325
|
+
try {
|
|
4326
|
+
params = JSON.parse(body);
|
|
4327
|
+
}
|
|
4328
|
+
catch {
|
|
4329
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
4330
|
+
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
const name = params.name;
|
|
4334
|
+
if (!name || typeof name !== 'string') {
|
|
4335
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
4336
|
+
res.end(JSON.stringify({ error: 'Missing required field: name' }));
|
|
4337
|
+
return;
|
|
4338
|
+
}
|
|
4339
|
+
const existing = this.templates.get(name);
|
|
4340
|
+
const result = this.templates.set(name, params);
|
|
4341
|
+
if (!result.success) {
|
|
4342
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
4343
|
+
res.end(JSON.stringify({ error: result.error }));
|
|
4344
|
+
return;
|
|
4345
|
+
}
|
|
4346
|
+
const eventType = existing ? 'template.updated' : 'template.created';
|
|
4347
|
+
this.audit.log(eventType, 'admin', `${existing ? 'Updated' : 'Created'} template: ${name}`, {
|
|
4348
|
+
templateName: name,
|
|
4349
|
+
});
|
|
4350
|
+
res.writeHead(existing ? 200 : 201, { 'Content-Type': 'application/json' });
|
|
4351
|
+
res.end(JSON.stringify({ template: result.template }));
|
|
4352
|
+
}
|
|
4353
|
+
async handleDeleteTemplate(req, res) {
|
|
4354
|
+
if (req.method !== 'POST') {
|
|
4355
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
4356
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use POST.' }));
|
|
4357
|
+
return;
|
|
4358
|
+
}
|
|
4359
|
+
if (!this.checkAdmin(req, res, 'admin'))
|
|
4360
|
+
return;
|
|
4361
|
+
const body = await this.readBody(req);
|
|
4362
|
+
let params;
|
|
4363
|
+
try {
|
|
4364
|
+
params = JSON.parse(body);
|
|
4365
|
+
}
|
|
4366
|
+
catch {
|
|
4367
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
4368
|
+
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
4369
|
+
return;
|
|
4370
|
+
}
|
|
4371
|
+
if (!params.name || typeof params.name !== 'string') {
|
|
4372
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
4373
|
+
res.end(JSON.stringify({ error: 'Missing required field: name' }));
|
|
4374
|
+
return;
|
|
4375
|
+
}
|
|
4376
|
+
const deleted = this.templates.delete(params.name);
|
|
4377
|
+
if (!deleted) {
|
|
4378
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
4379
|
+
res.end(JSON.stringify({ error: `Template "${params.name}" not found` }));
|
|
4380
|
+
return;
|
|
4381
|
+
}
|
|
4382
|
+
this.audit.log('template.deleted', 'admin', `Deleted template: ${params.name}`, {
|
|
4383
|
+
templateName: params.name,
|
|
4384
|
+
});
|
|
4385
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
4386
|
+
res.end(JSON.stringify({ deleted: true, name: params.name }));
|
|
4387
|
+
}
|
|
4272
4388
|
/**
|
|
4273
4389
|
* Route admin webhook events through the WebhookRouter (for filter rules) or direct emitter.
|
|
4274
4390
|
*/
|