@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,202 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const ALL_PROMPT_NAMES = [
|
|
3
|
+
'triage-recent-errors',
|
|
4
|
+
'find-regression-since-deploy',
|
|
5
|
+
'explain-error-cluster',
|
|
6
|
+
'weekly-error-report',
|
|
7
|
+
];
|
|
8
|
+
function userMessage(text) {
|
|
9
|
+
return {
|
|
10
|
+
messages: [
|
|
11
|
+
{
|
|
12
|
+
role: 'user',
|
|
13
|
+
content: { type: 'text', text },
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function registerPrompts(server, opts = {}) {
|
|
19
|
+
const registered = [];
|
|
20
|
+
// ─── triage-recent-errors ────────────────────────────────────────────────
|
|
21
|
+
server.registerPrompt('triage-recent-errors', {
|
|
22
|
+
title: 'Triage recent errors',
|
|
23
|
+
description: 'On-call инцидент-triage: какие ошибки случились за последние N часов, сгруппированные по severity и fingerprint.',
|
|
24
|
+
argsSchema: {
|
|
25
|
+
hours: z.string().optional().describe('Окно анализа в часах (1-24). Default: 1.'),
|
|
26
|
+
level: z.string().optional().describe('Минимальный уровень severity. Default: CRITICAL.'),
|
|
27
|
+
},
|
|
28
|
+
}, async (args) => {
|
|
29
|
+
const hoursStr = args.hours ?? '1';
|
|
30
|
+
const hoursNum = Math.max(1, Math.min(24, Number(hoursStr) || 1));
|
|
31
|
+
const level = args.level ?? 'CRITICAL';
|
|
32
|
+
const minutes = hoursNum * 60;
|
|
33
|
+
const text = [
|
|
34
|
+
'Ты — опытный SRE, дежурный по платформе ELS. Сейчас инцидент-triage.',
|
|
35
|
+
'',
|
|
36
|
+
'Контекст:',
|
|
37
|
+
`- Окно анализа: последние ${hoursNum} ч.`,
|
|
38
|
+
`- Severity: ${level} и выше.`,
|
|
39
|
+
'',
|
|
40
|
+
'Сделай следующее, используя доступные tools:',
|
|
41
|
+
'',
|
|
42
|
+
`1. Вызови \`triage_recent_critical\` с minutesBack=${minutes}, sampleSize=10.`,
|
|
43
|
+
'2. Если найдено ≥ 1 fingerprint, вызови `grouped_errors` за то же окно и покажи топ-5 по count.',
|
|
44
|
+
'3. Для top-1 fingerprint вызови `find_similar_errors` (по traceId из samples) — ошибка новая или recurring?',
|
|
45
|
+
'4. Сделай выводы в формате:',
|
|
46
|
+
' - **Заголовок:** одна строка — что сломалось',
|
|
47
|
+
` - **Severity:** ${level} × N`,
|
|
48
|
+
' - **Top causes (top-3):** fingerprint + краткое описание + count',
|
|
49
|
+
' - **Recurring vs new:** для top-1 — сколько раз за 7д',
|
|
50
|
+
' - **Recommended next step:** что проверять руками',
|
|
51
|
+
'',
|
|
52
|
+
'Отвечай по-русски, без emoji, кратко.',
|
|
53
|
+
].join('\n');
|
|
54
|
+
return userMessage(text);
|
|
55
|
+
});
|
|
56
|
+
registered.push('triage-recent-errors');
|
|
57
|
+
// ─── find-regression-since-deploy ────────────────────────────────────────
|
|
58
|
+
server.registerPrompt('find-regression-since-deploy', {
|
|
59
|
+
title: 'Find regressions after deploy',
|
|
60
|
+
description: 'Сравни ошибки между двумя версиями релиза и определи, что появилось нового в candidate.',
|
|
61
|
+
argsSchema: {
|
|
62
|
+
baselineVersion: z.string().min(1).describe('Стабильная предыдущая версия, напр. v2.3.0.'),
|
|
63
|
+
candidateVersion: z.string().min(1).describe('Новая версия для анализа, напр. v2.4.0.'),
|
|
64
|
+
},
|
|
65
|
+
}, async (args) => {
|
|
66
|
+
const baseline = args.baselineVersion;
|
|
67
|
+
const candidate = args.candidateVersion;
|
|
68
|
+
const text = [
|
|
69
|
+
`Ты — release-engineer. Только что был развёрнут ${candidate}.`,
|
|
70
|
+
`До этого работал ${baseline}. Нужно проверить, нет ли регрессий.`,
|
|
71
|
+
'',
|
|
72
|
+
'Шаги:',
|
|
73
|
+
'',
|
|
74
|
+
`1. Вызови \`version_regression\` с baselineVersion=${baseline}, candidateVersion=${candidate}.`,
|
|
75
|
+
'2. Если в `newFingerprints` есть записи — для каждого из топ-3 по `count`:',
|
|
76
|
+
' 2.1. Вызови `find_similar_errors` с traceId примера.',
|
|
77
|
+
' 2.2. Если ошибка появилась впервые за последние 24 часа — пометь как "REGRESSION SUSPECT".',
|
|
78
|
+
'3. Если в `disappeared` есть записи — упомяни их кратко.',
|
|
79
|
+
'',
|
|
80
|
+
'Финальный отчёт — markdown:',
|
|
81
|
+
'',
|
|
82
|
+
`# Regression check ${baseline} → ${candidate}`,
|
|
83
|
+
'',
|
|
84
|
+
'## Новые fingerprint\'ы (suspect regressions)',
|
|
85
|
+
'| FP | Message | Count | First seen | Verdict |',
|
|
86
|
+
'|----|---------|-------|------------|---------|',
|
|
87
|
+
'',
|
|
88
|
+
'## Исчезнувшие',
|
|
89
|
+
'- ...',
|
|
90
|
+
'',
|
|
91
|
+
'## Рекомендация',
|
|
92
|
+
'- (rollback / hotfix / safe-to-ignore)',
|
|
93
|
+
'',
|
|
94
|
+
'Отвечай по-русски, без emoji.',
|
|
95
|
+
].join('\n');
|
|
96
|
+
return userMessage(text);
|
|
97
|
+
});
|
|
98
|
+
registered.push('find-regression-since-deploy');
|
|
99
|
+
// ─── explain-error-cluster ───────────────────────────────────────────────
|
|
100
|
+
server.registerPrompt('explain-error-cluster', {
|
|
101
|
+
title: 'Explain error cluster',
|
|
102
|
+
description: 'Возьми traceId или fingerprint, собери контекст (similar, correlated) и объясни читабельно.',
|
|
103
|
+
argsSchema: {
|
|
104
|
+
traceId: z.string().optional().describe('TraceId конкретной ошибки.'),
|
|
105
|
+
fingerprint: z.string().optional().describe('Альтернатива traceId — fingerprint кластера.'),
|
|
106
|
+
locale: z.string().optional().describe('Язык объяснения: ru или en. Default: ru.'),
|
|
107
|
+
},
|
|
108
|
+
}, async (args) => {
|
|
109
|
+
const traceId = args.traceId;
|
|
110
|
+
const fingerprint = args.fingerprint;
|
|
111
|
+
const locale = args.locale ?? 'ru';
|
|
112
|
+
if (!traceId && !fingerprint) {
|
|
113
|
+
return userMessage('Не задан ни traceId, ни fingerprint. Уточни у пользователя одно из значений и повтори вызов prompt.');
|
|
114
|
+
}
|
|
115
|
+
const stepsTrace = traceId
|
|
116
|
+
? [
|
|
117
|
+
`Старт: traceId=${traceId}.`,
|
|
118
|
+
'',
|
|
119
|
+
'Шаги:',
|
|
120
|
+
`1. \`get_log_details\` с traceId=${traceId}.`,
|
|
121
|
+
`2. \`find_similar_errors\` с этим же traceId.`,
|
|
122
|
+
`3. \`find_correlated_errors\` (windowMinutes=15).`,
|
|
123
|
+
`4. \`explain_error\` traceId=${traceId} — соберёт контекст; AI-summary в Phase 2 пустое, синтезируй сам.`,
|
|
124
|
+
].join('\n')
|
|
125
|
+
: [
|
|
126
|
+
`Старт: fingerprint=${fingerprint}.`,
|
|
127
|
+
'',
|
|
128
|
+
'Шаги:',
|
|
129
|
+
`1. Вызови \`search_logs\` с filter \`fingerprint=${fingerprint}\`, limit=1 — получи свежий traceId.`,
|
|
130
|
+
'2. Дальше как с traceId — пункты 2-4.',
|
|
131
|
+
].join('\n');
|
|
132
|
+
const text = [
|
|
133
|
+
'Объясни этот кластер ошибок понятно, как для junior-разработчика.',
|
|
134
|
+
'',
|
|
135
|
+
stepsTrace,
|
|
136
|
+
'',
|
|
137
|
+
`Финальный ответ (${locale}):`,
|
|
138
|
+
'- **Что произошло:** 1-2 предложения',
|
|
139
|
+
'- **Почему скорее всего:** 2-3 гипотезы, ранжированные',
|
|
140
|
+
'- **Какие ещё ошибки случались рядом:** перечисли correlated (если есть)',
|
|
141
|
+
'- **Что проверить руками:** конкретные команды / dashboards',
|
|
142
|
+
'',
|
|
143
|
+
'Без emoji. Без markdown-heavy форматирования вне нужного.',
|
|
144
|
+
].join('\n');
|
|
145
|
+
return userMessage(text);
|
|
146
|
+
});
|
|
147
|
+
registered.push('explain-error-cluster');
|
|
148
|
+
// ─── weekly-error-report ─────────────────────────────────────────────────
|
|
149
|
+
server.registerPrompt('weekly-error-report', {
|
|
150
|
+
title: 'Weekly error report',
|
|
151
|
+
description: 'Сгенерируй markdown-отчёт за последние 7 дней: total, growth vs prev week, top fingerprints, регрессии, impact-priority.',
|
|
152
|
+
argsSchema: {
|
|
153
|
+
appSlug: z.string().min(1).describe('Slug приложения для отчёта.'),
|
|
154
|
+
},
|
|
155
|
+
}, async (args) => {
|
|
156
|
+
const appSlug = args.appSlug;
|
|
157
|
+
const locale = 'ru';
|
|
158
|
+
const text = [
|
|
159
|
+
`Подготовь еженедельный отчёт об ошибках для приложения ${appSlug}.`,
|
|
160
|
+
'',
|
|
161
|
+
'Окно: последние 7 дней. Сравни с предыдущей неделей.',
|
|
162
|
+
'',
|
|
163
|
+
'Шаги:',
|
|
164
|
+
'1. `error_stats_breakdown` с compareTo=previous-week.',
|
|
165
|
+
'2. `grouped_errors` take=10, sortBy=count.',
|
|
166
|
+
'3. Определи две последние версии в выборке через `error_histogram` (или прямо в фильтрах). Вызови `version_regression` baseline=prev, candidate=latest.',
|
|
167
|
+
'4. `impact_analysis` take=5 — приоритет на следующую неделю.',
|
|
168
|
+
'',
|
|
169
|
+
`Финальный отчёт (${locale}, markdown):`,
|
|
170
|
+
'',
|
|
171
|
+
`# Weekly Error Report — ${appSlug}`,
|
|
172
|
+
'**Период:** ...',
|
|
173
|
+
'**Тренд:** ↑/↓ NN%',
|
|
174
|
+
'',
|
|
175
|
+
'## Summary',
|
|
176
|
+
'- Total errors: ... (vs prev week: ...)',
|
|
177
|
+
'- Unique fingerprints: ...',
|
|
178
|
+
'- Affected users: ...',
|
|
179
|
+
'',
|
|
180
|
+
'## Top 10 проблем недели',
|
|
181
|
+
'| FP | Message | Count | trend |',
|
|
182
|
+
'|----|---------|-------|-------|',
|
|
183
|
+
'',
|
|
184
|
+
'## Регрессии (после deploy последней версии)',
|
|
185
|
+
'| FP | Message | First seen |',
|
|
186
|
+
'|----|---------|------------|',
|
|
187
|
+
'',
|
|
188
|
+
'## Приоритет на след. неделю (impact-ranked top-5)',
|
|
189
|
+
'1. ...',
|
|
190
|
+
'',
|
|
191
|
+
'## Что улучшилось',
|
|
192
|
+
'- ...',
|
|
193
|
+
'',
|
|
194
|
+
'Без emoji. Без «выводов» от себя — только данные.',
|
|
195
|
+
].join('\n');
|
|
196
|
+
return userMessage(text);
|
|
197
|
+
});
|
|
198
|
+
registered.push('weekly-error-report');
|
|
199
|
+
opts.log?.info?.({ prompts: registered }, 'MCP prompts registered');
|
|
200
|
+
return registered;
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Рекурсивная редакция структуры args / arbitrary JSON value.
|
|
3
|
+
*
|
|
4
|
+
* Для каждого string-value применяем `redactString` (regex PII). Для ключей
|
|
5
|
+
* password/token/secret/apiKey/authorization → drop value (заменяем на
|
|
6
|
+
* `[REDACTED]`). Не модифицируем исходный объект — возвращаем глубокий
|
|
7
|
+
* клон с применёнными правками.
|
|
8
|
+
*
|
|
9
|
+
* Ограничения:
|
|
10
|
+
* - Защита от циклов через Set<seen>. При обнаружении цикла подставляем
|
|
11
|
+
* строку `[CIRCULAR]`.
|
|
12
|
+
* - Защита от глубоких структур: depth-limit 16, дальше — `[TRUNCATED]`.
|
|
13
|
+
*/
|
|
14
|
+
export interface RedactResult {
|
|
15
|
+
value: unknown;
|
|
16
|
+
fieldsHit: Set<string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Главный entrypoint для редакции произвольных args / JSON value.
|
|
20
|
+
*/
|
|
21
|
+
export declare function redactValue(input: unknown): RedactResult;
|
|
22
|
+
//# sourceMappingURL=argsRedactor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"argsRedactor.d.ts","sourceRoot":"","sources":["../../src/redaction/argsRedactor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA4CH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AA8CD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAIxD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Рекурсивная редакция структуры args / arbitrary JSON value.
|
|
3
|
+
*
|
|
4
|
+
* Для каждого string-value применяем `redactString` (regex PII). Для ключей
|
|
5
|
+
* password/token/secret/apiKey/authorization → drop value (заменяем на
|
|
6
|
+
* `[REDACTED]`). Не модифицируем исходный объект — возвращаем глубокий
|
|
7
|
+
* клон с применёнными правками.
|
|
8
|
+
*
|
|
9
|
+
* Ограничения:
|
|
10
|
+
* - Защита от циклов через Set<seen>. При обнаружении цикла подставляем
|
|
11
|
+
* строку `[CIRCULAR]`.
|
|
12
|
+
* - Защита от глубоких структур: depth-limit 16, дальше — `[TRUNCATED]`.
|
|
13
|
+
*/
|
|
14
|
+
import { redactString } from './fields.js';
|
|
15
|
+
const SENSITIVE_KEYS = new Set([
|
|
16
|
+
'password',
|
|
17
|
+
'passwd',
|
|
18
|
+
'pwd',
|
|
19
|
+
'token',
|
|
20
|
+
'access_token',
|
|
21
|
+
'refresh_token',
|
|
22
|
+
'secret',
|
|
23
|
+
'apikey',
|
|
24
|
+
'api_key',
|
|
25
|
+
'authorization',
|
|
26
|
+
'cookie',
|
|
27
|
+
'set-cookie',
|
|
28
|
+
'session',
|
|
29
|
+
'csrf',
|
|
30
|
+
'private_key',
|
|
31
|
+
'client_secret',
|
|
32
|
+
'ssn',
|
|
33
|
+
'cardnumber',
|
|
34
|
+
'card_number',
|
|
35
|
+
'cvv',
|
|
36
|
+
'cvc',
|
|
37
|
+
// PII ключи — даже если значение «обычное», drop, чтобы не утекало
|
|
38
|
+
// в LLM-контекст через структурированный args. PII regex в текстовых
|
|
39
|
+
// полях обработает inline-вхождения (например, email в сообщении лога).
|
|
40
|
+
'email',
|
|
41
|
+
'mail',
|
|
42
|
+
'phone',
|
|
43
|
+
'ip',
|
|
44
|
+
'remoteaddr',
|
|
45
|
+
'remote_addr',
|
|
46
|
+
]);
|
|
47
|
+
const MAX_DEPTH = 16;
|
|
48
|
+
const REDACTED_VALUE = '[REDACTED]';
|
|
49
|
+
function isSensitiveKey(key) {
|
|
50
|
+
return SENSITIVE_KEYS.has(key.toLowerCase());
|
|
51
|
+
}
|
|
52
|
+
function redactInternal(input, fieldsHit, seen, depth) {
|
|
53
|
+
if (depth > MAX_DEPTH)
|
|
54
|
+
return '[TRUNCATED]';
|
|
55
|
+
if (input === null || input === undefined)
|
|
56
|
+
return input;
|
|
57
|
+
if (typeof input === 'string') {
|
|
58
|
+
const { value, fieldsHit: hits } = redactString(input);
|
|
59
|
+
for (const f of hits)
|
|
60
|
+
fieldsHit.add(f);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
if (typeof input === 'number' || typeof input === 'boolean' || typeof input === 'bigint') {
|
|
64
|
+
return input;
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(input)) {
|
|
67
|
+
if (seen.has(input))
|
|
68
|
+
return '[CIRCULAR]';
|
|
69
|
+
seen.add(input);
|
|
70
|
+
return input.map((v) => redactInternal(v, fieldsHit, seen, depth + 1));
|
|
71
|
+
}
|
|
72
|
+
if (typeof input === 'object') {
|
|
73
|
+
if (seen.has(input))
|
|
74
|
+
return '[CIRCULAR]';
|
|
75
|
+
seen.add(input);
|
|
76
|
+
const out = {};
|
|
77
|
+
for (const [k, v] of Object.entries(input)) {
|
|
78
|
+
if (isSensitiveKey(k)) {
|
|
79
|
+
fieldsHit.add(`key:${k.toLowerCase()}`);
|
|
80
|
+
out[k] = REDACTED_VALUE;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
out[k] = redactInternal(v, fieldsHit, seen, depth + 1);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
return input;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Главный entrypoint для редакции произвольных args / JSON value.
|
|
91
|
+
*/
|
|
92
|
+
export function redactValue(input) {
|
|
93
|
+
const fieldsHit = new Set();
|
|
94
|
+
const value = redactInternal(input, fieldsHit, new WeakSet(), 0);
|
|
95
|
+
return { value, fieldsHit };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=argsRedactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"argsRedactor.js","sourceRoot":"","sources":["../../src/redaction/argsRedactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regex-паттерны и маскировщики для PII redaction.
|
|
3
|
+
*
|
|
4
|
+
* Контракт: все функции — pure (без side effects), принимают строку и
|
|
5
|
+
* возвращают строку с применённой маской. Поведение детерминировано;
|
|
6
|
+
* порядок применения — IP → email → JWT → credit card → phone, чтобы более
|
|
7
|
+
* специфичные совпадения (например IP внутри текста) не были разрушены
|
|
8
|
+
* последующими более «жадными» regex'ами.
|
|
9
|
+
*/
|
|
10
|
+
/** IPv4: четыре октета 0–255, разделены `.`. */
|
|
11
|
+
export declare const IPV4_RE: RegExp;
|
|
12
|
+
/**
|
|
13
|
+
* IPv6 (упрощённо): 2–8 групп hex, разделённых `:`, с поддержкой `::`-сжатия.
|
|
14
|
+
* Не идеально, но покрывает типичные случаи в логах. False-positives на адресах
|
|
15
|
+
* вида `aaaa:bbbb` принимаемы — мы перестрахуемся.
|
|
16
|
+
*/
|
|
17
|
+
export declare const IPV6_RE: RegExp;
|
|
18
|
+
/** Email: local-part + @ + domain. */
|
|
19
|
+
export declare const EMAIL_RE: RegExp;
|
|
20
|
+
/**
|
|
21
|
+
* JWT: три base64url-сегмента, разделённые точкой. Начало `eyJ` (header `{"`)
|
|
22
|
+
* добавлено как anchor для снижения false-positives.
|
|
23
|
+
*/
|
|
24
|
+
export declare const JWT_RE: RegExp;
|
|
25
|
+
/** Bearer/Authorization header value. */
|
|
26
|
+
export declare const BEARER_RE: RegExp;
|
|
27
|
+
/**
|
|
28
|
+
* Phone: loose — от 8 цифр, **обязательно** с `+` префиксом или хотя бы
|
|
29
|
+
* одним разделителем (пробел / скобка / дефис). Это исключает совпадения
|
|
30
|
+
* с длинными числовыми ID и неаутентичными номерами карт.
|
|
31
|
+
*/
|
|
32
|
+
export declare const PHONE_RE: RegExp;
|
|
33
|
+
/**
|
|
34
|
+
* Credit card: 13–19 цифр с опциональными разделителями. После regex применяем
|
|
35
|
+
* Luhn-check, чтобы не маскировать обычные числовые ID.
|
|
36
|
+
*/
|
|
37
|
+
export declare const CARD_RE: RegExp;
|
|
38
|
+
/**
|
|
39
|
+
* Заменить IPv4 на «анонимизированный»: 192.168.1.42 → 192.168.1.0.
|
|
40
|
+
* IPv6 → /64 prefix (первые 4 группы + ::).
|
|
41
|
+
*/
|
|
42
|
+
export declare function maskIpv4(ip: string): string;
|
|
43
|
+
export declare function maskIpv6(ip: string): string;
|
|
44
|
+
/** Luhn algorithm для credit card validation. */
|
|
45
|
+
export declare function luhnValid(digits: string): boolean;
|
|
46
|
+
export declare const REDACTION_TOKENS: {
|
|
47
|
+
readonly ip: "[IP_REDACTED]";
|
|
48
|
+
readonly email: "[EMAIL_REDACTED]";
|
|
49
|
+
readonly jwt: "[JWT_REDACTED]";
|
|
50
|
+
readonly bearer: "[BEARER_REDACTED]";
|
|
51
|
+
readonly phone: "[PHONE_REDACTED]";
|
|
52
|
+
readonly card: "[CARD_REDACTED]";
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Применить все базовые правки к строке. Порядок важен (см. §1).
|
|
56
|
+
*
|
|
57
|
+
* Возвращает { value, fieldsHit } — массив имён полей, которые сработали
|
|
58
|
+
* (для метрик / `_meta.redactionFields`).
|
|
59
|
+
*/
|
|
60
|
+
export declare function redactString(input: string): {
|
|
61
|
+
value: string;
|
|
62
|
+
fieldsHit: string[];
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/redaction/fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,gDAAgD;AAChD,eAAO,MAAM,OAAO,QAA+E,CAAC;AAEpG;;;;GAIG;AACH,eAAO,MAAM,OAAO,QAAqI,CAAC;AAE1J,sCAAsC;AACtC,eAAO,MAAM,QAAQ,QAAoD,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,MAAM,QAAyD,CAAC;AAE7E,yCAAyC;AACzC,eAAO,MAAM,SAAS,QAAuC,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,QAAQ,QAA+E,CAAC;AAErG;;;GAGG;AACH,eAAO,MAAM,OAAO,QAA4B,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAI3C;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAK3C;AAgBD,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAejD;AAED,eAAO,MAAM,gBAAgB;;;;;;;CAOnB,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAkDlF"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regex-паттерны и маскировщики для PII redaction.
|
|
3
|
+
*
|
|
4
|
+
* Контракт: все функции — pure (без side effects), принимают строку и
|
|
5
|
+
* возвращают строку с применённой маской. Поведение детерминировано;
|
|
6
|
+
* порядок применения — IP → email → JWT → credit card → phone, чтобы более
|
|
7
|
+
* специфичные совпадения (например IP внутри текста) не были разрушены
|
|
8
|
+
* последующими более «жадными» regex'ами.
|
|
9
|
+
*/
|
|
10
|
+
/** IPv4: четыре октета 0–255, разделены `.`. */
|
|
11
|
+
export const IPV4_RE = /\b(?:(?:25[0-5]|2[0-4]\d|1?\d{1,2})\.){3}(?:25[0-5]|2[0-4]\d|1?\d{1,2})\b/g;
|
|
12
|
+
/**
|
|
13
|
+
* IPv6 (упрощённо): 2–8 групп hex, разделённых `:`, с поддержкой `::`-сжатия.
|
|
14
|
+
* Не идеально, но покрывает типичные случаи в логах. False-positives на адресах
|
|
15
|
+
* вида `aaaa:bbbb` принимаемы — мы перестрахуемся.
|
|
16
|
+
*/
|
|
17
|
+
export const IPV6_RE = /\b(?:[0-9a-fA-F]{1,4}:){2,7}[0-9a-fA-F]{1,4}\b|\b(?:[0-9a-fA-F]{1,4}:){1,7}:\b|\b::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\b/g;
|
|
18
|
+
/** Email: local-part + @ + domain. */
|
|
19
|
+
export const EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
20
|
+
/**
|
|
21
|
+
* JWT: три base64url-сегмента, разделённые точкой. Начало `eyJ` (header `{"`)
|
|
22
|
+
* добавлено как anchor для снижения false-positives.
|
|
23
|
+
*/
|
|
24
|
+
export const JWT_RE = /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
25
|
+
/** Bearer/Authorization header value. */
|
|
26
|
+
export const BEARER_RE = /\b[Bb]earer\s+[A-Za-z0-9._\-+/=]+/g;
|
|
27
|
+
/**
|
|
28
|
+
* Phone: loose — от 8 цифр, **обязательно** с `+` префиксом или хотя бы
|
|
29
|
+
* одним разделителем (пробел / скобка / дефис). Это исключает совпадения
|
|
30
|
+
* с длинными числовыми ID и неаутентичными номерами карт.
|
|
31
|
+
*/
|
|
32
|
+
export const PHONE_RE = /(?<![\d])(?:\+\d[\d\s()\-]{6,}\d|\d{1,4}[\s\-()][\d\s()\-]{5,}\d)(?![\d])/g;
|
|
33
|
+
/**
|
|
34
|
+
* Credit card: 13–19 цифр с опциональными разделителями. После regex применяем
|
|
35
|
+
* Luhn-check, чтобы не маскировать обычные числовые ID.
|
|
36
|
+
*/
|
|
37
|
+
export const CARD_RE = /\b(?:\d[ -]?){13,19}\b/g;
|
|
38
|
+
/**
|
|
39
|
+
* Заменить IPv4 на «анонимизированный»: 192.168.1.42 → 192.168.1.0.
|
|
40
|
+
* IPv6 → /64 prefix (первые 4 группы + ::).
|
|
41
|
+
*/
|
|
42
|
+
export function maskIpv4(ip) {
|
|
43
|
+
const parts = ip.split('.');
|
|
44
|
+
if (parts.length !== 4)
|
|
45
|
+
return ip;
|
|
46
|
+
return `${parts[0]}.${parts[1]}.${parts[2]}.0`;
|
|
47
|
+
}
|
|
48
|
+
export function maskIpv6(ip) {
|
|
49
|
+
// Раскрыть `::`-сжатие до 8 групп, взять первые 4, склеить обратно с `::`.
|
|
50
|
+
const expanded = expandIpv6(ip);
|
|
51
|
+
if (!expanded)
|
|
52
|
+
return ip;
|
|
53
|
+
return `${expanded.slice(0, 4).join(':')}::/64`;
|
|
54
|
+
}
|
|
55
|
+
function expandIpv6(ip) {
|
|
56
|
+
if (!ip.includes(':'))
|
|
57
|
+
return null;
|
|
58
|
+
const [head, tail] = ip.split('::');
|
|
59
|
+
const headParts = head ? head.split(':') : [];
|
|
60
|
+
const tailParts = tail ? tail.split(':') : [];
|
|
61
|
+
const missing = 8 - headParts.length - tailParts.length;
|
|
62
|
+
if (missing < 0)
|
|
63
|
+
return null;
|
|
64
|
+
if (ip.includes('::')) {
|
|
65
|
+
return [...headParts, ...Array(missing).fill('0'), ...tailParts];
|
|
66
|
+
}
|
|
67
|
+
if (headParts.length !== 8)
|
|
68
|
+
return null;
|
|
69
|
+
return headParts;
|
|
70
|
+
}
|
|
71
|
+
/** Luhn algorithm для credit card validation. */
|
|
72
|
+
export function luhnValid(digits) {
|
|
73
|
+
const clean = digits.replace(/\D/g, '');
|
|
74
|
+
if (clean.length < 13 || clean.length > 19)
|
|
75
|
+
return false;
|
|
76
|
+
let sum = 0;
|
|
77
|
+
let alt = false;
|
|
78
|
+
for (let i = clean.length - 1; i >= 0; i--) {
|
|
79
|
+
let n = parseInt(clean.charAt(i), 10);
|
|
80
|
+
if (alt) {
|
|
81
|
+
n *= 2;
|
|
82
|
+
if (n > 9)
|
|
83
|
+
n -= 9;
|
|
84
|
+
}
|
|
85
|
+
sum += n;
|
|
86
|
+
alt = !alt;
|
|
87
|
+
}
|
|
88
|
+
return sum % 10 === 0;
|
|
89
|
+
}
|
|
90
|
+
export const REDACTION_TOKENS = {
|
|
91
|
+
ip: '[IP_REDACTED]',
|
|
92
|
+
email: '[EMAIL_REDACTED]',
|
|
93
|
+
jwt: '[JWT_REDACTED]',
|
|
94
|
+
bearer: '[BEARER_REDACTED]',
|
|
95
|
+
phone: '[PHONE_REDACTED]',
|
|
96
|
+
card: '[CARD_REDACTED]',
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Применить все базовые правки к строке. Порядок важен (см. §1).
|
|
100
|
+
*
|
|
101
|
+
* Возвращает { value, fieldsHit } — массив имён полей, которые сработали
|
|
102
|
+
* (для метрик / `_meta.redactionFields`).
|
|
103
|
+
*/
|
|
104
|
+
export function redactString(input) {
|
|
105
|
+
if (typeof input !== 'string' || input.length === 0) {
|
|
106
|
+
return { value: input, fieldsHit: [] };
|
|
107
|
+
}
|
|
108
|
+
const fieldsHit = new Set();
|
|
109
|
+
let out = input;
|
|
110
|
+
// IPv6 первым — он не пересекается с другими ID'шками так часто, как IPv4.
|
|
111
|
+
out = out.replace(IPV6_RE, (m) => {
|
|
112
|
+
const masked = maskIpv6(m);
|
|
113
|
+
if (masked !== m) {
|
|
114
|
+
fieldsHit.add('ip');
|
|
115
|
+
return masked;
|
|
116
|
+
}
|
|
117
|
+
return m;
|
|
118
|
+
});
|
|
119
|
+
out = out.replace(IPV4_RE, (m) => {
|
|
120
|
+
fieldsHit.add('ip');
|
|
121
|
+
return maskIpv4(m);
|
|
122
|
+
});
|
|
123
|
+
out = out.replace(JWT_RE, () => {
|
|
124
|
+
fieldsHit.add('jwt');
|
|
125
|
+
return REDACTION_TOKENS.jwt;
|
|
126
|
+
});
|
|
127
|
+
out = out.replace(BEARER_RE, () => {
|
|
128
|
+
fieldsHit.add('bearer');
|
|
129
|
+
return REDACTION_TOKENS.bearer;
|
|
130
|
+
});
|
|
131
|
+
out = out.replace(EMAIL_RE, () => {
|
|
132
|
+
fieldsHit.add('email');
|
|
133
|
+
return REDACTION_TOKENS.email;
|
|
134
|
+
});
|
|
135
|
+
out = out.replace(CARD_RE, (m) => {
|
|
136
|
+
if (luhnValid(m)) {
|
|
137
|
+
fieldsHit.add('card');
|
|
138
|
+
return REDACTION_TOKENS.card;
|
|
139
|
+
}
|
|
140
|
+
return m;
|
|
141
|
+
});
|
|
142
|
+
out = out.replace(PHONE_RE, (m) => {
|
|
143
|
+
// Игнорим, если в найденной подстроке уже подменили IP/Card/etc.
|
|
144
|
+
if (m.includes('[') && m.includes('_REDACTED]'))
|
|
145
|
+
return m;
|
|
146
|
+
// Минимум 8 цифр.
|
|
147
|
+
const digits = m.replace(/\D/g, '');
|
|
148
|
+
if (digits.length < 8)
|
|
149
|
+
return m;
|
|
150
|
+
fieldsHit.add('phone');
|
|
151
|
+
return REDACTION_TOKENS.phone;
|
|
152
|
+
});
|
|
153
|
+
return { value: out, fieldsHit: Array.from(fieldsHit) };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/redaction/fields.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline редакции ErrorLog items перед возвратом из tools.
|
|
3
|
+
*
|
|
4
|
+
* Контракт:
|
|
5
|
+
* - Не мутирует исходный объект, возвращает плоский клон.
|
|
6
|
+
* - Применяет PII regex ко всем string-полям (включая компактные варианты).
|
|
7
|
+
* - Анонимизирует `ip` (last octet → 0 для IPv4, /64 для IPv6).
|
|
8
|
+
* - Усекает `userAgent` до family.
|
|
9
|
+
* - Strip query из `url` и `referrer`.
|
|
10
|
+
* - Оборачивает `message`/`stack` в `<untrusted>...</untrusted>` для compact/full форматов.
|
|
11
|
+
* - Считает `suspiciousContent` по deny-list (см. promptInjection.ts).
|
|
12
|
+
*
|
|
13
|
+
* Конфиг управляется ENV (см. src/config.ts):
|
|
14
|
+
* - MCP_REDACTION_ENABLED (default true)
|
|
15
|
+
* - MCP_REDACTION_FIELDS (csv override — например `email,phone,jwt`)
|
|
16
|
+
*/
|
|
17
|
+
export interface RedactionConfig {
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
/** Опциональный whitelist полей. Если задан — применяем только их. */
|
|
20
|
+
fields?: Set<string>;
|
|
21
|
+
/** Оборачивать ли строковые поля в <untrusted> при выводе. Default true. */
|
|
22
|
+
wrapUntrusted?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface RedactionStats {
|
|
25
|
+
fieldsHit: string[];
|
|
26
|
+
suspiciousContentBlocked: boolean;
|
|
27
|
+
suspiciousRule?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare const DEFAULT_REDACTION_CONFIG: RedactionConfig;
|
|
30
|
+
export interface RedactItemOptions {
|
|
31
|
+
config?: RedactionConfig;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Редактирует один ErrorLog (или его compact-вариант). Возвращает новый объект.
|
|
35
|
+
*/
|
|
36
|
+
export declare function redactErrorLog<T extends Record<string, unknown>>(log: T, opts?: RedactItemOptions): {
|
|
37
|
+
value: T;
|
|
38
|
+
stats: RedactionStats;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Массовая редакция items. Объединяет stats по всем.
|
|
42
|
+
*/
|
|
43
|
+
export declare function redactErrorLogs<T extends Record<string, unknown>>(logs: T[], opts?: RedactItemOptions): {
|
|
44
|
+
items: T[];
|
|
45
|
+
stats: RedactionStats;
|
|
46
|
+
};
|
|
47
|
+
export { redactValue } from './argsRedactor.js';
|
|
48
|
+
export { wrapUntrusted, detectSuspicious, containsSuspicious } from './promptInjection.js';
|
|
49
|
+
export { userAgentFamily } from './userAgent.js';
|
|
50
|
+
export { stripUrlQuery } from './url.js';
|
|
51
|
+
export { redactString } from './fields.js';
|
|
52
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/redaction/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wBAAwB,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAC;AA2BF,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,GAAG,EAAE,CAAC,EACN,IAAI,GAAE,iBAAsB,GAC3B;IAAE,KAAK,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CA2ErC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,IAAI,EAAE,CAAC,EAAE,EACT,IAAI,GAAE,iBAAsB,GAC3B;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAiBvC;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|