lucifer-gate 0.3.1 → 0.4.0-alpha.3.aedac37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,7 +35,7 @@ curl -X POST http://localhost:3001/api/v1/execute \
35
35
 
36
36
  Generated by `--init`, hand-editable:
37
37
 
38
- **config/lucifer.json** - Server settings (port, timeouts, limits)
38
+ **config/lucifer.json** - Server settings (port, timeouts, limits, log file path)
39
39
 
40
40
  **config/api-keys.json** - API key definitions (hashed, with optional IP allowlists)
41
41
 
@@ -56,15 +56,29 @@ Rules matched top-to-bottom, first match wins.
56
56
  ## Production setup (with Telegram)
57
57
 
58
58
  1. Create a Telegram bot via [@BotFather](https://t.me/BotFather) and get the token
59
- 2. Send any message to your bot, then get your chat ID from `https://api.telegram.org/bot<TOKEN>/getUpdates`
60
- 3. Run:
59
+ 2. Send any message to your bot from the chat you want to use for approvals
60
+ 3. Run the pairing command:
61
61
 
62
62
  ```bash
63
- LUCIFER_TELEGRAM_TOKEN=your_bot_token \
64
- LUCIFER_TELEGRAM_CHAT_ID=your_chat_id \
65
- npx lucifer-gate --config ./config/lucifer.json
63
+ LUCIFER_TELEGRAM_TOKEN=your_bot_token npx lucifer-gate pair --config ./config/lucifer.json
66
64
  ```
67
65
 
66
+ The pairing wizard will:
67
+ - Validate your bot token
68
+ - List all chats that have messaged the bot (most recent first)
69
+ - Let you pick which chat to use for approvals
70
+ - Send a 6-digit verification code to that chat
71
+ - Ask you to enter the code to prove you can read the chat
72
+ - Save the chat ID to `config/lucifer.json`
73
+
74
+ 4. Start the server (no `LUCIFER_TELEGRAM_CHAT_ID` env var needed — it's in the config):
75
+
76
+ ```bash
77
+ LUCIFER_TELEGRAM_TOKEN=your_bot_token npx lucifer-gate --config ./config/lucifer.json
78
+ ```
79
+
80
+ > **Manual alternative:** You can still set `LUCIFER_TELEGRAM_CHAT_ID` as an environment variable instead of using `pair`. The env var takes precedence over the config file value.
81
+
68
82
  When a `telegram_approve` command arrives, you'll see an inline keyboard in Telegram:
69
83
 
70
84
  ```
@@ -121,11 +135,12 @@ Codes: `MISSING_API_KEY`, `INVALID_API_KEY`, `IP_NOT_ALLOWED`, `RATE_LIMITED`, `
121
135
  ## CLI
122
136
 
123
137
  ```
124
- lucifer-gate --init [dir] Generate starter config + API key
125
- lucifer-gate --config <path> Start server with config
126
- lucifer-gate --auto-approve Dev mode (no Telegram)
127
- lucifer-gate log [--limit N] Query audit log
128
- lucifer-gate stats Show approval statistics
138
+ lucifer-gate --init [dir] Generate starter config + API key
139
+ lucifer-gate pair [--config <path>] Pair a Telegram chat for approvals
140
+ lucifer-gate --config <path> Start server with config
141
+ lucifer-gate --auto-approve Dev mode (no Telegram)
142
+ lucifer-gate log [--limit N] Query audit log
143
+ lucifer-gate stats Show approval statistics
129
144
  ```
130
145
 
131
146
  ## Docker
@@ -140,14 +155,46 @@ docker run -p 3001:3001 \
140
155
  lucifer-gate
141
156
  ```
142
157
 
158
+ ## Logging
159
+
160
+ Lucifer logs to **both console and file** by default.
161
+
162
+ **Console output** is human-readable (colorized, formatted) when `pino-pretty` is available, and falls back to structured JSON otherwise. `pino-pretty` is included when you clone the repo and run `npm install`, but is not bundled with the published npm package — so `npx lucifer-gate` uses JSON console output. This is expected and fully functional.
163
+
164
+ **File output** is always structured JSON (one object per line), written to `data/lucifer.log` by default. Each line is a complete JSON object, making it easy to search, filter, and feed into log aggregators.
165
+
166
+ File logging is enabled via `config/lucifer.json`:
167
+
168
+ ```json
169
+ {
170
+ "logFile": "lucifer.log",
171
+ ...
172
+ }
173
+ ```
174
+
175
+ The `logFile` path is relative to `dataDir` (default: `data/lucifer.log`). Remove the key to disable file logging. The `--init` command generates the config with file logging enabled.
176
+
177
+ **Log levels** (controlled via `LOG_LEVEL` env var):
178
+ - `debug` — verbose output (default in development)
179
+ - `info` — normal operations (default in production, when `NODE_ENV=production`)
180
+ - `warn` — potential issues
181
+ - `error` — failures only
182
+
183
+ Example:
184
+ ```bash
185
+ LOG_LEVEL=info LUCIFER_TELEGRAM_TOKEN=your_token npx lucifer-gate --config ./config/lucifer.json
186
+ ```
187
+
143
188
  ## Environment variables
144
189
 
145
190
  | Variable | Required | Description |
146
191
  |---|---|---|
147
192
  | `LUCIFER_TELEGRAM_TOKEN` | Yes (prod) | Telegram bot token from @BotFather |
148
- | `LUCIFER_TELEGRAM_CHAT_ID` | Yes (prod) | Telegram chat ID for approvals |
193
+ | `LUCIFER_TELEGRAM_CHAT_ID` | No | Telegram chat ID (use `pair` command instead, or set manually) |
149
194
  | `LUCIFER_ADMIN_SECRET` | No | Bearer token for admin endpoints |
150
195
  | `PORT` | No | Server port (default: 3001) |
196
+ | `LOG_LEVEL` | No | Log level: `debug`, `info`, `warn`, `error` (default: `debug` / `info` in production) |
197
+ | `NODE_ENV` | No | Set to `production` for production defaults (info log level, no pretty-printing) |
151
198
 
152
199
  ## Architecture
153
200
 
@@ -169,6 +216,6 @@ Dependency flow: Types -> Config -> Repository -> Service -> API
169
216
  - Express 5 + TypeScript
170
217
  - SQLite (better-sqlite3) for approvals + audit
171
218
  - Telegraf for Telegram bot
172
- - Pino for structured logging
219
+ - Pino for structured logging (pino-pretty for human-readable console output in dev)
173
220
  - Vitest for testing
174
221
  - React 19 + Vite 8 (admin UI planned for v1.1)
@@ -1,11 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
3
3
  import { resolve, join } from 'node:path';
4
+ import { createInterface } from 'node:readline/promises';
4
5
  import { createApp } from './create_app.js';
5
6
  import { generateApiKey } from './domains/command-gateway/repository/api_key_store.js';
6
7
  import { getDatabase } from './domains/command-gateway/repository/database.js';
7
8
  import { createAuditLog } from './domains/command-gateway/repository/audit_log.js';
8
9
  import { createApprovalStore } from './domains/command-gateway/repository/approval_store.js';
10
+ import { runTelegramPairing } from './domains/command-gateway/service/telegram_pairing.js';
11
+ import { getTelegramToken } from './domains/command-gateway/config/gateway_config.js';
12
+ import { updateJsonConfig } from './lib/json_config_writer.js';
9
13
  import { logger } from './lib/logger.js';
10
14
  const args = process.argv.slice(2);
11
15
  function printHelp() {
@@ -13,10 +17,11 @@ function printHelp() {
13
17
  lucifer-gate - AI Agent Command Firewall
14
18
 
15
19
  Usage:
16
- lucifer-gate [options] Start the server
17
- lucifer-gate --init [dir] Generate starter config files
18
- lucifer-gate log [--limit N] Query audit log
19
- lucifer-gate stats Show approval statistics
20
+ lucifer-gate [options] Start the server
21
+ lucifer-gate --init [dir] Generate starter config files
22
+ lucifer-gate pair [--config <path>] Pair a Telegram chat for approvals
23
+ lucifer-gate log [--limit N] Query audit log
24
+ lucifer-gate stats Show approval statistics
20
25
 
21
26
  Server options:
22
27
  --config <path> Path to lucifer.json (default: ./config/lucifer.json)
@@ -27,9 +32,10 @@ Server options:
27
32
 
28
33
  Environment variables:
29
34
  LUCIFER_TELEGRAM_TOKEN Telegram bot token (required for production)
30
- LUCIFER_TELEGRAM_CHAT_ID Telegram chat ID for approvals
35
+ LUCIFER_TELEGRAM_CHAT_ID Telegram chat ID for approvals (or use 'pair' command)
31
36
  LUCIFER_ADMIN_SECRET Admin API bearer token (optional)
32
37
  PORT Server port (default: 3001)
38
+ LOG_LEVEL Log level: debug, info, warn, error (default: debug / info in production)
33
39
  `);
34
40
  }
