lucifer-gate 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -0
  3. package/dist/server/cli.js +220 -0
  4. package/dist/server/cli.js.map +1 -0
  5. package/dist/server/create_app.js +95 -0
  6. package/dist/server/create_app.js.map +1 -0
  7. package/dist/server/domains/command-gateway/api/register_execute_routes.js +338 -0
  8. package/dist/server/domains/command-gateway/api/register_execute_routes.js.map +1 -0
  9. package/dist/server/domains/command-gateway/config/gateway_config.js +46 -0
  10. package/dist/server/domains/command-gateway/config/gateway_config.js.map +1 -0
  11. package/dist/server/domains/command-gateway/repository/api_key_store.js +44 -0
  12. package/dist/server/domains/command-gateway/repository/api_key_store.js.map +1 -0
  13. package/dist/server/domains/command-gateway/repository/approval_store.js +83 -0
  14. package/dist/server/domains/command-gateway/repository/approval_store.js.map +1 -0
  15. package/dist/server/domains/command-gateway/repository/audit_log.js +24 -0
  16. package/dist/server/domains/command-gateway/repository/audit_log.js.map +1 -0
  17. package/dist/server/domains/command-gateway/repository/command_rules_store.js +42 -0
  18. package/dist/server/domains/command-gateway/repository/command_rules_store.js.map +1 -0
  19. package/dist/server/domains/command-gateway/repository/database.js +59 -0
  20. package/dist/server/domains/command-gateway/repository/database.js.map +1 -0
  21. package/dist/server/domains/command-gateway/repository/pending_request_store.js +61 -0
  22. package/dist/server/domains/command-gateway/repository/pending_request_store.js.map +1 -0
  23. package/dist/server/domains/command-gateway/service/analyze_command_risk.js +44 -0
  24. package/dist/server/domains/command-gateway/service/analyze_command_risk.js.map +1 -0
  25. package/dist/server/domains/command-gateway/service/authenticate_request.js +71 -0
  26. package/dist/server/domains/command-gateway/service/authenticate_request.js.map +1 -0
  27. package/dist/server/domains/command-gateway/service/auto_approve_channel.js +24 -0
  28. package/dist/server/domains/command-gateway/service/auto_approve_channel.js.map +1 -0
  29. package/dist/server/domains/command-gateway/service/execute_command.js +139 -0
  30. package/dist/server/domains/command-gateway/service/execute_command.js.map +1 -0
  31. package/dist/server/domains/command-gateway/service/request_telegram_approval.js +126 -0
  32. package/dist/server/domains/command-gateway/service/request_telegram_approval.js.map +1 -0
  33. package/dist/server/domains/command-gateway/types/command_types.js +2 -0
  34. package/dist/server/domains/command-gateway/types/command_types.js.map +1 -0
  35. package/dist/server/domains/command-gateway/types/store_interfaces.js +2 -0
  36. package/dist/server/domains/command-gateway/types/store_interfaces.js.map +1 -0
  37. package/dist/server/domains/platform-api/api/register_health_routes.js +6 -0
  38. package/dist/server/domains/platform-api/api/register_health_routes.js.map +1 -0
  39. package/dist/server/domains/platform-api/config/server_config.js +17 -0
  40. package/dist/server/domains/platform-api/config/server_config.js.map +1 -0
  41. package/dist/server/domains/platform-api/repository/runtime_metadata_repository.js +7 -0
  42. package/dist/server/domains/platform-api/repository/runtime_metadata_repository.js.map +1 -0
  43. package/dist/server/domains/platform-api/service/create_health_report.js +10 -0
  44. package/dist/server/domains/platform-api/service/create_health_report.js.map +1 -0
  45. package/dist/server/domains/platform-api/types/health_report.js +2 -0
  46. package/dist/server/domains/platform-api/types/health_report.js.map +1 -0
  47. package/dist/server/index.js +18 -0
  48. package/dist/server/index.js.map +1 -0
  49. package/dist/server/lib/json_config_loader.js +31 -0
  50. package/dist/server/lib/json_config_loader.js.map +1 -0
  51. package/dist/server/lib/logger.js +12 -0
  52. package/dist/server/lib/logger.js.map +1 -0
  53. package/package.json +78 -0
