paygate-mcp 9.2.0 → 9.3.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 +10 -3
- package/dist/compliance.d.ts +64 -0
- package/dist/compliance.d.ts.map +1 -0
- package/dist/compliance.js +239 -0
- package/dist/compliance.js.map +1 -0
- package/dist/gate.d.ts +11 -0
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +53 -0
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +203 -1
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Monetize any MCP server with one command. Add API key auth, per-tool pricing, ra
|
|
|
11
11
|
- [Quick Start](#quick-start)
|
|
12
12
|
- [What It Does](#what-it-does)
|
|
13
13
|
- [Usage](#usage) — Local stdio, remote HTTP, multi-server, client SDK
|
|
14
|
-
- [API Reference](#api-reference) — All
|
|
14
|
+
- [API Reference](#api-reference) — All 143+ endpoints
|
|
15
15
|
- [CLI Options](#cli-options)
|
|
16
16
|
- [Deployment](#deployment) — Docker, docker-compose, systemd, PM2
|
|
17
17
|
- [Load Testing](#load-testing) — k6 benchmarking for production
|
|
@@ -66,7 +66,7 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
66
66
|
- **SSE Streaming** — Full MCP Streamable HTTP transport (POST SSE, GET notifications, DELETE sessions)
|
|
67
67
|
- **Audit Log** — Structured audit trail with retention policies, query API, CSV/JSON export
|
|
68
68
|
- **Registry/Discovery** — Agent-discoverable pricing via `/.well-known/mcp-payment`, `/pricing`, and `/.well-known/mcp.json` identity card
|
|
69
|
-
- **OpenAPI 3.1 + Interactive Docs** — Auto-generated spec at `/openapi.json`, Swagger UI at `/docs` — all
|
|
69
|
+
- **OpenAPI 3.1 + Interactive Docs** — Auto-generated spec at `/openapi.json`, Swagger UI at `/docs` — all 143+ endpoints documented
|
|
70
70
|
- **Public Endpoint Rate Limiting** — Configurable per-IP rate limit (default 300/min) on `/health`, `/info`, `/pricing`, `/docs`, `/openapi.json`, `/.well-known/*`, `/robots.txt`, `/` — 429 with Retry-After header
|
|
71
71
|
- **Robots.txt + HEAD Support** — Standard `/robots.txt` (allow public, disallow admin/keys), HEAD method on all public endpoints for uptime monitoring
|
|
72
72
|
- **Prometheus Metrics** — `/metrics` endpoint with counters, gauges, and uptime in standard text format
|
|
@@ -150,6 +150,9 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
150
150
|
- **Response Caching** — SHA-256 keyed response cache for identical tool calls — skips backend invocation and credit deduction on cache hit, LRU eviction, per-tool or global TTL, `X-Cache: HIT/MISS` header, admin management (`GET/DELETE /admin/cache`), Prometheus gauge
|
|
151
151
|
- **Circuit Breaker** — Three-state circuit breaker (closed → open → half_open) for backend failure detection — opens after N consecutive failures, auto-recovers after cooldown, error code `-32003`, admin management (`GET/POST /admin/circuit`)
|
|
152
152
|
- **Configurable Timeouts** — Per-tool and global timeout for tool calls — returns error code `-32004` on timeout, per-tool override via `toolPricing[tool].timeoutMs`, triggers circuit breaker failure recording
|
|
153
|
+
- **Outcome-Based Pricing** — Charge extra credits based on response output size — `creditsPerKbOutput` per-tool config, post-response billing, `X-Output-Surcharge` header, complements `creditsPerKbInput` for complete size-based pricing
|
|
154
|
+
- **Compliance Audit Export** — Framework-specific compliance reports for SOC 2, GDPR, HIPAA — `GET /admin/compliance/export`, event classification into access control/data processing/config changes/security, JSON or CSV export, configurable time periods
|
|
155
|
+
- **Per-Key Webhook URLs** — Key-level webhook routing — events for a specific key sent to key's webhook URL alongside global webhook, SSRF-protected, HMAC-SHA256 signed, lazy emitter management via `POST/GET/DELETE /keys/webhook`
|
|
153
156
|
- **Security Audit** — `GET /admin/security` security posture analysis identifying keys without IP allowlists, quotas, ACL restrictions, spending limits, or expiry dates, flagging high-credit keys, and computing a composite security score
|
|
154
157
|
- **Revenue Analysis** — `GET /admin/revenue` revenue metrics with per-tool revenue breakdown, per-key spending, hourly revenue trends, credit flow summary (allocated/spent/remaining), and average revenue per call
|
|
155
158
|
- **Key Portfolio Health** — `GET /admin/key-portfolio` portfolio-wide key health with active/inactive/suspended counts, stale keys, expiring-soon keys, age distribution, credit utilization, and namespace breakdown
|
|
@@ -453,6 +456,10 @@ A real-time admin UI for managing keys, viewing usage, and monitoring tool calls
|
|
|
453
456
|
| `/admin/cache` | DELETE | `X-Admin-Key` | Clear cache (all or `?tool=` filter) |
|
|
454
457
|
| `/admin/circuit` | GET | `X-Admin-Key` | Circuit breaker status (state, failures, rejections) |
|
|
455
458
|
| `/admin/circuit` | POST | `X-Admin-Key` | Reset circuit breaker to closed state |
|
|
459
|
+
| `/admin/compliance/export` | GET | `X-Admin-Key` | Compliance audit export (SOC 2/GDPR/HIPAA, JSON/CSV) |
|
|
460
|
+
| `/keys/webhook` | POST | `X-Admin-Key` | Set per-key webhook URL |
|
|
461
|
+
| `/keys/webhook` | GET | `X-Admin-Key` | Get per-key webhook status |
|
|
462
|
+
| `/keys/webhook` | DELETE | `X-Admin-Key` | Remove per-key webhook URL |
|
|
456
463
|
| `/.well-known/oauth-authorization-server` | GET | None | OAuth 2.1 server metadata |
|
|
457
464
|
| `/oauth/register` | POST | None | Dynamic Client Registration (RFC 7591) |
|
|
458
465
|
| `/oauth/authorize` | GET | None | Authorization endpoint (PKCE required) |
|
|
@@ -462,7 +469,7 @@ A real-time admin UI for managing keys, viewing usage, and monitoring tool calls
|
|
|
462
469
|
| `/.well-known/mcp-payment` | GET | None | Server payment metadata (SEP-2007) |
|
|
463
470
|
| `/.well-known/mcp.json` | GET | None | MCP Server Identity card (discovery) |
|
|
464
471
|
| `/pricing` | GET | None | Full per-tool pricing breakdown |
|
|
465
|
-
| `/openapi.json` | GET | None | OpenAPI 3.1 spec (all
|
|
472
|
+
| `/openapi.json` | GET | None | OpenAPI 3.1 spec (all 143+ endpoints) |
|
|
466
473
|
| `/docs` | GET | None | Interactive API docs (Swagger UI) |
|
|
467
474
|
| `/robots.txt` | GET | None | Crawler directives (allow public, disallow admin/keys) |
|
|
468
475
|
| `/portal` | GET | None | Self-service API key portal (browser UI, auth via X-API-Key prompt) |
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance Export — Generate audit reports for SOC 2, GDPR, and HIPAA compliance.
|
|
3
|
+
*
|
|
4
|
+
* Formats audit events into structured compliance reports with:
|
|
5
|
+
* - Report metadata (period, generation time, framework, version)
|
|
6
|
+
* - Access control events (key management, auth failures)
|
|
7
|
+
* - Data processing events (tool calls, credit operations)
|
|
8
|
+
* - Configuration changes (config reload, webhook updates)
|
|
9
|
+
* - Summary statistics
|
|
10
|
+
*/
|
|
11
|
+
import { AuditLogger } from './audit';
|
|
12
|
+
export type ComplianceFramework = 'soc2' | 'gdpr' | 'hipaa';
|
|
13
|
+
export interface ComplianceReportMeta {
|
|
14
|
+
framework: ComplianceFramework;
|
|
15
|
+
generatedAt: string;
|
|
16
|
+
periodStart: string;
|
|
17
|
+
periodEnd: string;
|
|
18
|
+
serverVersion: string;
|
|
19
|
+
totalEvents: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ComplianceSection {
|
|
22
|
+
title: string;
|
|
23
|
+
description: string;
|
|
24
|
+
events: ComplianceEvent[];
|
|
25
|
+
count: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ComplianceEvent {
|
|
28
|
+
timestamp: string;
|
|
29
|
+
category: string;
|
|
30
|
+
action: string;
|
|
31
|
+
actor: string;
|
|
32
|
+
detail: string;
|
|
33
|
+
severity: 'info' | 'warning' | 'critical';
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
export interface ComplianceReport {
|
|
37
|
+
meta: ComplianceReportMeta;
|
|
38
|
+
sections: ComplianceSection[];
|
|
39
|
+
summary: ComplianceSummary;
|
|
40
|
+
}
|
|
41
|
+
export interface ComplianceSummary {
|
|
42
|
+
totalAccessControlEvents: number;
|
|
43
|
+
totalDataProcessingEvents: number;
|
|
44
|
+
totalConfigChangeEvents: number;
|
|
45
|
+
totalSecurityEvents: number;
|
|
46
|
+
authFailures: number;
|
|
47
|
+
keysCreated: number;
|
|
48
|
+
keysRevoked: number;
|
|
49
|
+
keysSuspended: number;
|
|
50
|
+
uniqueActors: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate a compliance report from audit log events.
|
|
54
|
+
*/
|
|
55
|
+
export declare function generateComplianceReport(auditLogger: AuditLogger, framework: ComplianceFramework, options: {
|
|
56
|
+
since?: string;
|
|
57
|
+
until?: string;
|
|
58
|
+
serverVersion: string;
|
|
59
|
+
}): ComplianceReport;
|
|
60
|
+
/**
|
|
61
|
+
* Convert a compliance report to CSV format.
|
|
62
|
+
*/
|
|
63
|
+
export declare function complianceReportToCsv(report: ComplianceReport): string;
|
|
64
|
+
//# sourceMappingURL=compliance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../src/compliance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAc,WAAW,EAAc,MAAM,SAAS,CAAC;AAI9D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC;IAClC,uBAAuB,EAAE,MAAM,CAAC;IAChC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAiID;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,mBAAmB,EAC9B,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB,GACA,gBAAgB,CA8FlB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAatE"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Compliance Export — Generate audit reports for SOC 2, GDPR, and HIPAA compliance.
|
|
4
|
+
*
|
|
5
|
+
* Formats audit events into structured compliance reports with:
|
|
6
|
+
* - Report metadata (period, generation time, framework, version)
|
|
7
|
+
* - Access control events (key management, auth failures)
|
|
8
|
+
* - Data processing events (tool calls, credit operations)
|
|
9
|
+
* - Configuration changes (config reload, webhook updates)
|
|
10
|
+
* - Summary statistics
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.generateComplianceReport = generateComplianceReport;
|
|
14
|
+
exports.complianceReportToCsv = complianceReportToCsv;
|
|
15
|
+
// ─── Event Classification ─────────────────────────────────────────────────────
|
|
16
|
+
const ACCESS_CONTROL_EVENTS = new Set([
|
|
17
|
+
'key.created', 'key.revoked', 'key.suspended', 'key.resumed', 'key.cloned',
|
|
18
|
+
'key.rotated', 'key.acl_updated', 'key.expiry_updated', 'key.ip_updated',
|
|
19
|
+
'admin.auth_failed', 'admin_key.created', 'admin_key.revoked',
|
|
20
|
+
'admin_key.bootstrap_rotated', 'oauth.client_registered',
|
|
21
|
+
'oauth.token_issued', 'oauth.token_revoked', 'token.created', 'token.revoked',
|
|
22
|
+
'team.key_assigned', 'team.key_removed', 'group.key_assigned', 'group.key_removed',
|
|
23
|
+
]);
|
|
24
|
+
const DATA_PROCESSING_EVENTS = new Set([
|
|
25
|
+
'gate.allow', 'gate.deny', 'key.topup', 'key.auto_topped_up',
|
|
26
|
+
'key.credits_transferred', 'credits.reserved', 'credits.committed',
|
|
27
|
+
'credits.released', 'billing.refund', 'keys.exported', 'keys.imported',
|
|
28
|
+
'admin.backup_created', 'admin.backup_restored', 'stripe.checkout_created',
|
|
29
|
+
]);
|
|
30
|
+
const CONFIG_CHANGE_EVENTS = new Set([
|
|
31
|
+
'config.reloaded', 'config.export', 'maintenance.enabled', 'maintenance.disabled',
|
|
32
|
+
'key.quota_updated', 'key.tags_updated', 'key.limit_updated',
|
|
33
|
+
'key.alias_set', 'key.note_added', 'key.note_deleted',
|
|
34
|
+
'admin.alerts_configured', 'admin.cache_cleared', 'admin.circuit_reset',
|
|
35
|
+
'template.created', 'template.updated', 'template.deleted',
|
|
36
|
+
'team.created', 'team.updated', 'team.deleted',
|
|
37
|
+
'group.created', 'group.updated', 'group.deleted',
|
|
38
|
+
'webhook_filter.created', 'webhook_filter.updated', 'webhook_filter.deleted',
|
|
39
|
+
'schedule.created', 'schedule.executed', 'schedule.cancelled',
|
|
40
|
+
]);
|
|
41
|
+
const SECURITY_EVENTS = new Set([
|
|
42
|
+
'admin.auth_failed', 'key.revoked', 'key.suspended',
|
|
43
|
+
'admin_key.revoked', 'admin_key.bootstrap_rotated',
|
|
44
|
+
'oauth.token_revoked', 'token.revoked',
|
|
45
|
+
]);
|
|
46
|
+
// ─── Framework-specific descriptions ──────────────────────────────────────────
|
|
47
|
+
const FRAMEWORK_SECTIONS = {
|
|
48
|
+
soc2: {
|
|
49
|
+
accessControl: {
|
|
50
|
+
title: 'CC6.1 – Logical Access Controls',
|
|
51
|
+
description: 'Access provisioning, de-provisioning, key rotation, and authentication events.',
|
|
52
|
+
},
|
|
53
|
+
dataProcessing: {
|
|
54
|
+
title: 'CC7.2 – System Operations Monitoring',
|
|
55
|
+
description: 'Tool call processing, credit operations, billing, and data import/export events.',
|
|
56
|
+
},
|
|
57
|
+
configChanges: {
|
|
58
|
+
title: 'CC8.1 – Change Management',
|
|
59
|
+
description: 'Configuration changes, maintenance windows, template updates, and system modifications.',
|
|
60
|
+
},
|
|
61
|
+
security: {
|
|
62
|
+
title: 'CC6.8 – Security Incident Detection',
|
|
63
|
+
description: 'Authentication failures, key revocations, suspicious activity, and security events.',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
gdpr: {
|
|
67
|
+
accessControl: {
|
|
68
|
+
title: 'Article 25 – Data Protection by Design',
|
|
69
|
+
description: 'Access control events demonstrating data protection measures and access management.',
|
|
70
|
+
},
|
|
71
|
+
dataProcessing: {
|
|
72
|
+
title: 'Article 30 – Records of Processing Activities',
|
|
73
|
+
description: 'Data processing events including tool calls, data transfers, and billing operations.',
|
|
74
|
+
},
|
|
75
|
+
configChanges: {
|
|
76
|
+
title: 'Article 32 – Security of Processing',
|
|
77
|
+
description: 'System configuration changes and security measure updates.',
|
|
78
|
+
},
|
|
79
|
+
security: {
|
|
80
|
+
title: 'Article 33 – Notification of Data Breaches',
|
|
81
|
+
description: 'Security events, authentication failures, and potential breach indicators.',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
hipaa: {
|
|
85
|
+
accessControl: {
|
|
86
|
+
title: '§164.312(a) – Access Control',
|
|
87
|
+
description: 'Electronic access control events, user authentication, and authorization management.',
|
|
88
|
+
},
|
|
89
|
+
dataProcessing: {
|
|
90
|
+
title: '§164.312(b) – Audit Controls',
|
|
91
|
+
description: 'Information system activity records, data processing, and transaction logs.',
|
|
92
|
+
},
|
|
93
|
+
configChanges: {
|
|
94
|
+
title: '§164.312(e) – Transmission Security',
|
|
95
|
+
description: 'System configuration modifications and security parameter changes.',
|
|
96
|
+
},
|
|
97
|
+
security: {
|
|
98
|
+
title: '§164.308(a)(6) – Security Incident Procedures',
|
|
99
|
+
description: 'Security incidents, unauthorized access attempts, and incident response events.',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
// ─── Severity Mapping ─────────────────────────────────────────────────────────
|
|
104
|
+
function getSeverity(eventType) {
|
|
105
|
+
if (eventType === 'admin.auth_failed')
|
|
106
|
+
return 'critical';
|
|
107
|
+
if (eventType === 'key.revoked' || eventType === 'admin_key.revoked')
|
|
108
|
+
return 'warning';
|
|
109
|
+
if (eventType === 'key.suspended')
|
|
110
|
+
return 'warning';
|
|
111
|
+
if (eventType === 'gate.deny')
|
|
112
|
+
return 'warning';
|
|
113
|
+
if (eventType === 'maintenance.enabled')
|
|
114
|
+
return 'warning';
|
|
115
|
+
if (eventType === 'admin_key.bootstrap_rotated')
|
|
116
|
+
return 'warning';
|
|
117
|
+
return 'info';
|
|
118
|
+
}
|
|
119
|
+
// ─── Report Generator ─────────────────────────────────────────────────────────
|
|
120
|
+
function classifyEvent(event) {
|
|
121
|
+
const parts = event.type.split('.');
|
|
122
|
+
return {
|
|
123
|
+
timestamp: event.timestamp,
|
|
124
|
+
category: parts[0] || 'unknown',
|
|
125
|
+
action: parts.slice(1).join('.') || event.type,
|
|
126
|
+
actor: event.actor,
|
|
127
|
+
detail: event.message,
|
|
128
|
+
severity: getSeverity(event.type),
|
|
129
|
+
metadata: Object.keys(event.metadata).length > 0 ? event.metadata : undefined,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate a compliance report from audit log events.
|
|
134
|
+
*/
|
|
135
|
+
function generateComplianceReport(auditLogger, framework, options) {
|
|
136
|
+
const periodEnd = options.until || new Date().toISOString();
|
|
137
|
+
const periodStart = options.since || new Date(Date.now() - 30 * 86_400_000).toISOString(); // Default: last 30 days
|
|
138
|
+
// Query all events in the period
|
|
139
|
+
const query = {
|
|
140
|
+
since: periodStart,
|
|
141
|
+
until: periodEnd,
|
|
142
|
+
limit: 10_000, // Max export size
|
|
143
|
+
};
|
|
144
|
+
const result = auditLogger.query(query);
|
|
145
|
+
const events = result.events;
|
|
146
|
+
const frameworkConfig = FRAMEWORK_SECTIONS[framework];
|
|
147
|
+
// Classify events into sections
|
|
148
|
+
const accessControlEvents = [];
|
|
149
|
+
const dataProcessingEvents = [];
|
|
150
|
+
const configChangeEvents = [];
|
|
151
|
+
const securityEvents = [];
|
|
152
|
+
const actors = new Set();
|
|
153
|
+
let authFailures = 0;
|
|
154
|
+
let keysCreated = 0;
|
|
155
|
+
let keysRevoked = 0;
|
|
156
|
+
let keysSuspended = 0;
|
|
157
|
+
for (const event of events) {
|
|
158
|
+
const classified = classifyEvent(event);
|
|
159
|
+
actors.add(event.actor);
|
|
160
|
+
if (ACCESS_CONTROL_EVENTS.has(event.type)) {
|
|
161
|
+
accessControlEvents.push(classified);
|
|
162
|
+
}
|
|
163
|
+
if (DATA_PROCESSING_EVENTS.has(event.type)) {
|
|
164
|
+
dataProcessingEvents.push(classified);
|
|
165
|
+
}
|
|
166
|
+
if (CONFIG_CHANGE_EVENTS.has(event.type)) {
|
|
167
|
+
configChangeEvents.push(classified);
|
|
168
|
+
}
|
|
169
|
+
if (SECURITY_EVENTS.has(event.type)) {
|
|
170
|
+
securityEvents.push(classified);
|
|
171
|
+
}
|
|
172
|
+
// Count specific events
|
|
173
|
+
if (event.type === 'admin.auth_failed')
|
|
174
|
+
authFailures++;
|
|
175
|
+
if (event.type === 'key.created')
|
|
176
|
+
keysCreated++;
|
|
177
|
+
if (event.type === 'key.revoked')
|
|
178
|
+
keysRevoked++;
|
|
179
|
+
if (event.type === 'key.suspended')
|
|
180
|
+
keysSuspended++;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
meta: {
|
|
184
|
+
framework,
|
|
185
|
+
generatedAt: new Date().toISOString(),
|
|
186
|
+
periodStart,
|
|
187
|
+
periodEnd,
|
|
188
|
+
serverVersion: options.serverVersion,
|
|
189
|
+
totalEvents: events.length,
|
|
190
|
+
},
|
|
191
|
+
sections: [
|
|
192
|
+
{
|
|
193
|
+
...frameworkConfig.accessControl,
|
|
194
|
+
events: accessControlEvents,
|
|
195
|
+
count: accessControlEvents.length,
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
...frameworkConfig.dataProcessing,
|
|
199
|
+
events: dataProcessingEvents,
|
|
200
|
+
count: dataProcessingEvents.length,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
...frameworkConfig.configChanges,
|
|
204
|
+
events: configChangeEvents,
|
|
205
|
+
count: configChangeEvents.length,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
...frameworkConfig.security,
|
|
209
|
+
events: securityEvents,
|
|
210
|
+
count: securityEvents.length,
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
summary: {
|
|
214
|
+
totalAccessControlEvents: accessControlEvents.length,
|
|
215
|
+
totalDataProcessingEvents: dataProcessingEvents.length,
|
|
216
|
+
totalConfigChangeEvents: configChangeEvents.length,
|
|
217
|
+
totalSecurityEvents: securityEvents.length,
|
|
218
|
+
authFailures,
|
|
219
|
+
keysCreated,
|
|
220
|
+
keysRevoked,
|
|
221
|
+
keysSuspended,
|
|
222
|
+
uniqueActors: actors.size,
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Convert a compliance report to CSV format.
|
|
228
|
+
*/
|
|
229
|
+
function complianceReportToCsv(report) {
|
|
230
|
+
const header = 'section,timestamp,category,action,actor,severity,detail';
|
|
231
|
+
const rows = [];
|
|
232
|
+
for (const section of report.sections) {
|
|
233
|
+
for (const event of section.events) {
|
|
234
|
+
rows.push(`"${section.title}",${event.timestamp},${event.category},${event.action},"${event.actor.replace(/"/g, '""')}",${event.severity},"${event.detail.replace(/"/g, '""')}"`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return [header, ...rows].join('\n');
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=compliance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compliance.js","sourceRoot":"","sources":["../src/compliance.ts"],"names":[],"mappings":"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"}
|
package/dist/gate.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ export declare class Gate {
|
|
|
46
46
|
onCreditsDeducted?: (apiKey: string, amount: number) => void;
|
|
47
47
|
/** Optional hook called when auto-topup is triggered (for audit/webhook). */
|
|
48
48
|
onAutoTopup?: (apiKey: string, amount: number, newBalance: number) => void;
|
|
49
|
+
/** Per-key webhook emitters (lazily created, keyed by API key prefix). */
|
|
50
|
+
private keyWebhooks;
|
|
49
51
|
constructor(config: PayGateConfig, statePath?: string);
|
|
50
52
|
/**
|
|
51
53
|
* Evaluate a tool call request.
|
|
@@ -144,6 +146,15 @@ export declare class Gate {
|
|
|
144
146
|
*/
|
|
145
147
|
updateConfig(patch: Partial<PayGateConfig>): string[];
|
|
146
148
|
destroy(): void;
|
|
149
|
+
/**
|
|
150
|
+
* Get or create a per-key webhook emitter.
|
|
151
|
+
* Returns null if the key has no webhookUrl configured.
|
|
152
|
+
*/
|
|
153
|
+
getKeyWebhook(apiKey: string): WebhookEmitter | null;
|
|
154
|
+
/**
|
|
155
|
+
* Remove cached per-key webhook emitter (called when webhook URL is cleared).
|
|
156
|
+
*/
|
|
157
|
+
removeKeyWebhook(apiKey: string): void;
|
|
147
158
|
private recordEvent;
|
|
148
159
|
}
|
|
149
160
|
//# sourceMappingURL=gate.d.ts.map
|
package/dist/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAe,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC7I,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAqB,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,qBAAa,IAAI;IACf,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,yFAAyF;IACzF,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,gFAAgF;IAChF,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,oDAAoD;IACpD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,8DAA8D;IAC9D,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,mEAAmE;IACnE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzF,uDAAuD;IACvD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,6EAA6E;IAC7E,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAe,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC7I,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAqB,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,qBAAa,IAAI;IACf,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,yFAAyF;IACzF,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,gFAAgF;IAChF,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,oDAAoD;IACpD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,8DAA8D;IAC9D,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,mEAAmE;IACnE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzF,uDAAuD;IACvD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,6EAA6E;IAC7E,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,0EAA0E;IAC1E,OAAO,CAAC,WAAW,CAAqC;gBAE5C,MAAM,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,MAAM;IAwBrD;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY;IAiNvH;;;;;;;;OAQG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,eAAe;IA2S7H,oEAAoE;IACpE,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,GAAG,IAAI;IA+BjL;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAQrC;;;OAGG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IA4BvF;;OAEG;IACH,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;IAoB5B;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAa/D,2CAA2C;IAC3C,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IA4BvC;;;;;;;OAOG;IACH,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,EAAE;IAsGrD,OAAO,IAAI,IAAI;IAUf;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IA6BpD;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAStC,OAAO,CAAC,WAAW;CA6BpB"}
|
package/dist/gate.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.Gate = void 0;
|
|
|
16
16
|
const store_1 = require("./store");
|
|
17
17
|
const rate_limiter_1 = require("./rate-limiter");
|
|
18
18
|
const meter_1 = require("./meter");
|
|
19
|
+
const webhook_1 = require("./webhook");
|
|
19
20
|
const webhook_router_1 = require("./webhook-router");
|
|
20
21
|
const quota_1 = require("./quota");
|
|
21
22
|
class Gate {
|
|
@@ -42,6 +43,8 @@ class Gate {
|
|
|
42
43
|
onCreditsDeducted;
|
|
43
44
|
/** Optional hook called when auto-topup is triggered (for audit/webhook). */
|
|
44
45
|
onAutoTopup;
|
|
46
|
+
/** Per-key webhook emitters (lazily created, keyed by API key prefix). */
|
|
47
|
+
keyWebhooks = new Map();
|
|
45
48
|
constructor(config, statePath) {
|
|
46
49
|
this.config = config;
|
|
47
50
|
this.store = new store_1.KeyStore(statePath);
|
|
@@ -836,6 +839,51 @@ class Gate {
|
|
|
836
839
|
destroy() {
|
|
837
840
|
this.rateLimiter.destroy();
|
|
838
841
|
this.webhook?.destroy();
|
|
842
|
+
// Destroy per-key webhook emitters
|
|
843
|
+
for (const emitter of this.keyWebhooks.values()) {
|
|
844
|
+
emitter.destroy();
|
|
845
|
+
}
|
|
846
|
+
this.keyWebhooks.clear();
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Get or create a per-key webhook emitter.
|
|
850
|
+
* Returns null if the key has no webhookUrl configured.
|
|
851
|
+
*/
|
|
852
|
+
getKeyWebhook(apiKey) {
|
|
853
|
+
const keyRecord = this.store.getKey(apiKey);
|
|
854
|
+
if (!keyRecord?.webhookUrl)
|
|
855
|
+
return null;
|
|
856
|
+
const prefix = apiKey.slice(0, 10);
|
|
857
|
+
const existing = this.keyWebhooks.get(prefix);
|
|
858
|
+
// Return cached if URL hasn't changed
|
|
859
|
+
if (existing && existing.url === keyRecord.webhookUrl) {
|
|
860
|
+
return existing;
|
|
861
|
+
}
|
|
862
|
+
// Destroy old emitter if URL changed
|
|
863
|
+
if (existing) {
|
|
864
|
+
existing.destroy();
|
|
865
|
+
}
|
|
866
|
+
// Create new emitter for this key
|
|
867
|
+
const emitter = new webhook_1.WebhookEmitter(keyRecord.webhookUrl, {
|
|
868
|
+
secret: keyRecord.webhookSecret || null,
|
|
869
|
+
batchSize: 10,
|
|
870
|
+
flushIntervalMs: 5000,
|
|
871
|
+
maxRetries: 3,
|
|
872
|
+
ssrfCheckOnDelivery: this.config.webhookSsrfAtDelivery ?? true,
|
|
873
|
+
});
|
|
874
|
+
this.keyWebhooks.set(prefix, emitter);
|
|
875
|
+
return emitter;
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Remove cached per-key webhook emitter (called when webhook URL is cleared).
|
|
879
|
+
*/
|
|
880
|
+
removeKeyWebhook(apiKey) {
|
|
881
|
+
const prefix = apiKey.slice(0, 10);
|
|
882
|
+
const existing = this.keyWebhooks.get(prefix);
|
|
883
|
+
if (existing) {
|
|
884
|
+
existing.destroy();
|
|
885
|
+
this.keyWebhooks.delete(prefix);
|
|
886
|
+
}
|
|
839
887
|
}
|
|
840
888
|
recordEvent(apiKey, keyName, tool, creditsCharged, allowed, denyReason, namespace) {
|
|
841
889
|
const event = {
|
|
@@ -856,6 +904,11 @@ class Gate {
|
|
|
856
904
|
else if (this.webhook) {
|
|
857
905
|
this.webhook.emit(event);
|
|
858
906
|
}
|
|
907
|
+
// Per-key webhook: also emit to key-specific webhook URL
|
|
908
|
+
const keyWebhook = this.getKeyWebhook(apiKey);
|
|
909
|
+
if (keyWebhook) {
|
|
910
|
+
keyWebhook.emit(event);
|
|
911
|
+
}
|
|
859
912
|
this.onUsageEvent?.(event);
|
|
860
913
|
}
|
|
861
914
|
}
|