35
41
  function initConfig(targetDir) {
@@ -55,6 +61,7 @@ function initConfig(targetDir) {
55
61
  rateLimitPerMinute: 10,
56
62
  onApprovalTimeout: 'deny',
57
63
  dataDir: '../data',
64
+ logFile: 'lucifer.log',
58
65
  }, null, 2) + '\n');
59
66
  writeFileSync(apiKeysPath, JSON.stringify({
60
67
  keys: [{
@@ -91,8 +98,11 @@ function initConfig(targetDir) {
91
98
  console.log(' # Dev mode (no Telegram needed):');
92
99
  console.log(` LUCIFER_TELEGRAM_TOKEN=skip lucifer-gate --config ${luciferJsonPath} --auto-approve`);
93
100
  console.log('');
94
- console.log(' # Production (set your Telegram bot token):');
95
- console.log(` LUCIFER_TELEGRAM_TOKEN=your_token LUCIFER_TELEGRAM_CHAT_ID=your_chat_id lucifer-gate --config ${luciferJsonPath}`);
101
+ console.log(' # Production pair your Telegram chat first:');
102
+ console.log(` LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate pair --config ${luciferJsonPath}`);
103
+ console.log('');
104
+ console.log(' # Then start the server:');
105
+ console.log(` LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate --config ${luciferJsonPath}`);
96
106
  }
97
107
  async function runLog(limit) {
98
108
  const dataDir = getArgValue('--data-dir') ?? './data';
@@ -165,6 +175,61 @@ async function runStats() {
165
175
  }
166
176
  }
167
177
  }
178
+ function createReadlinePairingIO() {
179
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
180
+ return {
181
+ print(msg) {
182
+ console.log(msg);
183
+ },
184
+ async choose(prompt, options) {
185
+ console.log(`\n${prompt}`);
186
+ for (let i = 0; i < options.length; i++) {
187
+ console.log(` ${i + 1}. ${options[i]}`);
188
+ }
189
+ while (true) {
190
+ const answer = await rl.question(`\nEnter number (1-${options.length}): `);
191
+ const num = parseInt(answer.trim(), 10);
192
+ if (num >= 1 && num <= options.length)
193
+ return num - 1;
194
+ console.log(`Please enter a number between 1 and ${options.length}.`);
195
+ }
196
+ },
197
+ async confirm(prompt) {
198
+ const answer = await rl.question(`${prompt} [y/N] `);
199
+ return /^y(es)?$/i.test(answer.trim());
200
+ },
201
+ async prompt(msg) {
202
+ return rl.question(`${msg} `);
203
+ },
204
+ close() {
205
+ rl.close();
206
+ },
207
+ };
208
+ }
209
+ async function runPair() {
210
+ const configPath = resolve(getArgValue('--config') ?? './config/lucifer.json');
211
+ let token;
212
+ try {
213
+ token = getTelegramToken();
214
+ }
215
+ catch {
216
+ console.error('LUCIFER_TELEGRAM_TOKEN environment variable is required for pairing.\n' +
217
+ 'Create a bot via @BotFather on Telegram and set the token:\n\n' +
218
+ ' LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate pair');
219
+ process.exit(1);
220
+ }
221
+ const io = createReadlinePairingIO();
222
+ try {
223
+ const result = await runTelegramPairing(token, io);
224
+ updateJsonConfig(configPath, { telegramChatId: result.chatId });
225
+ console.log(`\nChat ID ${result.chatId} saved to ${configPath}`);
226
+ console.log('You can now start Lucifer without LUCIFER_TELEGRAM_CHAT_ID:');
227
+ console.log(`\n LUCIFER_TELEGRAM_TOKEN=your_token lucifer-gate --config ${configPath}`);
228
+ }
229
+ finally {
230
+ io.close();
231
+ }
232
+ }
168
233
  function getArgValue(flag) {
169
234
  const idx = args.indexOf(flag);
170
235
  if (idx === -1 || idx >= args.length - 1)
@@ -181,6 +246,10 @@ async function main() {
181
246
  initConfig(dir);
182
247
  return;
183
248
  }
249
+ if (args[0] === 'pair') {
250
+ await runPair();
251
+ return;
252
+ }
184
253
  if (args[0] === 'log') {
185
254
  const limitStr = getArgValue('--limit');
186
255
  await runLog(limitStr ? parseInt(limitStr, 10) : 50);
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../server/src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uDAAuD,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,mDAAmD,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;CAqBb,CAAC,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,SAAiB;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC3C,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAE/D,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,0BAA0B,eAAe,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAEhD,aAAa,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC;QAC5C,IAAI,EAAE,IAAI;QACV,sBAAsB,EAAE,GAAG;QAC3B,uBAAuB,EAAE,GAAG;QAC5B,uBAAuB,EAAE,CAAC;QAC1B,cAAc,EAAE,QAAQ;QACxB,kBAAkB,EAAE,EAAE;QACtB,iBAAiB,EAAE,MAAM;QACzB,OAAO,EAAE,SAAS;KACnB,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpB,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC;QACxC,IAAI,EAAE,CAAC;gBACL,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI,EAAE,SAAS;gBACf,OAAO;gBACP,IAAI;gBACJ,UAAU,EAAE,EAAE;gBACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,MAAM,EAAE,IAAI;aACb,CAAC;KACH,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpB,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;QAC7C,KAAK,EAAE;YACL,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAC7C,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAClD,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAClD,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAClD,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAChD,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE;YACjD,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE;SACzC;QACD,aAAa,EAAE,aAAa;KAC7B,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,KAAK,eAAe,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,gBAAgB,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,uDAAuD,eAAe,iBAAiB,CAAC,CAAC;IACrG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,mGAAmG,eAAe,EAAE,CAAC,CAAC;AACpI,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,KAAa;IACjC,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC;IACtD,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,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,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;AAED,KAAK,UAAU,QAAQ;IACrB,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC;IACtD,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAEjE,MAAM,eAAe,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IAE/F,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,uBAAuB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,uBAAuB,eAAe,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAErD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAW,CAAC,CAAC;QACvF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YAChF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,eAAe;IACf,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzD,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,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;AAED,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;IACT,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;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,QAAQ,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,cAAc;IACd,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAEpD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;QAC7C,UAAU;QACV,WAAW;KACZ,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,EAAE,mBAAmB,CAAC,CAAC;QACrE,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;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
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../server/src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uDAAuD,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,mDAAmD,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,uDAAuD,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,oDAAoD,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAGzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBb,CAAC,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,SAAiB;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC3C,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAE/D,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,0BAA0B,eAAe,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAEhD,aAAa,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC;QAC5C,IAAI,EAAE,IAAI;QACV,sBAAsB,EAAE,GAAG;QAC3B,uBAAuB,EAAE,GAAG;QAC5B,uBAAuB,EAAE,CAAC;QAC1B,cAAc,EAAE,QAAQ;QACxB,kBAAkB,EAAE,EAAE;QACtB,iBAAiB,EAAE,MAAM;QACzB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,aAAa;KACvB,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpB,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC;QACxC,IAAI,EAAE,CAAC;gBACL,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI,EAAE,SAAS;gBACf,OAAO;gBACP,IAAI;gBACJ,UAAU,EAAE,EAAE;gBACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,MAAM,EAAE,IAAI;aACb,CAAC;KACH,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpB,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC;QAC7C,KAAK,EAAE;YACL,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAC7C,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAClD,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAClD,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAClD,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE;YAChD,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE;YACjD,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE;SACzC;QACD,aAAa,EAAE,aAAa;KAC7B,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,KAAK,eAAe,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,gBAAgB,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,uDAAuD,eAAe,iBAAiB,CAAC,CAAC;IACrG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,kEAAkE,eAAe,EAAE,CAAC,CAAC;IACjG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,6DAA6D,eAAe,EAAE,CAAC,CAAC;AAC9F,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,KAAa;IACjC,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC;IACtD,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,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,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;AAED,KAAK,UAAU,QAAQ;IACrB,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC;IACtD,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAEjE,MAAM,eAAe,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IAE/F,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,uBAAuB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,uBAAuB,eAAe,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAErD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAW,CAAC,CAAC;QACvF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;YAChF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,eAAe;IACf,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzD,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB;IAC9B,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7E,OAAO;QACL,KAAK,CAAC,GAAW;YACf,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,OAAiB;YAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3C,CAAC;YAED,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;gBAC3E,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBACxC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM;oBAAE,OAAO,GAAG,GAAG,CAAC,CAAC;gBACtD,OAAO,CAAC,GAAG,CAAC,uCAAuC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC;YACrD,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,GAAW;YACtB,OAAO,EAAE,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAChC,CAAC;QAED,KAAK;YACH,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,OAAO;IACpB,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,uBAAuB,CAAC,CAAC;IAE/E,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,gBAAgB,EAAE,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CACX,wEAAwE;YACxE,gEAAgE;YAChE,uDAAuD,CACxD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,GAAG,uBAAuB,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACnD,gBAAgB,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,aAAa,UAAU,EAAE,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,+DAA+D,UAAU,EAAE,CAAC,CAAC;IAC3F,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,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;AAED,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;IACT,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;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,OAAO,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,QAAQ,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,cAAc;IACd,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAEpD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;QAC7C,UAAU;QACV,WAAW;KACZ,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,EAAE,mBAAmB,CAAC,CAAC;QACrE,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;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"}
@@ -5,7 +5,7 @@ import { getServerConfig } from './domains/platform-api/config/server_config.js'
5
5
  import { registerHealthRoutes } from './domains/platform-api/api/register_health_routes.js';
6
6
  import { createRuntimeMetadataRepository } from './domains/platform-api/repository/runtime_metadata_repository.js';
7
7
  import { createHealthReportService } from './domains/platform-api/service/create_health_report.js';
8
- import { loadGatewayConfig, getTelegramToken } from './domains/command-gateway/config/gateway_config.js';
8
+ import { loadGatewayConfig, getAdminSecret } from './domains/command-gateway/config/gateway_config.js';
9
9
  import { getDatabase, closeDatabase } from './domains/command-gateway/repository/database.js';
10
10
  import { createApprovalStore } from './domains/command-gateway/repository/approval_store.js';
11
11
  import { createAuditLog } from './domains/command-gateway/repository/audit_log.js';
@@ -15,8 +15,35 @@ import { createPendingRequestStore } from './domains/command-gateway/repository/
15
15
  import { registerExecuteRoutes } from './domains/command-gateway/api/register_execute_routes.js';
16
16
  import { createTelegramApprovalChannel } from './domains/command-gateway/service/request_telegram_approval.js';
17
17
  import { createAutoApproveChannel } from './domains/command-gateway/service/auto_approve_channel.js';
18
- import { createChildLogger } from './lib/logger.js';
18
+ import { createWebApprovalChannel } from './domains/command-gateway/service/web_approval_channel.js';
19
+ import { createMultiApprovalChannel } from './domains/command-gateway/service/multi_approval_channel.js';
20
+ import { registerApprovalRoutes } from './domains/command-gateway/api/register_approval_routes.js';
21
+ import { createChildLogger, addLogFile } from './lib/logger.js';
19
22
  const log = createChildLogger('app');
23
+ function initApprovalChannel(deps, autoApprove) {
24
+ if (autoApprove) {
25
+ return createAutoApproveChannel();
26
+ }
27
+ const channels = [];
28
+ const { app, pendingStore, approvalStore, auditLog, gatewayConfig } = deps;
29
+ const telegramToken = process.env.LUCIFER_TELEGRAM_TOKEN;
30
+ const chatId = gatewayConfig.telegramChatId ?? process.env.LUCIFER_TELEGRAM_CHAT_ID;
31
+ if (telegramToken && chatId) {
32
+ channels.push(createTelegramApprovalChannel(telegramToken, chatId, pendingStore, approvalStore, auditLog));
33
+ }
34
+ const adminSecret = getAdminSecret();
35
+ if (adminSecret) {
36
+ const webChannel = createWebApprovalChannel();
37
+ channels.push(webChannel);
38
+ registerApprovalRoutes({ router: app, adminSecret, webChannel, approvalStore, auditLog });
39
+ log.info('Web approval UI enabled at /admin/approvals');
40
+ }
41
+ if (channels.length === 0) {
42
+ throw new Error('No approval channels configured. Set LUCIFER_TELEGRAM_TOKEN + LUCIFER_TELEGRAM_CHAT_ID for Telegram, ' +
43
+ 'or LUCIFER_ADMIN_SECRET for web UI, or use --auto-approve for development.');
44
+ }
45
+ return channels.length === 1 ? channels[0] : createMultiApprovalChannel(channels);
46
+ }
20
47
  export function createApp(options = {}) {
21
48
  const serverConfig = getServerConfig();
22
49
  const metadataRepository = createRuntimeMetadataRepository();
@@ -36,6 +63,12 @@ export function createApp(options = {}) {
36
63
  // Resolve dataDir relative to config directory
37
64
  const resolvedDataDir = path.resolve(configDir, gatewayConfig.dataDir);
38
65
  gatewayConfig.dataDir = resolvedDataDir;
66
+ // Enable file logging (logFile is relative to dataDir)
67
+ if (gatewayConfig.logFile) {
68
+ const logPath = path.resolve(resolvedDataDir, gatewayConfig.logFile);
69
+ addLogFile(logPath);
70
+ log.info({ logFile: logPath }, 'File logging enabled');
71
+ }
39
72
  let approvalChannel;
40
73
  let cleanupInterval;
41
74
  // Only initialize gateway if config files exist
@@ -46,17 +79,7 @@ export function createApp(options = {}) {
46
79
  const apiKeyStore = createApiKeyStore(apiKeysPath);
47
80
  const commandRulesStore = createCommandRulesStore(commandRulesPath);
48
81
  const pendingStore = createPendingRequestStore();
49
- if (options.autoApprove) {
50
- approvalChannel = createAutoApproveChannel();
51
- }
52
- else {
53
- const token = getTelegramToken();
54
- const chatId = gatewayConfig.telegramChatId ?? process.env.LUCIFER_TELEGRAM_CHAT_ID;
55
- if (!chatId) {
56
- throw new Error('Telegram chat ID is required. Set LUCIFER_TELEGRAM_CHAT_ID env var or telegramChatId in config.');
57
- }
58
- approvalChannel = createTelegramApprovalChannel(token, chatId, pendingStore, approvalStore, auditLog);
59
- }
82
+ approvalChannel = initApprovalChannel({ app, pendingStore, approvalStore, auditLog, gatewayConfig }, options.autoApprove ?? false);
60
83
  registerExecuteRoutes({
61
84
  router: app, config: gatewayConfig, apiKeyStore, commandRulesStore,
62
85
  approvalStore, pendingStore, auditLog, approvalChannel,
@@ -1 +1 @@
1
- {"version":3,"file":"create_app.js","sourceRoot":"","sources":["../../server/src/create_app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create_app.js","sourceRoot":"","sources":["../../server/src/create_app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { fileURLToPath } from 'node:url';
5
+ import rateLimit from 'express-rate-limit';
6
+ import { createChildLogger } from '../../../lib/logger.js';
7
+ const log = createChildLogger('admin-routes');
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const authRateLimits = new Map();
10
+ const MAX_FAILURES = 5;
11
+ const LOCKOUT_MS = 60_000;
12
+ const sseTickets = new Map();
13
+ const TICKET_TTL_MS = 10_000;
14
+ // Clean up expired tickets periodically
15
+ setInterval(() => {
16
+ const now = Date.now();
17
+ for (const [token, ticket] of sseTickets.entries()) {
18
+ if (now - ticket.createdAt > TICKET_TTL_MS) {
19
+ sseTickets.delete(token);
20
+ }
21
+ }
22
+ }, 5_000);
23
+ function checkAdminAuth(adminSecret, req, res) {
24
+ const ip = req.headers['x-forwarded-for']?.split(',')[0]?.trim() ?? req.socket.remoteAddress ?? 'unknown';
25
+ // Check lockout
26
+ const limit = authRateLimits.get(ip);
27
+ if (limit && Date.now() < limit.lockedUntil) {
28
+ const retryAfter = Math.ceil((limit.lockedUntil - Date.now()) / 1000);
29
+ res.status(429).json({
30
+ code: 'RATE_LIMITED',
31
+ message: 'Too many failed auth attempts. Try again later.',
32
+ retryable: true,
33
+ details: `Locked out for ${retryAfter}s`,
34
+ });
35
+ return false;
36
+ }
37
+ const authHeader = req.headers.authorization;
38
+ const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : undefined;
39
+ if (!token || token !== adminSecret) {
40
+ // Track failure
41
+ const current = authRateLimits.get(ip) ?? { failures: 0, lockedUntil: 0 };
42
+ current.failures++;
43
+ if (current.failures >= MAX_FAILURES) {
44
+ current.lockedUntil = Date.now() + LOCKOUT_MS;
45
+ current.failures = 0;
46
+ log.warn({ ip }, 'Admin auth locked out after repeated failures');
47
+ }
48
+ authRateLimits.set(ip, current);
49
+ res.status(401).json({
50
+ code: 'UNAUTHORIZED',
51
+ message: 'Invalid or missing admin secret',
52
+ retryable: false,
53
+ });
54
+ return false;
55
+ }
56
+ // Reset failures on success
57
+ authRateLimits.delete(ip);
58
+ return true;
59
+ }
60
+ function validateDecideInput(body) {
61
+ const { action, matchType, duration } = body;
62
+ if (!action || (action !== 'approve' && action !== 'deny')) {
63
+ return { code: 'INVALID_ACTION', message: 'action must be "approve" or "deny"', retryable: false };
64
+ }
65
+ const decision = action === 'approve' ? 'approved' : 'denied';
66
+ if (decision === 'approved') {
67
+ if (!matchType || (matchType !== 'exact' && matchType !== 'prefix')) {
68
+ return { code: 'INVALID_MATCH_TYPE', message: 'matchType must be "exact" or "prefix" when approving', retryable: false };
69
+ }
70
+ if (!duration || !['2', '8', 'permanent'].includes(duration)) {
71
+ return { code: 'INVALID_DURATION', message: 'duration must be "2", "8", or "permanent" when approving', retryable: false };
72
+ }
73
+ }
74
+ return {
75
+ decision,
76
+ matchType: matchType ?? 'exact',
77
+ duration: duration ?? '0',
78
+ };
79
+ }
80
+ function isValidationError(result) {
81
+ return 'code' in result;
82
+ }
83
+ export function registerApprovalRoutes(deps) {
84
+ const { router, adminSecret, webChannel, approvalStore, auditLog } = deps;
85
+ // Rate limiter middleware for admin API routes
86
+ const adminRateLimiter = rateLimit({
87
+ windowMs: 60_000,
88
+ max: 60,
89
+ standardHeaders: true,
90
+ legacyHeaders: false,
91
+ message: { code: 'RATE_LIMITED', message: 'Too many requests. Try again later.', retryable: true },
92
+ });
93
+ // Load HTML page at startup -- try compiled location first, then source
94
+ const possiblePaths = [
95
+ path.join(__dirname, 'approval_page.html'),
96
+ path.resolve(__dirname, '../../../../server/src/domains/command-gateway/api/approval_page.html'),
97
+ path.resolve(process.cwd(), 'server/src/domains/command-gateway/api/approval_page.html'),
98
+ ];
99
+ const htmlPath = possiblePaths.find(p => fs.existsSync(p));
100
+ const approvalPageHtml = htmlPath
101
+ ? fs.readFileSync(htmlPath, 'utf8')
102
+ : '<html><body><h1>Approval page not found</h1></body></html>';
103
+ // Serve the admin HTML page (no auth - page handles login client-side)
104
+ router.get('/admin/approvals', (_req, res) => {
105
+ res.type('html').send(approvalPageHtml);
106
+ });
107
+ // List pending requests
108
+ router.get('/api/v1/admin/approvals/pending', adminRateLimiter, (req, res) => {
109
+ if (!checkAdminAuth(adminSecret, req, res))
110
+ return;
111
+ res.json({ pending: webChannel.getPendingRequests() });
112
+ });
113
+ // Exchange bearer token for one-time SSE ticket
114
+ router.post('/api/v1/admin/approvals/stream-ticket', adminRateLimiter, (req, res) => {
115
+ if (!checkAdminAuth(adminSecret, req, res))
116
+ return;
117
+ const token = randomUUID();
118
+ sseTickets.set(token, { token, createdAt: Date.now() });
119
+ res.json({ ticket: token, ttlSeconds: TICKET_TTL_MS / 1000 });
120
+ });
121
+ // SSE stream for real-time updates
122
+ router.get('/api/v1/admin/approvals/stream', (req, res) => {
123
+ const ticket = req.query.ticket;
124
+ if (!ticket) {
125
+ res.status(401).json({ code: 'UNAUTHORIZED', message: 'Missing SSE ticket', retryable: false });
126
+ return;
127
+ }
128
+ const storedTicket = sseTickets.get(ticket);
129
+ if (!storedTicket || Date.now() - storedTicket.createdAt > TICKET_TTL_MS) {
130
+ sseTickets.delete(ticket);
131
+ res.status(401).json({ code: 'TICKET_EXPIRED', message: 'SSE ticket expired or invalid', retryable: true });
132
+ return;
133
+ }
134
+ // Consume ticket (one-time use)
135
+ sseTickets.delete(ticket);
136
+ res.writeHead(200, {
137
+ 'Content-Type': 'text/event-stream',
138
+ 'Cache-Control': 'no-cache',
139
+ 'Connection': 'keep-alive',
140
+ 'X-Accel-Buffering': 'no',
141
+ });
142
+ // Send initial pending list
143
+ const pending = webChannel.getPendingRequests();
144
+ res.write(`event: init\ndata: ${JSON.stringify({ pending })}\n\n`);
145
+ webChannel.addSSEClient(res);
146
+ // Heartbeat to detect broken connections
147
+ const heartbeat = setInterval(() => {
148
+ res.write(': heartbeat\n\n');
149
+ }, 30_000);
150
+ req.on('close', () => {
151
+ clearInterval(heartbeat);
152
+ webChannel.removeSSEClient(res);
153
+ });
154
+ });
155
+ // Approve or deny a request
156
+ router.post('/api/v1/admin/approvals/:requestId/decide', adminRateLimiter, (req, res) => {
157
+ if (!checkAdminAuth(adminSecret, req, res))
158
+ return;
159
+ const requestId = Array.isArray(req.params.requestId) ? req.params.requestId[0] : req.params.requestId;
160
+ const validated = validateDecideInput(req.body);
161
+ if (isValidationError(validated)) {
162
+ res.status(400).json(validated);
163
+ return;
164
+ }
165
+ const { decision, matchType: resolvedMatchType, duration: resolvedDuration } = validated;
166
+ // Try to resolve via web channel
167
+ const pending = webChannel.getPendingRequests().find(p => p.requestId === requestId);
168
+ if (!pending) {
169
+ res.status(409).json({
170
+ code: 'ALREADY_DECIDED',
171
+ message: 'Request already decided or expired',
172
+ retryable: false,
173
+ });
174
+ return;
175
+ }
176
+ if (decision === 'approved') {
177
+ const approvalCommand = resolvedMatchType === 'prefix'
178
+ ? pending.command.split(/\s+/).slice(0, 2).join(' ')
179
+ : pending.command;
180
+ approvalStore.addApproval(approvalCommand, resolvedMatchType, resolvedDuration, 'web:admin');
181
+ }
182
+ auditLog.append({
183
+ ts: new Date().toISOString(),
184
+ type: decision === 'approved' ? 'approved' : 'denied',
185
+ requestId,
186
+ command: pending.command,
187
+ duration: decision === 'approved' ? resolvedDuration : undefined,
188
+ approvedBy: 'web:admin',
189
+ });
190
+ const resolved = webChannel.resolveRequest(requestId, decision, resolvedMatchType, resolvedDuration);
191
+ if (!resolved) {
192
+ res.status(409).json({
193
+ code: 'ALREADY_DECIDED',
194
+ message: 'Request was decided by another channel',
195
+ retryable: false,
196
+ });
197
+ return;
198
+ }
199
+ log.info({ requestId, decision, matchType: resolvedMatchType, duration: resolvedDuration }, 'Admin decision via web UI');
200
+ res.json({ ok: true, requestId, decision });
201
+ });
202
+ }
203
+ //# sourceMappingURL=register_approval_routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register_approval_routes.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/api/register_approval_routes.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,10 @@ function isLuciferConfig(data) {
23
23
  return false;
24
24
  if (!checkOptionalType(d, 'dataDir', 'string'))
25
25
  return false;
26
+ if (!checkOptionalType(d, 'telegramChatId', 'string'))
27
+ return false;
28
+ if (!checkOptionalType(d, 'logFile', 'string'))
29
+ return false;
26
30
  return true;
27
31
  }
28
32
  const defaults = {
@@ -1 +1 @@
1
- {"version":3,"file":"gateway_config.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/config/gateway_config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gateway_config.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/config/gateway_config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { createChildLogger } from '../../../lib/logger.js';
2
+ const log = createChildLogger('multi-channel');
3
+ export function createMultiApprovalChannel(channels) {
4
+ if (channels.length === 0) {
5
+ throw new Error('At least one approval channel is required');
6
+ }
7
+ return {
8
+ async requestApproval(command, apiKeyName, ip, requestId, riskAnalysis) {
9
+ const promises = channels.map(ch => ch.requestApproval(command, apiKeyName, ip, requestId, riskAnalysis));
10
+ const result = await Promise.race(promises);
11
+ // Clean up losing channels' internal state
12
+ for (const ch of channels) {
13
+ ch.cancel?.(requestId);
14
+ }
15
+ log.info({ requestId, decision: result.decision }, 'Multi-channel approval resolved');
16
+ return result;
17
+ },
18
+ async start() {
19
+ await Promise.all(channels.map(ch => ch.start()));
20
+ log.info({ channelCount: channels.length }, 'All approval channels started');
21
+ },
22
+ async stop() {
23
+ await Promise.all(channels.map(ch => ch.stop()));
24
+ log.info('All approval channels stopped');
25
+ },
26
+ cancel(requestId) {
27
+ for (const ch of channels) {
28
+ ch.cancel?.(requestId);
29
+ }
30
+ },
31
+ };
32
+ }
33
+ //# sourceMappingURL=multi_approval_channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi_approval_channel.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/multi_approval_channel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAE/C,MAAM,UAAU,0BAA0B,CAAC,QAA2B;IACpE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO;QACL,KAAK,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,YAAY;YACpE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CACjC,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,YAAY,CAAC,CACrE,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAE5C,2CAA2C;YAC3C,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC1B,EAAE,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC;YACzB,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,iCAAiC,CAAC,CAAC;YACtF,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAClD,GAAG,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,+BAA+B,CAAC,CAAC;QAC/E,CAAC;QAED,KAAK,CAAC,IAAI;YACR,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACjD,GAAG,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,CAAC,SAAiB;YACtB,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC1B,EAAE,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -32,6 +32,8 @@ export function createTelegramApprovalChannel(token, chatId, pendingStore, appro
32
32
  : pending.command;
33
33
  approvalStore.addApproval(approvalCommand, matchType, duration, `telegram:${ctx.callbackQuery.from.id}`);
34
34
  }
35
+ // Store decision metadata so the Promise resolve can read the actual values
36
+ decisionMeta.set(requestId, { matchType: matchType, duration });
35
37
  auditLog.append({
36
38
  ts: new Date().toISOString(),
37
39
  type: decision === 'approved' ? 'approved' : 'denied',
@@ -46,8 +48,31 @@ export function createTelegramApprovalChannel(token, chatId, pendingStore, appro
46
48
  await ctx.answerCbQuery(label);
47
49
  await ctx.editMessageText(`${emoji} ${label}\n\n${pending.command}`);
48
50
  });
51
+ // Track per-request decision metadata from callbacks
52
+ const decisionMeta = new Map();
49
53
  return {
50
54
  async requestApproval(command, apiKeyName, ip, requestId, riskAnalysis) {
55
+ // Wire Promise callbacks BEFORE sending the notification to avoid race condition
56
+ const approvalPromise = new Promise((resolve, reject) => {
57
+ const pending = pendingStore.get(requestId);
58
+ if (!pending) {
59
+ reject(new Error('Request not found in pending store'));
60
+ return;
61
+ }
62
+ const originalResolve = pending.resolve;
63
+ const originalReject = pending.reject;
64
+ pending.resolve = (decision) => {
65
+ const meta = decisionMeta.get(requestId) ?? { matchType: 'exact', duration: '2' };
66
+ decisionMeta.delete(requestId);
67
+ originalResolve(decision);
68
+ resolve({ decision, matchType: meta.matchType, duration: meta.duration });
69
+ };
70
+ pending.reject = (reason) => {
71
+ decisionMeta.delete(requestId);
72
+ originalReject(reason);
73
+ reject(reason);
74
+ };
75
+ });
51
76
  let text = `\u{1f6a8} **Command Request**\n\n`;
52
77
  text += `From: \`${apiKeyName}\` (${ip})\n`;
53
78
  text += `ID: \`${requestId}\`\n\n`;
@@ -85,25 +110,7 @@ export function createTelegramApprovalChannel(token, chatId, pendingStore, appro
85
110
  ip,
86
111
  });
87
112
  log.info({ requestId, command, chatId }, 'Telegram approval request sent');
88
- return new Promise((resolve, reject) => {
89
- const pending = pendingStore.get(requestId);
90
- if (!pending) {
91
- reject(new Error('Request not found in pending store'));
92
- return;
93
- }
94
- const originalResolve = pending.resolve;
95
- const originalReject = pending.reject;
96
- pending.resolve = (decision) => {
97
- const matchType = 'exact';
98
- const duration = 'unknown';
99
- originalResolve(decision);
100
- resolve({ decision, matchType, duration });
101
- };
102
- pending.reject = (reason) => {
103
- originalReject(reason);
104
- reject(reason);
105
- };
106
- });
113
+ return approvalPromise;
107
114
  },
108
115
  async start() {
109
116
  await bot.launch();
@@ -1 +1 @@
1
- {"version":3,"file":"request_telegram_approval.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/request_telegram_approval.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request_telegram_approval.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/request_telegram_approval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { Telegram } from 'telegraf';
2
+ import { randomInt } from 'node:crypto';
3
+ /**
4
+ * Run the interactive Telegram pairing flow:
5
+ * 1. Validate bot token via getMe
6
+ * 2. Fetch recent updates and extract unique chats
7
+ * 3. Let the user pick a chat
8
+ * 4. Send a 6-digit verification code to the chosen chat
9
+ * 5. Prompt the user to enter the code (up to 3 attempts)
10
+ */
11
+ export async function runTelegramPairing(token, io) {
12
+ const telegram = new Telegram(token);
13
+ // 1. Validate the bot token
14
+ io.print('Connecting to Telegram...');
15
+ let botInfo;
16
+ try {
17
+ botInfo = await telegram.getMe();
18
+ }
19
+ catch (err) {
20
+ const msg = err instanceof Error ? err.message : String(err);
21
+ throw new Error(`Invalid Telegram bot token. Could not connect: ${msg}\n` +
22
+ 'Check your LUCIFER_TELEGRAM_TOKEN environment variable.');
23
+ }
24
+ io.print(`Connected to bot: @${botInfo.username} (${botInfo.first_name})`);
25
+ // 2. Fetch recent updates and extract unique chats
26
+ io.print('Fetching recent chats...');
27
+ // Delete any active webhook first — getUpdates and webhooks are mutually exclusive
28
+ try {
29
+ await telegram.deleteWebhook();
30
+ }
31
+ catch {
32
+ // Ignore — the bot may not have a webhook set
33
+ }
34
+ let updates;
35
+ try {
36
+ updates = await telegram.getUpdates(0, 100, 0, undefined);
37
+ }
38
+ catch (err) {
39
+ const msg = err instanceof Error ? err.message : String(err);
40
+ throw new Error(`Failed to fetch updates from Telegram: ${msg}\n` +
41
+ 'If the bot is in webhook mode, the webhook has been removed. Please retry.');
42
+ }
43
+ // Deduplicate chats, keeping the most recent message date per chat
44
+ const chatMap = new Map();
45
+ for (const update of updates) {
46
+ const message = 'message' in update ? update.message
47
+ : 'channel_post' in update ? update.channel_post
48
+ : undefined;
49
+ if (!message?.chat)
50
+ continue;
51
+ const chat = message.chat;
52
+ const chatId = chat.id.toString();
53
+ const existing = chatMap.get(chatId);
54
+ const date = message.date ?? 0;
55
+ if (!existing || date > existing.lastMessageDate) {
56
+ const title = chat.type === 'private'
57
+ ? [('first_name' in chat ? chat.first_name : ''), ('last_name' in chat ? chat.last_name : '')].filter(Boolean).join(' ')
58
+ : ('title' in chat ? chat.title : undefined) ?? chatId;
59
+ chatMap.set(chatId, {
60
+ chatId,
61
+ title,
62
+ type: chat.type,
63
+ lastMessageDate: date,
64
+ });
65
+ }
66
+ }
67
+ const chats = [...chatMap.values()].sort((a, b) => b.lastMessageDate - a.lastMessageDate);
68
+ if (chats.length === 0) {
69
+ throw new Error(`No chats found. Please send a message to @${botInfo.username} on Telegram first, then re-run this command.`);
70
+ }
71
+ // 3. Let the user pick a chat
72
+ const options = chats.map((c) => {
73
+ const date = new Date(c.lastMessageDate * 1000).toLocaleString();
74
+ return `${c.title} (${c.type}, ID: ${c.chatId}) — last message: ${date}`;
75
+ });
76
+ const index = await io.choose('Select a chat for approvals:', options);
77
+ const chosen = chats[index];
78
+ io.print(`\nSelected: ${chosen.title} (${chosen.chatId})`);
79
+ const confirmed = await io.confirm('Use this chat for Telegram approvals?');
80
+ if (!confirmed) {
81
+ throw new Error('Pairing cancelled.');
82
+ }
83
+ // 4. Generate and send a 6-digit verification code
84
+ const code = randomInt(100000, 999999).toString();
85
+ try {
86
+ await telegram.sendMessage(chosen.chatId, `🔑 *Lucifer Pairing Code*\n\nYour pairing code is: \`${code}\`\n\nEnter this code in your terminal to complete pairing.`, { parse_mode: 'Markdown' });
87
+ }
88
+ catch (err) {
89
+ const msg = err instanceof Error ? err.message : String(err);
90
+ throw new Error(`Failed to send pairing code to chat ${chosen.chatId}: ${msg}\n` +
91
+ 'Make sure the bot can send messages to this chat.');
92
+ }
93
+ io.print('\nA 6-digit pairing code has been sent to your Telegram chat.');
94
+ // 5. Verify the code (up to 3 attempts)
95
+ const maxAttempts = 3;
96
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
97
+ const entered = (await io.prompt('Enter the 6-digit code:')).trim();
98
+ if (entered === code) {
99
+ io.print('Pairing verified successfully!');
100
+ return { chatId: chosen.chatId, chatTitle: chosen.title };
101
+ }
102
+ const remaining = maxAttempts - attempt;
103
+ if (remaining > 0) {
104
+ io.print(`Incorrect code. ${remaining} attempt${remaining > 1 ? 's' : ''} remaining.`);
105
+ }
106
+ }
107
+ throw new Error('Pairing failed: incorrect code entered 3 times.');
108
+ }
109
+ //# sourceMappingURL=telegram_pairing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram_pairing.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/telegram_pairing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAqBxC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,EAAa;IAEb,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;IAErC,4BAA4B;IAC5B,EAAE,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACtC,IAAI,OAA+C,CAAC;IACpD,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,kDAAkD,GAAG,IAAI;YACzD,yDAAyD,CAC1D,CAAC;IACJ,CAAC;IACD,EAAE,CAAC,KAAK,CAAC,sBAAsB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,UAAU,GAAG,CAAC,CAAC;IAE3E,mDAAmD;IACnD,EAAE,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAErC,mFAAmF;IACnF,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;IAChD,CAAC;IAED,IAAI,OAAoD,CAAC;IACzD,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,0CAA0C,GAAG,IAAI;YACjD,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAChD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO;YAClD,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY;gBAChD,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,CAAC,OAAO,EAAE,IAAI;YAAE,SAAS;QAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QAE/B,IAAI,CAAC,QAAQ,IAAI,IAAI,GAAG,QAAQ,CAAC,eAAe,EAAE,CAAC;YACjD,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,SAAS;gBACrB,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACxH,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC;YAE3D,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;gBAClB,MAAM;gBACN,KAAK;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,eAAe,EAAE,IAAI;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IAE1F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,6CAA6C,OAAO,CAAC,QAAQ,+CAA+C,CAC7G,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;QACjE,OAAO,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,MAAM,qBAAqB,IAAI,EAAE,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE5B,EAAE,CAAC,KAAK,CAAC,eAAe,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAE3D,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC;IAC5E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,mDAAmD;IACnD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,WAAW,CACxB,MAAM,CAAC,MAAM,EACb,wDAAwD,IAAI,6DAA6D,EACzH,EAAE,UAAU,EAAE,UAAU,EAAE,CAC3B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,uCAAuC,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI;YAChE,mDAAmD,CACpD,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAE1E,wCAAwC;IACxC,MAAM,WAAW,GAAG,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEpE,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,EAAE,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAC5D,CAAC;QAED,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;QACxC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,EAAE,CAAC,KAAK,CAAC,mBAAmB,SAAS,WAAW,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { createChildLogger } from '../../../lib/logger.js';
2
+ const log = createChildLogger('web-channel');
3
+ export function createWebApprovalChannel() {
4
+ const callbacks = new Map();
5
+ const sseClients = new Set();
6
+ function broadcast(event, data) {
7
+ const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
8
+ for (const client of sseClients) {
9
+ client.write(payload);
10
+ }
11
+ }
12
+ return {
13
+ async requestApproval(command, apiKeyName, ip, requestId, riskAnalysis) {
14
+ const request = {
15
+ requestId,
16
+ command,
17
+ apiKeyName,
18
+ ip,
19
+ createdAt: new Date().toISOString(),
20
+ riskAnalysis,
21
+ };
22
+ const promise = new Promise((resolve, reject) => {
23
+ callbacks.set(requestId, { request, resolve, reject });
24
+ });
25
+ broadcast('new_request', request);
26
+ log.info({ requestId, command }, 'Web approval request broadcast');
27
+ return promise;
28
+ },
29
+ async start() {
30
+ log.info('Web approval channel started');
31
+ },
32
+ async stop() {
33
+ // Reject all pending callbacks
34
+ for (const [requestId, cb] of callbacks.entries()) {
35
+ cb.reject(new Error('Web approval channel shutting down'));
36
+ callbacks.delete(requestId);
37
+ }
38
+ // Close all SSE connections
39
+ for (const client of sseClients) {
40
+ client.end();
41
+ }
42
+ sseClients.clear();
43
+ log.info('Web approval channel stopped');
44
+ },
45
+ cancel(requestId) {
46
+ const cb = callbacks.get(requestId);
47
+ if (cb) {
48
+ callbacks.delete(requestId);
49
+ broadcast('request_decided', { requestId, decision: 'cancelled' });
50
+ log.debug({ requestId }, 'Web channel request cancelled (decided via another channel)');
51
+ }
52
+ },
53
+ getPendingRequests() {
54
+ return Array.from(callbacks.values()).map(cb => cb.request);
55
+ },
56
+ resolveRequest(requestId, decision, matchType, duration) {
57
+ const cb = callbacks.get(requestId);
58
+ if (!cb) {
59
+ return false;
60
+ }
61
+ callbacks.delete(requestId);
62
+ cb.resolve({ decision, matchType, duration });
63
+ broadcast('request_decided', { requestId, decision, matchType, duration });
64
+ log.info({ requestId, decision, matchType, duration }, 'Web approval resolved');
65
+ return true;
66
+ },
67
+ addSSEClient(res) {
68
+ sseClients.add(res);
69
+ log.debug({ clientCount: sseClients.size }, 'SSE client connected');
70
+ },
71
+ removeSSEClient(res) {
72
+ sseClients.delete(res);
73
+ log.debug({ clientCount: sseClients.size }, 'SSE client disconnected');
74
+ },
75
+ };
76
+ }
77
+ //# sourceMappingURL=web_approval_channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web_approval_channel.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/web_approval_channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ /**
3
+ * Read-modify-write a JSON config file, merging the given updates
4
+ * into the existing object. Only top-level keys are merged (shallow).
5
+ */
6
+ export function updateJsonConfig(filePath, updates) {
7
+ let raw;
8
+ try {
9
+ raw = readFileSync(filePath, 'utf-8');
10
+ }
11
+ catch (err) {
12
+ const code = err.code;
13
+ if (code === 'ENOENT') {
14
+ throw new Error(`Config file not found: ${filePath}. Run \`lucifer-gate --init\` first.`);
15
+ }
16
+ throw new Error(`Cannot read config file: ${filePath} (${code})`);
17
+ }
18
+ let parsed;
19
+ try {
20
+ parsed = JSON.parse(raw);
21
+ }
22
+ catch {
23
+ throw new Error(`Invalid JSON in config file: ${filePath}`);
24
+ }
25
+ const merged = { ...parsed, ...updates };
26
+ writeFileSync(filePath, JSON.stringify(merged, null, 2) + '\n');
27
+ }
28
+ //# sourceMappingURL=json_config_writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json_config_writer.js","sourceRoot":"","sources":["../../../server/src/lib/json_config_writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEtD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,OAAgC;IACjF,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,sCAAsC,CAAC,CAAC;QAC5F,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,KAAK,IAAI,GAAG,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;IACzC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAClE,CAAC"}
@@ -1,11 +1,36 @@
1
1
  import pino from 'pino';
2
2
  const isProduction = process.env.NODE_ENV === 'production';
3
+ // Resolve console stream: use pino-pretty for human-readable output in dev,
4
+ // fall back to plain JSON when pino-pretty is unavailable (e.g. npx installs).
5
+ let consoleStream = process.stdout;
6
+ if (!isProduction) {
7
+ try {
8
+ const mod = await import('pino-pretty');
9
+ const build = typeof mod.default === 'function' ? mod.default : mod.build;
10
+ consoleStream = build({ colorize: true });
11
+ }
12
+ catch {
13
+ // pino-pretty is a devDependency — unavailable when installed via npx or in production.
14
+ // Falls back to structured JSON on console, which is still fully functional.
15
+ }
16
+ }
17
+ const streams = pino.multistream([
18
+ { level: 'trace', stream: consoleStream },
19
+ ]);
3
20
  export const logger = pino({
4
21
  level: process.env.LOG_LEVEL ?? (isProduction ? 'info' : 'debug'),
5
- transport: isProduction
6
- ? undefined
7
- : { target: 'pino-pretty', options: { colorize: true } },
8
- });
22
+ }, streams);
23
+ /**
24
+ * Add a log file destination. Logs are written as structured JSON (one object
25
+ * per line), independent of the console format. Safe to call after startup —
26
+ * new entries are appended; the file is created if it does not exist.
27
+ */
28
+ export function addLogFile(filePath) {
29
+ streams.add({
30
+ level: 'trace',
31
+ stream: pino.destination({ dest: filePath, mkdir: true, sync: false }),
32
+ });
33
+ }
9
34
  export function createChildLogger(name) {
10
35
  return logger.child({ module: name });
11
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../server/src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAE3D,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,SAAS,EAAE,YAAY;QACrB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;CAC3D,CAAC,CAAC;AAEH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../server/src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAE3D,4EAA4E;AAC5E,+EAA+E;AAC/E,IAAI,aAAa,GAA2B,OAAO,CAAC,MAAM,CAAC;AAE3D,IAAI,CAAC,YAAY,EAAE,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAE,GAAuF,CAAC,KAAK,CAAC;QAC/J,aAAa,GAAG,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAsC,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,wFAAwF;QACxF,6EAA6E;IAC/E,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;IAC/B,EAAE,KAAK,EAAE,OAAgB,EAAE,MAAM,EAAE,aAAa,EAAE;CACnD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;CAClE,EAAE,OAAO,CAAC,CAAC;AAEZ;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,OAAO,CAAC,GAAG,CAAC;QACV,KAAK,EAAE,OAAgB;QACvB,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;KACvE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACxC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucifer-gate",
3
- "version": "0.3.1",
3
+ "version": "0.4.0-alpha.3.aedac37",
4
4
  "description": "AI agent command firewall with Telegram-based human approval",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,6 +45,7 @@
45
45
  "dependencies": {
46
46
  "better-sqlite3": "^12.8.0",
47
47
  "express": "^5.2.1",
48
+ "express-rate-limit": "^8.3.2",
48
49
  "pino": "^10.3.1",
49
50
  "react": "^19.2.4",
50
51
  "react-dom": "^19.2.4",