@@ -0,0 +1,59 @@
1
+ import Database from 'better-sqlite3';
2
+ import { mkdirSync } from 'node:fs';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { createChildLogger } from '../../../lib/logger.js';
5
+ const log = createChildLogger('database');
6
+ let db = null;
7
+ export function getDatabase(dataDir) {
8
+ if (db)
9
+ return db;
10
+ const dbPath = resolve(dataDir, 'lucifer.db');
11
+ mkdirSync(dirname(dbPath), { recursive: true });
12
+ log.info({ dbPath }, 'Opening SQLite database');
13
+ db = new Database(dbPath, { fileMustExist: false });
14
+ db.pragma('journal_mode = WAL');
15
+ db.pragma('busy_timeout = 5000');
16
+ db.exec(`
17
+ CREATE TABLE IF NOT EXISTS approvals (
18
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
19
+ command TEXT NOT NULL,
20
+ match_type TEXT NOT NULL CHECK (match_type IN ('exact', 'prefix')),
21
+ duration TEXT NOT NULL,
22
+ approved_at TEXT NOT NULL,
23
+ expires_at TEXT,
24
+ approved_by TEXT NOT NULL
25
+ );
26
+
27
+ CREATE INDEX IF NOT EXISTS idx_approvals_command ON approvals (command);
28
+ CREATE INDEX IF NOT EXISTS idx_approvals_expires ON approvals (expires_at);
29
+
30
+ CREATE TABLE IF NOT EXISTS audit_log (
31
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
32
+ ts TEXT NOT NULL,
33
+ type TEXT NOT NULL,
34
+ request_id TEXT NOT NULL,
35
+ command TEXT,
36
+ api_key_name TEXT,
37
+ ip TEXT,
38
+ rule_action TEXT,
39
+ duration TEXT,
40
+ approved_by TEXT,
41
+ exit_code INTEGER,
42
+ duration_ms INTEGER,
43
+ error TEXT
44
+ );
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_audit_request_id ON audit_log (request_id);
47
+ CREATE INDEX IF NOT EXISTS idx_audit_ts ON audit_log (ts);
48
+ `);
49
+ log.info('Database schema initialized');
50
+ return db;
51
+ }
52
+ export function closeDatabase() {
53
+ if (db) {
54
+ db.close();
55
+ db = null;
56
+ log.info('Database closed');
57
+ }
58
+ }
59
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/repository/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;AAE1C,IAAI,EAAE,GAA6B,IAAI,CAAC;AAExC,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC9C,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhD,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,yBAAyB,CAAC,CAAC;IAChD,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAEjC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCP,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACxC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;QACV,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { createChildLogger } from '../../../lib/logger.js';
2
+ const log = createChildLogger('pending-requests');
3
+ export function createPendingRequestStore() {
4
+ const store = new Map();
5
+ return {
6
+ add(request) {
7
+ store.set(request.requestId, request);
8
+ log.debug({ requestId: request.requestId, command: request.command }, 'Pending request added');
9
+ },
10
+ resolve(requestId, decision) {
11
+ const pending = store.get(requestId);
12
+ if (!pending) {
13
+ log.debug({ requestId }, 'Resolve called for unknown/expired request');
14
+ return false;
15
+ }
16
+ pending.resolve(decision);
17
+ store.delete(requestId);
18
+ log.info({ requestId, decision }, 'Pending request resolved');
19
+ return true;
20
+ },
21
+ get(requestId) {
22
+ return store.get(requestId);
23
+ },
24
+ remove(requestId) {
25
+ const pending = store.get(requestId);
26
+ if (pending) {
27
+ pending.abortController.abort();
28
+ store.delete(requestId);
29
+ }
30
+ },
31
+ findByCommand(command, apiKeyName) {
32
+ for (const pending of store.values()) {
33
+ if (pending.command === command && pending.apiKeyName === apiKeyName) {
34
+ return pending;
35
+ }
36
+ }
37
+ return undefined;
38
+ },
39
+ cleanup(maxAgeMs) {
40
+ const now = Date.now();
41
+ let removed = 0;
42
+ for (const [id, pending] of store.entries()) {
43
+ const age = now - new Date(pending.createdAt).getTime();
44
+ if (age > maxAgeMs) {
45
+ pending.reject(new Error('Approval timed out'));
46
+ pending.abortController.abort();
47
+ store.delete(id);
48
+ removed++;
49
+ }
50
+ }
51
+ if (removed > 0) {
52
+ log.info({ removed }, 'Stale pending requests cleaned up');
53
+ }
54
+ return removed;
55
+ },
56
+ size() {
57
+ return store.size;
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=pending_request_store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending_request_store.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/repository/pending_request_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;AAYlD,MAAM,UAAU,yBAAyB;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEhD,OAAO;QACL,GAAG,CAAC,OAAuB;YACzB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,uBAAuB,CAAC,CAAC;QACjG,CAAC;QAED,OAAO,CAAC,SAAiB,EAAE,QAA0B;YACnD,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,EAAE,4CAA4C,CAAC,CAAC;gBACvE,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC1B,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,0BAA0B,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,GAAG,CAAC,SAAiB;YACnB,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,CAAC,SAAiB;YACtB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrC,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;gBAChC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,aAAa,CAAC,OAAe,EAAE,UAAkB;YAC/C,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACrC,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;oBACrE,OAAO,OAAO,CAAC;gBACjB,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,CAAC,QAAgB;YACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,OAAO,GAAG,CAAC,CAAC;YAChB,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC5C,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;gBACxD,IAAI,GAAG,GAAG,QAAQ,EAAE,CAAC;oBACnB,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;oBAChD,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;oBAChC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBACjB,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC;YACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,mCAAmC,CAAC,CAAC;YAC7D,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,IAAI;YACF,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ const DANGER_PATTERNS = [
2
+ { pattern: /\|/, warning: 'Pipe (|) detected: output is passed to another command' },
3
+ { pattern: /&&/, warning: 'Chained command (&&): runs a second command on success' },
4
+ { pattern: /;/, warning: 'Semicolon (;): runs multiple commands sequentially' },
5
+ { pattern: /`[^`]*`/, warning: 'Backtick command substitution detected' },
6
+ { pattern: /\$\(/, warning: 'Command substitution $() detected' },
7
+ { pattern: />>?\s/, warning: 'Output redirect (>) detected: writes to file' },
8
+ { pattern: /<\s/, warning: 'Input redirect (<) detected' },
9
+ { pattern: /\brm\s+-r/, warning: 'Recursive delete (rm -r) detected' },
10
+ { pattern: /\bsudo\b/, warning: 'sudo: runs with elevated privileges' },
11
+ { pattern: /\bcurl\b.*\|\s*\b(bash|sh|zsh)\b/, warning: 'curl piped to shell: remote code execution' },
12
+ { pattern: /\beval\b/, warning: 'eval: executes dynamically constructed commands' },
13
+ ];
14
+ const WARNING_PATTERNS = [
15
+ { pattern: /\bdd\b/, warning: 'dd: disk/device operations' },
16
+ { pattern: /\bchmod\b/, warning: 'chmod: changes file permissions' },
17
+ { pattern: /\bchown\b/, warning: 'chown: changes file ownership' },
18
+ { pattern: /\bmkfs\b/, warning: 'mkfs: formats filesystem' },
19
+ { pattern: /\bkill\b/, warning: 'kill: terminates processes' },
20
+ ];
21
+ export function analyzeCommandRisk(command) {
22
+ const warnings = [];
23
+ let hasDanger = false;
24
+ for (const { pattern, warning } of DANGER_PATTERNS) {
25
+ if (pattern.test(command)) {
26
+ warnings.push(warning);
27
+ hasDanger = true;
28
+ }
29
+ }
30
+ for (const { pattern, warning } of WARNING_PATTERNS) {
31
+ if (pattern.test(command)) {
32
+ warnings.push(warning);
33
+ }
34
+ }
35
+ let level = 'safe';
36
+ if (hasDanger) {
37
+ level = 'danger';
38
+ }
39
+ else if (warnings.length > 0) {
40
+ level = 'warning';
41
+ }
42
+ return { level, warnings };
43
+ }
44
+ //# sourceMappingURL=analyze_command_risk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze_command_risk.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/analyze_command_risk.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAgD;IACnE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,wDAAwD,EAAE;IACpF,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,wDAAwD,EAAE;IACpF,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,oDAAoD,EAAE;IAC/E,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,wCAAwC,EAAE;IACzE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mCAAmC,EAAE;IACjE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,8CAA8C,EAAE;IAC7E,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,6BAA6B,EAAE;IAC1D,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,mCAAmC,EAAE;IACtE,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,qCAAqC,EAAE;IACvE,EAAE,OAAO,EAAE,kCAAkC,EAAE,OAAO,EAAE,4CAA4C,EAAE;IACtG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,iDAAiD,EAAE;CACpF,CAAC;AAEF,MAAM,gBAAgB,GAAgD;IACpE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,4BAA4B,EAAE;IAC5D,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,iCAAiC,EAAE;IACpE,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,+BAA+B,EAAE;IAClE,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,0BAA0B,EAAE;IAC5D,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,4BAA4B,EAAE;CAC/D,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,eAAe,EAAE,CAAC;QACnD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,CAAC;QACpD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAA+B,MAAM,CAAC;IAC/C,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,GAAG,QAAQ,CAAC;IACnB,CAAC;SAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,GAAG,SAAS,CAAC;IACpB,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { createChildLogger } from '../../../lib/logger.js';
2
+ const log = createChildLogger('auth');
3
+ export function createRateLimiter(maxPerMinute) {
4
+ return { counts: new Map(), maxPerMinute };
5
+ }
6
+ export function checkRateLimit(state, keyName) {
7
+ const now = Date.now();
8
+ const windowMs = 60_000;
9
+ const entry = state.counts.get(keyName);
10
+ if (!entry || now - entry.windowStart > windowMs) {
11
+ state.counts.set(keyName, { count: 1, windowStart: now });
12
+ return true;
13
+ }
14
+ entry.count++;
15
+ return entry.count <= state.maxPerMinute;
16
+ }
17
+ export function authenticateRequest(apiKeyStore, rateLimiter, rawKey, ip) {
18
+ if (!rawKey) {
19
+ log.warn({ ip }, 'Missing API key');
20
+ return {
21
+ ok: false,
22
+ statusCode: 401,
23
+ error: { code: 'MISSING_API_KEY', message: 'x-api-key header is required', retryable: false },
24
+ };
25
+ }
26
+ const keyConfig = apiKeyStore.findByKey(rawKey);
27
+ if (!keyConfig) {
28
+ log.warn({ ip }, 'Invalid API key');
29
+ return {
30
+ ok: false,
31
+ statusCode: 401,
32
+ error: { code: 'INVALID_API_KEY', message: 'Invalid API key', retryable: false },
33
+ };
34
+ }
35
+ if (keyConfig.allowedIps && keyConfig.allowedIps.length > 0) {
36
+ const allowed = keyConfig.allowedIps.some(allowedIp => {
37
+ if (allowedIp.includes('/')) {
38
+ return ipInCidr(ip, allowedIp);
39
+ }
40
+ return ip === allowedIp;
41
+ });
42
+ if (!allowed) {
43
+ log.warn({ ip, keyName: keyConfig.name }, 'IP not in allowlist');
44
+ return {
45
+ ok: false,
46
+ statusCode: 403,
47
+ error: { code: 'IP_NOT_ALLOWED', message: 'IP address not in allowlist', retryable: false },
48
+ };
49
+ }
50
+ }
51
+ if (!checkRateLimit(rateLimiter, keyConfig.name)) {
52
+ log.warn({ keyName: keyConfig.name, ip }, 'Rate limit exceeded');
53
+ return {
54
+ ok: false,
55
+ statusCode: 429,
56
+ error: { code: 'RATE_LIMITED', message: 'Rate limit exceeded. Try again later.', retryable: true },
57
+ };
58
+ }
59
+ return { ok: true, keyConfig };
60
+ }
61
+ function ipInCidr(ip, cidr) {
62
+ const [network, bits] = cidr.split('/');
63
+ const mask = ~(2 ** (32 - Number(bits)) - 1);
64
+ const ipNum = ipToInt(ip);
65
+ const netNum = ipToInt(network);
66
+ return (ipNum & mask) === (netNum & mask);
67
+ }
68
+ function ipToInt(ip) {
69
+ return ip.split('.').reduce((acc, octet) => (acc << 8) + Number(octet), 0) >>> 0;
70
+ }
71
+ //# sourceMappingURL=authenticate_request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticate_request.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/authenticate_request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { createChildLogger } from '../../../lib/logger.js';
2
+ const log = createChildLogger('auto-approve');
3
+ export function createAutoApproveChannel() {
4
+ return {
5
+ async requestApproval(command, apiKeyName, ip, requestId, riskAnalysis) {
6
+ log.info({ requestId, command, apiKeyName, ip, risk: riskAnalysis.level }, 'AUTO-APPROVE: Command approved without Telegram');
7
+ if (riskAnalysis.warnings.length > 0) {
8
+ log.warn({ requestId, warnings: riskAnalysis.warnings }, 'Risk warnings (auto-approved)');
9
+ }
10
+ const decision = 'approved';
11
+ const matchType = 'exact';
12
+ const duration = '2';
13
+ return { decision, matchType, duration };
14
+ },
15
+ async start() {
16
+ log.warn('Running in AUTO-APPROVE mode. All commands will be approved without Telegram confirmation.');
17
+ log.warn('This mode is for development only. Do not use in production.');
18
+ },
19
+ async stop() {
20
+ // nothing to clean up
21
+ },
22
+ };
23
+ }
24
+ //# sourceMappingURL=auto_approve_channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto_approve_channel.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/auto_approve_channel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,GAAG,GAAG,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAE9C,MAAM,UAAU,wBAAwB;IACtC,OAAO;QACL,KAAK,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,YAAY;YACpE,GAAG,CAAC,IAAI,CACN,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,EAChE,iDAAiD,CAClD,CAAC;YACF,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrC,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,EAAE,+BAA+B,CAAC,CAAC;YAC5F,CAAC;YACD,MAAM,QAAQ,GAAqB,UAAU,CAAC;YAC9C,MAAM,SAAS,GAAsB,OAAO,CAAC;YAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC;YACrB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QAC3C,CAAC;QAED,KAAK,CAAC,KAAK;YACT,GAAG,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;YACvG,GAAG,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QAC3E,CAAC;QAED,KAAK,CAAC,IAAI;YACR,sBAAsB;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,139 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { createChildLogger } from '../../../lib/logger.js';
3
+ const log = createChildLogger('executor');
4
+ let activeExecutions = 0;
5
+ export async function executeCommand(options) {
6
+ const { command, requestId, cwd, timeoutMs, maxOutputBytes, maxConcurrent, abortSignal } = options;
7
+ if (activeExecutions >= maxConcurrent) {
8
+ log.warn({ requestId, active: activeExecutions, max: maxConcurrent }, 'Max concurrent executions reached');
9
+ return {
10
+ requestId,
11
+ status: 'failed',
12
+ error: 'Too many concurrent commands. Try again later.',
13
+ };
14
+ }
15
+ activeExecutions++;
16
+ const startTime = Date.now();
17
+ log.info({ requestId, command, cwd }, 'Executing command');
18
+ try {
19
+ return await new Promise((resolve) => {
20
+ const child = spawn(command, { shell: true, cwd: cwd ?? process.cwd(), detached: true });
21
+ let stdout = '';
22
+ let stderr = '';
23
+ let outputBytes = 0;
24
+ let killed = false;
25
+ const timer = setTimeout(() => {
26
+ killed = true;
27
+ try {
28
+ process.kill(-child.pid, 'SIGKILL');
29
+ }
30
+ catch {
31
+ child.kill('SIGKILL');
32
+ }
33
+ log.warn({ requestId, timeoutMs }, 'Command timed out');
34
+ }, timeoutMs);
35
+ const onAbort = () => {
36
+ killed = true;
37
+ try {
38
+ process.kill(-child.pid, 'SIGKILL');
39
+ }
40
+ catch {
41
+ child.kill('SIGKILL');
42
+ }
43
+ clearTimeout(timer);
44
+ log.info({ requestId }, 'Command aborted (client disconnected)');
45
+ };
46
+ if (abortSignal) {
47
+ if (abortSignal.aborted) {
48
+ try {
49
+ process.kill(-child.pid, 'SIGKILL');
50
+ }
51
+ catch {
52
+ child.kill('SIGKILL');
53
+ }
54
+ clearTimeout(timer);
55
+ resolve({ requestId, status: 'failed', error: 'Request aborted' });
56
+ return;
57
+ }
58
+ abortSignal.addEventListener('abort', onAbort, { once: true });
59
+ }
60
+ child.stdout.on('data', (chunk) => {
61
+ outputBytes += chunk.length;
62
+ if (outputBytes <= maxOutputBytes) {
63
+ stdout += chunk.toString();
64
+ }
65
+ else if (!killed) {
66
+ killed = true;
67
+ try {
68
+ process.kill(-child.pid, 'SIGKILL');
69
+ }
70
+ catch {
71
+ child.kill('SIGKILL');
72
+ }
73
+ clearTimeout(timer);
74
+ log.warn({ requestId, outputBytes, maxOutputBytes }, 'Output buffer exceeded');
75
+ }
76
+ });
77
+ child.stderr.on('data', (chunk) => {
78
+ outputBytes += chunk.length;
79
+ if (outputBytes <= maxOutputBytes) {
80
+ stderr += chunk.toString();
81
+ }
82
+ });
83
+ child.on('close', (code) => {
84
+ clearTimeout(timer);
85
+ if (abortSignal) {
86
+ abortSignal.removeEventListener('abort', onAbort);
87
+ }
88
+ const durationMs = Date.now() - startTime;
89
+ if (killed && outputBytes > maxOutputBytes) {
90
+ resolve({
91
+ requestId,
92
+ status: 'failed',
93
+ stdout: stdout.slice(0, maxOutputBytes),
94
+ stderr,
95
+ durationMs,
96
+ error: `Output exceeded ${maxOutputBytes} bytes limit`,
97
+ });
98
+ return;
99
+ }
100
+ if (killed) {
101
+ resolve({
102
+ requestId,
103
+ status: 'timed_out',
104
+ stdout,
105
+ stderr,
106
+ durationMs,
107
+ error: `Command timed out after ${timeoutMs}ms`,
108
+ });
109
+ return;
110
+ }
111
+ resolve({
112
+ requestId,
113
+ status: code === 0 ? 'completed' : 'failed',
114
+ exitCode: code ?? undefined,
115
+ stdout,
116
+ stderr,
117
+ durationMs,
118
+ });
119
+ log.info({ requestId, exitCode: code, durationMs }, 'Command completed');
120
+ });
121
+ child.on('error', (err) => {
122
+ clearTimeout(timer);
123
+ if (abortSignal) {
124
+ abortSignal.removeEventListener('abort', onAbort);
125
+ }
126
+ resolve({
127
+ requestId,
128
+ status: 'failed',
129
+ error: `Failed to execute: ${err.message}`,
130
+ durationMs: Date.now() - startTime,
131
+ });
132
+ });
133
+ });
134
+ }
135
+ finally {
136
+ activeExecutions--;
137
+ }
138
+ }
139
+ //# sourceMappingURL=execute_command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute_command.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/service/execute_command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { Telegraf, Markup } from 'telegraf';
2
+ import { createChildLogger } from '../../../lib/logger.js';
3
+ const log = createChildLogger('telegram');
4
+ export function createTelegramApprovalChannel(token, chatId, pendingStore, approvalStore, auditLog) {
5
+ const bot = new Telegraf(token);
6
+ bot.on('callback_query', async (ctx) => {
7
+ const data = 'data' in ctx.callbackQuery ? ctx.callbackQuery.data : undefined;
8
+ if (!data)
9
+ return;
10
+ // Validate chat ID to prevent unauthorized approvals
11
+ const callbackChatId = ctx.callbackQuery.message?.chat?.id?.toString();
12
+ if (callbackChatId !== chatId) {
13
+ log.warn({ callbackChatId, expectedChatId: chatId }, 'Callback from unauthorized chat');
14
+ await ctx.answerCbQuery('Unauthorized');
15
+ return;
16
+ }
17
+ // Parse callback data: "action:requestId:matchType:duration"
18
+ const parts = data.split(':');
19
+ if (parts.length !== 4)
20
+ return;
21
+ const [action, requestId, matchType, duration] = parts;
22
+ const pending = pendingStore.get(requestId);
23
+ if (!pending) {
24
+ await ctx.answerCbQuery('Request expired or already decided');
25
+ await ctx.editMessageReplyMarkup(undefined);
26
+ return;
27
+ }
28
+ const decision = action === 'approve' ? 'approved' : 'denied';
29
+ if (decision === 'approved') {
30
+ const approvalCommand = matchType === 'prefix'
31
+ ? pending.command.split(/\s+/).slice(0, 2).join(' ')
32
+ : pending.command;
33
+ approvalStore.addApproval(approvalCommand, matchType, duration, `telegram:${ctx.callbackQuery.from.id}`);
34
+ }
35
+ auditLog.append({
36
+ ts: new Date().toISOString(),
37
+ type: decision === 'approved' ? 'approved' : 'denied',
38
+ requestId,
39
+ command: pending.command,
40
+ duration: decision === 'approved' ? duration : undefined,
41
+ approvedBy: `telegram:${ctx.callbackQuery.from.id}`,
42
+ });
43
+ pendingStore.resolve(requestId, decision);
44
+ const emoji = decision === 'approved' ? '\u2705' : '\u274c';
45
+ const label = decision === 'approved' ? `Approved (${matchType} ${duration}h)` : 'Denied';
46
+ await ctx.answerCbQuery(label);
47
+ await ctx.editMessageText(`${emoji} ${label}\n\n${pending.command}`);
48
+ });
49
+ return {
50
+ async requestApproval(command, apiKeyName, ip, requestId, riskAnalysis) {
51
+ let text = `\u{1f6a8} **Command Request**\n\n`;
52
+ text += `From: \`${apiKeyName}\` (${ip})\n`;
53
+ text += `ID: \`${requestId}\`\n\n`;
54
+ text += `\`\`\`\n${command}\n\`\`\``;
55
+ if (riskAnalysis.warnings.length > 0) {
56
+ const icon = riskAnalysis.level === 'danger' ? '\u{26a0}\ufe0f DANGER' : '\u{26a0}\ufe0f WARNING';
57
+ text += `\n\n${icon}:\n`;
58
+ text += riskAnalysis.warnings.map(w => `• ${w}`).join('\n');
59
+ }
60
+ const prefix = command.split(/\s+/).slice(0, 2).join(' ');
61
+ const keyboard = Markup.inlineKeyboard([
62
+ [
63
+ Markup.button.callback('Exact 2h', `approve:${requestId}:exact:2`),
64
+ Markup.button.callback('Exact 8h', `approve:${requestId}:exact:8`),
65
+ Markup.button.callback('Exact \u221e', `approve:${requestId}:exact:permanent`),
66
+ ],
67
+ [
68
+ Markup.button.callback(`"${prefix}" 2h`, `approve:${requestId}:prefix:2`),
69
+ Markup.button.callback(`"${prefix}" 8h`, `approve:${requestId}:prefix:8`),
70
+ ],
71
+ [
72
+ Markup.button.callback('\u274c Deny', `deny:${requestId}:exact:0`),
73
+ ],
74
+ ]);
75
+ await bot.telegram.sendMessage(chatId, text, {
76
+ parse_mode: 'Markdown',
77
+ ...keyboard,
78
+ });
79
+ auditLog.append({
80
+ ts: new Date().toISOString(),
81
+ type: 'telegram_sent',
82
+ requestId,
83
+ command,
84
+ apiKeyName,
85
+ ip,
86
+ });
87
+ 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
+ });
107
+ },
108
+ async start() {
109
+ await bot.launch();
110
+ log.info('Telegram bot started');
111
+ // Startup health check
112
+ try {
113
+ await bot.telegram.sendMessage(chatId, '\u{1f7e2} Lucifer started. Approval channel active.');
114
+ log.info({ chatId }, 'Telegram health check passed');
115
+ }
116
+ catch (err) {
117
+ log.error({ chatId, err }, 'Failed to send startup message. Check LUCIFER_TELEGRAM_CHAT_ID.');
118
+ }
119
+ },
120
+ async stop() {
121
+ bot.stop('Shutdown');
122
+ log.info('Telegram bot stopped');
123
+ },
124
+ };
125
+ }
126
+ //# sourceMappingURL=request_telegram_approval.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=command_types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command_types.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/types/command_types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=store_interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store_interfaces.js","sourceRoot":"","sources":["../../../../../server/src/domains/command-gateway/types/store_interfaces.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export function registerHealthRoutes(app, getHealthReport) {
2
+ app.get('/api/health', (_request, response) => {
3
+ response.json(getHealthReport());
4
+ });
5
+ }
6
+ //# sourceMappingURL=register_health_routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register_health_routes.js","sourceRoot":"","sources":["../../../../../server/src/domains/platform-api/api/register_health_routes.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,oBAAoB,CAClC,GAAY,EACZ,eAAoC;IAEpC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,QAAiB,EAAE,QAAkB,EAAE,EAAE;QAC/D,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import path from 'node:path';
2
+ function parsePort(value) {
3
+ const parsedPort = Number.parseInt(value ?? '3001', 10);
4
+ if (Number.isInteger(parsedPort) && parsedPort >= 1 && parsedPort <= 65535) {
5
+ return parsedPort;
6
+ }
7
+ return 3001;
8
+ }
9
+ export function getServerConfig() {
10
+ return {
11
+ appName: 'lucifer',
12
+ clientDistPath: path.resolve(process.cwd(), 'dist/client'),
13
+ environment: process.env.NODE_ENV ?? 'development',
14
+ port: parsePort(process.env.PORT),
15
+ };
16
+ }
17
+ //# sourceMappingURL=server_config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server_config.js","sourceRoot":"","sources":["../../../../../server/src/domains/platform-api/config/server_config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAS5B,SAAS,SAAS,CAAC,KAAyB;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,MAAM,EAAE,EAAE,CAAC,CAAA;IAEvD,IAAI,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,IAAI,KAAK,EAAE,CAAC;QAC3E,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,OAAO,EAAE,SAAS;QAClB,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC;QAC1D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa;QAClD,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;KAClC,CAAA;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export function createRuntimeMetadataRepository() {
2
+ return {
3
+ getCurrentTimestamp: () => new Date().toISOString(),
4
+ getNodeVersion: () => process.version,
5
+ };
6
+ }
7
+ //# sourceMappingURL=runtime_metadata_repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime_metadata_repository.js","sourceRoot":"","sources":["../../../../../server/src/domains/platform-api/repository/runtime_metadata_repository.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,+BAA+B;IAC7C,OAAO;QACL,mBAAmB,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnD,cAAc,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO;KACtC,CAAA;AACH,CAAC"}