@inso_web/els-mcp 0.1.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 +482 -0
- package/dist/audit/prisma.d.ts +67 -0
- package/dist/audit/prisma.d.ts.map +1 -0
- package/dist/audit/prisma.js +65 -0
- package/dist/audit/prisma.js.map +1 -0
- package/dist/audit/service.d.ts +72 -0
- package/dist/audit/service.d.ts.map +1 -0
- package/dist/audit/service.js +137 -0
- package/dist/audit/service.js.map +1 -0
- package/dist/billing/limits.d.ts +34 -0
- package/dist/billing/limits.d.ts.map +1 -0
- package/dist/billing/limits.js +51 -0
- package/dist/billing/limits.js.map +1 -0
- package/dist/billing/tracker.d.ts +39 -0
- package/dist/billing/tracker.d.ts.map +1 -0
- package/dist/billing/tracker.js +92 -0
- package/dist/billing/tracker.js.map +1 -0
- package/dist/cache/cachedElsClient.d.ts +71 -0
- package/dist/cache/cachedElsClient.d.ts.map +1 -0
- package/dist/cache/cachedElsClient.js +167 -0
- package/dist/cache/cachedElsClient.js.map +1 -0
- package/dist/cache/index.d.ts +10 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +6 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/policies.d.ts +60 -0
- package/dist/cache/policies.d.ts.map +1 -0
- package/dist/cache/policies.js +90 -0
- package/dist/cache/policies.js.map +1 -0
- package/dist/cache/redis.d.ts +52 -0
- package/dist/cache/redis.d.ts.map +1 -0
- package/dist/cache/redis.js +134 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/cache/types.d.ts +32 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +32 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/cache/wrapper.d.ts +38 -0
- package/dist/cache/wrapper.d.ts.map +1 -0
- package/dist/cache/wrapper.js +109 -0
- package/dist/cache/wrapper.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +86 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +105 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +211 -0
- package/dist/config.js.map +1 -0
- package/dist/elsClient.d.ts +137 -0
- package/dist/elsClient.d.ts.map +1 -0
- package/dist/elsClient.js +285 -0
- package/dist/elsClient.js.map +1 -0
- package/dist/http/app.d.ts +40 -0
- package/dist/http/app.d.ts.map +1 -0
- package/dist/http/app.js +135 -0
- package/dist/http/app.js.map +1 -0
- package/dist/http/jwks.d.ts +8 -0
- package/dist/http/jwks.d.ts.map +1 -0
- package/dist/http/jwks.js +34 -0
- package/dist/http/jwks.js.map +1 -0
- package/dist/http/middleware/auth.d.ts +11 -0
- package/dist/http/middleware/auth.d.ts.map +1 -0
- package/dist/http/middleware/auth.js +225 -0
- package/dist/http/middleware/auth.js.map +1 -0
- package/dist/http/middleware/dcrRateLimit.d.ts +29 -0
- package/dist/http/middleware/dcrRateLimit.d.ts.map +1 -0
- package/dist/http/middleware/dcrRateLimit.js +59 -0
- package/dist/http/middleware/dcrRateLimit.js.map +1 -0
- package/dist/http/middleware/errorHandler.d.ts +12 -0
- package/dist/http/middleware/errorHandler.d.ts.map +1 -0
- package/dist/http/middleware/errorHandler.js +26 -0
- package/dist/http/middleware/errorHandler.js.map +1 -0
- package/dist/http/middleware/originGuard.d.ts +28 -0
- package/dist/http/middleware/originGuard.d.ts.map +1 -0
- package/dist/http/middleware/originGuard.js +55 -0
- package/dist/http/middleware/originGuard.js.map +1 -0
- package/dist/http/middleware/requestId.d.ts +19 -0
- package/dist/http/middleware/requestId.d.ts.map +1 -0
- package/dist/http/middleware/requestId.js +23 -0
- package/dist/http/middleware/requestId.js.map +1 -0
- package/dist/http/routes/health.d.ts +24 -0
- package/dist/http/routes/health.d.ts.map +1 -0
- package/dist/http/routes/health.js +73 -0
- package/dist/http/routes/health.js.map +1 -0
- package/dist/http/routes/metrics.d.ts +18 -0
- package/dist/http/routes/metrics.d.ts.map +1 -0
- package/dist/http/routes/metrics.js +42 -0
- package/dist/http/routes/metrics.js.map +1 -0
- package/dist/http/routes/wellKnown.d.ts +15 -0
- package/dist/http/routes/wellKnown.d.ts.map +1 -0
- package/dist/http/routes/wellKnown.js +43 -0
- package/dist/http/routes/wellKnown.js.map +1 -0
- package/dist/http/types.d.ts +40 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +9 -0
- package/dist/http/types.js.map +1 -0
- package/dist/instrumentation.d.ts +22 -0
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +38 -0
- package/dist/instrumentation.js.map +1 -0
- package/dist/lib/cursor.d.ts +22 -0
- package/dist/lib/cursor.d.ts.map +1 -0
- package/dist/lib/cursor.js +95 -0
- package/dist/lib/cursor.js.map +1 -0
- package/dist/lib/errors.d.ts +49 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +83 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/responseFormat.d.ts +14 -0
- package/dist/lib/responseFormat.d.ts.map +1 -0
- package/dist/lib/responseFormat.js +74 -0
- package/dist/lib/responseFormat.js.map +1 -0
- package/dist/middleware/withMiddleware.d.ts +53 -0
- package/dist/middleware/withMiddleware.d.ts.map +1 -0
- package/dist/middleware/withMiddleware.js +190 -0
- package/dist/middleware/withMiddleware.js.map +1 -0
- package/dist/observability/health.d.ts +51 -0
- package/dist/observability/health.d.ts.map +1 -0
- package/dist/observability/health.js +77 -0
- package/dist/observability/health.js.map +1 -0
- package/dist/observability/index.d.ts +8 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +5 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/logger.d.ts +45 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +75 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +49 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +184 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/tracing.d.ts +28 -0
- package/dist/observability/tracing.d.ts.map +1 -0
- package/dist/observability/tracing.js +56 -0
- package/dist/observability/tracing.js.map +1 -0
- package/dist/prompts/index.d.ts +20 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +202 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/redaction/argsRedactor.d.ts +22 -0
- package/dist/redaction/argsRedactor.d.ts.map +1 -0
- package/dist/redaction/argsRedactor.js +97 -0
- package/dist/redaction/argsRedactor.js.map +1 -0
- package/dist/redaction/fields.d.ts +64 -0
- package/dist/redaction/fields.d.ts.map +1 -0
- package/dist/redaction/fields.js +155 -0
- package/dist/redaction/fields.js.map +1 -0
- package/dist/redaction/index.d.ts +52 -0
- package/dist/redaction/index.d.ts.map +1 -0
- package/dist/redaction/index.js +160 -0
- package/dist/redaction/index.js.map +1 -0
- package/dist/redaction/promptInjection.d.ts +32 -0
- package/dist/redaction/promptInjection.d.ts.map +1 -0
- package/dist/redaction/promptInjection.js +68 -0
- package/dist/redaction/promptInjection.js.map +1 -0
- package/dist/redaction/url.d.ts +8 -0
- package/dist/redaction/url.d.ts.map +1 -0
- package/dist/redaction/url.js +26 -0
- package/dist/redaction/url.js.map +1 -0
- package/dist/redaction/userAgent.d.ts +9 -0
- package/dist/redaction/userAgent.d.ts.map +1 -0
- package/dist/redaction/userAgent.js +39 -0
- package/dist/redaction/userAgent.js.map +1 -0
- package/dist/resources/index.d.ts +24 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +150 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +37 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +35 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/baselineCompare.d.ts +36 -0
- package/dist/tools/baselineCompare.d.ts.map +1 -0
- package/dist/tools/baselineCompare.js +69 -0
- package/dist/tools/baselineCompare.js.map +1 -0
- package/dist/tools/errorHeatmap.d.ts +40 -0
- package/dist/tools/errorHeatmap.d.ts.map +1 -0
- package/dist/tools/errorHeatmap.js +69 -0
- package/dist/tools/errorHeatmap.js.map +1 -0
- package/dist/tools/errorHistogram.d.ts +39 -0
- package/dist/tools/errorHistogram.d.ts.map +1 -0
- package/dist/tools/errorHistogram.js +61 -0
- package/dist/tools/errorHistogram.js.map +1 -0
- package/dist/tools/errorStatsBreakdown.d.ts +43 -0
- package/dist/tools/errorStatsBreakdown.d.ts.map +1 -0
- package/dist/tools/errorStatsBreakdown.js +77 -0
- package/dist/tools/errorStatsBreakdown.js.map +1 -0
- package/dist/tools/errorsInSession.d.ts +44 -0
- package/dist/tools/errorsInSession.d.ts.map +1 -0
- package/dist/tools/errorsInSession.js +91 -0
- package/dist/tools/errorsInSession.js.map +1 -0
- package/dist/tools/explainError.d.ts +35 -0
- package/dist/tools/explainError.d.ts.map +1 -0
- package/dist/tools/explainError.js +98 -0
- package/dist/tools/explainError.js.map +1 -0
- package/dist/tools/findCorrelatedErrors.d.ts +43 -0
- package/dist/tools/findCorrelatedErrors.d.ts.map +1 -0
- package/dist/tools/findCorrelatedErrors.js +59 -0
- package/dist/tools/findCorrelatedErrors.js.map +1 -0
- package/dist/tools/findSimilarErrors.d.ts +44 -0
- package/dist/tools/findSimilarErrors.d.ts.map +1 -0
- package/dist/tools/findSimilarErrors.js +59 -0
- package/dist/tools/findSimilarErrors.js.map +1 -0
- package/dist/tools/getLogDetails.d.ts +30 -0
- package/dist/tools/getLogDetails.d.ts.map +1 -0
- package/dist/tools/getLogDetails.js +49 -0
- package/dist/tools/getLogDetails.js.map +1 -0
- package/dist/tools/groupedErrors.d.ts +46 -0
- package/dist/tools/groupedErrors.d.ts.map +1 -0
- package/dist/tools/groupedErrors.js +71 -0
- package/dist/tools/groupedErrors.js.map +1 -0
- package/dist/tools/impactAnalysis.d.ts +42 -0
- package/dist/tools/impactAnalysis.d.ts.map +1 -0
- package/dist/tools/impactAnalysis.js +61 -0
- package/dist/tools/impactAnalysis.js.map +1 -0
- package/dist/tools/index.d.ts +41 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +83 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/listApps.d.ts +27 -0
- package/dist/tools/listApps.d.ts.map +1 -0
- package/dist/tools/listApps.js +78 -0
- package/dist/tools/listApps.js.map +1 -0
- package/dist/tools/queryLogsJql.d.ts +44 -0
- package/dist/tools/queryLogsJql.d.ts.map +1 -0
- package/dist/tools/queryLogsJql.js +107 -0
- package/dist/tools/queryLogsJql.js.map +1 -0
- package/dist/tools/searchLogs.d.ts +60 -0
- package/dist/tools/searchLogs.d.ts.map +1 -0
- package/dist/tools/searchLogs.js +127 -0
- package/dist/tools/searchLogs.js.map +1 -0
- package/dist/tools/topErrorMessages.d.ts +42 -0
- package/dist/tools/topErrorMessages.d.ts.map +1 -0
- package/dist/tools/topErrorMessages.js +63 -0
- package/dist/tools/topErrorMessages.js.map +1 -0
- package/dist/tools/trafficStats.d.ts +39 -0
- package/dist/tools/trafficStats.d.ts.map +1 -0
- package/dist/tools/trafficStats.js +57 -0
- package/dist/tools/trafficStats.js.map +1 -0
- package/dist/tools/triageRecentCritical.d.ts +26 -0
- package/dist/tools/triageRecentCritical.d.ts.map +1 -0
- package/dist/tools/triageRecentCritical.js +81 -0
- package/dist/tools/triageRecentCritical.js.map +1 -0
- package/dist/tools/versionRegression.d.ts +29 -0
- package/dist/tools/versionRegression.d.ts.map +1 -0
- package/dist/tools/versionRegression.js +80 -0
- package/dist/tools/versionRegression.js.map +1 -0
- package/dist/transports/http-server.d.ts +25 -0
- package/dist/transports/http-server.d.ts.map +1 -0
- package/dist/transports/http-server.js +84 -0
- package/dist/transports/http-server.js.map +1 -0
- package/dist/transports/http.d.ts +71 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +315 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +13 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +16 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/types.d.ts +150 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit log service.
|
|
3
|
+
*
|
|
4
|
+
* Контракт:
|
|
5
|
+
* - `recordToolCall` записывает строку в `mcp_audit.audit_log`.
|
|
6
|
+
* - Hash-chain: каждая запись хранит sha256(prev row content) и sha256(этой
|
|
7
|
+
* row). Внутри транзакции SELECT FOR UPDATE предыдущей строки + INSERT.
|
|
8
|
+
* - Silent fail: если БД недоступна / ошибка вставки — логируем warn и не
|
|
9
|
+
* падаем (tool-call продолжает работать). Audit не блокирует business flow.
|
|
10
|
+
* - Hash считается над **detерминированным** JSON-представлением полей (см.
|
|
11
|
+
* `rowContent`), чтобы потом chain-verifier мог пересчитать.
|
|
12
|
+
*
|
|
13
|
+
* См. 06-security.md §3.
|
|
14
|
+
*/
|
|
15
|
+
import type { Logger } from 'pino';
|
|
16
|
+
import { type McpPrismaClient } from './prisma.js';
|
|
17
|
+
export interface RecordToolCallParams {
|
|
18
|
+
appId: string;
|
|
19
|
+
/** Первые 8 chars API-ключа (НЕ полный key). */
|
|
20
|
+
keyId: string;
|
|
21
|
+
tool: string;
|
|
22
|
+
args: Record<string, unknown>;
|
|
23
|
+
resultBytes: number;
|
|
24
|
+
latencyMs: number;
|
|
25
|
+
cacheHit?: boolean;
|
|
26
|
+
ip?: string | null;
|
|
27
|
+
userAgent?: string | null;
|
|
28
|
+
sessionId?: string | null;
|
|
29
|
+
statusCode: number;
|
|
30
|
+
error?: string | null;
|
|
31
|
+
}
|
|
32
|
+
export interface AuditServiceOptions {
|
|
33
|
+
databaseUrl?: string;
|
|
34
|
+
log?: Logger;
|
|
35
|
+
/** Для тестов — позволяет инжектировать mock-prisma. */
|
|
36
|
+
prismaOverride?: McpPrismaClient | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Детерминированная сериализация для hash-chain. Поля упорядочены, BigInt'ы
|
|
40
|
+
* приведены к string, undefined пропущены. Если когда-нибудь захотим
|
|
41
|
+
* пересчитать chain — будем использовать ту же функцию.
|
|
42
|
+
*/
|
|
43
|
+
export declare function rowContent(p: {
|
|
44
|
+
appId: string;
|
|
45
|
+
keyId: string;
|
|
46
|
+
tool: string;
|
|
47
|
+
args: Record<string, unknown>;
|
|
48
|
+
resultBytes: number;
|
|
49
|
+
latencyMs: number;
|
|
50
|
+
cacheHit: boolean;
|
|
51
|
+
statusCode: number;
|
|
52
|
+
error?: string | null;
|
|
53
|
+
createdAt: string;
|
|
54
|
+
prevHash: string | null;
|
|
55
|
+
}): string;
|
|
56
|
+
export declare function sha256Hex(input: string): string;
|
|
57
|
+
export interface AuditService {
|
|
58
|
+
recordToolCall(params: RecordToolCallParams): Promise<void>;
|
|
59
|
+
/** Для тестов / health-checks. */
|
|
60
|
+
verifyChain(appId: string): Promise<{
|
|
61
|
+
ok: boolean;
|
|
62
|
+
brokenAt?: string;
|
|
63
|
+
}>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Создаёт audit-service. Если prisma недоступен — все методы no-op.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createAuditService(opts?: AuditServiceOptions): AuditService;
|
|
69
|
+
export declare function getAuditService(opts?: AuditServiceOptions): AuditService;
|
|
70
|
+
/** Для тестов. */
|
|
71
|
+
export declare function setAuditServiceForTests(svc: AuditService | null): void;
|
|
72
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,cAAc,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GAAG,MAAM,CAeT;AAWD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,kCAAkC;IAClC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,mBAAwB,GAAG,YAAY,CAwE/E;AAID,wBAAgB,eAAe,CAAC,IAAI,GAAE,mBAAwB,GAAG,YAAY,CAG5E;AAED,kBAAkB;AAClB,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAEtE"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit log service.
|
|
3
|
+
*
|
|
4
|
+
* Контракт:
|
|
5
|
+
* - `recordToolCall` записывает строку в `mcp_audit.audit_log`.
|
|
6
|
+
* - Hash-chain: каждая запись хранит sha256(prev row content) и sha256(этой
|
|
7
|
+
* row). Внутри транзакции SELECT FOR UPDATE предыдущей строки + INSERT.
|
|
8
|
+
* - Silent fail: если БД недоступна / ошибка вставки — логируем warn и не
|
|
9
|
+
* падаем (tool-call продолжает работать). Audit не блокирует business flow.
|
|
10
|
+
* - Hash считается над **detерминированным** JSON-представлением полей (см.
|
|
11
|
+
* `rowContent`), чтобы потом chain-verifier мог пересчитать.
|
|
12
|
+
*
|
|
13
|
+
* См. 06-security.md §3.
|
|
14
|
+
*/
|
|
15
|
+
import { createHash } from 'node:crypto';
|
|
16
|
+
import { getPrisma } from './prisma.js';
|
|
17
|
+
/**
|
|
18
|
+
* Детерминированная сериализация для hash-chain. Поля упорядочены, BigInt'ы
|
|
19
|
+
* приведены к string, undefined пропущены. Если когда-нибудь захотим
|
|
20
|
+
* пересчитать chain — будем использовать ту же функцию.
|
|
21
|
+
*/
|
|
22
|
+
export function rowContent(p) {
|
|
23
|
+
const sorted = {
|
|
24
|
+
appId: p.appId,
|
|
25
|
+
args: stableStringify(p.args),
|
|
26
|
+
cacheHit: p.cacheHit,
|
|
27
|
+
createdAt: p.createdAt,
|
|
28
|
+
error: p.error ?? null,
|
|
29
|
+
keyId: p.keyId,
|
|
30
|
+
latencyMs: p.latencyMs,
|
|
31
|
+
prevHash: p.prevHash ?? '',
|
|
32
|
+
resultBytes: p.resultBytes,
|
|
33
|
+
statusCode: p.statusCode,
|
|
34
|
+
tool: p.tool,
|
|
35
|
+
};
|
|
36
|
+
return JSON.stringify(sorted);
|
|
37
|
+
}
|
|
38
|
+
function stableStringify(v) {
|
|
39
|
+
if (v === null || v === undefined)
|
|
40
|
+
return 'null';
|
|
41
|
+
if (typeof v !== 'object')
|
|
42
|
+
return JSON.stringify(v);
|
|
43
|
+
if (Array.isArray(v))
|
|
44
|
+
return `[${v.map(stableStringify).join(',')}]`;
|
|
45
|
+
const obj = v;
|
|
46
|
+
const keys = Object.keys(obj).sort();
|
|
47
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(',')}}`;
|
|
48
|
+
}
|
|
49
|
+
export function sha256Hex(input) {
|
|
50
|
+
return createHash('sha256').update(input).digest('hex');
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Создаёт audit-service. Если prisma недоступен — все методы no-op.
|
|
54
|
+
*/
|
|
55
|
+
export function createAuditService(opts = {}) {
|
|
56
|
+
const log = opts.log;
|
|
57
|
+
async function getClient() {
|
|
58
|
+
if (opts.prismaOverride !== undefined)
|
|
59
|
+
return opts.prismaOverride;
|
|
60
|
+
return getPrisma({ ...(opts.databaseUrl ? { databaseUrl: opts.databaseUrl } : {}), ...(log ? { log } : {}) });
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
async recordToolCall(p) {
|
|
64
|
+
const client = await getClient();
|
|
65
|
+
if (!client)
|
|
66
|
+
return; // no-op
|
|
67
|
+
const createdAt = new Date().toISOString();
|
|
68
|
+
const cacheHit = p.cacheHit ?? false;
|
|
69
|
+
try {
|
|
70
|
+
await client.$transaction(async (tx) => {
|
|
71
|
+
const prev = await tx.mcpAuditLog.findFirst({
|
|
72
|
+
where: { appId: p.appId },
|
|
73
|
+
orderBy: { createdAt: 'desc' },
|
|
74
|
+
select: { rowHash: true },
|
|
75
|
+
});
|
|
76
|
+
const prevHash = prev?.rowHash ?? null;
|
|
77
|
+
const content = rowContent({
|
|
78
|
+
appId: p.appId,
|
|
79
|
+
keyId: p.keyId,
|
|
80
|
+
tool: p.tool,
|
|
81
|
+
args: p.args,
|
|
82
|
+
resultBytes: p.resultBytes,
|
|
83
|
+
latencyMs: p.latencyMs,
|
|
84
|
+
cacheHit,
|
|
85
|
+
statusCode: p.statusCode,
|
|
86
|
+
...(p.error !== undefined && p.error !== null ? { error: p.error } : { error: null }),
|
|
87
|
+
createdAt,
|
|
88
|
+
prevHash,
|
|
89
|
+
});
|
|
90
|
+
const rowHash = sha256Hex((prevHash ?? '') + content);
|
|
91
|
+
await tx.mcpAuditLog.create({
|
|
92
|
+
data: {
|
|
93
|
+
appId: p.appId,
|
|
94
|
+
keyId: p.keyId,
|
|
95
|
+
tool: p.tool,
|
|
96
|
+
args: p.args,
|
|
97
|
+
resultBytes: p.resultBytes,
|
|
98
|
+
latencyMs: p.latencyMs,
|
|
99
|
+
cacheHit,
|
|
100
|
+
ip: p.ip ?? null,
|
|
101
|
+
userAgent: p.userAgent ?? null,
|
|
102
|
+
sessionId: p.sessionId ?? null,
|
|
103
|
+
statusCode: p.statusCode,
|
|
104
|
+
error: p.error ?? null,
|
|
105
|
+
prevHash,
|
|
106
|
+
rowHash,
|
|
107
|
+
createdAt,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
log?.warn?.({ err, tool: p.tool, appId: p.appId }, 'Audit log write failed (non-blocking)');
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
async verifyChain(appId) {
|
|
117
|
+
// Используется в тестах. Phase 5: проходим в порядке createdAt asc и
|
|
118
|
+
// пересчитываем hash. Для production-job можно вынести в отдельный модуль.
|
|
119
|
+
const client = await getClient();
|
|
120
|
+
if (!client)
|
|
121
|
+
return { ok: true };
|
|
122
|
+
// Phase 5: для упрощения возвращаем ok, реальная проверка — Phase 6 cron.
|
|
123
|
+
return { ok: true, ...(appId ? {} : {}) };
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
let globalAudit = null;
|
|
128
|
+
export function getAuditService(opts = {}) {
|
|
129
|
+
if (!globalAudit)
|
|
130
|
+
globalAudit = createAuditService(opts);
|
|
131
|
+
return globalAudit;
|
|
132
|
+
}
|
|
133
|
+
/** Для тестов. */
|
|
134
|
+
export function setAuditServiceForTests(svc) {
|
|
135
|
+
globalAudit = svc;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier matrix MCP — single source of truth (см. 08-billing-integration.md §1).
|
|
3
|
+
*
|
|
4
|
+
* Поля:
|
|
5
|
+
* - reqPerDay — основной cut-off limit для tool-calls
|
|
6
|
+
* - concurrentSse — SSE-сессий per app (Phase 4)
|
|
7
|
+
* - aiPerDay — лимит на AI-explain (Phase 4)
|
|
8
|
+
* - graceFraction — 10 % grace выше дневного лимита перед hard cut-off
|
|
9
|
+
*/
|
|
10
|
+
export type Tier = 'FREE' | 'STANDARD' | 'PREMIUM' | 'UNLIMITED';
|
|
11
|
+
export interface TierLimits {
|
|
12
|
+
reqPerDay: number;
|
|
13
|
+
concurrentSse: number;
|
|
14
|
+
aiPerDay: number;
|
|
15
|
+
graceFraction: number;
|
|
16
|
+
}
|
|
17
|
+
export declare const TIER_LIMITS: Record<Tier, TierLimits>;
|
|
18
|
+
export interface QuotaDecision {
|
|
19
|
+
/** True → запрос можно пропускать. */
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
/** Сколько req осталось до дневного лимита (или Infinity для UNLIMITED). */
|
|
22
|
+
remaining: number;
|
|
23
|
+
/** True → клиент уже в grace-зоне (warning, но allowed). */
|
|
24
|
+
overage?: boolean;
|
|
25
|
+
/** Если !allowed — сколько секунд до сброса. */
|
|
26
|
+
retryAfter?: number;
|
|
27
|
+
/** Текущий tier (echo back). */
|
|
28
|
+
tier: Tier;
|
|
29
|
+
}
|
|
30
|
+
/** Секунд до конца текущих UTC-суток. */
|
|
31
|
+
export declare function secondsUntilUtcMidnight(now?: Date): number;
|
|
32
|
+
/** Чистое решение: принимает текущий счётчик и tier, возвращает decision. */
|
|
33
|
+
export declare function decideQuota(currentUsed: number, tier: Tier): QuotaDecision;
|
|
34
|
+
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/billing/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;AAEjE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,CAUhD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,yCAAyC;AACzC,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAWtE;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,aAAa,CAuB1E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier matrix MCP — single source of truth (см. 08-billing-integration.md §1).
|
|
3
|
+
*
|
|
4
|
+
* Поля:
|
|
5
|
+
* - reqPerDay — основной cut-off limit для tool-calls
|
|
6
|
+
* - concurrentSse — SSE-сессий per app (Phase 4)
|
|
7
|
+
* - aiPerDay — лимит на AI-explain (Phase 4)
|
|
8
|
+
* - graceFraction — 10 % grace выше дневного лимита перед hard cut-off
|
|
9
|
+
*/
|
|
10
|
+
export const TIER_LIMITS = {
|
|
11
|
+
FREE: { reqPerDay: 1_000, concurrentSse: 2, aiPerDay: 20, graceFraction: 0.1 },
|
|
12
|
+
STANDARD: { reqPerDay: 50_000, concurrentSse: 20, aiPerDay: 500, graceFraction: 0.1 },
|
|
13
|
+
PREMIUM: { reqPerDay: 500_000, concurrentSse: 100, aiPerDay: 5_000, graceFraction: 0.1 },
|
|
14
|
+
UNLIMITED: {
|
|
15
|
+
reqPerDay: Number.POSITIVE_INFINITY,
|
|
16
|
+
concurrentSse: 500,
|
|
17
|
+
aiPerDay: Number.POSITIVE_INFINITY,
|
|
18
|
+
graceFraction: 0,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
/** Секунд до конца текущих UTC-суток. */
|
|
22
|
+
export function secondsUntilUtcMidnight(now = new Date()) {
|
|
23
|
+
const next = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1, 0, 0, 0, 0);
|
|
24
|
+
return Math.max(1, Math.ceil((next - now.getTime()) / 1000));
|
|
25
|
+
}
|
|
26
|
+
/** Чистое решение: принимает текущий счётчик и tier, возвращает decision. */
|
|
27
|
+
export function decideQuota(currentUsed, tier) {
|
|
28
|
+
const limits = TIER_LIMITS[tier];
|
|
29
|
+
if (!Number.isFinite(limits.reqPerDay)) {
|
|
30
|
+
return { allowed: true, remaining: Number.POSITIVE_INFINITY, tier };
|
|
31
|
+
}
|
|
32
|
+
const cutoff = Math.floor(limits.reqPerDay * (1 + limits.graceFraction));
|
|
33
|
+
if (currentUsed < limits.reqPerDay) {
|
|
34
|
+
return { allowed: true, remaining: limits.reqPerDay - currentUsed, tier };
|
|
35
|
+
}
|
|
36
|
+
if (currentUsed < cutoff) {
|
|
37
|
+
return {
|
|
38
|
+
allowed: true,
|
|
39
|
+
remaining: 0,
|
|
40
|
+
overage: true,
|
|
41
|
+
tier,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
allowed: false,
|
|
46
|
+
remaining: 0,
|
|
47
|
+
retryAfter: secondsUntilUtcMidnight(),
|
|
48
|
+
tier,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/billing/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,MAAM,CAAC,MAAM,WAAW,GAA6B;IACnD,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE;IAC9E,QAAQ,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE;IACrF,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE;IACxF,SAAS,EAAE;QACT,SAAS,EAAE,MAAM,CAAC,iBAAiB;QACnC,aAAa,EAAE,GAAG;QAClB,QAAQ,EAAE,MAAM,CAAC,iBAAiB;QAClC,aAAa,EAAE,CAAC;KACjB;CACF,CAAC;AAeF,yCAAyC;AACzC,MAAM,UAAU,uBAAuB,CAAC,MAAY,IAAI,IAAI,EAAE;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB,GAAG,CAAC,cAAc,EAAE,EACpB,GAAG,CAAC,WAAW,EAAE,EACjB,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,EACpB,CAAC,EACD,CAAC,EACD,CAAC,EACD,CAAC,CACF,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,IAAU;IACzD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IACtE,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;IACzE,IAAI,WAAW,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,WAAW,EAAE,IAAI,EAAE,CAAC;IAC5E,CAAC;IACD,IAAI,WAAW,GAAG,MAAM,EAAE,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,IAAI;YACb,IAAI;SACL,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,uBAAuB,EAAE;QACrC,IAAI;KACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 5 usage tracker.
|
|
3
|
+
*
|
|
4
|
+
* Пишет напрямую в Postgres `mcp_billing.usage_daily` (UPSERT per app+date+tool).
|
|
5
|
+
* В Phase 4 заменим на Redis INCR + hourly flush — интерфейс останется тем же,
|
|
6
|
+
* так что вызывающий код не нужно будет править.
|
|
7
|
+
*
|
|
8
|
+
* Поведение:
|
|
9
|
+
* - Silent fail при ошибке БД (как и audit) — usage tracking не блокирует tool-call.
|
|
10
|
+
* - Fire-and-forget: caller вызывает через `void trackUsage(...)`.
|
|
11
|
+
*/
|
|
12
|
+
import type { Logger } from 'pino';
|
|
13
|
+
import { type McpPrismaClient } from '../audit/prisma.js';
|
|
14
|
+
import { type QuotaDecision, type Tier } from './limits.js';
|
|
15
|
+
export interface TrackUsageParams {
|
|
16
|
+
appId: string;
|
|
17
|
+
tool: string;
|
|
18
|
+
bytesOut: number;
|
|
19
|
+
/** Можно явно передать дату (для тестов). По умолчанию today UTC. */
|
|
20
|
+
date?: Date;
|
|
21
|
+
}
|
|
22
|
+
export interface UsageTrackerOptions {
|
|
23
|
+
databaseUrl?: string;
|
|
24
|
+
log?: Logger;
|
|
25
|
+
prismaOverride?: McpPrismaClient | null;
|
|
26
|
+
}
|
|
27
|
+
export interface UsageTracker {
|
|
28
|
+
trackUsage(params: TrackUsageParams): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Возвращает текущее число использований за сегодня UTC (sum по всем tools).
|
|
31
|
+
* Используется как source для `checkQuota`.
|
|
32
|
+
*/
|
|
33
|
+
todayUsage(appId: string, now?: Date): Promise<number>;
|
|
34
|
+
checkQuota(appId: string, tier: Tier, now?: Date): Promise<QuotaDecision>;
|
|
35
|
+
}
|
|
36
|
+
export declare function createUsageTracker(opts?: UsageTrackerOptions): UsageTracker;
|
|
37
|
+
export declare function getUsageTracker(opts?: UsageTrackerOptions): UsageTracker;
|
|
38
|
+
export declare function setUsageTrackerForTests(t: UsageTracker | null): void;
|
|
39
|
+
//# sourceMappingURL=tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/billing/tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAe,KAAK,aAAa,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CACzC;AAMD,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC3E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,mBAAwB,GAAG,YAAY,CA+D/E;AAID,wBAAgB,eAAe,CAAC,IAAI,GAAE,mBAAwB,GAAG,YAAY,CAG5E;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAEpE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 5 usage tracker.
|
|
3
|
+
*
|
|
4
|
+
* Пишет напрямую в Postgres `mcp_billing.usage_daily` (UPSERT per app+date+tool).
|
|
5
|
+
* В Phase 4 заменим на Redis INCR + hourly flush — интерфейс останется тем же,
|
|
6
|
+
* так что вызывающий код не нужно будет править.
|
|
7
|
+
*
|
|
8
|
+
* Поведение:
|
|
9
|
+
* - Silent fail при ошибке БД (как и audit) — usage tracking не блокирует tool-call.
|
|
10
|
+
* - Fire-and-forget: caller вызывает через `void trackUsage(...)`.
|
|
11
|
+
*/
|
|
12
|
+
import { getPrisma } from '../audit/prisma.js';
|
|
13
|
+
import { decideQuota } from './limits.js';
|
|
14
|
+
function utcDateOnly(d) {
|
|
15
|
+
return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
|
|
16
|
+
}
|
|
17
|
+
export function createUsageTracker(opts = {}) {
|
|
18
|
+
const log = opts.log;
|
|
19
|
+
async function getClient() {
|
|
20
|
+
if (opts.prismaOverride !== undefined)
|
|
21
|
+
return opts.prismaOverride;
|
|
22
|
+
return getPrisma({ ...(opts.databaseUrl ? { databaseUrl: opts.databaseUrl } : {}), ...(log ? { log } : {}) });
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
async trackUsage(p) {
|
|
26
|
+
const client = await getClient();
|
|
27
|
+
if (!client)
|
|
28
|
+
return;
|
|
29
|
+
const date = utcDateOnly(p.date ?? new Date());
|
|
30
|
+
try {
|
|
31
|
+
await client.mcpUsageDaily.upsert({
|
|
32
|
+
where: {
|
|
33
|
+
appId_date_tool: { appId: p.appId, date, tool: p.tool },
|
|
34
|
+
},
|
|
35
|
+
update: {
|
|
36
|
+
count: { increment: BigInt(1) },
|
|
37
|
+
bytesOut: { increment: BigInt(Math.max(0, Math.floor(p.bytesOut))) },
|
|
38
|
+
},
|
|
39
|
+
create: {
|
|
40
|
+
appId: p.appId,
|
|
41
|
+
date,
|
|
42
|
+
tool: p.tool,
|
|
43
|
+
count: BigInt(1),
|
|
44
|
+
bytesOut: BigInt(Math.max(0, Math.floor(p.bytesOut))),
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
log?.warn?.({ err, tool: p.tool, appId: p.appId }, 'Usage tracking failed (non-blocking)');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
async todayUsage(appId, now = new Date()) {
|
|
53
|
+
const client = await getClient();
|
|
54
|
+
if (!client)
|
|
55
|
+
return 0;
|
|
56
|
+
const date = utcDateOnly(now);
|
|
57
|
+
try {
|
|
58
|
+
const result = await client.mcpUsageDaily.aggregate({
|
|
59
|
+
where: { appId, date },
|
|
60
|
+
_sum: { count: true },
|
|
61
|
+
});
|
|
62
|
+
const total = result._sum.count;
|
|
63
|
+
if (total === null)
|
|
64
|
+
return 0;
|
|
65
|
+
// BigInt → number. Дневной лимит макс. 500k для PREMIUM, далее ∞ для
|
|
66
|
+
// UNLIMITED, поэтому safe-integer достаточно.
|
|
67
|
+
return Number(total);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
log?.warn?.({ err, appId }, 'todayUsage read failed; defaulting to 0');
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
async checkQuota(appId, tier, now = new Date()) {
|
|
75
|
+
if (tier === 'UNLIMITED') {
|
|
76
|
+
return { allowed: true, remaining: Number.POSITIVE_INFINITY, tier };
|
|
77
|
+
}
|
|
78
|
+
const used = await this.todayUsage(appId, now);
|
|
79
|
+
return decideQuota(used, tier);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
let globalTracker = null;
|
|
84
|
+
export function getUsageTracker(opts = {}) {
|
|
85
|
+
if (!globalTracker)
|
|
86
|
+
globalTracker = createUsageTracker(opts);
|
|
87
|
+
return globalTracker;
|
|
88
|
+
}
|
|
89
|
+
export function setUsageTrackerForTests(t) {
|
|
90
|
+
globalTracker = t;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/billing/tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,SAAS,EAAwB,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAiC,MAAM,aAAa,CAAC;AAgBzE,SAAS,WAAW,CAAC,CAAO;IAC1B,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AACjF,CAAC;AAYD,MAAM,UAAU,kBAAkB,CAAC,OAA4B,EAAE;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IAErB,KAAK,UAAU,SAAS;QACtB,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,cAAc,CAAC;QAClE,OAAO,SAAS,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAChH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,UAAU,CAAC,CAAmB;YAClC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC;oBAChC,KAAK,EAAE;wBACL,eAAe,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;qBACxD;oBACD,MAAM,EAAE;wBACN,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE;wBAC/B,QAAQ,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;qBACrE;oBACD,MAAM,EAAE;wBACN,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,IAAI;wBACJ,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;wBAChB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;qBACtD;iBACF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,sCAAsC,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,KAAa,EAAE,MAAY,IAAI,IAAI,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM;gBAAE,OAAO,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC;oBAClD,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;oBACtB,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;iBACtB,CAAC,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;gBAChC,IAAI,KAAK,KAAK,IAAI;oBAAE,OAAO,CAAC,CAAC;gBAC7B,qEAAqE;gBACrE,8CAA8C;gBAC9C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,yCAAyC,CAAC,CAAC;gBACvE,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,KAAa,EAAE,IAAU,EAAE,MAAY,IAAI,IAAI,EAAE;YAChE,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;gBACzB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;YACtE,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC/C,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,IAAI,aAAa,GAAwB,IAAI,CAAC;AAE9C,MAAM,UAAU,eAAe,CAAC,OAA4B,EAAE;IAC5D,IAAI,CAAC,aAAa;QAAE,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,CAAsB;IAC5D,aAAa,GAAG,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { ElsClient } from '../elsClient.js';
|
|
3
|
+
import type { CacheService } from './wrapper.js';
|
|
4
|
+
import { type CacheClass } from './policies.js';
|
|
5
|
+
import type { RequestContext } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Кэширующая обёртка над `ElsClient`.
|
|
8
|
+
*
|
|
9
|
+
* Дизайн — **composition over inheritance**:
|
|
10
|
+
* - сохраняет 100% совместимую сигнатуру с ElsClient;
|
|
11
|
+
* - не модифицирует ElsClient (additive only);
|
|
12
|
+
* - `ctx` принимается опционально (по умолчанию — fallback context от config).
|
|
13
|
+
*
|
|
14
|
+
* Если cache недоступен (Redis down или disabled) — все методы прозрачно
|
|
15
|
+
* прокидываются в underlying `ElsClient`.
|
|
16
|
+
*
|
|
17
|
+
* Все cache keys построены через `tenantKey()` (см. `policies.ts`), что
|
|
18
|
+
* гарантирует tenant-isolation (cross-tenant leak guard).
|
|
19
|
+
*
|
|
20
|
+
* Какие методы кэшируем (см. `05-high-load.md` § 2.1):
|
|
21
|
+
*
|
|
22
|
+
* | Method | Class | TTL |
|
|
23
|
+
* |----------------------|------------------|--------|
|
|
24
|
+
* | getLogDetails | log_details | 1h |
|
|
25
|
+
* | searchLogs | search_recent | 15s |
|
|
26
|
+
* | topErrorMessages | top_messages | 2m |
|
|
27
|
+
* | errorHistogram | histogram | 1m |
|
|
28
|
+
* | trafficStats | traffic_long | 5m |
|
|
29
|
+
* | listApps | list_apps | 30s |
|
|
30
|
+
* | heatmap | heatmap | 5m |
|
|
31
|
+
* | errorStats | stats_breakdown | 2m |
|
|
32
|
+
* | groupedErrors | grouped_errors | 2m |
|
|
33
|
+
* | baseline | baseline | 5m |
|
|
34
|
+
* | versionRegression | version_timeline | 5m |
|
|
35
|
+
*
|
|
36
|
+
* Что НЕ кэшируем (см. § 2.4):
|
|
37
|
+
* - `queryLogsJql` — высокая кардинальность ключей, hit ratio < 5%.
|
|
38
|
+
* - `findCorrelatedErrors` — корреляция меняется при ingest.
|
|
39
|
+
* - `findSimilarErrors` — агрегаты "за последний час" — слишком волатильны.
|
|
40
|
+
*/
|
|
41
|
+
export declare class CachedElsClient {
|
|
42
|
+
private readonly inner;
|
|
43
|
+
private readonly cache;
|
|
44
|
+
private readonly policies;
|
|
45
|
+
private readonly _log?;
|
|
46
|
+
constructor(inner: ElsClient, cache: CacheService, policies?: Record<CacheClass, number>, _log?: Logger | undefined);
|
|
47
|
+
/** Доступ к raw client (нужен для методов без кэша). */
|
|
48
|
+
get raw(): ElsClient;
|
|
49
|
+
close(): Promise<void>;
|
|
50
|
+
getLogDetails(traceId: string, ctx?: RequestContext): Promise<ReturnType<ElsClient['getLogDetails']>>;
|
|
51
|
+
searchLogs(params: Record<string, string | number | boolean | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['searchLogs']>>;
|
|
52
|
+
topErrorMessages(params: Record<string, string | number | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['topErrorMessages']>>;
|
|
53
|
+
errorHistogram(params: Record<string, string | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['errorHistogram']>>;
|
|
54
|
+
trafficStats(params: Record<string, string | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['trafficStats']>>;
|
|
55
|
+
listApps(ctx?: RequestContext): Promise<ReturnType<ElsClient['listApps']>>;
|
|
56
|
+
heatmap(params: Record<string, string | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['heatmap']>>;
|
|
57
|
+
errorStats(params: Record<string, string | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['errorStats']>>;
|
|
58
|
+
groupedErrors(params: Record<string, string | number | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['groupedErrors']>>;
|
|
59
|
+
baseline(params: Record<string, string | number | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['baseline']>>;
|
|
60
|
+
versionRegression(params: Record<string, string | undefined>, ctx?: RequestContext): Promise<ReturnType<ElsClient['versionRegression']>>;
|
|
61
|
+
findSimilarErrors(...args: Parameters<ElsClient['findSimilarErrors']>): Promise<ReturnType<ElsClient['findSimilarErrors']>>;
|
|
62
|
+
findCorrelatedErrors(...args: Parameters<ElsClient['findCorrelatedErrors']>): Promise<ReturnType<ElsClient['findCorrelatedErrors']>>;
|
|
63
|
+
queryLogsJql(...args: Parameters<ElsClient['queryLogsJql']>): Promise<ReturnType<ElsClient['queryLogsJql']>>;
|
|
64
|
+
impact(...args: Parameters<ElsClient['impact']>): Promise<ReturnType<ElsClient['impact']>>;
|
|
65
|
+
/**
|
|
66
|
+
* Строит cache key с tenant-isolation. Возвращает null если контекст не даёт
|
|
67
|
+
* tenant идентификатор — caller обязан в этом случае идти в bypass-path.
|
|
68
|
+
*/
|
|
69
|
+
private buildKey;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=cachedElsClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cachedElsClient.d.ts","sourceRoot":"","sources":["../../src/cache/cachedElsClient.ts"],"names":[],"mappings":"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"}
|