@dotsetlabs/tollgate 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/LICENSE +21 -0
- package/README.md +885 -0
- package/dist/analyzers/filesystem.d.ts +26 -0
- package/dist/analyzers/filesystem.d.ts.map +1 -0
- package/dist/analyzers/filesystem.js +284 -0
- package/dist/analyzers/filesystem.js.map +1 -0
- package/dist/analyzers/http.d.ts +90 -0
- package/dist/analyzers/http.d.ts.map +1 -0
- package/dist/analyzers/http.js +433 -0
- package/dist/analyzers/http.js.map +1 -0
- package/dist/analyzers/index.d.ts +101 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +342 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/loader.d.ts +114 -0
- package/dist/analyzers/loader.d.ts.map +1 -0
- package/dist/analyzers/loader.js +184 -0
- package/dist/analyzers/loader.js.map +1 -0
- package/dist/analyzers/prompt-injection.d.ts +95 -0
- package/dist/analyzers/prompt-injection.d.ts.map +1 -0
- package/dist/analyzers/prompt-injection.js +725 -0
- package/dist/analyzers/prompt-injection.js.map +1 -0
- package/dist/analyzers/sdk.d.ts +230 -0
- package/dist/analyzers/sdk.d.ts.map +1 -0
- package/dist/analyzers/sdk.js +283 -0
- package/dist/analyzers/sdk.js.map +1 -0
- package/dist/analyzers/shell.d.ts +20 -0
- package/dist/analyzers/shell.d.ts.map +1 -0
- package/dist/analyzers/shell.js +297 -0
- package/dist/analyzers/shell.js.map +1 -0
- package/dist/analyzers/sql.d.ts +37 -0
- package/dist/analyzers/sql.d.ts.map +1 -0
- package/dist/analyzers/sql.js +455 -0
- package/dist/analyzers/sql.js.map +1 -0
- package/dist/analyzers/types.d.ts +117 -0
- package/dist/analyzers/types.d.ts.map +1 -0
- package/dist/analyzers/types.js +46 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/approval/interactive.d.ts +72 -0
- package/dist/approval/interactive.d.ts.map +1 -0
- package/dist/approval/interactive.js +550 -0
- package/dist/approval/interactive.js.map +1 -0
- package/dist/approval/terminal.d.ts +59 -0
- package/dist/approval/terminal.d.ts.map +1 -0
- package/dist/approval/terminal.js +238 -0
- package/dist/approval/terminal.js.map +1 -0
- package/dist/approval/types.d.ts +66 -0
- package/dist/approval/types.d.ts.map +1 -0
- package/dist/approval/types.js +2 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/audit/exporter.d.ts +138 -0
- package/dist/audit/exporter.d.ts.map +1 -0
- package/dist/audit/exporter.js +366 -0
- package/dist/audit/exporter.js.map +1 -0
- package/dist/audit/logger.d.ts +156 -0
- package/dist/audit/logger.d.ts.map +1 -0
- package/dist/audit/logger.js +406 -0
- package/dist/audit/logger.js.map +1 -0
- package/dist/audit/redaction.d.ts +110 -0
- package/dist/audit/redaction.d.ts.map +1 -0
- package/dist/audit/redaction.js +307 -0
- package/dist/audit/redaction.js.map +1 -0
- package/dist/audit/schema.d.ts +76 -0
- package/dist/audit/schema.d.ts.map +1 -0
- package/dist/audit/schema.js +122 -0
- package/dist/audit/schema.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +34 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +431 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export.d.ts +18 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +63 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/init.d.ts +12 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +102 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/logs.d.ts +11 -0
- package/dist/cli/commands/logs.d.ts.map +1 -0
- package/dist/cli/commands/logs.js +60 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +29 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +251 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +26 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +424 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/start.d.ts +20 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +82 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +10 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +42 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/templates.d.ts +26 -0
- package/dist/cli/commands/templates.d.ts.map +1 -0
- package/dist/cli/commands/templates.js +221 -0
- package/dist/cli/commands/templates.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +12 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +107 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/commands/wrap.d.ts +19 -0
- package/dist/cli/commands/wrap.d.ts.map +1 -0
- package/dist/cli/commands/wrap.js +59 -0
- package/dist/cli/commands/wrap.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +202 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui.d.ts +139 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +271 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/constants.d.ts +33 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +54 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +28 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +37 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator/index.d.ts +11 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +10 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/manager.d.ts +127 -0
- package/dist/orchestrator/manager.d.ts.map +1 -0
- package/dist/orchestrator/manager.js +498 -0
- package/dist/orchestrator/manager.js.map +1 -0
- package/dist/orchestrator/types.d.ts +141 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +9 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/policy/engine.d.ts +55 -0
- package/dist/policy/engine.d.ts.map +1 -0
- package/dist/policy/engine.js +288 -0
- package/dist/policy/engine.js.map +1 -0
- package/dist/policy/natural-language.d.ts +141 -0
- package/dist/policy/natural-language.d.ts.map +1 -0
- package/dist/policy/natural-language.js +552 -0
- package/dist/policy/natural-language.js.map +1 -0
- package/dist/policy/parser.d.ts +141 -0
- package/dist/policy/parser.d.ts.map +1 -0
- package/dist/policy/parser.js +314 -0
- package/dist/policy/parser.js.map +1 -0
- package/dist/policy/types.d.ts +428 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +32 -0
- package/dist/policy/types.js.map +1 -0
- package/dist/policy/validator.d.ts +72 -0
- package/dist/policy/validator.d.ts.map +1 -0
- package/dist/policy/validator.js +453 -0
- package/dist/policy/validator.js.map +1 -0
- package/dist/proxy/bridge.d.ts +84 -0
- package/dist/proxy/bridge.d.ts.map +1 -0
- package/dist/proxy/bridge.js +217 -0
- package/dist/proxy/bridge.js.map +1 -0
- package/dist/proxy/client.d.ts +130 -0
- package/dist/proxy/client.d.ts.map +1 -0
- package/dist/proxy/client.js +290 -0
- package/dist/proxy/client.js.map +1 -0
- package/dist/proxy/server.d.ts +111 -0
- package/dist/proxy/server.d.ts.map +1 -0
- package/dist/proxy/server.js +444 -0
- package/dist/proxy/server.js.map +1 -0
- package/dist/scanner.d.ts +91 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +373 -0
- package/dist/scanner.js.map +1 -0
- package/dist/session/index.d.ts +32 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +31 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +166 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +454 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/sqlite-store.d.ts +54 -0
- package/dist/session/sqlite-store.d.ts.map +1 -0
- package/dist/session/sqlite-store.js +209 -0
- package/dist/session/sqlite-store.js.map +1 -0
- package/dist/session/types.d.ts +179 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +38 -0
- package/dist/session/types.js.map +1 -0
- package/dist/templates.d.ts +64 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +451 -0
- package/dist/templates.js.map +1 -0
- package/dist/utils/config.d.ts +57 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +104 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/errors.d.ts +18 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +35 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +144 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +300 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/wizard.d.ts +68 -0
- package/dist/wizard.d.ts.map +1 -0
- package/dist/wizard.js +395 -0
- package/dist/wizard.js.map +1 -0
- package/package.json +99 -0
package/dist/scanner.js
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Scanner
|
|
3
|
+
*
|
|
4
|
+
* Scans MCP servers to discover tools and assess security risks.
|
|
5
|
+
* Spawns the server, calls tools/list, analyzes tool definitions,
|
|
6
|
+
* and generates recommended security policies.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* tollgate scan @modelcontextprotocol/server-postgres
|
|
10
|
+
* tollgate scan npx -y @anthropic/mcp-server-filesystem ./
|
|
11
|
+
*
|
|
12
|
+
* @module scanner
|
|
13
|
+
*/
|
|
14
|
+
import { UpstreamClient } from './proxy/client.js';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Risk Analysis Engine
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Keywords indicating read-only operations.
|
|
20
|
+
*/
|
|
21
|
+
const READ_KEYWORDS = [
|
|
22
|
+
'get', 'list', 'read', 'fetch', 'query', 'search', 'find', 'show', 'describe',
|
|
23
|
+
'view', 'retrieve', 'lookup', 'check', 'info', 'status', 'history', 'log',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Keywords indicating write operations.
|
|
27
|
+
*/
|
|
28
|
+
const WRITE_KEYWORDS = [
|
|
29
|
+
'create', 'add', 'insert', 'update', 'modify', 'edit', 'set', 'put', 'post',
|
|
30
|
+
'write', 'upload', 'send', 'push', 'publish', 'save', 'store', 'append',
|
|
31
|
+
'move', 'rename', 'copy', 'enable', 'disable', 'configure',
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Keywords indicating destructive operations.
|
|
35
|
+
*/
|
|
36
|
+
const DESTRUCTIVE_KEYWORDS = [
|
|
37
|
+
'delete', 'remove', 'drop', 'truncate', 'clear', 'purge', 'destroy', 'erase',
|
|
38
|
+
'revoke', 'terminate', 'kill', 'reset', 'wipe', 'archive', 'trash',
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Keywords indicating dangerous operations.
|
|
42
|
+
*/
|
|
43
|
+
const DANGEROUS_KEYWORDS = [
|
|
44
|
+
'execute', 'run', 'eval', 'exec', 'shell', 'command', 'script', 'sudo',
|
|
45
|
+
'admin', 'root', 'system', 'raw', 'arbitrary', 'inject', 'grant', 'permission',
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Parameter names indicating sensitive input.
|
|
49
|
+
*/
|
|
50
|
+
const DANGEROUS_PARAMETERS = [
|
|
51
|
+
'sql', 'query', 'command', 'script', 'code', 'shell', 'exec', 'path',
|
|
52
|
+
'file', 'url', 'endpoint', 'password', 'secret', 'token', 'key',
|
|
53
|
+
];
|
|
54
|
+
/**
|
|
55
|
+
* Tool name patterns mapped to recommended analyzers.
|
|
56
|
+
*/
|
|
57
|
+
const ANALYZER_PATTERNS = [
|
|
58
|
+
{ pattern: /sql|query|database|postgres|mysql|sqlite/i, analyzer: 'sql' },
|
|
59
|
+
{ pattern: /file|path|directory|folder|read|write|fs/i, analyzer: 'filesystem' },
|
|
60
|
+
{ pattern: /shell|command|exec|run|bash|terminal/i, analyzer: 'shell' },
|
|
61
|
+
{ pattern: /http|fetch|request|api|url|web|browse/i, analyzer: 'http' },
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Analyze a single tool definition to assess its risk.
|
|
65
|
+
*/
|
|
66
|
+
export function analyzeTool(tool) {
|
|
67
|
+
const indicators = [];
|
|
68
|
+
const name = tool.name.toLowerCase();
|
|
69
|
+
const description = (tool.description ?? '').toLowerCase();
|
|
70
|
+
const combined = `${name} ${description}`;
|
|
71
|
+
// Helper function to check for word boundary matches (not substring matches)
|
|
72
|
+
const matchesKeyword = (text, keyword) => {
|
|
73
|
+
// Match keyword as a word or at word boundaries (handles underscores, camelCase breaks)
|
|
74
|
+
const pattern = new RegExp(`(?:^|[_\\s])${keyword}(?:[_\\s]|$)`, 'i');
|
|
75
|
+
return pattern.test(text) || text.startsWith(keyword) || text.endsWith(keyword);
|
|
76
|
+
};
|
|
77
|
+
// Check for dangerous keywords first (highest priority)
|
|
78
|
+
for (const keyword of DANGEROUS_KEYWORDS) {
|
|
79
|
+
if (matchesKeyword(combined, keyword)) {
|
|
80
|
+
indicators.push({
|
|
81
|
+
type: 'keyword',
|
|
82
|
+
value: keyword,
|
|
83
|
+
risk: 'dangerous',
|
|
84
|
+
description: `Contains dangerous keyword: "${keyword}"`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Check for destructive keywords
|
|
89
|
+
for (const keyword of DESTRUCTIVE_KEYWORDS) {
|
|
90
|
+
if (matchesKeyword(combined, keyword)) {
|
|
91
|
+
indicators.push({
|
|
92
|
+
type: 'keyword',
|
|
93
|
+
value: keyword,
|
|
94
|
+
risk: 'destructive',
|
|
95
|
+
description: `Contains destructive keyword: "${keyword}"`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Check for write keywords
|
|
100
|
+
for (const keyword of WRITE_KEYWORDS) {
|
|
101
|
+
if (matchesKeyword(name, keyword)) {
|
|
102
|
+
indicators.push({
|
|
103
|
+
type: 'keyword',
|
|
104
|
+
value: keyword,
|
|
105
|
+
risk: 'write',
|
|
106
|
+
description: `Tool name suggests write operation: "${keyword}"`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Check for read keywords
|
|
111
|
+
for (const keyword of READ_KEYWORDS) {
|
|
112
|
+
if (matchesKeyword(name, keyword)) {
|
|
113
|
+
indicators.push({
|
|
114
|
+
type: 'keyword',
|
|
115
|
+
value: keyword,
|
|
116
|
+
risk: 'read',
|
|
117
|
+
description: `Tool name suggests read operation: "${keyword}"`,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Check input schema for dangerous parameters
|
|
122
|
+
if (tool.inputSchema && typeof tool.inputSchema === 'object') {
|
|
123
|
+
const schema = tool.inputSchema;
|
|
124
|
+
const properties = (schema.properties ?? {});
|
|
125
|
+
for (const paramName of Object.keys(properties)) {
|
|
126
|
+
const lowerParam = paramName.toLowerCase();
|
|
127
|
+
for (const dangerous of DANGEROUS_PARAMETERS) {
|
|
128
|
+
if (lowerParam.includes(dangerous)) {
|
|
129
|
+
indicators.push({
|
|
130
|
+
type: 'parameter',
|
|
131
|
+
value: paramName,
|
|
132
|
+
risk: 'write',
|
|
133
|
+
description: `Has potentially sensitive parameter: "${paramName}"`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Determine overall risk level (highest indicator wins)
|
|
140
|
+
let risk = 'safe';
|
|
141
|
+
const riskOrder = ['safe', 'read', 'write', 'destructive', 'dangerous'];
|
|
142
|
+
for (const indicator of indicators) {
|
|
143
|
+
if (riskOrder.indexOf(indicator.risk) > riskOrder.indexOf(risk)) {
|
|
144
|
+
risk = indicator.risk;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Determine category
|
|
148
|
+
let category = 'unknown';
|
|
149
|
+
if (risk === 'dangerous') {
|
|
150
|
+
category = 'admin';
|
|
151
|
+
}
|
|
152
|
+
else if (risk === 'destructive' || risk === 'write') {
|
|
153
|
+
category = 'write';
|
|
154
|
+
}
|
|
155
|
+
else if (risk === 'read') {
|
|
156
|
+
category = 'read';
|
|
157
|
+
}
|
|
158
|
+
// Determine recommended action
|
|
159
|
+
let recommendedAction = 'prompt';
|
|
160
|
+
switch (risk) {
|
|
161
|
+
case 'safe':
|
|
162
|
+
recommendedAction = 'allow';
|
|
163
|
+
break;
|
|
164
|
+
case 'read':
|
|
165
|
+
recommendedAction = 'allow';
|
|
166
|
+
break;
|
|
167
|
+
case 'write':
|
|
168
|
+
recommendedAction = 'prompt';
|
|
169
|
+
break;
|
|
170
|
+
case 'destructive':
|
|
171
|
+
recommendedAction = 'deny';
|
|
172
|
+
break;
|
|
173
|
+
case 'dangerous':
|
|
174
|
+
recommendedAction = 'deny';
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
// Check if smart analysis is available
|
|
178
|
+
let recommendedAnalyzer;
|
|
179
|
+
for (const { pattern, analyzer } of ANALYZER_PATTERNS) {
|
|
180
|
+
if (pattern.test(combined)) {
|
|
181
|
+
recommendedAnalyzer = analyzer;
|
|
182
|
+
// If we have an analyzer, suggest smart action for write operations
|
|
183
|
+
if (risk === 'write' || risk === 'destructive') {
|
|
184
|
+
recommendedAction = 'smart';
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
name: tool.name,
|
|
191
|
+
description: tool.description ?? '',
|
|
192
|
+
risk,
|
|
193
|
+
category,
|
|
194
|
+
indicators,
|
|
195
|
+
recommendedAction,
|
|
196
|
+
recommendedAnalyzer,
|
|
197
|
+
inputSchema: tool.inputSchema,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Calculate overall risk from analyzed tools.
|
|
202
|
+
*/
|
|
203
|
+
function calculateOverallRisk(tools) {
|
|
204
|
+
const riskOrder = ['safe', 'read', 'write', 'destructive', 'dangerous'];
|
|
205
|
+
let maxRisk = 'safe';
|
|
206
|
+
for (const tool of tools) {
|
|
207
|
+
if (riskOrder.indexOf(tool.risk) > riskOrder.indexOf(maxRisk)) {
|
|
208
|
+
maxRisk = tool.risk;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return maxRisk;
|
|
212
|
+
}
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// Scanner
|
|
215
|
+
// ============================================================================
|
|
216
|
+
/**
|
|
217
|
+
* Scan an MCP server to discover tools and assess security risks.
|
|
218
|
+
*
|
|
219
|
+
* @param command - Server command (e.g., "npx")
|
|
220
|
+
* @param args - Server arguments (e.g., ["-y", "@modelcontextprotocol/server-postgres"])
|
|
221
|
+
* @param options - Scanner options
|
|
222
|
+
* @returns Scan result with tool analysis
|
|
223
|
+
*/
|
|
224
|
+
export async function scanServer(command, args, options = {}) {
|
|
225
|
+
const timeoutMs = options.timeoutMs ?? 30000;
|
|
226
|
+
// Create upstream client
|
|
227
|
+
const client = new UpstreamClient({
|
|
228
|
+
config: {
|
|
229
|
+
command,
|
|
230
|
+
args,
|
|
231
|
+
env: options.env,
|
|
232
|
+
},
|
|
233
|
+
callTimeoutMs: timeoutMs,
|
|
234
|
+
healthCheck: { enabled: false },
|
|
235
|
+
});
|
|
236
|
+
try {
|
|
237
|
+
// Initialize connection (spawns server)
|
|
238
|
+
await client.initialize();
|
|
239
|
+
// List all tools
|
|
240
|
+
const toolsResult = await client.listTools();
|
|
241
|
+
const tools = toolsResult.tools ?? [];
|
|
242
|
+
// Analyze each tool
|
|
243
|
+
const analyzedTools = tools.map(analyzeTool);
|
|
244
|
+
// Calculate summary
|
|
245
|
+
const summary = {
|
|
246
|
+
safe: analyzedTools.filter((t) => t.risk === 'safe').length,
|
|
247
|
+
read: analyzedTools.filter((t) => t.risk === 'read').length,
|
|
248
|
+
write: analyzedTools.filter((t) => t.risk === 'write').length,
|
|
249
|
+
destructive: analyzedTools.filter((t) => t.risk === 'destructive').length,
|
|
250
|
+
dangerous: analyzedTools.filter((t) => t.risk === 'dangerous').length,
|
|
251
|
+
};
|
|
252
|
+
return {
|
|
253
|
+
serverCommand: command,
|
|
254
|
+
serverArgs: args,
|
|
255
|
+
scanTime: new Date(),
|
|
256
|
+
toolCount: tools.length,
|
|
257
|
+
tools: analyzedTools,
|
|
258
|
+
overallRisk: calculateOverallRisk(analyzedTools),
|
|
259
|
+
summary,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
// Always close the client
|
|
264
|
+
await client.close();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// Policy Generation
|
|
269
|
+
// ============================================================================
|
|
270
|
+
/**
|
|
271
|
+
* Generate a tollgate.yaml policy configuration from scan results.
|
|
272
|
+
*/
|
|
273
|
+
export function generatePolicy(scanResult, serverName = 'scanned-server') {
|
|
274
|
+
const lines = [
|
|
275
|
+
'# Tollgate Configuration',
|
|
276
|
+
'# Generated by `tollgate scan`',
|
|
277
|
+
'# Review and customize before use',
|
|
278
|
+
'',
|
|
279
|
+
'version: "1"',
|
|
280
|
+
'',
|
|
281
|
+
'defaults:',
|
|
282
|
+
' action: prompt',
|
|
283
|
+
' timeout: 60000',
|
|
284
|
+
'',
|
|
285
|
+
'servers:',
|
|
286
|
+
` ${serverName}:`,
|
|
287
|
+
` command: "${scanResult.serverCommand}"`,
|
|
288
|
+
` args: [${scanResult.serverArgs.map((a) => `"${a}"`).join(', ')}]`,
|
|
289
|
+
'',
|
|
290
|
+
' tools:',
|
|
291
|
+
];
|
|
292
|
+
// Determine if we should use an analyzer
|
|
293
|
+
const analyzers = new Set(scanResult.tools.map((t) => t.recommendedAnalyzer).filter(Boolean));
|
|
294
|
+
const primaryAnalyzer = analyzers.size === 1 ? [...analyzers][0] : undefined;
|
|
295
|
+
if (primaryAnalyzer) {
|
|
296
|
+
lines.push(' defaults:');
|
|
297
|
+
lines.push(` analyzer: ${primaryAnalyzer}`);
|
|
298
|
+
lines.push('');
|
|
299
|
+
lines.push(' tools:');
|
|
300
|
+
}
|
|
301
|
+
// Group tools by recommended action
|
|
302
|
+
const byAction = {
|
|
303
|
+
allow: scanResult.tools.filter((t) => t.recommendedAction === 'allow'),
|
|
304
|
+
prompt: scanResult.tools.filter((t) => t.recommendedAction === 'prompt'),
|
|
305
|
+
smart: scanResult.tools.filter((t) => t.recommendedAction === 'smart'),
|
|
306
|
+
deny: scanResult.tools.filter((t) => t.recommendedAction === 'deny'),
|
|
307
|
+
};
|
|
308
|
+
// Add allow rules
|
|
309
|
+
if (byAction.allow.length > 0) {
|
|
310
|
+
lines.push(' # Read-only operations (safe)');
|
|
311
|
+
for (const tool of byAction.allow) {
|
|
312
|
+
lines.push(` "${tool.name}":`);
|
|
313
|
+
lines.push(' action: allow');
|
|
314
|
+
}
|
|
315
|
+
lines.push('');
|
|
316
|
+
}
|
|
317
|
+
// Add smart rules
|
|
318
|
+
if (byAction.smart.length > 0) {
|
|
319
|
+
lines.push(' # Write operations (with smart analysis)');
|
|
320
|
+
for (const tool of byAction.smart) {
|
|
321
|
+
lines.push(` "${tool.name}":`);
|
|
322
|
+
lines.push(' action: smart');
|
|
323
|
+
if (tool.recommendedAnalyzer) {
|
|
324
|
+
lines.push(` analyzer: ${tool.recommendedAnalyzer}`);
|
|
325
|
+
}
|
|
326
|
+
lines.push(' risks:');
|
|
327
|
+
lines.push(' read: allow');
|
|
328
|
+
lines.push(' write: prompt');
|
|
329
|
+
lines.push(' destructive: deny');
|
|
330
|
+
lines.push(' dangerous: deny');
|
|
331
|
+
}
|
|
332
|
+
lines.push('');
|
|
333
|
+
}
|
|
334
|
+
// Add prompt rules
|
|
335
|
+
if (byAction.prompt.length > 0) {
|
|
336
|
+
lines.push(' # Write operations (require approval)');
|
|
337
|
+
for (const tool of byAction.prompt) {
|
|
338
|
+
lines.push(` "${tool.name}":`);
|
|
339
|
+
lines.push(' action: prompt');
|
|
340
|
+
lines.push(` message: "Agent wants to run ${tool.name}"`);
|
|
341
|
+
}
|
|
342
|
+
lines.push('');
|
|
343
|
+
}
|
|
344
|
+
// Add deny rules
|
|
345
|
+
if (byAction.deny.length > 0) {
|
|
346
|
+
lines.push(' # Dangerous operations (blocked)');
|
|
347
|
+
for (const tool of byAction.deny) {
|
|
348
|
+
lines.push(` "${tool.name}":`);
|
|
349
|
+
lines.push(' action: deny');
|
|
350
|
+
lines.push(` reason: "${tool.risk === 'dangerous' ? 'Dangerous operation blocked' : 'Destructive operation blocked'}"`);
|
|
351
|
+
}
|
|
352
|
+
lines.push('');
|
|
353
|
+
}
|
|
354
|
+
// Add catch-all
|
|
355
|
+
lines.push(' # Catch-all for unknown tools');
|
|
356
|
+
lines.push(' "*":');
|
|
357
|
+
lines.push(' action: prompt');
|
|
358
|
+
return lines.join('\n');
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Generate a partial config to append to existing tollgate.yaml.
|
|
362
|
+
*/
|
|
363
|
+
export function generateServerConfig(scanResult, serverName = 'scanned-server') {
|
|
364
|
+
// Generate full config then extract just the server section
|
|
365
|
+
const fullConfig = generatePolicy(scanResult, serverName);
|
|
366
|
+
const lines = fullConfig.split('\n');
|
|
367
|
+
// Find the servers: section and return from there
|
|
368
|
+
const serverIndex = lines.findIndex((l) => l.startsWith('servers:'));
|
|
369
|
+
if (serverIndex === -1)
|
|
370
|
+
return fullConfig;
|
|
371
|
+
return lines.slice(serverIndex).join('\n');
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session module for Tollgate
|
|
3
|
+
*
|
|
4
|
+
* Provides session-based approval management, allowing users to grant
|
|
5
|
+
* time-bounded permissions for tool calls.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { SessionManager, type SessionGrant } from './session/index.js';
|
|
10
|
+
*
|
|
11
|
+
* const manager = new SessionManager();
|
|
12
|
+
*
|
|
13
|
+
* // Create grant on approval
|
|
14
|
+
* const grant = manager.createGrant({
|
|
15
|
+
* context,
|
|
16
|
+
* scope: 'tool',
|
|
17
|
+
* duration: '5min',
|
|
18
|
+
* grantedBy: 'terminal',
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Check before prompting
|
|
22
|
+
* const result = manager.checkGrant(context);
|
|
23
|
+
* if (result.granted) {
|
|
24
|
+
* // Skip prompt, use cached approval
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export { SessionManager, InMemorySessionStore } from './manager.js';
|
|
29
|
+
export { SqliteSessionStore } from './sqlite-store.js';
|
|
30
|
+
export type { SessionScope, SessionDuration, SessionGrant, CreateSessionGrantInput, SessionCheckResult, SessionPolicyConfig, SessionStats, SessionStore, } from './types.js';
|
|
31
|
+
export { durationToTtlSeconds, DEFAULT_SESSION_CONFIG, } from './types.js';
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,YAAY,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session module for Tollgate
|
|
3
|
+
*
|
|
4
|
+
* Provides session-based approval management, allowing users to grant
|
|
5
|
+
* time-bounded permissions for tool calls.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { SessionManager, type SessionGrant } from './session/index.js';
|
|
10
|
+
*
|
|
11
|
+
* const manager = new SessionManager();
|
|
12
|
+
*
|
|
13
|
+
* // Create grant on approval
|
|
14
|
+
* const grant = manager.createGrant({
|
|
15
|
+
* context,
|
|
16
|
+
* scope: 'tool',
|
|
17
|
+
* duration: '5min',
|
|
18
|
+
* grantedBy: 'terminal',
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Check before prompting
|
|
22
|
+
* const result = manager.checkGrant(context);
|
|
23
|
+
* if (result.granted) {
|
|
24
|
+
* // Skip prompt, use cached approval
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export { SessionManager, InMemorySessionStore } from './manager.js';
|
|
29
|
+
export { SqliteSessionStore } from './sqlite-store.js';
|
|
30
|
+
export { durationToTtlSeconds, DEFAULT_SESSION_CONFIG, } from './types.js';
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAavD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Manager for Tollgate
|
|
3
|
+
*
|
|
4
|
+
* Manages session-based approvals, allowing users to grant time-bounded
|
|
5
|
+
* permissions that reduce approval fatigue while maintaining security.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const manager = new SessionManager();
|
|
10
|
+
*
|
|
11
|
+
* // Create a grant when user approves with session option
|
|
12
|
+
* const grant = manager.createGrant({
|
|
13
|
+
* context: { server: 'postgres', tool: 'query', args: {}, timestamp: new Date() },
|
|
14
|
+
* scope: 'tool',
|
|
15
|
+
* duration: '5min',
|
|
16
|
+
* grantedBy: 'terminal',
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Check if a future call is covered
|
|
20
|
+
* const result = manager.checkGrant({
|
|
21
|
+
* server: 'postgres',
|
|
22
|
+
* tool: 'query',
|
|
23
|
+
* args: { sql: 'SELECT * FROM users' },
|
|
24
|
+
* timestamp: new Date(),
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* if (result.granted) {
|
|
28
|
+
* // Skip prompting, forward directly
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
import type { ToolCallContext } from '../policy/types.js';
|
|
33
|
+
import type { SessionGrant, CreateSessionGrantInput, SessionCheckResult, SessionStore, SessionStats } from './types.js';
|
|
34
|
+
/**
|
|
35
|
+
* In-memory session store implementation.
|
|
36
|
+
*
|
|
37
|
+
* Grants are stored in memory and lost on restart.
|
|
38
|
+
* For persistence, use SqliteSessionStore (see session/sqlite-store.ts).
|
|
39
|
+
*/
|
|
40
|
+
export declare class InMemorySessionStore implements SessionStore {
|
|
41
|
+
private grants;
|
|
42
|
+
set(grant: SessionGrant): void;
|
|
43
|
+
get(id: string): SessionGrant | undefined;
|
|
44
|
+
findMatching(context: ToolCallContext): SessionGrant[];
|
|
45
|
+
delete(id: string): boolean;
|
|
46
|
+
pruneExpired(): number;
|
|
47
|
+
getAll(): SessionGrant[];
|
|
48
|
+
clear(): void;
|
|
49
|
+
getStats(): SessionStats;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* SessionManager handles creation, checking, and lifecycle of session grants.
|
|
53
|
+
*
|
|
54
|
+
* Thread-safe and designed for concurrent access from the proxy server.
|
|
55
|
+
*/
|
|
56
|
+
export declare class SessionManager {
|
|
57
|
+
private readonly store;
|
|
58
|
+
private pruneInterval;
|
|
59
|
+
private readonly mutex;
|
|
60
|
+
/**
|
|
61
|
+
* Request deduplication cache to prevent double-counting for the same request.
|
|
62
|
+
* Maps requestId -> grantId for recently processed requests.
|
|
63
|
+
* Entries are cleared after 5 seconds to prevent memory leaks.
|
|
64
|
+
*/
|
|
65
|
+
private readonly recentRequests;
|
|
66
|
+
private readonly REQUEST_CACHE_TTL_MS;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new SessionManager.
|
|
69
|
+
*
|
|
70
|
+
* @param store - Session store backend (defaults to in-memory)
|
|
71
|
+
* @param autoPrune - Whether to automatically prune expired grants (default: true)
|
|
72
|
+
* @param pruneIntervalMs - How often to prune (default: 60 seconds)
|
|
73
|
+
*/
|
|
74
|
+
constructor(store?: SessionStore, autoPrune?: boolean, pruneIntervalMs?: number);
|
|
75
|
+
/**
|
|
76
|
+
* Clean up old entries from the request deduplication cache.
|
|
77
|
+
*/
|
|
78
|
+
private pruneRecentRequests;
|
|
79
|
+
/**
|
|
80
|
+
* Creates a new session grant based on an approved tool call.
|
|
81
|
+
*
|
|
82
|
+
* @param input - Grant creation parameters
|
|
83
|
+
* @returns The created grant
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const grant = manager.createGrant({
|
|
88
|
+
* context: { server: 'postgres', tool: 'query', args: {}, timestamp: new Date() },
|
|
89
|
+
* scope: 'tool',
|
|
90
|
+
* duration: '5min',
|
|
91
|
+
* grantedBy: 'terminal',
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
createGrant(input: CreateSessionGrantInput): SessionGrant;
|
|
96
|
+
/**
|
|
97
|
+
* Checks if a tool call is covered by an existing session grant.
|
|
98
|
+
*
|
|
99
|
+
* Returns the most specific matching grant if multiple exist.
|
|
100
|
+
* Order of specificity: exact > tool > pattern > server
|
|
101
|
+
*
|
|
102
|
+
* @param context - The tool call to check
|
|
103
|
+
* @param requestId - Optional request ID for deduplication (prevents double-counting on retry)
|
|
104
|
+
* @returns Check result with grant details if matched
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const result = manager.checkGrant({
|
|
109
|
+
* server: 'postgres',
|
|
110
|
+
* tool: 'query',
|
|
111
|
+
* args: { sql: 'SELECT * FROM users' },
|
|
112
|
+
* timestamp: new Date(),
|
|
113
|
+
* }, 'req-123');
|
|
114
|
+
*
|
|
115
|
+
* if (result.granted) {
|
|
116
|
+
* console.log(`Authorized by session grant ${result.grant.id}`);
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
checkGrant(context: ToolCallContext, requestId?: string): SessionCheckResult;
|
|
121
|
+
/**
|
|
122
|
+
* Checks if a specific grant matches a tool call context.
|
|
123
|
+
*/
|
|
124
|
+
private grantMatchesContext;
|
|
125
|
+
/**
|
|
126
|
+
* Revokes a session grant by ID.
|
|
127
|
+
*
|
|
128
|
+
* @param id - Grant ID to revoke
|
|
129
|
+
* @returns true if grant was found and revoked
|
|
130
|
+
*/
|
|
131
|
+
revokeGrant(id: string): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Revokes all grants for a specific server.
|
|
134
|
+
*
|
|
135
|
+
* @param server - Server name
|
|
136
|
+
* @returns Number of grants revoked
|
|
137
|
+
*/
|
|
138
|
+
revokeByServer(server: string): number;
|
|
139
|
+
/**
|
|
140
|
+
* Revokes all session grants.
|
|
141
|
+
*/
|
|
142
|
+
revokeAll(): void;
|
|
143
|
+
/**
|
|
144
|
+
* Gets all active (non-expired) grants.
|
|
145
|
+
*/
|
|
146
|
+
getActiveGrants(): SessionGrant[];
|
|
147
|
+
/**
|
|
148
|
+
* Gets session statistics.
|
|
149
|
+
*/
|
|
150
|
+
getStats(): SessionStats;
|
|
151
|
+
/**
|
|
152
|
+
* Manually trigger expired grant cleanup.
|
|
153
|
+
*
|
|
154
|
+
* @returns Number of grants pruned
|
|
155
|
+
*/
|
|
156
|
+
pruneExpired(): number;
|
|
157
|
+
/**
|
|
158
|
+
* Formats a grant for display in terminal or logs.
|
|
159
|
+
*/
|
|
160
|
+
formatGrant(grant: SessionGrant): string;
|
|
161
|
+
/**
|
|
162
|
+
* Cleans up resources. Call when shutting down.
|
|
163
|
+
*/
|
|
164
|
+
close(): void;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EACV,YAAY,EAEZ,uBAAuB,EACvB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAgCpB;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,MAAM,CAAwC;IAEtD,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAI9B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIzC,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,YAAY,EAAE;IAqBtD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI3B,YAAY,IAAI,MAAM;IActB,MAAM,IAAI,YAAY,EAAE;IAIxB,KAAK,IAAI,IAAI;IAIb,QAAQ,IAAI,YAAY;CA4BzB;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6D;IAC5F,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IAE7C;;;;;;OAMG;gBAED,KAAK,CAAC,EAAE,YAAY,EACpB,SAAS,GAAE,OAAc,EACzB,eAAe,GAAE,MAAe;IAsBlC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,KAAK,EAAE,uBAAuB,GAAG,YAAY;IAsDzD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,kBAAkB;IA6D5E;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIhC;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAatC;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB;;OAEG;IACH,eAAe,IAAI,YAAY,EAAE;IAOjC;;OAEG;IACH,QAAQ,IAAI,YAAY;IAIxB;;;;OAIG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM;IA0CxC;;OAEG;IACH,KAAK,IAAI,IAAI;CAMd"}
|