lucifer-gate 0.1.0-alpha.1
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 +174 -0
- package/dist/server/cli.js +220 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/server/create_app.js +95 -0
- package/dist/server/create_app.js.map +1 -0
- package/dist/server/domains/command-gateway/api/register_execute_routes.js +338 -0
- package/dist/server/domains/command-gateway/api/register_execute_routes.js.map +1 -0
- package/dist/server/domains/command-gateway/config/gateway_config.js +46 -0
- package/dist/server/domains/command-gateway/config/gateway_config.js.map +1 -0
- package/dist/server/domains/command-gateway/repository/api_key_store.js +44 -0
- package/dist/server/domains/command-gateway/repository/api_key_store.js.map +1 -0
- package/dist/server/domains/command-gateway/repository/approval_store.js +83 -0
- package/dist/server/domains/command-gateway/repository/approval_store.js.map +1 -0
- package/dist/server/domains/command-gateway/repository/audit_log.js +24 -0
- package/dist/server/domains/command-gateway/repository/audit_log.js.map +1 -0
- package/dist/server/domains/command-gateway/repository/command_rules_store.js +42 -0
- package/dist/server/domains/command-gateway/repository/command_rules_store.js.map +1 -0
- package/dist/server/domains/command-gateway/repository/database.js +59 -0
- package/dist/server/domains/command-gateway/repository/database.js.map +1 -0
- package/dist/server/domains/command-gateway/repository/pending_request_store.js +61 -0
- package/dist/server/domains/command-gateway/repository/pending_request_store.js.map +1 -0
- package/dist/server/domains/command-gateway/service/analyze_command_risk.js +44 -0
- package/dist/server/domains/command-gateway/service/analyze_command_risk.js.map +1 -0
- package/dist/server/domains/command-gateway/service/authenticate_request.js +71 -0
- package/dist/server/domains/command-gateway/service/authenticate_request.js.map +1 -0
- package/dist/server/domains/command-gateway/service/auto_approve_channel.js +24 -0
- package/dist/server/domains/command-gateway/service/auto_approve_channel.js.map +1 -0
- package/dist/server/domains/command-gateway/service/execute_command.js +139 -0
- package/dist/server/domains/command-gateway/service/execute_command.js.map +1 -0
- package/dist/server/domains/command-gateway/service/request_telegram_approval.js +126 -0
- package/dist/server/domains/command-gateway/service/request_telegram_approval.js.map +1 -0
- package/dist/server/domains/command-gateway/types/command_types.js +2 -0
- package/dist/server/domains/command-gateway/types/command_types.js.map +1 -0
- package/dist/server/domains/command-gateway/types/store_interfaces.js +2 -0
- package/dist/server/domains/command-gateway/types/store_interfaces.js.map +1 -0
- package/dist/server/domains/platform-api/api/register_health_routes.js +6 -0
- package/dist/server/domains/platform-api/api/register_health_routes.js.map +1 -0
- package/dist/server/domains/platform-api/config/server_config.js +17 -0
- package/dist/server/domains/platform-api/config/server_config.js.map +1 -0
- package/dist/server/domains/platform-api/repository/runtime_metadata_repository.js +7 -0
- package/dist/server/domains/platform-api/repository/runtime_metadata_repository.js.map +1 -0
- package/dist/server/domains/platform-api/service/create_health_report.js +10 -0
- package/dist/server/domains/platform-api/service/create_health_report.js.map +1 -0
- package/dist/server/domains/platform-api/types/health_report.js +2 -0
- package/dist/server/domains/platform-api/types/health_report.js.map +1 -0
- package/dist/server/index.js +18 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/lib/json_config_loader.js +31 -0
- package/dist/server/lib/json_config_loader.js.map +1 -0
- package/dist/server/lib/logger.js +12 -0
- package/dist/server/lib/logger.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { authenticateRequest, createRateLimiter } from '../service/authenticate_request.js';
|
|
3
|
+
import { analyzeCommandRisk } from '../service/analyze_command_risk.js';
|
|
4
|
+
import { executeCommand } from '../service/execute_command.js';
|
|
5
|
+
import { createChildLogger } from '../../../lib/logger.js';
|
|
6
|
+
const log = createChildLogger('routes');
|
|
7
|
+
const completedResults = new Map();
|
|
8
|
+
// Clean up completed results older than 10 minutes
|
|
9
|
+
setInterval(() => {
|
|
10
|
+
const cutoff = Date.now() - 10 * 60_000;
|
|
11
|
+
for (const [id, entry] of completedResults.entries()) {
|
|
12
|
+
if (entry.completedAt < cutoff) {
|
|
13
|
+
completedResults.delete(id);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}, 60_000);
|
|
17
|
+
export function registerExecuteRoutes(router, config, apiKeyStore, commandRulesStore, approvalStore, pendingStore, auditLog, approvalChannel) {
|
|
18
|
+
const rateLimiter = createRateLimiter(process.env.NODE_ENV === 'development' ? 1000 : config.rateLimitPerMinute);
|
|
19
|
+
router.post('/api/v1/execute', async (req, res) => {
|
|
20
|
+
const rawKey = req.headers['x-api-key'];
|
|
21
|
+
const ip = req.headers['x-forwarded-for']?.split(',')[0]?.trim() ?? req.socket.remoteAddress ?? 'unknown';
|
|
22
|
+
const { command, cwd } = req.body;
|
|
23
|
+
if (!command || typeof command !== 'string') {
|
|
24
|
+
res.status(400).json({
|
|
25
|
+
code: 'MISSING_COMMAND',
|
|
26
|
+
message: 'Request body must include a "command" string',
|
|
27
|
+
retryable: false,
|
|
28
|
+
});
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (command.length > 4096) {
|
|
32
|
+
res.status(400).json({
|
|
33
|
+
code: 'COMMAND_TOO_LONG',
|
|
34
|
+
message: 'Command exceeds 4096 character limit',
|
|
35
|
+
retryable: false,
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Validate cwd if provided
|
|
40
|
+
if (cwd !== undefined) {
|
|
41
|
+
if (typeof cwd !== 'string' || cwd.includes('..') || !cwd.startsWith('/')) {
|
|
42
|
+
res.status(400).json({
|
|
43
|
+
code: 'INVALID_CWD',
|
|
44
|
+
message: 'cwd must be an absolute path without ".." components',
|
|
45
|
+
retryable: false,
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const authResult = authenticateRequest(apiKeyStore, rateLimiter, rawKey, ip);
|
|
51
|
+
if (!authResult.ok) {
|
|
52
|
+
res.status(authResult.statusCode).json(authResult.error);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const requestId = randomUUID();
|
|
56
|
+
const apiKeyName = authResult.keyConfig.name;
|
|
57
|
+
const isSync = req.query.sync === 'true';
|
|
58
|
+
auditLog.append({
|
|
59
|
+
ts: new Date().toISOString(),
|
|
60
|
+
type: 'request',
|
|
61
|
+
requestId,
|
|
62
|
+
command,
|
|
63
|
+
apiKeyName,
|
|
64
|
+
ip,
|
|
65
|
+
});
|
|
66
|
+
// Match against command rules
|
|
67
|
+
const ruleMatch = commandRulesStore.matchRule(command);
|
|
68
|
+
auditLog.append({
|
|
69
|
+
ts: new Date().toISOString(),
|
|
70
|
+
type: 'rule_match',
|
|
71
|
+
requestId,
|
|
72
|
+
command,
|
|
73
|
+
ruleAction: ruleMatch.action,
|
|
74
|
+
});
|
|
75
|
+
if (ruleMatch.action === 'always_deny') {
|
|
76
|
+
auditLog.append({ ts: new Date().toISOString(), type: 'denied', requestId, command });
|
|
77
|
+
res.status(403).json({
|
|
78
|
+
code: 'COMMAND_DENIED',
|
|
79
|
+
message: 'Command is not permitted by policy',
|
|
80
|
+
retryable: false,
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (ruleMatch.action === 'always_approve') {
|
|
85
|
+
auditLog.append({ ts: new Date().toISOString(), type: 'approved', requestId, command, duration: 'policy' });
|
|
86
|
+
const result = await executeCommand({
|
|
87
|
+
command,
|
|
88
|
+
requestId,
|
|
89
|
+
cwd,
|
|
90
|
+
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
91
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
92
|
+
maxConcurrent: config.maxConcurrentExecutions,
|
|
93
|
+
});
|
|
94
|
+
auditLog.append({
|
|
95
|
+
ts: new Date().toISOString(),
|
|
96
|
+
type: 'executed',
|
|
97
|
+
requestId,
|
|
98
|
+
command,
|
|
99
|
+
exitCode: result.exitCode,
|
|
100
|
+
durationMs: result.durationMs,
|
|
101
|
+
error: result.error,
|
|
102
|
+
});
|
|
103
|
+
res.json(result);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// telegram_approve: check existing approval in SQLite
|
|
107
|
+
const existingApproval = approvalStore.findApproval(command);
|
|
108
|
+
if (existingApproval) {
|
|
109
|
+
auditLog.append({
|
|
110
|
+
ts: new Date().toISOString(),
|
|
111
|
+
type: 'approval_check',
|
|
112
|
+
requestId,
|
|
113
|
+
command,
|
|
114
|
+
duration: 'cached',
|
|
115
|
+
});
|
|
116
|
+
const result = await executeCommand({
|
|
117
|
+
command,
|
|
118
|
+
requestId,
|
|
119
|
+
cwd,
|
|
120
|
+
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
121
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
122
|
+
maxConcurrent: config.maxConcurrentExecutions,
|
|
123
|
+
});
|
|
124
|
+
auditLog.append({
|
|
125
|
+
ts: new Date().toISOString(),
|
|
126
|
+
type: 'executed',
|
|
127
|
+
requestId,
|
|
128
|
+
command,
|
|
129
|
+
exitCode: result.exitCode,
|
|
130
|
+
durationMs: result.durationMs,
|
|
131
|
+
error: result.error,
|
|
132
|
+
});
|
|
133
|
+
res.json(result);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Need Telegram approval
|
|
137
|
+
const riskAnalysis = analyzeCommandRisk(command);
|
|
138
|
+
const abortController = new AbortController();
|
|
139
|
+
// Coalesce: check if same command from same key is already pending
|
|
140
|
+
const existingPending = pendingStore.findByCommand(command, apiKeyName);
|
|
141
|
+
if (!isSync) {
|
|
142
|
+
// Async mode (default): return requestId, process in background
|
|
143
|
+
if (!existingPending) {
|
|
144
|
+
pendingStore.add({
|
|
145
|
+
requestId,
|
|
146
|
+
command,
|
|
147
|
+
apiKeyName,
|
|
148
|
+
ip,
|
|
149
|
+
createdAt: new Date().toISOString(),
|
|
150
|
+
resolve: () => { },
|
|
151
|
+
reject: () => { },
|
|
152
|
+
abortController,
|
|
153
|
+
});
|
|
154
|
+
// Fire and forget the approval request + execution
|
|
155
|
+
processApprovalAsync(requestId, command, apiKeyName, ip, cwd, riskAnalysis, config, approvalChannel, pendingStore, auditLog, abortController);
|
|
156
|
+
}
|
|
157
|
+
res.status(202).json({
|
|
158
|
+
requestId: existingPending?.requestId ?? requestId,
|
|
159
|
+
status: 'pending_approval',
|
|
160
|
+
});
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// Sync mode: block until decision
|
|
164
|
+
if (existingPending) {
|
|
165
|
+
// Wait for the existing pending request to resolve
|
|
166
|
+
// For simplicity in sync mode, just wait for a bit then poll
|
|
167
|
+
res.status(202).json({
|
|
168
|
+
requestId: existingPending.requestId,
|
|
169
|
+
status: 'pending_approval',
|
|
170
|
+
message: 'Another request for the same command is pending. Poll for status.',
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
pendingStore.add({
|
|
176
|
+
requestId,
|
|
177
|
+
command,
|
|
178
|
+
apiKeyName,
|
|
179
|
+
ip,
|
|
180
|
+
createdAt: new Date().toISOString(),
|
|
181
|
+
resolve: () => { },
|
|
182
|
+
reject: () => { },
|
|
183
|
+
abortController,
|
|
184
|
+
});
|
|
185
|
+
req.on('close', () => {
|
|
186
|
+
abortController.abort();
|
|
187
|
+
pendingStore.remove(requestId);
|
|
188
|
+
});
|
|
189
|
+
const approvalResult = await Promise.race([
|
|
190
|
+
approvalChannel.requestApproval(command, apiKeyName, ip, requestId, riskAnalysis),
|
|
191
|
+
new Promise((_, reject) => {
|
|
192
|
+
setTimeout(() => reject(new Error('Approval timed out')), config.approvalTimeoutSeconds * 1000);
|
|
193
|
+
}),
|
|
194
|
+
]);
|
|
195
|
+
if (approvalResult.decision === 'denied') {
|
|
196
|
+
res.status(403).json({
|
|
197
|
+
requestId,
|
|
198
|
+
status: 'denied',
|
|
199
|
+
code: 'DENIED',
|
|
200
|
+
message: 'Command was denied via Telegram',
|
|
201
|
+
retryable: false,
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const result = await executeCommand({
|
|
206
|
+
command,
|
|
207
|
+
requestId,
|
|
208
|
+
cwd,
|
|
209
|
+
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
210
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
211
|
+
maxConcurrent: config.maxConcurrentExecutions,
|
|
212
|
+
abortSignal: abortController.signal,
|
|
213
|
+
});
|
|
214
|
+
auditLog.append({
|
|
215
|
+
ts: new Date().toISOString(),
|
|
216
|
+
type: 'executed',
|
|
217
|
+
requestId,
|
|
218
|
+
command,
|
|
219
|
+
exitCode: result.exitCode,
|
|
220
|
+
durationMs: result.durationMs,
|
|
221
|
+
error: result.error,
|
|
222
|
+
});
|
|
223
|
+
res.json(result);
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
227
|
+
if (message.includes('timed out')) {
|
|
228
|
+
res.status(408).json({
|
|
229
|
+
requestId,
|
|
230
|
+
status: 'timed_out',
|
|
231
|
+
code: 'APPROVAL_TIMEOUT',
|
|
232
|
+
message: 'Approval timed out. No response from Telegram.',
|
|
233
|
+
retryable: true,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
res.status(503).json({
|
|
238
|
+
requestId,
|
|
239
|
+
code: 'APPROVAL_ERROR',
|
|
240
|
+
message: `Approval channel error: ${message}`,
|
|
241
|
+
retryable: true,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
pendingStore.remove(requestId);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
router.get('/api/v1/status/:requestId', (req, res) => {
|
|
250
|
+
const requestId = Array.isArray(req.params.requestId) ? req.params.requestId[0] : req.params.requestId;
|
|
251
|
+
// Auth check: require valid API key for status queries
|
|
252
|
+
const rawKey = req.headers['x-api-key'];
|
|
253
|
+
const ip = req.headers['x-forwarded-for']?.split(',')[0]?.trim() ?? req.socket.remoteAddress ?? 'unknown';
|
|
254
|
+
const authResult = authenticateRequest(apiKeyStore, rateLimiter, rawKey, ip);
|
|
255
|
+
if (!authResult.ok) {
|
|
256
|
+
res.status(authResult.statusCode).json(authResult.error);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
// Check completed results cache
|
|
260
|
+
const completed = completedResults.get(requestId);
|
|
261
|
+
if (completed) {
|
|
262
|
+
res.json(completed.result);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
// Check pending store
|
|
266
|
+
const pending = pendingStore.get(requestId);
|
|
267
|
+
if (pending) {
|
|
268
|
+
// Scope check: only the same API key can query status
|
|
269
|
+
if (pending.apiKeyName !== authResult.keyConfig.name) {
|
|
270
|
+
res.status(404).json({
|
|
271
|
+
code: 'NOT_FOUND',
|
|
272
|
+
message: 'Request not found',
|
|
273
|
+
retryable: false,
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
res.json({ requestId, status: 'pending_approval' });
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
res.status(404).json({
|
|
281
|
+
code: 'NOT_FOUND',
|
|
282
|
+
message: 'Request not found or expired',
|
|
283
|
+
retryable: false,
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
async function processApprovalAsync(requestId, command, apiKeyName, ip, cwd, riskAnalysis, config, approvalChannel, pendingStore, auditLog, abortController) {
|
|
288
|
+
try {
|
|
289
|
+
const approvalResult = await Promise.race([
|
|
290
|
+
approvalChannel.requestApproval(command, apiKeyName, ip, requestId, riskAnalysis),
|
|
291
|
+
new Promise((_, reject) => {
|
|
292
|
+
setTimeout(() => reject(new Error('Approval timed out')), config.approvalTimeoutSeconds * 1000);
|
|
293
|
+
}),
|
|
294
|
+
]);
|
|
295
|
+
if (approvalResult.decision === 'denied') {
|
|
296
|
+
completedResults.set(requestId, {
|
|
297
|
+
result: { requestId, status: 'denied' },
|
|
298
|
+
completedAt: Date.now(),
|
|
299
|
+
});
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const result = await executeCommand({
|
|
303
|
+
command,
|
|
304
|
+
requestId,
|
|
305
|
+
cwd,
|
|
306
|
+
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
307
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
308
|
+
maxConcurrent: config.maxConcurrentExecutions,
|
|
309
|
+
abortSignal: abortController.signal,
|
|
310
|
+
});
|
|
311
|
+
auditLog.append({
|
|
312
|
+
ts: new Date().toISOString(),
|
|
313
|
+
type: 'executed',
|
|
314
|
+
requestId,
|
|
315
|
+
command,
|
|
316
|
+
exitCode: result.exitCode,
|
|
317
|
+
durationMs: result.durationMs,
|
|
318
|
+
error: result.error,
|
|
319
|
+
});
|
|
320
|
+
completedResults.set(requestId, { result, completedAt: Date.now() });
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
324
|
+
log.error({ requestId, err: message }, 'Async approval/execution failed');
|
|
325
|
+
completedResults.set(requestId, {
|
|
326
|
+
result: {
|
|
327
|
+
requestId,
|
|
328
|
+
status: message.includes('timed out') ? 'timed_out' : 'failed',
|
|
329
|
+
error: message,
|
|
330
|
+
},
|
|
331
|
+
completedAt: Date.now(),
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
finally {
|
|
335
|
+
pendingStore.remove(requestId);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=register_execute_routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register_execute_routes.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/api/register_execute_routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { loadJsonConfig } from '../../../lib/json_config_loader.js';
|
|
3
|
+
function isLuciferConfig(data) {
|
|
4
|
+
if (typeof data !== 'object' || data === null)
|
|
5
|
+
return false;
|
|
6
|
+
const d = data;
|
|
7
|
+
if (typeof d.port !== 'undefined' && typeof d.port !== 'number')
|
|
8
|
+
return false;
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
const defaults = {
|
|
12
|
+
port: Number(process.env.PORT) || 3001,
|
|
13
|
+
telegramChatId: process.env.LUCIFER_TELEGRAM_CHAT_ID,
|
|
14
|
+
approvalTimeoutSeconds: 300,
|
|
15
|
+
executionTimeoutSeconds: 120,
|
|
16
|
+
maxConcurrentExecutions: 5,
|
|
17
|
+
maxOutputBytes: 10 * 1024 * 1024,
|
|
18
|
+
rateLimitPerMinute: 10,
|
|
19
|
+
onApprovalTimeout: 'deny',
|
|
20
|
+
dataDir: './data',
|
|
21
|
+
};
|
|
22
|
+
export function loadGatewayConfig(configPath) {
|
|
23
|
+
if (!configPath) {
|
|
24
|
+
return { ...defaults };
|
|
25
|
+
}
|
|
26
|
+
const resolvedPath = resolve(configPath);
|
|
27
|
+
const loaded = loadJsonConfig(resolvedPath, isLuciferConfig);
|
|
28
|
+
return {
|
|
29
|
+
...defaults,
|
|
30
|
+
...loaded,
|
|
31
|
+
port: loaded.port ?? defaults.port,
|
|
32
|
+
dataDir: loaded.dataDir ?? defaults.dataDir,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function getTelegramToken() {
|
|
36
|
+
const token = process.env.LUCIFER_TELEGRAM_TOKEN;
|
|
37
|
+
if (!token) {
|
|
38
|
+
throw new Error('LUCIFER_TELEGRAM_TOKEN environment variable is required. ' +
|
|
39
|
+
'Create a bot via @BotFather on Telegram and set the token.');
|
|
40
|
+
}
|
|
41
|
+
return token;
|
|
42
|
+
}
|
|
43
|
+
export function getAdminSecret() {
|
|
44
|
+
return process.env.LUCIFER_ADMIN_SECRET;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=gateway_config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway_config.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/config/gateway_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,SAAS,eAAe,CAAC,IAAa;IACpC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,QAAQ,GAAkB;IAC9B,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI;IACtC,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;IACpD,sBAAsB,EAAE,GAAG;IAC3B,uBAAuB,EAAE,GAAG;IAC5B,uBAAuB,EAAE,CAAC;IAC1B,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IAChC,kBAAkB,EAAE,EAAE;IACtB,iBAAiB,EAAE,MAAM;IACzB,OAAO,EAAE,QAAQ;CAClB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,UAAmB;IACnD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;IAE7D,OAAO;QACL,GAAG,QAAQ;QACX,GAAG,MAAM;QACT,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI;QAClC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO;KAC5C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,2DAA2D;YAC3D,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { loadJsonConfig } from '../../../lib/json_config_loader.js';
|
|
3
|
+
import { createChildLogger } from '../../../lib/logger.js';
|
|
4
|
+
const log = createChildLogger('api-key-store');
|
|
5
|
+
function isApiKeysConfig(data) {
|
|
6
|
+
if (typeof data !== 'object' || data === null)
|
|
7
|
+
return false;
|
|
8
|
+
const d = data;
|
|
9
|
+
return Array.isArray(d.keys);
|
|
10
|
+
}
|
|
11
|
+
export function hashApiKey(key, salt) {
|
|
12
|
+
return createHash('sha256').update(salt + key).digest('hex');
|
|
13
|
+
}
|
|
14
|
+
export function generateApiKey() {
|
|
15
|
+
const key = 'luc_' + randomBytes(24).toString('hex');
|
|
16
|
+
const salt = randomBytes(16).toString('hex');
|
|
17
|
+
const keyHash = hashApiKey(key, salt);
|
|
18
|
+
return { key, salt, keyHash };
|
|
19
|
+
}
|
|
20
|
+
export function createApiKeyStore(configPath) {
|
|
21
|
+
let config;
|
|
22
|
+
function load() {
|
|
23
|
+
config = loadJsonConfig(configPath, isApiKeysConfig);
|
|
24
|
+
log.info({ keyCount: config.keys.length }, 'API keys loaded');
|
|
25
|
+
}
|
|
26
|
+
load();
|
|
27
|
+
return {
|
|
28
|
+
findByKey(rawKey) {
|
|
29
|
+
for (const keyConfig of config.keys) {
|
|
30
|
+
if (!keyConfig.active)
|
|
31
|
+
continue;
|
|
32
|
+
const hash = hashApiKey(rawKey, keyConfig.salt);
|
|
33
|
+
if (hash === keyConfig.keyHash) {
|
|
34
|
+
return keyConfig;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
},
|
|
39
|
+
reload() {
|
|
40
|
+
load();
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=api_key_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api_key_store.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/repository/api_key_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAE/C,SAAS,eAAe,CAAC,IAAa;IACpC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,IAAY;IAClD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC;AAOD,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,IAAI,MAAqB,CAAC;IAE1B,SAAS,IAAI;QACX,MAAM,GAAG,cAAc,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QACrD,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,EAAE,CAAC;IAEP,OAAO;QACL,SAAS,CAAC,MAAc;YACtB,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBACpC,IAAI,CAAC,SAAS,CAAC,MAAM;oBAAE,SAAS;gBAChC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,IAAI,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;oBAC/B,OAAO,SAAS,CAAC;gBACnB,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM;YACJ,IAAI,EAAE,CAAC;QACT,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createChildLogger } from '../../../lib/logger.js';
|
|
2
|
+
const log = createChildLogger('approval-store');
|
|
3
|
+
export function createApprovalStore(db) {
|
|
4
|
+
const APPROVAL_COLUMNS = `id, command, match_type as matchType, duration, approved_at as approvedAt, expires_at as expiresAt, approved_by as approvedBy`;
|
|
5
|
+
const findExact = db.prepare(`SELECT ${APPROVAL_COLUMNS} FROM approvals
|
|
6
|
+
WHERE match_type = 'exact' AND command = ?
|
|
7
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
8
|
+
ORDER BY approved_at DESC LIMIT 1`);
|
|
9
|
+
const findPrefix = db.prepare(`SELECT ${APPROVAL_COLUMNS} FROM approvals
|
|
10
|
+
WHERE match_type = 'prefix' AND ? LIKE (command || '%')
|
|
11
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
12
|
+
ORDER BY LENGTH(command) DESC LIMIT 1`);
|
|
13
|
+
const insertApproval = db.prepare(`INSERT INTO approvals (command, match_type, duration, approved_at, expires_at, approved_by)
|
|
14
|
+
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
15
|
+
const deleteExpired = db.prepare(`DELETE FROM approvals WHERE expires_at IS NOT NULL AND expires_at <= ?`);
|
|
16
|
+
const selectAll = db.prepare(`SELECT ${APPROVAL_COLUMNS} FROM approvals ORDER BY approved_at DESC LIMIT ? OFFSET ?`);
|
|
17
|
+
const deleteById = db.prepare(`DELETE FROM approvals WHERE id = ?`);
|
|
18
|
+
return {
|
|
19
|
+
findApproval(command) {
|
|
20
|
+
const now = new Date().toISOString();
|
|
21
|
+
const exact = findExact.get(command, now);
|
|
22
|
+
if (exact) {
|
|
23
|
+
log.debug({ command, approvalId: exact.id, matchType: 'exact' }, 'Exact approval found');
|
|
24
|
+
return exact;
|
|
25
|
+
}
|
|
26
|
+
const prefix = findPrefix.get(command, now);
|
|
27
|
+
if (prefix) {
|
|
28
|
+
log.debug({ command, approvalId: prefix.id, matchType: 'prefix', prefix: prefix.command }, 'Prefix approval found');
|
|
29
|
+
return prefix;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
},
|
|
33
|
+
addApproval(command, matchType, duration, approvedBy) {
|
|
34
|
+
const approvedAt = new Date().toISOString();
|
|
35
|
+
let expiresAt = null;
|
|
36
|
+
if (duration !== 'permanent') {
|
|
37
|
+
const hours = parseInt(duration, 10);
|
|
38
|
+
if (!isNaN(hours) && hours > 0) {
|
|
39
|
+
const expires = new Date(Date.now() + hours * 3600_000);
|
|
40
|
+
expiresAt = expires.toISOString();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Prefix approvals capped at 8h per security policy
|
|
44
|
+
if (matchType === 'prefix' && (duration === 'permanent' || parseInt(duration, 10) > 8)) {
|
|
45
|
+
const capped = new Date(Date.now() + 8 * 3600_000);
|
|
46
|
+
expiresAt = capped.toISOString();
|
|
47
|
+
log.warn({ command, matchType, duration }, 'Prefix approval capped at 8h');
|
|
48
|
+
}
|
|
49
|
+
const result = insertApproval.run(command, matchType, duration, approvedAt, expiresAt, approvedBy);
|
|
50
|
+
const approval = {
|
|
51
|
+
id: result.lastInsertRowid,
|
|
52
|
+
command,
|
|
53
|
+
matchType: matchType,
|
|
54
|
+
duration,
|
|
55
|
+
approvedAt,
|
|
56
|
+
expiresAt,
|
|
57
|
+
approvedBy,
|
|
58
|
+
};
|
|
59
|
+
log.info({ approvalId: approval.id, command, matchType, duration, expiresAt }, 'Approval added');
|
|
60
|
+
return approval;
|
|
61
|
+
},
|
|
62
|
+
removeExpired() {
|
|
63
|
+
const now = new Date().toISOString();
|
|
64
|
+
const result = deleteExpired.run(now);
|
|
65
|
+
if (result.changes > 0) {
|
|
66
|
+
log.info({ removed: result.changes }, 'Expired approvals cleaned up');
|
|
67
|
+
}
|
|
68
|
+
return result.changes;
|
|
69
|
+
},
|
|
70
|
+
listAll(limit = 100, offset = 0) {
|
|
71
|
+
return selectAll.all(limit, offset);
|
|
72
|
+
},
|
|
73
|
+
revokeById(id) {
|
|
74
|
+
const result = deleteById.run(id);
|
|
75
|
+
if (result.changes > 0) {
|
|
76
|
+
log.info({ approvalId: id }, 'Approval revoked');
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=approval_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval_store.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/repository/approval_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function createAuditLog(db) {
|
|
2
|
+
const insert = db.prepare(`INSERT INTO audit_log (ts, type, request_id, command, api_key_name, ip, rule_action, duration, approved_by, exit_code, duration_ms, error)
|
|
3
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
4
|
+
const selectRecent = db.prepare(`SELECT ts, type, request_id as requestId, command, api_key_name as apiKeyName, ip,
|
|
5
|
+
rule_action as ruleAction, duration, approved_by as approvedBy,
|
|
6
|
+
exit_code as exitCode, duration_ms as durationMs, error
|
|
7
|
+
FROM audit_log ORDER BY id DESC LIMIT ? OFFSET ?`);
|
|
8
|
+
const selectByRequest = db.prepare(`SELECT ts, type, request_id as requestId, command, api_key_name as apiKeyName, ip,
|
|
9
|
+
rule_action as ruleAction, duration, approved_by as approvedBy,
|
|
10
|
+
exit_code as exitCode, duration_ms as durationMs, error
|
|
11
|
+
FROM audit_log WHERE request_id = ? ORDER BY id ASC`);
|
|
12
|
+
return {
|
|
13
|
+
append(entry) {
|
|
14
|
+
insert.run(entry.ts, entry.type, entry.requestId, entry.command ?? null, entry.apiKeyName ?? null, entry.ip ?? null, entry.ruleAction ?? null, entry.duration ?? null, entry.approvedBy ?? null, entry.exitCode ?? null, entry.durationMs ?? null, entry.error ?? null);
|
|
15
|
+
},
|
|
16
|
+
query(limit = 100, offset = 0) {
|
|
17
|
+
return selectRecent.all(limit, offset);
|
|
18
|
+
},
|
|
19
|
+
queryByRequestId(requestId) {
|
|
20
|
+
return selectByRequest.all(requestId);
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=audit_log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit_log.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/repository/audit_log.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,cAAc,CAAC,EAAqB;IAClD,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CACvB;iDAC6C,CAC9C,CAAC;IAEF,MAAM,YAAY,GAAG,EAAE,CAAC,OAAO,CAC7B;;;sDAGkD,CACnD,CAAC;IAEF,MAAM,eAAe,GAAG,EAAE,CAAC,OAAO,CAChC;;;yDAGqD,CACtD,CAAC;IAEF,OAAO;QACL,MAAM,CAAC,KAAiB;YACtB,MAAM,CAAC,GAAG,CACR,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,IAAI,IAAI,EACrB,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,KAAK,CAAC,EAAE,IAAI,IAAI,EAChB,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,KAAK,CAAC,QAAQ,IAAI,IAAI,EACtB,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,KAAK,CAAC,QAAQ,IAAI,IAAI,EACtB,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,KAAK,CAAC,KAAK,IAAI,IAAI,CACpB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,KAAK,GAAG,GAAG,EAAE,MAAM,GAAG,CAAC;YAC3B,OAAO,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC;QAED,gBAAgB,CAAC,SAAiB;YAChC,OAAO,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { loadJsonConfig } from '../../../lib/json_config_loader.js';
|
|
2
|
+
import { createChildLogger } from '../../../lib/logger.js';
|
|
3
|
+
const log = createChildLogger('command-rules');
|
|
4
|
+
function isCommandRulesConfig(data) {
|
|
5
|
+
if (typeof data !== 'object' || data === null)
|
|
6
|
+
return false;
|
|
7
|
+
const d = data;
|
|
8
|
+
if (!Array.isArray(d.rules))
|
|
9
|
+
return false;
|
|
10
|
+
const validActions = ['always_approve', 'telegram_approve', 'always_deny'];
|
|
11
|
+
if (d.defaultAction && !validActions.includes(d.defaultAction))
|
|
12
|
+
return false;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
export function createCommandRulesStore(configPath) {
|
|
16
|
+
let config;
|
|
17
|
+
function load() {
|
|
18
|
+
config = loadJsonConfig(configPath, isCommandRulesConfig);
|
|
19
|
+
if (!config.defaultAction) {
|
|
20
|
+
config.defaultAction = 'always_deny';
|
|
21
|
+
}
|
|
22
|
+
log.info({ ruleCount: config.rules.length, defaultAction: config.defaultAction }, 'Command rules loaded');
|
|
23
|
+
}
|
|
24
|
+
load();
|
|
25
|
+
return {
|
|
26
|
+
matchRule(command) {
|
|
27
|
+
const trimmed = command.trim();
|
|
28
|
+
for (const rule of config.rules) {
|
|
29
|
+
if (trimmed.startsWith(rule.prefix)) {
|
|
30
|
+
log.debug({ command: trimmed, matchedPrefix: rule.prefix, action: rule.action }, 'Rule matched');
|
|
31
|
+
return { rule, action: rule.action };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
log.debug({ command: trimmed, action: config.defaultAction }, 'No rule matched, using default');
|
|
35
|
+
return { rule: null, action: config.defaultAction };
|
|
36
|
+
},
|
|
37
|
+
reload() {
|
|
38
|
+
load();
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=command_rules_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command_rules_store.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/repository/command_rules_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAE/C,SAAS,oBAAoB,CAAC,IAAa;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,YAAY,GAAG,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,CAAC,CAAC;IAC3E,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAuB,CAAC;QAAE,OAAO,KAAK,CAAC;IACvF,OAAO,IAAI,CAAC;AACd,CAAC;AAOD,MAAM,UAAU,uBAAuB,CAAC,UAAkB;IACxD,IAAI,MAA0B,CAAC;IAE/B,SAAS,IAAI;QACX,MAAM,GAAG,cAAc,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC1B,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;QACvC,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAC5G,CAAC;IAED,IAAI,EAAE,CAAC;IAEP,OAAO;QACL,SAAS,CAAC,OAAe;YACvB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAChC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACpC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;oBACjG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACvC,CAAC;YACH,CAAC;YACD,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,EAAE,gCAAgC,CAAC,CAAC;YAChG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC;QACtD,CAAC;QAED,MAAM;YACJ,IAAI,EAAE,CAAC;QACT,CAAC;KACF,CAAC;AACJ,CAAC"}
|