paygate-mcp 8.28.0 → 8.30.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 +60 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +147 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -135,6 +135,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
135
135
|
- **Key Status Overview** — `GET /admin/key-status` key status dashboard with active/suspended/revoked/expired counts and keys needing attention (low credits, near expiry)
|
|
136
136
|
- **Webhook Health** — `GET /admin/webhook-health` webhook delivery health overview with success rate, pending retries, dead letter count, pause status, and buffered events
|
|
137
137
|
- **Consumer Insights** — `GET /admin/consumer-insights` per-key behavioral analytics with top spenders, most active callers, tool diversity, and spending patterns
|
|
138
|
+
- **System Health Score** — `GET /admin/system-health` composite 0-100 health score with weighted component breakdowns for key health, error rates, and credit utilization
|
|
139
|
+
- **Tool Adoption** — `GET /admin/tool-adoption` per-tool adoption metrics with unique consumers, adoption rate, first/last seen timestamps, and usage ranking
|
|
138
140
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
139
141
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
140
142
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -3135,6 +3137,64 @@ curl http://localhost:3000/admin/consumer-insights -H "X-Admin-Key: YOUR_ADMIN_K
|
|
|
3135
3137
|
|
|
3136
3138
|
Per-key behavioral analytics. Top 10 spenders ranked by credits consumed, top 10 most active by call count. Each entry includes tool diversity (unique tools used). Summary shows total/active consumers and aggregate spend. Read-only.
|
|
3137
3139
|
|
|
3140
|
+
### System Health Score
|
|
3141
|
+
|
|
3142
|
+
```bash
|
|
3143
|
+
curl http://localhost:3000/admin/system-health -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
3144
|
+
```
|
|
3145
|
+
|
|
3146
|
+
```json
|
|
3147
|
+
{
|
|
3148
|
+
"score": 85,
|
|
3149
|
+
"level": "healthy",
|
|
3150
|
+
"components": {
|
|
3151
|
+
"keyHealth": { "score": 90, "weight": 0.4, "detail": "2 suspended" },
|
|
3152
|
+
"errorRate": { "score": 80, "weight": 0.35, "detail": "10% denial rate (5/50)" },
|
|
3153
|
+
"creditUtilization": { "score": 85, "weight": 0.25, "detail": "45% utilized (4500/10000 credits)" }
|
|
3154
|
+
},
|
|
3155
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
3156
|
+
}
|
|
3157
|
+
```
|
|
3158
|
+
|
|
3159
|
+
Composite system health score 0-100 with weighted component breakdowns. Key health (40%): penalizes suspended/revoked/expired/low-credit keys. Error rate (35%): penalizes high denial rates. Credit utilization (25%): healthy at 10-80%, degrades at >80%. Levels: healthy (>=80), good (>=60), warning (>=40), critical (<40). Read-only.
|
|
3160
|
+
|
|
3161
|
+
### Tool Adoption
|
|
3162
|
+
|
|
3163
|
+
```bash
|
|
3164
|
+
curl http://localhost:3000/admin/tool-adoption -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
3165
|
+
```
|
|
3166
|
+
|
|
3167
|
+
```json
|
|
3168
|
+
{
|
|
3169
|
+
"tools": [
|
|
3170
|
+
{
|
|
3171
|
+
"tool": "search",
|
|
3172
|
+
"uniqueConsumers": 8,
|
|
3173
|
+
"adoptionRate": 80,
|
|
3174
|
+
"totalCalls": 245,
|
|
3175
|
+
"firstSeen": "2025-01-10T08:00:00Z",
|
|
3176
|
+
"lastSeen": "2025-01-15T14:30:00Z"
|
|
3177
|
+
},
|
|
3178
|
+
{
|
|
3179
|
+
"tool": "translate",
|
|
3180
|
+
"uniqueConsumers": 3,
|
|
3181
|
+
"adoptionRate": 30,
|
|
3182
|
+
"totalCalls": 42,
|
|
3183
|
+
"firstSeen": "2025-01-12T10:00:00Z",
|
|
3184
|
+
"lastSeen": "2025-01-15T12:00:00Z"
|
|
3185
|
+
}
|
|
3186
|
+
],
|
|
3187
|
+
"summary": {
|
|
3188
|
+
"totalTools": 2,
|
|
3189
|
+
"usedTools": 2,
|
|
3190
|
+
"unusedTools": 0
|
|
3191
|
+
},
|
|
3192
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
3193
|
+
}
|
|
3194
|
+
```
|
|
3195
|
+
|
|
3196
|
+
Per-tool adoption metrics showing which tools are being used and by how many consumers. `uniqueConsumers` counts distinct API keys that called the tool. `adoptionRate` is the percentage of active keys that have used the tool. Sorted by adoption rate descending, then by total calls. Read-only.
|
|
3197
|
+
|
|
3138
3198
|
### IP Allowlisting
|
|
3139
3199
|
|
|
3140
3200
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -270,6 +270,8 @@ export declare class PayGateServer {
|
|
|
270
270
|
private handleKeyStatus;
|
|
271
271
|
private handleWebhookHealth;
|
|
272
272
|
private handleConsumerInsights;
|
|
273
|
+
private handleSystemHealth;
|
|
274
|
+
private handleToolAdoption;
|
|
273
275
|
private handleGetNotes;
|
|
274
276
|
private handleAddNote;
|
|
275
277
|
private handleDeleteNote;
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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
|
|
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;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,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;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAKrD,0EAA0E;AAC1E,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAsBvF;AAyCD,yCAAyC;AACzC,KAAK,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC;AAa5C,qBAAa,aAAa;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,aAAa,CAAqC;IAC1D,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAQ;IAC5C,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,2BAA2B;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,mCAAmC;IACnC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC5C,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,oCAAoC;IACpC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,sCAAsC;IACtC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,gEAAgE;IAChE,OAAO,CAAC,QAAQ,CAAS;IACzB,wEAAwE;IACxE,OAAO,CAAC,eAAe,CAAS;IAChC,mDAAmD;IACnD,OAAO,CAAC,kBAAkB,CAAiC;IAC3D,kDAAkD;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,gDAAgD;IAChD,OAAO,CAAC,iBAAiB,CAAqF;IAC9G,8CAA8C;IAC9C,OAAO,CAAC,wBAAwB,CAA+C;IAC/E,8BAA8B;IAC9B,OAAO,CAAC,gBAAgB,CAOhB;IACR,2CAA2C;IAC3C,OAAO,CAAC,aAAa,CAA+C;IACpE,4CAA4C;IAC5C,OAAO,CAAC,cAAc,CAAK;IAC3B,kCAAkC;IAClC,OAAO,CAAC,kBAAkB,CAOX;IACf,+CAA+C;IAC/C,OAAO,CAAC,iBAAiB,CAAK;IAC9B,qDAAqD;IACrD,OAAO,CAAC,UAAU,CAUV;IACR,gCAAgC;IAChC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IAC7C,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAK;IACrB,sEAAsE;IACtE,OAAO,CAAC,UAAU,CAAuB;IAEzC,0DAA0D;IAC1D,OAAO,KAAK,OAAO,GAElB;gBAGC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,EAC1D,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,mBAAmB,CAAC,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE,mBAAmB,EAAE,EAC/B,QAAQ,CAAC,EAAE,MAAM;IAsMnB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAK1B,KAAK,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;YA0C5C,aAAa;YAyeb,SAAS;IAmQvB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA+C1B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAyB9B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAyCrB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAuC7B,OAAO,CAAC,UAAU;IA+IlB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,YAAY;IAyCpB,OAAO,CAAC,UAAU;IAuElB,OAAO,CAAC,kBAAkB;IA0D1B,kEAAkE;IAClE,OAAO,CAAC,OAAO;YAWD,eAAe;IAqH7B,OAAO,CAAC,cAAc;YA0CR,WAAW;YAuEX,oBAAoB;YAwHpB,oBAAoB;IA4IlC,OAAO,CAAC,eAAe;YAoDT,eAAe;YAsEf,eAAe;YAsDf,gBAAgB;YAkEhB,eAAe;YAgEf,cAAc;YAuFd,cAAc;YAoEd,eAAe;YA0Df,YAAY;YAkDZ,eAAe;YAwDf,cAAc;YA+Dd,aAAa;YAsDb,oBAAoB;YAsDpB,qBAAqB;IAgCnC,OAAO,CAAC,cAAc;IA2CtB,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,cAAc;IAyEtB,OAAO,CAAC,qBAAqB;IAsD7B,OAAO,CAAC,iBAAiB;IAuEzB,OAAO,CAAC,mBAAmB;IA8C3B,OAAO,CAAC,sBAAsB;IAwD9B,OAAO,CAAC,mBAAmB;IAoG3B,OAAO,CAAC,eAAe;IAiJvB,OAAO,CAAC,kBAAkB;YA4LZ,kBAAkB;IAoFhC,OAAO,CAAC,aAAa;YAuDP,YAAY;IAkD1B,OAAO,CAAC,WAAW;YA+CL,mBAAmB;IAmCjC,OAAO,CAAC,eAAe;IAYvB,+EAA+E;IAC/E,OAAO,CAAC,mBAAmB;IAU3B,oEAAoE;YACtD,mBAAmB;IA4DjC,yDAAyD;YAC3C,oBAAoB;IAuFlC,yCAAyC;YAC3B,gBAAgB;IA8E9B,uDAAuD;YACzC,iBAAiB;IAiC/B,sEAAsE;IACtE,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,eAAe;YAYT,qBAAqB;IAmDnC,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,sBAAsB;YAwBhB,mBAAmB;IAoDjC,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,oBAAoB;IA0D5B,OAAO,CAAC,sBAAsB;IA2D9B,OAAO,CAAC,wBAAwB;IAwJhC,OAAO,CAAC,qBAAqB;IA8G7B,OAAO,CAAC,wBAAwB;IAwGhC,OAAO,CAAC,kBAAkB;IAsH1B,OAAO,CAAC,uBAAuB;IAmH/B,OAAO,CAAC,mBAAmB;IAiH3B,OAAO,CAAC,oBAAoB;IA6H5B,OAAO,CAAC,qBAAqB;IAmI7B,OAAO,CAAC,mBAAmB;IAwH3B,OAAO,CAAC,qBAAqB;IAiF7B,OAAO,CAAC,uBAAuB;IAwF/B,OAAO,CAAC,sBAAsB;IAsG9B,OAAO,CAAC,sBAAsB;IAuF9B,OAAO,CAAC,sBAAsB;IA4G9B,OAAO,CAAC,mBAAmB;IA+E3B,OAAO,CAAC,sBAAsB;IA8F9B,OAAO,CAAC,mBAAmB;IAoE3B,OAAO,CAAC,qBAAqB;IAuF7B,OAAO,CAAC,iBAAiB;IA0EzB,OAAO,CAAC,gBAAgB;IAuExB,OAAO,CAAC,YAAY;IAmEpB,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,CAAC,kBAAkB;IAkD1B,OAAO,CAAC,sBAAsB;IAoE9B,OAAO,CAAC,mBAAmB;IAkF3B,OAAO,CAAC,eAAe;IAkEvB,OAAO,CAAC,mBAAmB;IAsD3B,OAAO,CAAC,sBAAsB;IA6E9B,OAAO,CAAC,kBAAkB;IAqF1B,OAAO,CAAC,kBAAkB;IA2D1B,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,aAAa;IAiErB,OAAO,CAAC,gBAAgB;IAkDxB,OAAO,CAAC,kBAAkB;IA6B1B,OAAO,CAAC,oBAAoB;IAiG5B,OAAO,CAAC,oBAAoB;IAmC5B,gFAAgF;IAChF,OAAO,CAAC,uBAAuB;IAiD/B,OAAO,CAAC,iBAAiB;IAmGzB,OAAO,CAAC,sBAAsB;IAgC9B,OAAO,CAAC,uBAAuB;IAqG/B,OAAO,CAAC,uBAAuB;IAqE/B,OAAO,CAAC,wBAAwB;IA+ChC,uEAAuE;IACvE,OAAO,CAAC,cAAc;IAQtB,mCAAmC;IACnC,OAAO,CAAC,0BAA0B;YAWpB,kBAAkB;IA4IhC,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,gBAAgB;IA6CxB,OAAO,CAAC,kBAAkB;IAgC1B,OAAO,CAAC,mBAAmB;YAiCb,iBAAiB;IA6H/B,OAAO,CAAC,wBAAwB;YAclB,yBAAyB;YAsCzB,yBAAyB;YAiDzB,yBAAyB;IA4CvC,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,UAAU;IAiClB,OAAO,CAAC,eAAe;YAiBT,gBAAgB;YA4ChB,gBAAgB;YA6ChB,gBAAgB;YAsChB,mBAAmB;YAsDnB,mBAAmB;IA8CjC,OAAO,CAAC,eAAe;IA8BvB,OAAO,CAAC,oBAAoB;YAgBd,iBAAiB;YAyDjB,iBAAiB;IAiE/B,OAAO,CAAC,uBAAuB;IAyB/B,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,gBAAgB;YAOV,iBAAiB;YA2CjB,iBAAiB;YAuDjB,iBAAiB;YAyCjB,sBAAsB;YAsDtB,wBAAwB;IAiDtC,OAAO,CAAC,mBAAmB;YAsBb,oBAAoB;YAwDpB,oBAAoB;IAwDlC,OAAO,CAAC,mBAAmB;YAQb,oBAAoB;YAsCpB,oBAAoB;IAuClC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,eAAe;IAUvB,iFAAiF;IACjF,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,QAAQ;IAkBV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC3B;;;;;;;OAOG;IACG,YAAY,CAAC,SAAS,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDrD,OAAO,CAAC,gBAAgB;IAuExB,OAAO,CAAC,eAAe;YA+GT,mBAAmB;YAgJnB,wBAAwB;IAoJtC,OAAO,CAAC,sBAAsB;IA0F9B,OAAO,CAAC,sBAAsB;IA6E9B,qDAAqD;IACrD,OAAO,CAAC,UAAU;CAMnB"}
|
package/dist/server.js
CHANGED
|
@@ -966,6 +966,18 @@ class PayGateServer {
|
|
|
966
966
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
967
967
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
968
968
|
return;
|
|
969
|
+
case '/admin/system-health':
|
|
970
|
+
if (req.method === 'GET')
|
|
971
|
+
return this.handleSystemHealth(req, res);
|
|
972
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
973
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
974
|
+
return;
|
|
975
|
+
case '/admin/tool-adoption':
|
|
976
|
+
if (req.method === 'GET')
|
|
977
|
+
return this.handleToolAdoption(req, res);
|
|
978
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
979
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
980
|
+
return;
|
|
969
981
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
970
982
|
case '/plugins':
|
|
971
983
|
return this.handleListPlugins(req, res);
|
|
@@ -1534,6 +1546,8 @@ class PayGateServer {
|
|
|
1534
1546
|
keyStatus: 'GET /admin/key-status — Key status dashboard with active/suspended/revoked/expired counts and keys needing attention (requires X-Admin-Key)',
|
|
1535
1547
|
webhookHealth: 'GET /admin/webhook-health — Webhook delivery health overview with success rate, retries, dead letters, and pause status (requires X-Admin-Key)',
|
|
1536
1548
|
consumerInsights: 'GET /admin/consumer-insights — Per-key behavioral analytics with top spenders, most active callers, tool diversity, and spending patterns (requires X-Admin-Key)',
|
|
1549
|
+
systemHealth: 'GET /admin/system-health — Composite system health score 0-100 with component breakdowns for key health, error rates, and credit utilization (requires X-Admin-Key)',
|
|
1550
|
+
toolAdoption: 'GET /admin/tool-adoption — Per-tool adoption metrics with unique consumers, adoption rate, first/last seen, and never-used tool identification (requires X-Admin-Key)',
|
|
1537
1551
|
...(this.oauth ? {
|
|
1538
1552
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1539
1553
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -6863,6 +6877,139 @@ class PayGateServer {
|
|
|
6863
6877
|
generatedAt: new Date().toISOString(),
|
|
6864
6878
|
}));
|
|
6865
6879
|
}
|
|
6880
|
+
// ─── /admin/system-health — Composite system health score ─────────────────
|
|
6881
|
+
handleSystemHealth(req, res) {
|
|
6882
|
+
if (!this.checkAdmin(req, res))
|
|
6883
|
+
return;
|
|
6884
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
6885
|
+
const now = Date.now();
|
|
6886
|
+
// ── Component 1: Key Health (weight: 40%) ──
|
|
6887
|
+
let keyHealthScore = 100;
|
|
6888
|
+
let keyHealthDetail = 'All keys healthy';
|
|
6889
|
+
if (allRecords.length > 0) {
|
|
6890
|
+
const active = allRecords.filter(r => r.active && !r.suspended).length;
|
|
6891
|
+
const suspended = allRecords.filter(r => r.suspended).length;
|
|
6892
|
+
const revoked = allRecords.filter(r => !r.active && !r.suspended).length;
|
|
6893
|
+
const expired = allRecords.filter(r => r.active && !r.suspended && r.expiresAt && new Date(r.expiresAt).getTime() <= now).length;
|
|
6894
|
+
const lowCredits = allRecords.filter(r => r.active && !r.suspended && r.credits <= 10).length;
|
|
6895
|
+
const problemRatio = (suspended + revoked + expired + lowCredits) / allRecords.length;
|
|
6896
|
+
keyHealthScore = Math.max(0, Math.round(100 - problemRatio * 100));
|
|
6897
|
+
const issues = [];
|
|
6898
|
+
if (suspended > 0)
|
|
6899
|
+
issues.push(`${suspended} suspended`);
|
|
6900
|
+
if (revoked > 0)
|
|
6901
|
+
issues.push(`${revoked} revoked`);
|
|
6902
|
+
if (expired > 0)
|
|
6903
|
+
issues.push(`${expired} expired`);
|
|
6904
|
+
if (lowCredits > 0)
|
|
6905
|
+
issues.push(`${lowCredits} low credits`);
|
|
6906
|
+
keyHealthDetail = issues.length > 0 ? issues.join(', ') : `${active} active keys`;
|
|
6907
|
+
}
|
|
6908
|
+
// ── Component 2: Error Rate (weight: 35%) ──
|
|
6909
|
+
let errorRateScore = 100;
|
|
6910
|
+
let errorRateDetail = 'No errors';
|
|
6911
|
+
const totalRequests = this.requestLog.length;
|
|
6912
|
+
if (totalRequests > 0) {
|
|
6913
|
+
const denied = this.requestLog.filter(e => e.status === 'denied').length;
|
|
6914
|
+
const errorRate = denied / totalRequests;
|
|
6915
|
+
errorRateScore = Math.max(0, Math.round(100 - errorRate * 200)); // 50% error rate = 0 score
|
|
6916
|
+
errorRateDetail = `${Math.round(errorRate * 100)}% denial rate (${denied}/${totalRequests})`;
|
|
6917
|
+
}
|
|
6918
|
+
// ── Component 3: Credit Utilization (weight: 25%) ──
|
|
6919
|
+
let creditScore = 100;
|
|
6920
|
+
let creditDetail = 'No credits tracked';
|
|
6921
|
+
const totalAllocated = allRecords.reduce((s, r) => s + (r.credits || 0) + (r.totalSpent || 0), 0);
|
|
6922
|
+
const totalRemaining = allRecords.reduce((s, r) => s + (r.credits || 0), 0);
|
|
6923
|
+
if (totalAllocated > 0) {
|
|
6924
|
+
const utilization = (totalAllocated - totalRemaining) / totalAllocated;
|
|
6925
|
+
// Healthy: 10-80% utilization; too low or too high degrade score
|
|
6926
|
+
if (utilization > 0.9) {
|
|
6927
|
+
creditScore = Math.round(50 - (utilization - 0.9) * 500);
|
|
6928
|
+
}
|
|
6929
|
+
else if (utilization > 0.8) {
|
|
6930
|
+
creditScore = Math.round(80 - (utilization - 0.8) * 300);
|
|
6931
|
+
}
|
|
6932
|
+
else {
|
|
6933
|
+
creditScore = 100;
|
|
6934
|
+
}
|
|
6935
|
+
creditScore = Math.max(0, Math.min(100, creditScore));
|
|
6936
|
+
creditDetail = `${Math.round(utilization * 100)}% utilized (${totalAllocated - totalRemaining}/${totalAllocated} credits)`;
|
|
6937
|
+
}
|
|
6938
|
+
// ── Composite Score ──
|
|
6939
|
+
const compositeScore = Math.round(keyHealthScore * 0.4 +
|
|
6940
|
+
errorRateScore * 0.35 +
|
|
6941
|
+
creditScore * 0.25);
|
|
6942
|
+
let level;
|
|
6943
|
+
if (compositeScore >= 80)
|
|
6944
|
+
level = 'healthy';
|
|
6945
|
+
else if (compositeScore >= 60)
|
|
6946
|
+
level = 'good';
|
|
6947
|
+
else if (compositeScore >= 40)
|
|
6948
|
+
level = 'warning';
|
|
6949
|
+
else
|
|
6950
|
+
level = 'critical';
|
|
6951
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6952
|
+
res.end(JSON.stringify({
|
|
6953
|
+
score: compositeScore,
|
|
6954
|
+
level,
|
|
6955
|
+
components: {
|
|
6956
|
+
keyHealth: { score: keyHealthScore, weight: 0.4, detail: keyHealthDetail },
|
|
6957
|
+
errorRate: { score: errorRateScore, weight: 0.35, detail: errorRateDetail },
|
|
6958
|
+
creditUtilization: { score: creditScore, weight: 0.25, detail: creditDetail },
|
|
6959
|
+
},
|
|
6960
|
+
generatedAt: new Date().toISOString(),
|
|
6961
|
+
}));
|
|
6962
|
+
}
|
|
6963
|
+
// ─── /admin/tool-adoption — Per-tool adoption metrics ─────────────────────
|
|
6964
|
+
handleToolAdoption(req, res) {
|
|
6965
|
+
if (!this.checkAdmin(req, res))
|
|
6966
|
+
return;
|
|
6967
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
6968
|
+
const activeKeys = allRecords.filter(r => r.active && !r.suspended);
|
|
6969
|
+
const activeKeyCount = activeKeys.length;
|
|
6970
|
+
// Build per-tool metrics from request log
|
|
6971
|
+
const toolMap = new Map();
|
|
6972
|
+
for (const entry of this.requestLog) {
|
|
6973
|
+
if (entry.status !== 'allowed')
|
|
6974
|
+
continue;
|
|
6975
|
+
let data = toolMap.get(entry.tool);
|
|
6976
|
+
if (!data) {
|
|
6977
|
+
data = { consumers: new Set(), totalCalls: 0, firstSeen: Infinity, lastSeen: 0 };
|
|
6978
|
+
toolMap.set(entry.tool, data);
|
|
6979
|
+
}
|
|
6980
|
+
data.consumers.add(entry.key);
|
|
6981
|
+
data.totalCalls++;
|
|
6982
|
+
const ts = new Date(entry.timestamp).getTime();
|
|
6983
|
+
if (ts < data.firstSeen)
|
|
6984
|
+
data.firstSeen = ts;
|
|
6985
|
+
if (ts > data.lastSeen)
|
|
6986
|
+
data.lastSeen = ts;
|
|
6987
|
+
}
|
|
6988
|
+
// Build sorted tools array by adoption rate descending
|
|
6989
|
+
const tools = Array.from(toolMap.entries()).map(([tool, data]) => ({
|
|
6990
|
+
tool,
|
|
6991
|
+
uniqueConsumers: data.consumers.size,
|
|
6992
|
+
adoptionRate: activeKeyCount > 0
|
|
6993
|
+
? Math.round((data.consumers.size / activeKeyCount) * 100)
|
|
6994
|
+
: 0,
|
|
6995
|
+
totalCalls: data.totalCalls,
|
|
6996
|
+
firstSeen: new Date(data.firstSeen).toISOString(),
|
|
6997
|
+
lastSeen: new Date(data.lastSeen).toISOString(),
|
|
6998
|
+
})).sort((a, b) => b.adoptionRate - a.adoptionRate || b.totalCalls - a.totalCalls);
|
|
6999
|
+
const usedTools = toolMap.size;
|
|
7000
|
+
// Count total known tools from request log (we don't have access to the child process tool list)
|
|
7001
|
+
const totalTools = usedTools;
|
|
7002
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
7003
|
+
res.end(JSON.stringify({
|
|
7004
|
+
tools,
|
|
7005
|
+
summary: {
|
|
7006
|
+
totalTools,
|
|
7007
|
+
usedTools,
|
|
7008
|
+
unusedTools: totalTools - usedTools,
|
|
7009
|
+
},
|
|
7010
|
+
generatedAt: new Date().toISOString(),
|
|
7011
|
+
}));
|
|
7012
|
+
}
|
|
6866
7013
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
6867
7014
|
handleGetNotes(req, res) {
|
|
6868
7015
|
if (!this.checkAdmin(req, res))
|