lucifer-gate 0.8.9 → 0.8.10
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/dist/server/cli/args.js +7 -0
- package/dist/server/cli/args.js.map +1 -0
- package/dist/server/cli/init_config.js +81 -0
- package/dist/server/cli/init_config.js.map +1 -0
- package/dist/server/cli/print_help.js +27 -0
- package/dist/server/cli/print_help.js.map +1 -0
- package/dist/server/cli/run_log.js +29 -0
- package/dist/server/cli/run_log.js.map +1 -0
- package/dist/server/cli/run_pair.js +61 -0
- package/dist/server/cli/run_pair.js.map +1 -0
- package/dist/server/cli/run_server.js +24 -0
- package/dist/server/cli/run_server.js.map +1 -0
- package/dist/server/cli/run_stats.js +48 -0
- package/dist/server/cli/run_stats.js.map +1 -0
- package/dist/server/cli.js +15 -273
- package/dist/server/cli.js.map +1 -1
- package/dist/server/domains/command-gateway/api/register_execute_routes.js +8 -168
- package/dist/server/domains/command-gateway/api/register_execute_routes.js.map +1 -1
- package/dist/server/domains/command-gateway/service/execute_and_audit.js +32 -0
- package/dist/server/domains/command-gateway/service/execute_and_audit.js.map +1 -0
- package/dist/server/domains/command-gateway/service/handle_manual_approval.js +122 -0
- package/dist/server/domains/command-gateway/service/handle_manual_approval.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../server/src/cli/args.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,IAAc,EAAE,IAAY;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { resolve, join } from 'node:path';
|
|
3
|
+
import { generateApiKey, generateAdminSecret } from '../domains/command-gateway/repository/api_key_store.js';
|
|
4
|
+
export function initConfig(targetDir) {
|
|
5
|
+
const configDir = resolve(targetDir, 'config');
|
|
6
|
+
const dataDir = resolve(targetDir, 'data');
|
|
7
|
+
mkdirSync(configDir, { recursive: true });
|
|
8
|
+
mkdirSync(dataDir, { recursive: true });
|
|
9
|
+
const luciferJsonPath = join(configDir, 'lucifer.json');
|
|
10
|
+
const apiKeysPath = join(configDir, 'api-keys.json');
|
|
11
|
+
const commandRulesPath = join(configDir, 'command-rules.json');
|
|
12
|
+
const proxyConfigPath = join(configDir, 'proxy-config.json');
|
|
13
|
+
if (existsSync(luciferJsonPath)) {
|
|
14
|
+
console.log(`Config already exists: ${luciferJsonPath}`);
|
|
15
|
+
console.log('Delete it first if you want to regenerate.');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const { key, salt, keyHash } = generateApiKey();
|
|
19
|
+
const { secret: adminSecret, salt: adminSalt, secretHash: adminHash } = generateAdminSecret();
|
|
20
|
+
writeFileSync(luciferJsonPath, JSON.stringify({
|
|
21
|
+
port: 3001,
|
|
22
|
+
adminSecretHash: adminHash,
|
|
23
|
+
adminSecretSalt: adminSalt,
|
|
24
|
+
approvalTimeoutSeconds: 300,
|
|
25
|
+
executionTimeoutSeconds: 120,
|
|
26
|
+
maxConcurrentExecutions: 5,
|
|
27
|
+
maxOutputBytes: 10485760,
|
|
28
|
+
rateLimitPerMinute: 10,
|
|
29
|
+
onApprovalTimeout: 'deny',
|
|
30
|
+
dataDir: '../data',
|
|
31
|
+
logFile: 'lucifer.log',
|
|
32
|
+
}, null, 2) + '\n');
|
|
33
|
+
writeFileSync(apiKeysPath, JSON.stringify({
|
|
34
|
+
keys: [{
|
|
35
|
+
id: crypto.randomUUID(),
|
|
36
|
+
name: 'default',
|
|
37
|
+
keyHash,
|
|
38
|
+
salt,
|
|
39
|
+
allowedIps: [],
|
|
40
|
+
createdAt: new Date().toISOString(),
|
|
41
|
+
active: true,
|
|
42
|
+
}],
|
|
43
|
+
}, null, 2) + '\n');
|
|
44
|
+
writeFileSync(commandRulesPath, JSON.stringify({
|
|
45
|
+
rules: [
|
|
46
|
+
{ prefix: 'echo ', action: 'always_approve' },
|
|
47
|
+
{ prefix: 'git status', action: 'always_approve' },
|
|
48
|
+
{ prefix: 'git pull', action: 'manual_approve' },
|
|
49
|
+
{ prefix: 'git push', action: 'manual_approve' },
|
|
50
|
+
{ prefix: 'npm test', action: 'always_approve' },
|
|
51
|
+
{ prefix: 'npm run', action: 'manual_approve' },
|
|
52
|
+
{ prefix: 'rm ', action: 'always_deny' },
|
|
53
|
+
],
|
|
54
|
+
defaultAction: 'always_deny',
|
|
55
|
+
}, null, 2) + '\n');
|
|
56
|
+
writeFileSync(proxyConfigPath, JSON.stringify({
|
|
57
|
+
proxies: [],
|
|
58
|
+
}, null, 2) + '\n');
|
|
59
|
+
console.log('Config files generated:');
|
|
60
|
+
console.log(` ${luciferJsonPath}`);
|
|
61
|
+
console.log(` ${apiKeysPath}`);
|
|
62
|
+
console.log(` ${commandRulesPath}`);
|
|
63
|
+
console.log(` ${proxyConfigPath}`);
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log('Your API key (save this, it cannot be recovered):');
|
|
66
|
+
console.log(` ${key}`);
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log('Your admin secret for the web approval UI (save this, it cannot be recovered):');
|
|
69
|
+
console.log(` ${adminSecret}`);
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log('Quick start:');
|
|
72
|
+
console.log(' # Dev mode (no Telegram needed):');
|
|
73
|
+
console.log(` LUCIFER_TELEGRAM_TOKEN=skip lucifer-gate --config ${luciferJsonPath} --auto-approve`);
|
|
74
|
+
console.log('');
|
|
75
|
+
console.log(' # Production — pair your Telegram chat first:');
|
|
76
|
+
console.log(` LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate pair --config ${luciferJsonPath}`);
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log(' # Then start the server:');
|
|
79
|
+
console.log(` LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate --config ${luciferJsonPath}`);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=init_config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init_config.js","sourceRoot":"","sources":["../../../server/src/cli/init_config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function printHelp() {
|
|
2
|
+
console.log(`
|
|
3
|
+
lucifer-gate - AI Agent Command Firewall
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
lucifer-gate start [options] Start the server (explicit form)
|
|
7
|
+
lucifer-gate [options] Start the server (implicit, same as 'start')
|
|
8
|
+
lucifer-gate --init [dir] Generate starter config files
|
|
9
|
+
lucifer-gate pair [--config <path>] Pair a Telegram chat for approvals
|
|
10
|
+
lucifer-gate log [--limit N] Query audit log
|
|
11
|
+
lucifer-gate stats Show approval statistics
|
|
12
|
+
|
|
13
|
+
Server options:
|
|
14
|
+
--config <path> Path to lucifer.json (default: ./config/lucifer.json)
|
|
15
|
+
--port <number> Server port (default: 3001, or PORT env var)
|
|
16
|
+
--data-dir <path> Directory for SQLite database (default: ./data)
|
|
17
|
+
--auto-approve Auto-approve all commands (dev mode, no Telegram needed)
|
|
18
|
+
--help Show this help
|
|
19
|
+
|
|
20
|
+
Environment variables:
|
|
21
|
+
LUCIFER_TELEGRAM_TOKEN Telegram bot token (required for production)
|
|
22
|
+
LUCIFER_TELEGRAM_CHAT_ID Telegram chat ID for approvals (or use 'pair' command)
|
|
23
|
+
PORT Server port (default: 3001)
|
|
24
|
+
LOG_LEVEL Log level: debug, info, warn, error (default: debug / info in production)
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=print_help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"print_help.js","sourceRoot":"","sources":["../../../server/src/cli/print_help.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBb,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getDatabase } from '../domains/command-gateway/repository/database.js';
|
|
2
|
+
import { createAuditLog } from '../domains/command-gateway/repository/audit_log.js';
|
|
3
|
+
import { redactApiKeyName } from '../domains/command-gateway/service/redact_api_key_name.js';
|
|
4
|
+
export async function runLog(limit, dataDir) {
|
|
5
|
+
const db = getDatabase(dataDir);
|
|
6
|
+
const auditLog = createAuditLog(db);
|
|
7
|
+
const entries = auditLog.query(limit);
|
|
8
|
+
if (entries.length === 0) {
|
|
9
|
+
console.log('No audit log entries found.');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const reversed = [...entries].reverse();
|
|
13
|
+
for (const entry of reversed) {
|
|
14
|
+
const time = entry.ts.replace('T', ' ').replace(/\.\d+Z$/, 'Z');
|
|
15
|
+
const parts = [time, entry.type.toUpperCase().padEnd(16)];
|
|
16
|
+
if (entry.command)
|
|
17
|
+
parts.push(entry.command);
|
|
18
|
+
if (entry.apiKeyName)
|
|
19
|
+
parts.push(`key=${redactApiKeyName(entry.apiKeyName)}`);
|
|
20
|
+
if (entry.exitCode !== undefined && entry.exitCode !== null)
|
|
21
|
+
parts.push(`exit=${entry.exitCode}`);
|
|
22
|
+
if (entry.durationMs !== undefined && entry.durationMs !== null)
|
|
23
|
+
parts.push(`${entry.durationMs}ms`);
|
|
24
|
+
if (entry.error)
|
|
25
|
+
parts.push(`error: ${entry.error}`);
|
|
26
|
+
console.log(parts.join(' '));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=run_log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_log.js","sourceRoot":"","sources":["../../../server/src/cli/run_log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mDAAmD,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAE7F,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAa,EAAE,OAAe;IACzD,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,IAAI,KAAK,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9E,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAClG,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;QACrG,IAAI,KAAK,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { createInterface } from 'node:readline/promises';
|
|
3
|
+
import { runTelegramPairing } from '../domains/command-gateway/service/telegram_pairing.js';
|
|
4
|
+
import { getTelegramToken } from '../domains/command-gateway/config/gateway_config.js';
|
|
5
|
+
import { updateJsonConfig } from '../lib/json_config_writer.js';
|
|
6
|
+
function createReadlinePairingIO() {
|
|
7
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
8
|
+
return {
|
|
9
|
+
print(msg) {
|
|
10
|
+
console.log(msg);
|
|
11
|
+
},
|
|
12
|
+
async choose(prompt, options) {
|
|
13
|
+
console.log(`\n${prompt}`);
|
|
14
|
+
for (let i = 0; i < options.length; i++) {
|
|
15
|
+
console.log(` ${i + 1}. ${options[i]}`);
|
|
16
|
+
}
|
|
17
|
+
while (true) {
|
|
18
|
+
const answer = await rl.question(`\nEnter number (1-${options.length}): `);
|
|
19
|
+
const num = Number.parseInt(answer.trim(), 10);
|
|
20
|
+
if (num >= 1 && num <= options.length)
|
|
21
|
+
return num - 1;
|
|
22
|
+
console.log(`Please enter a number between 1 and ${options.length}.`);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
async confirm(prompt) {
|
|
26
|
+
const answer = await rl.question(`${prompt} [y/N] `);
|
|
27
|
+
return /^y(es)?$/i.test(answer.trim());
|
|
28
|
+
},
|
|
29
|
+
async prompt(msg) {
|
|
30
|
+
return rl.question(`${msg} `);
|
|
31
|
+
},
|
|
32
|
+
close() {
|
|
33
|
+
rl.close();
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export async function runPair(configPath) {
|
|
38
|
+
const resolvedConfigPath = resolve(configPath);
|
|
39
|
+
let token;
|
|
40
|
+
try {
|
|
41
|
+
token = getTelegramToken();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
console.error('LUCIFER_TELEGRAM_TOKEN environment variable is required for pairing.\n' +
|
|
45
|
+
'Create a bot via @BotFather on Telegram and set the token:\n\n' +
|
|
46
|
+
' LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate pair');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const io = createReadlinePairingIO();
|
|
50
|
+
try {
|
|
51
|
+
const result = await runTelegramPairing(token, io, { waitForChats: true });
|
|
52
|
+
updateJsonConfig(resolvedConfigPath, { telegramChatId: result.chatId });
|
|
53
|
+
console.log(`\nChat ID ${result.chatId} saved to ${resolvedConfigPath}`);
|
|
54
|
+
console.log('You can now start Lucifer without LUCIFER_TELEGRAM_CHAT_ID:');
|
|
55
|
+
console.log(`\n LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate start --config ${resolvedConfigPath}`);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
io.close();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=run_pair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_pair.js","sourceRoot":"","sources":["../../../server/src/cli/run_pair.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createApp } from '../create_app.js';
|
|
2
|
+
import { logger } from '../lib/logger.js';
|
|
3
|
+
export async function runServer(options) {
|
|
4
|
+
if (options.port) {
|
|
5
|
+
process.env.PORT = options.port;
|
|
6
|
+
}
|
|
7
|
+
const { app, config, start, stop } = createApp({
|
|
8
|
+
configPath: options.configPath,
|
|
9
|
+
autoApprove: options.autoApprove,
|
|
10
|
+
});
|
|
11
|
+
const server = app.listen(config.port, async () => {
|
|
12
|
+
logger.info({ port: config.port, autoApprove: options.autoApprove }, 'Lucifer listening');
|
|
13
|
+
await start();
|
|
14
|
+
});
|
|
15
|
+
const shutdown = async () => {
|
|
16
|
+
logger.info('Shutting down');
|
|
17
|
+
await stop();
|
|
18
|
+
server.close();
|
|
19
|
+
process.exit(0);
|
|
20
|
+
};
|
|
21
|
+
process.on('SIGTERM', shutdown);
|
|
22
|
+
process.on('SIGINT', shutdown);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=run_server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_server.js","sourceRoot":"","sources":["../../../server/src/cli/run_server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ1C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAyB;IACvD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAClC,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;QAC7C,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAC1F,MAAM,KAAK,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7B,MAAM,IAAI,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getDatabase } from '../domains/command-gateway/repository/database.js';
|
|
2
|
+
import { createAuditLog } from '../domains/command-gateway/repository/audit_log.js';
|
|
3
|
+
import { createApprovalStore } from '../domains/command-gateway/repository/approval_store.js';
|
|
4
|
+
export async function runStats(dataDir) {
|
|
5
|
+
const db = getDatabase(dataDir);
|
|
6
|
+
const auditLog = createAuditLog(db);
|
|
7
|
+
const approvalStore = createApprovalStore(db);
|
|
8
|
+
const allEntries = auditLog.query(10000);
|
|
9
|
+
const requests = allEntries.filter(e => e.type === 'request');
|
|
10
|
+
const approvals = allEntries.filter(e => e.type === 'approved');
|
|
11
|
+
const denials = allEntries.filter(e => e.type === 'denied');
|
|
12
|
+
const executions = allEntries.filter(e => e.type === 'executed');
|
|
13
|
+
const activeApprovals = approvalStore.listAll(10000);
|
|
14
|
+
const expired = activeApprovals.filter(a => a.expiresAt && new Date(a.expiresAt) < new Date());
|
|
15
|
+
console.log('Lucifer Stats');
|
|
16
|
+
console.log('=============');
|
|
17
|
+
console.log(`Total requests: ${requests.length}`);
|
|
18
|
+
console.log(`Approved: ${approvals.length}`);
|
|
19
|
+
console.log(`Denied: ${denials.length}`);
|
|
20
|
+
console.log(`Executed: ${executions.length}`);
|
|
21
|
+
console.log(`Active approvals: ${activeApprovals.length - expired.length}`);
|
|
22
|
+
console.log(`Expired approvals: ${expired.length}`);
|
|
23
|
+
if (executions.length > 0) {
|
|
24
|
+
const durations = executions.filter(e => e.durationMs != null).map(e => e.durationMs);
|
|
25
|
+
if (durations.length > 0) {
|
|
26
|
+
const avg = Math.round(durations.reduce((a, b) => a + b, 0) / durations.length);
|
|
27
|
+
const max = Math.max(...durations);
|
|
28
|
+
console.log(`Avg exec time: ${avg}ms`);
|
|
29
|
+
console.log(`Max exec time: ${max}ms`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Top commands
|
|
33
|
+
const cmdCounts = new Map();
|
|
34
|
+
for (const r of requests) {
|
|
35
|
+
if (r.command) {
|
|
36
|
+
const cmd = r.command.split(/\s+/).slice(0, 2).join(' ');
|
|
37
|
+
cmdCounts.set(cmd, (cmdCounts.get(cmd) ?? 0) + 1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const topCmds = [...cmdCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10);
|
|
41
|
+
if (topCmds.length > 0) {
|
|
42
|
+
console.log('\nTop commands:');
|
|
43
|
+
for (const [cmd, count] of topCmds) {
|
|
44
|
+
console.log(` ${count.toString().padStart(5)} ${cmd}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=run_stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_stats.js","sourceRoot":"","sources":["../../../server/src/cli/run_stats.ts"],"names":[],"mappings":"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"}
|
package/dist/server/cli.js
CHANGED
|
@@ -1,253 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { createApprovalStore } from './domains/command-gateway/repository/approval_store.js';
|
|
10
|
-
import { runTelegramPairing } from './domains/command-gateway/service/telegram_pairing.js';
|
|
11
|
-
import { redactApiKeyName } from './domains/command-gateway/service/redact_api_key_name.js';
|
|
12
|
-
import { getTelegramToken } from './domains/command-gateway/config/gateway_config.js';
|
|
13
|
-
import { updateJsonConfig } from './lib/json_config_writer.js';
|
|
14
|
-
import { logger } from './lib/logger.js';
|
|
2
|
+
import { getArgValue } from './cli/args.js';
|
|
3
|
+
import { printHelp } from './cli/print_help.js';
|
|
4
|
+
import { initConfig } from './cli/init_config.js';
|
|
5
|
+
import { runLog } from './cli/run_log.js';
|
|
6
|
+
import { runStats } from './cli/run_stats.js';
|
|
7
|
+
import { runPair } from './cli/run_pair.js';
|
|
8
|
+
import { runServer } from './cli/run_server.js';
|
|
15
9
|
const args = process.argv.slice(2);
|
|
16
|
-
function printHelp() {
|
|
17
|
-
console.log(`
|
|
18
|
-
lucifer-gate - AI Agent Command Firewall
|
|
19
|
-
|
|
20
|
-
Usage:
|
|
21
|
-
lucifer-gate start [options] Start the server (explicit form)
|
|
22
|
-
lucifer-gate [options] Start the server (implicit, same as 'start')
|
|
23
|
-
lucifer-gate --init [dir] Generate starter config files
|
|
24
|
-
lucifer-gate pair [--config <path>] Pair a Telegram chat for approvals
|
|
25
|
-
lucifer-gate log [--limit N] Query audit log
|
|
26
|
-
lucifer-gate stats Show approval statistics
|
|
27
|
-
|
|
28
|
-
Server options:
|
|
29
|
-
--config <path> Path to lucifer.json (default: ./config/lucifer.json)
|
|
30
|
-
--port <number> Server port (default: 3001, or PORT env var)
|
|
31
|
-
--data-dir <path> Directory for SQLite database (default: ./data)
|
|
32
|
-
--auto-approve Auto-approve all commands (dev mode, no Telegram needed)
|
|
33
|
-
--help Show this help
|
|
34
|
-
|
|
35
|
-
Environment variables:
|
|
36
|
-
LUCIFER_TELEGRAM_TOKEN Telegram bot token (required for production)
|
|
37
|
-
LUCIFER_TELEGRAM_CHAT_ID Telegram chat ID for approvals (or use 'pair' command)
|
|
38
|
-
PORT Server port (default: 3001)
|
|
39
|
-
LOG_LEVEL Log level: debug, info, warn, error (default: debug / info in production)
|
|
40
|
-
`);
|
|
41
|
-
}
|
|
42
|
-
function initConfig(targetDir) {
|
|
43
|
-
const configDir = resolve(targetDir, 'config');
|
|
44
|
-
const dataDir = resolve(targetDir, 'data');
|
|
45
|
-
mkdirSync(configDir, { recursive: true });
|
|
46
|
-
mkdirSync(dataDir, { recursive: true });
|
|
47
|
-
const luciferJsonPath = join(configDir, 'lucifer.json');
|
|
48
|
-
const apiKeysPath = join(configDir, 'api-keys.json');
|
|
49
|
-
const commandRulesPath = join(configDir, 'command-rules.json');
|
|
50
|
-
const proxyConfigPath = join(configDir, 'proxy-config.json');
|
|
51
|
-
if (existsSync(luciferJsonPath)) {
|
|
52
|
-
console.log(`Config already exists: ${luciferJsonPath}`);
|
|
53
|
-
console.log('Delete it first if you want to regenerate.');
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const { key, salt, keyHash } = generateApiKey();
|
|
57
|
-
const { secret: adminSecret, salt: adminSalt, secretHash: adminHash } = generateAdminSecret();
|
|
58
|
-
writeFileSync(luciferJsonPath, JSON.stringify({
|
|
59
|
-
port: 3001,
|
|
60
|
-
adminSecretHash: adminHash,
|
|
61
|
-
adminSecretSalt: adminSalt,
|
|
62
|
-
approvalTimeoutSeconds: 300,
|
|
63
|
-
executionTimeoutSeconds: 120,
|
|
64
|
-
maxConcurrentExecutions: 5,
|
|
65
|
-
maxOutputBytes: 10485760,
|
|
66
|
-
rateLimitPerMinute: 10,
|
|
67
|
-
onApprovalTimeout: 'deny',
|
|
68
|
-
dataDir: '../data',
|
|
69
|
-
logFile: 'lucifer.log',
|
|
70
|
-
}, null, 2) + '\n');
|
|
71
|
-
writeFileSync(apiKeysPath, JSON.stringify({
|
|
72
|
-
keys: [{
|
|
73
|
-
id: crypto.randomUUID(),
|
|
74
|
-
name: 'default',
|
|
75
|
-
keyHash,
|
|
76
|
-
salt,
|
|
77
|
-
allowedIps: [],
|
|
78
|
-
createdAt: new Date().toISOString(),
|
|
79
|
-
active: true,
|
|
80
|
-
}],
|
|
81
|
-
}, null, 2) + '\n');
|
|
82
|
-
writeFileSync(commandRulesPath, JSON.stringify({
|
|
83
|
-
rules: [
|
|
84
|
-
{ prefix: 'echo ', action: 'always_approve' },
|
|
85
|
-
{ prefix: 'git status', action: 'always_approve' },
|
|
86
|
-
{ prefix: 'git pull', action: 'manual_approve' },
|
|
87
|
-
{ prefix: 'git push', action: 'manual_approve' },
|
|
88
|
-
{ prefix: 'npm test', action: 'always_approve' },
|
|
89
|
-
{ prefix: 'npm run', action: 'manual_approve' },
|
|
90
|
-
{ prefix: 'rm ', action: 'always_deny' },
|
|
91
|
-
],
|
|
92
|
-
defaultAction: 'always_deny',
|
|
93
|
-
}, null, 2) + '\n');
|
|
94
|
-
writeFileSync(proxyConfigPath, JSON.stringify({
|
|
95
|
-
proxies: [],
|
|
96
|
-
}, null, 2) + '\n');
|
|
97
|
-
console.log('Config files generated:');
|
|
98
|
-
console.log(` ${luciferJsonPath}`);
|
|
99
|
-
console.log(` ${apiKeysPath}`);
|
|
100
|
-
console.log(` ${commandRulesPath}`);
|
|
101
|
-
console.log(` ${proxyConfigPath}`);
|
|
102
|
-
console.log('');
|
|
103
|
-
console.log('Your API key (save this, it cannot be recovered):');
|
|
104
|
-
console.log(` ${key}`);
|
|
105
|
-
console.log('');
|
|
106
|
-
console.log('Your admin secret for the web approval UI (save this, it cannot be recovered):');
|
|
107
|
-
console.log(` ${adminSecret}`);
|
|
108
|
-
console.log('');
|
|
109
|
-
console.log('Quick start:');
|
|
110
|
-
console.log(' # Dev mode (no Telegram needed):');
|
|
111
|
-
console.log(` LUCIFER_TELEGRAM_TOKEN=skip lucifer-gate --config ${luciferJsonPath} --auto-approve`);
|
|
112
|
-
console.log('');
|
|
113
|
-
console.log(' # Production — pair your Telegram chat first:');
|
|
114
|
-
console.log(` LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate pair --config ${luciferJsonPath}`);
|
|
115
|
-
console.log('');
|
|
116
|
-
console.log(' # Then start the server:');
|
|
117
|
-
console.log(` LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate --config ${luciferJsonPath}`);
|
|
118
|
-
}
|
|
119
|
-
async function runLog(limit) {
|
|
120
|
-
const dataDir = getArgValue('--data-dir') ?? './data';
|
|
121
|
-
const db = getDatabase(dataDir);
|
|
122
|
-
const auditLog = createAuditLog(db);
|
|
123
|
-
const entries = auditLog.query(limit);
|
|
124
|
-
if (entries.length === 0) {
|
|
125
|
-
console.log('No audit log entries found.');
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const reversed = [...entries].reverse();
|
|
129
|
-
for (const entry of reversed) {
|
|
130
|
-
const time = entry.ts.replace('T', ' ').replace(/\.\d+Z$/, 'Z');
|
|
131
|
-
const parts = [time, entry.type.toUpperCase().padEnd(16)];
|
|
132
|
-
if (entry.command)
|
|
133
|
-
parts.push(entry.command);
|
|
134
|
-
if (entry.apiKeyName)
|
|
135
|
-
parts.push(`key=${redactApiKeyName(entry.apiKeyName)}`);
|
|
136
|
-
if (entry.exitCode !== undefined && entry.exitCode !== null)
|
|
137
|
-
parts.push(`exit=${entry.exitCode}`);
|
|
138
|
-
if (entry.durationMs !== undefined && entry.durationMs !== null)
|
|
139
|
-
parts.push(`${entry.durationMs}ms`);
|
|
140
|
-
if (entry.error)
|
|
141
|
-
parts.push(`error: ${entry.error}`);
|
|
142
|
-
console.log(parts.join(' '));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
async function runStats() {
|
|
146
|
-
const dataDir = getArgValue('--data-dir') ?? './data';
|
|
147
|
-
const db = getDatabase(dataDir);
|
|
148
|
-
const auditLog = createAuditLog(db);
|
|
149
|
-
const approvalStore = createApprovalStore(db);
|
|
150
|
-
const allEntries = auditLog.query(10000);
|
|
151
|
-
const requests = allEntries.filter(e => e.type === 'request');
|
|
152
|
-
const approvals = allEntries.filter(e => e.type === 'approved');
|
|
153
|
-
const denials = allEntries.filter(e => e.type === 'denied');
|
|
154
|
-
const executions = allEntries.filter(e => e.type === 'executed');
|
|
155
|
-
const activeApprovals = approvalStore.listAll(10000);
|
|
156
|
-
const expired = activeApprovals.filter(a => a.expiresAt && new Date(a.expiresAt) < new Date());
|
|
157
|
-
console.log('Lucifer Stats');
|
|
158
|
-
console.log('=============');
|
|
159
|
-
console.log(`Total requests: ${requests.length}`);
|
|
160
|
-
console.log(`Approved: ${approvals.length}`);
|
|
161
|
-
console.log(`Denied: ${denials.length}`);
|
|
162
|
-
console.log(`Executed: ${executions.length}`);
|
|
163
|
-
console.log(`Active approvals: ${activeApprovals.length - expired.length}`);
|
|
164
|
-
console.log(`Expired approvals: ${expired.length}`);
|
|
165
|
-
if (executions.length > 0) {
|
|
166
|
-
const durations = executions.filter(e => e.durationMs != null).map(e => e.durationMs);
|
|
167
|
-
if (durations.length > 0) {
|
|
168
|
-
const avg = Math.round(durations.reduce((a, b) => a + b, 0) / durations.length);
|
|
169
|
-
const max = Math.max(...durations);
|
|
170
|
-
console.log(`Avg exec time: ${avg}ms`);
|
|
171
|
-
console.log(`Max exec time: ${max}ms`);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
// Top commands
|
|
175
|
-
const cmdCounts = new Map();
|
|
176
|
-
for (const r of requests) {
|
|
177
|
-
if (r.command) {
|
|
178
|
-
const cmd = r.command.split(/\s+/).slice(0, 2).join(' ');
|
|
179
|
-
cmdCounts.set(cmd, (cmdCounts.get(cmd) ?? 0) + 1);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const topCmds = [...cmdCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10);
|
|
183
|
-
if (topCmds.length > 0) {
|
|
184
|
-
console.log('\nTop commands:');
|
|
185
|
-
for (const [cmd, count] of topCmds) {
|
|
186
|
-
console.log(` ${count.toString().padStart(5)} ${cmd}`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
function createReadlinePairingIO() {
|
|
191
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
192
|
-
return {
|
|
193
|
-
print(msg) {
|
|
194
|
-
console.log(msg);
|
|
195
|
-
},
|
|
196
|
-
async choose(prompt, options) {
|
|
197
|
-
console.log(`\n${prompt}`);
|
|
198
|
-
for (let i = 0; i < options.length; i++) {
|
|
199
|
-
console.log(` ${i + 1}. ${options[i]}`);
|
|
200
|
-
}
|
|
201
|
-
while (true) {
|
|
202
|
-
const answer = await rl.question(`\nEnter number (1-${options.length}): `);
|
|
203
|
-
const num = Number.parseInt(answer.trim(), 10);
|
|
204
|
-
if (num >= 1 && num <= options.length)
|
|
205
|
-
return num - 1;
|
|
206
|
-
console.log(`Please enter a number between 1 and ${options.length}.`);
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
async confirm(prompt) {
|
|
210
|
-
const answer = await rl.question(`${prompt} [y/N] `);
|
|
211
|
-
return /^y(es)?$/i.test(answer.trim());
|
|
212
|
-
},
|
|
213
|
-
async prompt(msg) {
|
|
214
|
-
return rl.question(`${msg} `);
|
|
215
|
-
},
|
|
216
|
-
close() {
|
|
217
|
-
rl.close();
|
|
218
|
-
},
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
async function runPair() {
|
|
222
|
-
const configPath = resolve(getArgValue('--config') ?? './config/lucifer.json');
|
|
223
|
-
let token;
|
|
224
|
-
try {
|
|
225
|
-
token = getTelegramToken();
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
console.error('LUCIFER_TELEGRAM_TOKEN environment variable is required for pairing.\n' +
|
|
229
|
-
'Create a bot via @BotFather on Telegram and set the token:\n\n' +
|
|
230
|
-
' LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate pair');
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
const io = createReadlinePairingIO();
|
|
234
|
-
try {
|
|
235
|
-
const result = await runTelegramPairing(token, io, { waitForChats: true });
|
|
236
|
-
updateJsonConfig(configPath, { telegramChatId: result.chatId });
|
|
237
|
-
console.log(`\nChat ID ${result.chatId} saved to ${configPath}`);
|
|
238
|
-
console.log('You can now start Lucifer without LUCIFER_TELEGRAM_CHAT_ID:');
|
|
239
|
-
console.log(`\n LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate start --config ${configPath}`);
|
|
240
|
-
}
|
|
241
|
-
finally {
|
|
242
|
-
io.close();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
function getArgValue(flag) {
|
|
246
|
-
const idx = args.indexOf(flag);
|
|
247
|
-
if (idx === -1 || idx >= args.length - 1)
|
|
248
|
-
return undefined;
|
|
249
|
-
return args[idx + 1];
|
|
250
|
-
}
|
|
251
10
|
async function main() {
|
|
252
11
|
if (args.includes('--help') || args.includes('-h')) {
|
|
253
12
|
printHelp();
|
|
@@ -259,16 +18,16 @@ async function main() {
|
|
|
259
18
|
process.exit(0);
|
|
260
19
|
}
|
|
261
20
|
if (args[0] === 'pair') {
|
|
262
|
-
await runPair();
|
|
21
|
+
await runPair(getArgValue(args, '--config') ?? './config/lucifer.json');
|
|
263
22
|
process.exit(0);
|
|
264
23
|
}
|
|
265
24
|
if (args[0] === 'log') {
|
|
266
|
-
const limitStr = getArgValue('--limit');
|
|
267
|
-
await runLog(limitStr ? parseInt(limitStr, 10) : 50);
|
|
25
|
+
const limitStr = getArgValue(args, '--limit');
|
|
26
|
+
await runLog(limitStr ? parseInt(limitStr, 10) : 50, getArgValue(args, '--data-dir') ?? './data');
|
|
268
27
|
process.exit(0);
|
|
269
28
|
}
|
|
270
29
|
if (args[0] === 'stats') {
|
|
271
|
-
await runStats();
|
|
30
|
+
await runStats(getArgValue(args, '--data-dir') ?? './data');
|
|
272
31
|
process.exit(0);
|
|
273
32
|
}
|
|
274
33
|
// Server mode — either `start` (explicit) or no subcommand (implicit).
|
|
@@ -280,28 +39,11 @@ async function main() {
|
|
|
280
39
|
console.error(`Run 'lucifer-gate --help' for usage.`);
|
|
281
40
|
process.exit(1);
|
|
282
41
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
process.env.PORT = port;
|
|
288
|
-
}
|
|
289
|
-
const { app, config, start, stop } = createApp({
|
|
290
|
-
configPath,
|
|
291
|
-
autoApprove,
|
|
42
|
+
await runServer({
|
|
43
|
+
configPath: getArgValue(args, '--config') ?? './config/lucifer.json',
|
|
44
|
+
port: getArgValue(args, '--port'),
|
|
45
|
+
autoApprove: args.includes('--auto-approve'),
|
|
292
46
|
});
|
|
293
|
-
const server = app.listen(config.port, async () => {
|
|
294
|
-
logger.info({ port: config.port, autoApprove }, 'Lucifer listening');
|
|
295
|
-
await start();
|
|
296
|
-
});
|
|
297
|
-
const shutdown = async () => {
|
|
298
|
-
logger.info('Shutting down');
|
|
299
|
-
await stop();
|
|
300
|
-
server.close();
|
|
301
|
-
process.exit(0);
|
|
302
|
-
};
|
|
303
|
-
process.on('SIGTERM', shutdown);
|
|
304
|
-
process.on('SIGINT', shutdown);
|
|
305
47
|
}
|
|
306
48
|
try {
|
|
307
49
|
await main();
|
package/dist/server/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../server/src/cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../server/src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,KAAK,UAAU,IAAI;IACjB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QAC3B,UAAU,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,uBAAuB,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC9C,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,QAAQ,CAAC,CAAC;QAClG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,QAAQ,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,uEAAuE;IACvE,oEAAoE;IACpE,iEAAiE;IACjE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,KAAK,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,CAAC;QACd,UAAU,EAAE,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,uBAAuB;QACpE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QACjC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,IAAI,CAAC;IACH,MAAM,IAAI,EAAE,CAAC;AACf,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import rateLimit from 'express-rate-limit';
|
|
3
3
|
import { authenticateRequest, createRateLimiter } from '../service/authenticate_request.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { executeAndAudit } from '../service/execute_and_audit.js';
|
|
5
|
+
import { handleManualApproval } from '../service/handle_manual_approval.js';
|
|
6
6
|
import { findAliasArgsBypass, resolveAlias } from '../service/resolve_alias.js';
|
|
7
|
-
import { createChildLogger } from '../../../lib/logger.js';
|
|
8
|
-
const log = createChildLogger('routes');
|
|
9
7
|
function validateExecuteInput(command, cwd) {
|
|
10
8
|
if (!command || typeof command !== 'string') {
|
|
11
9
|
return {
|
|
@@ -123,26 +121,7 @@ export function registerExecuteRoutes(deps) {
|
|
|
123
121
|
}
|
|
124
122
|
if (ruleMatch.action === 'always_approve') {
|
|
125
123
|
auditLog.append({ ts: new Date().toISOString(), type: 'approved', requestId, command, duration: 'policy', ...aliasAudit });
|
|
126
|
-
|
|
127
|
-
command,
|
|
128
|
-
requestId,
|
|
129
|
-
cwd,
|
|
130
|
-
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
131
|
-
maxOutputBytes: config.maxOutputBytes,
|
|
132
|
-
maxConcurrent: config.maxConcurrentExecutions,
|
|
133
|
-
aliases: config.aliases,
|
|
134
|
-
});
|
|
135
|
-
auditLog.append({
|
|
136
|
-
ts: new Date().toISOString(),
|
|
137
|
-
type: 'executed',
|
|
138
|
-
requestId,
|
|
139
|
-
command,
|
|
140
|
-
exitCode: result.exitCode,
|
|
141
|
-
durationMs: result.durationMs,
|
|
142
|
-
error: result.error,
|
|
143
|
-
...aliasAudit,
|
|
144
|
-
});
|
|
145
|
-
res.json(result);
|
|
124
|
+
await executeAndAudit({ command, requestId, cwd, config, auditLog, aliasAudit, res });
|
|
146
125
|
return;
|
|
147
126
|
}
|
|
148
127
|
// manual_approve: check existing approval in SQLite
|
|
@@ -156,153 +135,14 @@ export function registerExecuteRoutes(deps) {
|
|
|
156
135
|
duration: 'cached',
|
|
157
136
|
...aliasAudit,
|
|
158
137
|
});
|
|
159
|
-
|
|
160
|
-
command,
|
|
161
|
-
requestId,
|
|
162
|
-
cwd,
|
|
163
|
-
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
164
|
-
maxOutputBytes: config.maxOutputBytes,
|
|
165
|
-
maxConcurrent: config.maxConcurrentExecutions,
|
|
166
|
-
aliases: config.aliases,
|
|
167
|
-
});
|
|
168
|
-
auditLog.append({
|
|
169
|
-
ts: new Date().toISOString(),
|
|
170
|
-
type: 'executed',
|
|
171
|
-
requestId,
|
|
172
|
-
command,
|
|
173
|
-
exitCode: result.exitCode,
|
|
174
|
-
durationMs: result.durationMs,
|
|
175
|
-
error: result.error,
|
|
176
|
-
...aliasAudit,
|
|
177
|
-
});
|
|
178
|
-
res.json(result);
|
|
138
|
+
await executeAndAudit({ command, requestId, cwd, config, auditLog, aliasAudit, res });
|
|
179
139
|
return;
|
|
180
140
|
}
|
|
181
141
|
// Need manual approval (Telegram / web admin)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// awaiting an approval decision — two parallel prompts for the same
|
|
187
|
-
// command would confuse the human approver. The pendingStore entry is
|
|
188
|
-
// cleared as soon as a decision is reached (below), so this gate does
|
|
189
|
-
// NOT apply while an approved command is executing; a concurrent caller
|
|
190
|
-
// will fall through to the normal `findApproval` cached-approval path.
|
|
191
|
-
if (pendingStore.findByCommand(command, apiKeyName)) {
|
|
192
|
-
res.status(409).json({
|
|
193
|
-
code: 'DUPLICATE_IN_FLIGHT',
|
|
194
|
-
message: 'An identical command from this API key is already awaiting approval. Retry after it settles.',
|
|
195
|
-
retryable: true,
|
|
196
|
-
});
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
try {
|
|
200
|
-
pendingStore.add({
|
|
201
|
-
requestId,
|
|
202
|
-
command,
|
|
203
|
-
apiKeyName,
|
|
204
|
-
ip,
|
|
205
|
-
createdAt: new Date().toISOString(),
|
|
206
|
-
resolve: () => { },
|
|
207
|
-
reject: () => { },
|
|
208
|
-
abortController,
|
|
209
|
-
});
|
|
210
|
-
// Abort execution if the client disconnects before we finish writing
|
|
211
|
-
// the response. `res.on('close')` fires for both premature disconnects
|
|
212
|
-
// and normal completion, so we gate on `res.writableEnded` to ignore
|
|
213
|
-
// the normal-completion case.
|
|
214
|
-
res.on('close', () => {
|
|
215
|
-
if (res.writableEnded)
|
|
216
|
-
return;
|
|
217
|
-
abortController.abort();
|
|
218
|
-
pendingStore.remove(requestId);
|
|
219
|
-
});
|
|
220
|
-
const approvalResult = await Promise.race([
|
|
221
|
-
approvalChannel.requestApproval(command, apiKeyName, ip, requestId, riskAnalysis),
|
|
222
|
-
new Promise((_, reject) => {
|
|
223
|
-
setTimeout(() => reject(new Error('Approval timed out')), config.approvalTimeoutSeconds * 1000);
|
|
224
|
-
}),
|
|
225
|
-
// Bail out of the approval wait if the client disconnected. Otherwise
|
|
226
|
-
// the handler would continue awaiting the channel until either the
|
|
227
|
-
// approver acts or the approval timeout fires — orphaning work that
|
|
228
|
-
// nobody is listening for.
|
|
229
|
-
new Promise((_, reject) => {
|
|
230
|
-
if (abortController.signal.aborted) {
|
|
231
|
-
reject(new Error('Request aborted'));
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
abortController.signal.addEventListener('abort', () => reject(new Error('Request aborted')), { once: true });
|
|
235
|
-
}),
|
|
236
|
-
]);
|
|
237
|
-
// Approval decision obtained — release the pending-store slot now so
|
|
238
|
-
// DUPLICATE_IN_FLIGHT only gates *awaiting-approval* duplicates and
|
|
239
|
-
// not in-flight execution. `release` (unlike `remove`) does not abort
|
|
240
|
-
// the live AbortController, which still guards the upcoming execution.
|
|
241
|
-
pendingStore.release(requestId);
|
|
242
|
-
if (approvalResult.decision === 'denied') {
|
|
243
|
-
res.status(403).json({
|
|
244
|
-
requestId,
|
|
245
|
-
status: 'denied',
|
|
246
|
-
code: 'DENIED',
|
|
247
|
-
message: 'Command was denied',
|
|
248
|
-
retryable: false,
|
|
249
|
-
});
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
const result = await executeCommand({
|
|
253
|
-
command,
|
|
254
|
-
requestId,
|
|
255
|
-
cwd,
|
|
256
|
-
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
257
|
-
maxOutputBytes: config.maxOutputBytes,
|
|
258
|
-
maxConcurrent: config.maxConcurrentExecutions,
|
|
259
|
-
abortSignal: abortController.signal,
|
|
260
|
-
aliases: config.aliases,
|
|
261
|
-
});
|
|
262
|
-
auditLog.append({
|
|
263
|
-
ts: new Date().toISOString(),
|
|
264
|
-
type: 'executed',
|
|
265
|
-
requestId,
|
|
266
|
-
command,
|
|
267
|
-
exitCode: result.exitCode,
|
|
268
|
-
durationMs: result.durationMs,
|
|
269
|
-
error: result.error,
|
|
270
|
-
...aliasAudit,
|
|
271
|
-
});
|
|
272
|
-
res.json(result);
|
|
273
|
-
}
|
|
274
|
-
catch (err) {
|
|
275
|
-
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
276
|
-
if (message.includes('aborted')) {
|
|
277
|
-
// Client disconnected before a decision landed. Ask the channel to
|
|
278
|
-
// clean up any bot message / admin queue entry. No response to send.
|
|
279
|
-
try {
|
|
280
|
-
approvalChannel.cancel?.(requestId);
|
|
281
|
-
}
|
|
282
|
-
catch { /* best-effort */ }
|
|
283
|
-
log.info({ requestId }, 'Approval wait aborted by client disconnect');
|
|
284
|
-
}
|
|
285
|
-
else if (message.includes('timed out')) {
|
|
286
|
-
res.status(408).json({
|
|
287
|
-
requestId,
|
|
288
|
-
status: 'timed_out',
|
|
289
|
-
code: 'APPROVAL_TIMEOUT',
|
|
290
|
-
message: 'Approval timed out. No response from approver.',
|
|
291
|
-
retryable: true,
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
res.status(503).json({
|
|
296
|
-
requestId,
|
|
297
|
-
code: 'APPROVAL_ERROR',
|
|
298
|
-
message: `Approval channel error: ${message}`,
|
|
299
|
-
retryable: true,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
finally {
|
|
304
|
-
pendingStore.remove(requestId);
|
|
305
|
-
}
|
|
142
|
+
await handleManualApproval({
|
|
143
|
+
command, requestId, apiKeyName, ip, cwd, config,
|
|
144
|
+
approvalChannel, pendingStore, auditLog, aliasAudit, res,
|
|
145
|
+
});
|
|
306
146
|
});
|
|
307
147
|
}
|
|
308
148
|
//# sourceMappingURL=register_execute_routes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register_execute_routes.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/api/register_execute_routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAK3C,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,
|
|
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,32 @@
|
|
|
1
|
+
import { executeCommand } from './execute_command.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs `executeCommand` with config-derived options, writes the `executed`
|
|
4
|
+
* audit entry (carrying alias context when present), and returns the JSON
|
|
5
|
+
* response. Shared across the always_approve, cached-approval, and
|
|
6
|
+
* manual-approve branches so audit shape stays identical.
|
|
7
|
+
*/
|
|
8
|
+
export async function executeAndAudit(args) {
|
|
9
|
+
const { command, requestId, cwd, config, auditLog, aliasAudit, abortSignal, res } = args;
|
|
10
|
+
const result = await executeCommand({
|
|
11
|
+
command,
|
|
12
|
+
requestId,
|
|
13
|
+
cwd,
|
|
14
|
+
timeoutMs: config.executionTimeoutSeconds * 1000,
|
|
15
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
16
|
+
maxConcurrent: config.maxConcurrentExecutions,
|
|
17
|
+
abortSignal,
|
|
18
|
+
aliases: config.aliases,
|
|
19
|
+
});
|
|
20
|
+
auditLog.append({
|
|
21
|
+
ts: new Date().toISOString(),
|
|
22
|
+
type: 'executed',
|
|
23
|
+
requestId,
|
|
24
|
+
command,
|
|
25
|
+
exitCode: result.exitCode,
|
|
26
|
+
durationMs: result.durationMs,
|
|
27
|
+
error: result.error,
|
|
28
|
+
...aliasAudit,
|
|
29
|
+
});
|
|
30
|
+
res.json(result);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=execute_and_audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute_and_audit.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/execute_and_audit.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAetD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAyB;IAC7D,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACzF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,OAAO;QACP,SAAS;QACT,GAAG;QACH,SAAS,EAAE,MAAM,CAAC,uBAAuB,GAAG,IAAI;QAChD,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,aAAa,EAAE,MAAM,CAAC,uBAAuB;QAC7C,WAAW;QACX,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;IACH,QAAQ,CAAC,MAAM,CAAC;QACd,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,IAAI,EAAE,UAAU;QAChB,SAAS;QACT,OAAO;QACP,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,UAAU;KACd,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { analyzeCommandRisk } from './analyze_command_risk.js';
|
|
2
|
+
import { executeAndAudit } from './execute_and_audit.js';
|
|
3
|
+
import { createChildLogger } from '../../../lib/logger.js';
|
|
4
|
+
const log = createChildLogger('routes');
|
|
5
|
+
/**
|
|
6
|
+
* Handles the manual_approve branch: pending-store gating, abort-on-disconnect
|
|
7
|
+
* wiring, approval channel race with timeout, and the final execute+audit or
|
|
8
|
+
* decision-rejection response. Separated from `registerExecuteRoutes` because
|
|
9
|
+
* it dominated the route handler's line count; behaviour is unchanged.
|
|
10
|
+
*/
|
|
11
|
+
export async function handleManualApproval(args) {
|
|
12
|
+
const { command, requestId, apiKeyName, ip, cwd, config, approvalChannel, pendingStore, auditLog, aliasAudit, res, } = args;
|
|
13
|
+
const riskAnalysis = analyzeCommandRisk(command);
|
|
14
|
+
const abortController = new AbortController();
|
|
15
|
+
log.info({ requestId, command, ip }, 'Command requires manual approval, forwarding to approval channel');
|
|
16
|
+
// Reject an identical command from the same API key that is still
|
|
17
|
+
// awaiting an approval decision — two parallel prompts for the same
|
|
18
|
+
// command would confuse the human approver. The pendingStore entry is
|
|
19
|
+
// cleared as soon as a decision is reached (below), so this gate does
|
|
20
|
+
// NOT apply while an approved command is executing; a concurrent caller
|
|
21
|
+
// will fall through to the normal `findApproval` cached-approval path.
|
|
22
|
+
if (pendingStore.findByCommand(command, apiKeyName)) {
|
|
23
|
+
res.status(409).json({
|
|
24
|
+
code: 'DUPLICATE_IN_FLIGHT',
|
|
25
|
+
message: 'An identical command from this API key is already awaiting approval. Retry after it settles.',
|
|
26
|
+
retryable: true,
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
pendingStore.add({
|
|
32
|
+
requestId,
|
|
33
|
+
command,
|
|
34
|
+
apiKeyName,
|
|
35
|
+
ip,
|
|
36
|
+
createdAt: new Date().toISOString(),
|
|
37
|
+
resolve: () => { },
|
|
38
|
+
reject: () => { },
|
|
39
|
+
abortController,
|
|
40
|
+
});
|
|
41
|
+
// Abort execution if the client disconnects before we finish writing
|
|
42
|
+
// the response. `res.on('close')` fires for both premature disconnects
|
|
43
|
+
// and normal completion, so we gate on `res.writableEnded` to ignore
|
|
44
|
+
// the normal-completion case.
|
|
45
|
+
res.on('close', () => {
|
|
46
|
+
if (res.writableEnded)
|
|
47
|
+
return;
|
|
48
|
+
abortController.abort();
|
|
49
|
+
pendingStore.remove(requestId);
|
|
50
|
+
});
|
|
51
|
+
const approvalResult = await Promise.race([
|
|
52
|
+
approvalChannel.requestApproval(command, apiKeyName, ip, requestId, riskAnalysis),
|
|
53
|
+
new Promise((_, reject) => {
|
|
54
|
+
setTimeout(() => reject(new Error('Approval timed out')), config.approvalTimeoutSeconds * 1000);
|
|
55
|
+
}),
|
|
56
|
+
// Bail out of the approval wait if the client disconnected. Otherwise
|
|
57
|
+
// the handler would continue awaiting the channel until either the
|
|
58
|
+
// approver acts or the approval timeout fires — orphaning work that
|
|
59
|
+
// nobody is listening for.
|
|
60
|
+
new Promise((_, reject) => {
|
|
61
|
+
if (abortController.signal.aborted) {
|
|
62
|
+
reject(new Error('Request aborted'));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
abortController.signal.addEventListener('abort', () => reject(new Error('Request aborted')), { once: true });
|
|
66
|
+
}),
|
|
67
|
+
]);
|
|
68
|
+
// Approval decision obtained — release the pending-store slot now so
|
|
69
|
+
// DUPLICATE_IN_FLIGHT only gates *awaiting-approval* duplicates and
|
|
70
|
+
// not in-flight execution. `release` (unlike `remove`) does not abort
|
|
71
|
+
// the live AbortController, which still guards the upcoming execution.
|
|
72
|
+
pendingStore.release(requestId);
|
|
73
|
+
if (approvalResult.decision === 'denied') {
|
|
74
|
+
res.status(403).json({
|
|
75
|
+
requestId,
|
|
76
|
+
status: 'denied',
|
|
77
|
+
code: 'DENIED',
|
|
78
|
+
message: 'Command was denied',
|
|
79
|
+
retryable: false,
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
await executeAndAudit({
|
|
84
|
+
command, requestId, cwd, config, auditLog, aliasAudit,
|
|
85
|
+
abortSignal: abortController.signal,
|
|
86
|
+
res,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
91
|
+
if (message.includes('aborted')) {
|
|
92
|
+
// Client disconnected before a decision landed. Ask the channel to
|
|
93
|
+
// clean up any bot message / admin queue entry. No response to send.
|
|
94
|
+
try {
|
|
95
|
+
approvalChannel.cancel?.(requestId);
|
|
96
|
+
}
|
|
97
|
+
catch { /* best-effort */ }
|
|
98
|
+
log.info({ requestId }, 'Approval wait aborted by client disconnect');
|
|
99
|
+
}
|
|
100
|
+
else if (message.includes('timed out')) {
|
|
101
|
+
res.status(408).json({
|
|
102
|
+
requestId,
|
|
103
|
+
status: 'timed_out',
|
|
104
|
+
code: 'APPROVAL_TIMEOUT',
|
|
105
|
+
message: 'Approval timed out. No response from approver.',
|
|
106
|
+
retryable: true,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
res.status(503).json({
|
|
111
|
+
requestId,
|
|
112
|
+
code: 'APPROVAL_ERROR',
|
|
113
|
+
message: `Approval channel error: ${message}`,
|
|
114
|
+
retryable: true,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
pendingStore.remove(requestId);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=handle_manual_approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle_manual_approval.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/handle_manual_approval.ts"],"names":[],"mappings":"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"}
|