@aion0/bastion 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/README.zh.md +468 -0
- package/config/default.yaml +73 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +31 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/env.d.ts +3 -0
- package/dist/cli/commands/env.d.ts.map +1 -0
- package/dist/cli/commands/env.js +83 -0
- package/dist/cli/commands/env.js.map +1 -0
- package/dist/cli/commands/health.d.ts +3 -0
- package/dist/cli/commands/health.d.ts.map +1 -0
- package/dist/cli/commands/health.js +45 -0
- package/dist/cli/commands/health.js.map +1 -0
- package/dist/cli/commands/openclaw.d.ts +3 -0
- package/dist/cli/commands/openclaw.d.ts.map +1 -0
- package/dist/cli/commands/openclaw.js +1062 -0
- package/dist/cli/commands/openclaw.js.map +1 -0
- package/dist/cli/commands/proxy.d.ts +8 -0
- package/dist/cli/commands/proxy.d.ts.map +1 -0
- package/dist/cli/commands/proxy.js +433 -0
- package/dist/cli/commands/proxy.js.map +1 -0
- package/dist/cli/commands/start.d.ts +3 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +62 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +3 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +32 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +3 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +28 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/token.d.ts +3 -0
- package/dist/cli/commands/token.d.ts.map +1 -0
- package/dist/cli/commands/token.js +32 -0
- package/dist/cli/commands/token.js.map +1 -0
- package/dist/cli/commands/trust-ca.d.ts +3 -0
- package/dist/cli/commands/trust-ca.d.ts.map +1 -0
- package/dist/cli/commands/trust-ca.js +44 -0
- package/dist/cli/commands/trust-ca.js.map +1 -0
- package/dist/cli/commands/wrap.d.ts +3 -0
- package/dist/cli/commands/wrap.d.ts.map +1 -0
- package/dist/cli/commands/wrap.js +70 -0
- package/dist/cli/commands/wrap.js.map +1 -0
- package/dist/cli/daemon.d.ts +11 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +82 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +60 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +12 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +73 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/paths.d.ts +10 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +16 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +85 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +3 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/dashboard/api-routes.d.ts +6 -0
- package/dist/dashboard/api-routes.d.ts.map +1 -0
- package/dist/dashboard/api-routes.js +671 -0
- package/dist/dashboard/api-routes.js.map +1 -0
- package/dist/dashboard/api.d.ts +4 -0
- package/dist/dashboard/api.d.ts.map +1 -0
- package/dist/dashboard/api.js +25 -0
- package/dist/dashboard/api.js.map +1 -0
- package/dist/dashboard/page.d.ts +3 -0
- package/dist/dashboard/page.d.ts.map +1 -0
- package/dist/dashboard/page.js +1622 -0
- package/dist/dashboard/page.js.map +1 -0
- package/dist/dlp/actions.d.ts +13 -0
- package/dist/dlp/actions.d.ts.map +1 -0
- package/dist/dlp/actions.js +3 -0
- package/dist/dlp/actions.js.map +1 -0
- package/dist/dlp/ai-validator.d.ts +28 -0
- package/dist/dlp/ai-validator.d.ts.map +1 -0
- package/dist/dlp/ai-validator.js +214 -0
- package/dist/dlp/ai-validator.js.map +1 -0
- package/dist/dlp/engine.d.ts +34 -0
- package/dist/dlp/engine.d.ts.map +1 -0
- package/dist/dlp/engine.js +342 -0
- package/dist/dlp/engine.js.map +1 -0
- package/dist/dlp/entropy.d.ts +22 -0
- package/dist/dlp/entropy.d.ts.map +1 -0
- package/dist/dlp/entropy.js +43 -0
- package/dist/dlp/entropy.js.map +1 -0
- package/dist/dlp/message-cache.d.ts +45 -0
- package/dist/dlp/message-cache.d.ts.map +1 -0
- package/dist/dlp/message-cache.js +251 -0
- package/dist/dlp/message-cache.js.map +1 -0
- package/dist/dlp/patterns/context-aware.d.ts +4 -0
- package/dist/dlp/patterns/context-aware.d.ts.map +1 -0
- package/dist/dlp/patterns/context-aware.js +45 -0
- package/dist/dlp/patterns/context-aware.js.map +1 -0
- package/dist/dlp/patterns/high-confidence.d.ts +4 -0
- package/dist/dlp/patterns/high-confidence.d.ts.map +1 -0
- package/dist/dlp/patterns/high-confidence.js +140 -0
- package/dist/dlp/patterns/high-confidence.js.map +1 -0
- package/dist/dlp/patterns/prompt-injection.d.ts +4 -0
- package/dist/dlp/patterns/prompt-injection.d.ts.map +1 -0
- package/dist/dlp/patterns/prompt-injection.js +244 -0
- package/dist/dlp/patterns/prompt-injection.js.map +1 -0
- package/dist/dlp/patterns/validated.d.ts +4 -0
- package/dist/dlp/patterns/validated.d.ts.map +1 -0
- package/dist/dlp/patterns/validated.js +21 -0
- package/dist/dlp/patterns/validated.js.map +1 -0
- package/dist/dlp/remote-sync.d.ts +47 -0
- package/dist/dlp/remote-sync.d.ts.map +1 -0
- package/dist/dlp/remote-sync.js +252 -0
- package/dist/dlp/remote-sync.js.map +1 -0
- package/dist/dlp/semantics.d.ts +27 -0
- package/dist/dlp/semantics.d.ts.map +1 -0
- package/dist/dlp/semantics.js +93 -0
- package/dist/dlp/semantics.js.map +1 -0
- package/dist/dlp/structure.d.ts +25 -0
- package/dist/dlp/structure.d.ts.map +1 -0
- package/dist/dlp/structure.js +86 -0
- package/dist/dlp/structure.js.map +1 -0
- package/dist/dlp/validators.d.ts +6 -0
- package/dist/dlp/validators.d.ts.map +1 -0
- package/dist/dlp/validators.js +46 -0
- package/dist/dlp/validators.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +200 -0
- package/dist/index.js.map +1 -0
- package/dist/license/verify.d.ts +18 -0
- package/dist/license/verify.d.ts.map +1 -0
- package/dist/license/verify.js +71 -0
- package/dist/license/verify.js.map +1 -0
- package/dist/metrics/collector.d.ts +11 -0
- package/dist/metrics/collector.d.ts.map +1 -0
- package/dist/metrics/collector.js +17 -0
- package/dist/metrics/collector.js.map +1 -0
- package/dist/metrics/dashboard.d.ts +6 -0
- package/dist/metrics/dashboard.d.ts.map +1 -0
- package/dist/metrics/dashboard.js +66 -0
- package/dist/metrics/dashboard.js.map +1 -0
- package/dist/metrics/pricing.d.ts +10 -0
- package/dist/metrics/pricing.d.ts.map +1 -0
- package/dist/metrics/pricing.js +62 -0
- package/dist/metrics/pricing.js.map +1 -0
- package/dist/optimizer/cache.d.ts +14 -0
- package/dist/optimizer/cache.d.ts.map +1 -0
- package/dist/optimizer/cache.js +58 -0
- package/dist/optimizer/cache.js.map +1 -0
- package/dist/optimizer/estimator.d.ts +6 -0
- package/dist/optimizer/estimator.d.ts.map +1 -0
- package/dist/optimizer/estimator.js +12 -0
- package/dist/optimizer/estimator.js.map +1 -0
- package/dist/optimizer/reorder.d.ts +9 -0
- package/dist/optimizer/reorder.d.ts.map +1 -0
- package/dist/optimizer/reorder.js +27 -0
- package/dist/optimizer/reorder.js.map +1 -0
- package/dist/optimizer/trimmer.d.ts +9 -0
- package/dist/optimizer/trimmer.d.ts.map +1 -0
- package/dist/optimizer/trimmer.js +47 -0
- package/dist/optimizer/trimmer.js.map +1 -0
- package/dist/plugin-api/index.d.ts +3 -0
- package/dist/plugin-api/index.d.ts.map +1 -0
- package/dist/plugin-api/index.js +6 -0
- package/dist/plugin-api/index.js.map +1 -0
- package/dist/plugin-api/types.d.ts +77 -0
- package/dist/plugin-api/types.d.ts.map +1 -0
- package/dist/plugin-api/types.js +6 -0
- package/dist/plugin-api/types.js.map +1 -0
- package/dist/plugins/adapter.d.ts +12 -0
- package/dist/plugins/adapter.d.ts.map +1 -0
- package/dist/plugins/adapter.js +116 -0
- package/dist/plugins/adapter.js.map +1 -0
- package/dist/plugins/builtin/audit-logger.d.ts +9 -0
- package/dist/plugins/builtin/audit-logger.d.ts.map +1 -0
- package/dist/plugins/builtin/audit-logger.js +53 -0
- package/dist/plugins/builtin/audit-logger.js.map +1 -0
- package/dist/plugins/builtin/dlp-scanner.d.ts +19 -0
- package/dist/plugins/builtin/dlp-scanner.d.ts.map +1 -0
- package/dist/plugins/builtin/dlp-scanner.js +284 -0
- package/dist/plugins/builtin/dlp-scanner.js.map +1 -0
- package/dist/plugins/builtin/metrics-collector.d.ts +4 -0
- package/dist/plugins/builtin/metrics-collector.d.ts.map +1 -0
- package/dist/plugins/builtin/metrics-collector.js +111 -0
- package/dist/plugins/builtin/metrics-collector.js.map +1 -0
- package/dist/plugins/builtin/token-optimizer.d.ts +10 -0
- package/dist/plugins/builtin/token-optimizer.d.ts.map +1 -0
- package/dist/plugins/builtin/token-optimizer.js +120 -0
- package/dist/plugins/builtin/token-optimizer.js.map +1 -0
- package/dist/plugins/builtin/tool-guard.d.ts +20 -0
- package/dist/plugins/builtin/tool-guard.d.ts.map +1 -0
- package/dist/plugins/builtin/tool-guard.js +259 -0
- package/dist/plugins/builtin/tool-guard.js.map +1 -0
- package/dist/plugins/context.d.ts +8 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +33 -0
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/event-bus.d.ts +9 -0
- package/dist/plugins/event-bus.d.ts.map +1 -0
- package/dist/plugins/event-bus.js +25 -0
- package/dist/plugins/event-bus.js.map +1 -0
- package/dist/plugins/index.d.ts +18 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +148 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/loader.d.ts +14 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +98 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/types.d.ts +91 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +3 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/proxy/certs.d.ts +10 -0
- package/dist/proxy/certs.d.ts.map +1 -0
- package/dist/proxy/certs.js +110 -0
- package/dist/proxy/certs.js.map +1 -0
- package/dist/proxy/connect.d.ts +11 -0
- package/dist/proxy/connect.d.ts.map +1 -0
- package/dist/proxy/connect.js +298 -0
- package/dist/proxy/connect.js.map +1 -0
- package/dist/proxy/forwarder.d.ts +14 -0
- package/dist/proxy/forwarder.d.ts.map +1 -0
- package/dist/proxy/forwarder.js +342 -0
- package/dist/proxy/forwarder.js.map +1 -0
- package/dist/proxy/passthrough.d.ts +4 -0
- package/dist/proxy/passthrough.d.ts.map +1 -0
- package/dist/proxy/passthrough.js +68 -0
- package/dist/proxy/passthrough.js.map +1 -0
- package/dist/proxy/providers/anthropic.d.ts +4 -0
- package/dist/proxy/providers/anthropic.d.ts.map +1 -0
- package/dist/proxy/providers/anthropic.js +46 -0
- package/dist/proxy/providers/anthropic.js.map +1 -0
- package/dist/proxy/providers/classify.d.ts +14 -0
- package/dist/proxy/providers/classify.d.ts.map +1 -0
- package/dist/proxy/providers/classify.js +37 -0
- package/dist/proxy/providers/classify.js.map +1 -0
- package/dist/proxy/providers/claude-web.d.ts +8 -0
- package/dist/proxy/providers/claude-web.d.ts.map +1 -0
- package/dist/proxy/providers/claude-web.js +50 -0
- package/dist/proxy/providers/claude-web.js.map +1 -0
- package/dist/proxy/providers/gemini.d.ts +4 -0
- package/dist/proxy/providers/gemini.d.ts.map +1 -0
- package/dist/proxy/providers/gemini.js +38 -0
- package/dist/proxy/providers/gemini.js.map +1 -0
- package/dist/proxy/providers/index.d.ts +27 -0
- package/dist/proxy/providers/index.d.ts.map +1 -0
- package/dist/proxy/providers/index.js +32 -0
- package/dist/proxy/providers/index.js.map +1 -0
- package/dist/proxy/providers/messaging.d.ts +2 -0
- package/dist/proxy/providers/messaging.d.ts.map +1 -0
- package/dist/proxy/providers/messaging.js +53 -0
- package/dist/proxy/providers/messaging.js.map +1 -0
- package/dist/proxy/providers/openai.d.ts +4 -0
- package/dist/proxy/providers/openai.d.ts.map +1 -0
- package/dist/proxy/providers/openai.js +38 -0
- package/dist/proxy/providers/openai.js.map +1 -0
- package/dist/proxy/providers/telegram.d.ts +8 -0
- package/dist/proxy/providers/telegram.d.ts.map +1 -0
- package/dist/proxy/providers/telegram.js +35 -0
- package/dist/proxy/providers/telegram.js.map +1 -0
- package/dist/proxy/router.d.ts +12 -0
- package/dist/proxy/router.d.ts.map +1 -0
- package/dist/proxy/router.js +26 -0
- package/dist/proxy/router.js.map +1 -0
- package/dist/proxy/safety.d.ts +13 -0
- package/dist/proxy/safety.d.ts.map +1 -0
- package/dist/proxy/safety.js +58 -0
- package/dist/proxy/safety.js.map +1 -0
- package/dist/proxy/server.d.ts +8 -0
- package/dist/proxy/server.d.ts.map +1 -0
- package/dist/proxy/server.js +126 -0
- package/dist/proxy/server.js.map +1 -0
- package/dist/proxy/streaming.d.ts +21 -0
- package/dist/proxy/streaming.d.ts.map +1 -0
- package/dist/proxy/streaming.js +70 -0
- package/dist/proxy/streaming.js.map +1 -0
- package/dist/storage/database.d.ts +6 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +44 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/encryption.d.ts +11 -0
- package/dist/storage/encryption.d.ts.map +1 -0
- package/dist/storage/encryption.js +47 -0
- package/dist/storage/encryption.js.map +1 -0
- package/dist/storage/migrations.d.ts +3 -0
- package/dist/storage/migrations.d.ts.map +1 -0
- package/dist/storage/migrations.js +265 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/repositories/audit-log.d.ts +115 -0
- package/dist/storage/repositories/audit-log.d.ts.map +1 -0
- package/dist/storage/repositories/audit-log.js +586 -0
- package/dist/storage/repositories/audit-log.js.map +1 -0
- package/dist/storage/repositories/cache.d.ts +26 -0
- package/dist/storage/repositories/cache.d.ts.map +1 -0
- package/dist/storage/repositories/cache.js +44 -0
- package/dist/storage/repositories/cache.js.map +1 -0
- package/dist/storage/repositories/dlp-config-history.d.ts +17 -0
- package/dist/storage/repositories/dlp-config-history.d.ts.map +1 -0
- package/dist/storage/repositories/dlp-config-history.js +30 -0
- package/dist/storage/repositories/dlp-config-history.js.map +1 -0
- package/dist/storage/repositories/dlp-events.d.ts +35 -0
- package/dist/storage/repositories/dlp-events.d.ts.map +1 -0
- package/dist/storage/repositories/dlp-events.js +57 -0
- package/dist/storage/repositories/dlp-events.js.map +1 -0
- package/dist/storage/repositories/dlp-patterns.d.ts +70 -0
- package/dist/storage/repositories/dlp-patterns.d.ts.map +1 -0
- package/dist/storage/repositories/dlp-patterns.js +187 -0
- package/dist/storage/repositories/dlp-patterns.js.map +1 -0
- package/dist/storage/repositories/optimizer-events.d.ts +28 -0
- package/dist/storage/repositories/optimizer-events.d.ts.map +1 -0
- package/dist/storage/repositories/optimizer-events.js +49 -0
- package/dist/storage/repositories/optimizer-events.js.map +1 -0
- package/dist/storage/repositories/plugin-events.d.ts +34 -0
- package/dist/storage/repositories/plugin-events.d.ts.map +1 -0
- package/dist/storage/repositories/plugin-events.js +64 -0
- package/dist/storage/repositories/plugin-events.js.map +1 -0
- package/dist/storage/repositories/requests.d.ts +68 -0
- package/dist/storage/repositories/requests.d.ts.map +1 -0
- package/dist/storage/repositories/requests.js +113 -0
- package/dist/storage/repositories/requests.js.map +1 -0
- package/dist/storage/repositories/sessions.d.ts +23 -0
- package/dist/storage/repositories/sessions.d.ts.map +1 -0
- package/dist/storage/repositories/sessions.js +42 -0
- package/dist/storage/repositories/sessions.js.map +1 -0
- package/dist/storage/repositories/tool-calls.d.ts +49 -0
- package/dist/storage/repositories/tool-calls.d.ts.map +1 -0
- package/dist/storage/repositories/tool-calls.js +61 -0
- package/dist/storage/repositories/tool-calls.js.map +1 -0
- package/dist/storage/repositories/tool-guard-rules.d.ts +50 -0
- package/dist/storage/repositories/tool-guard-rules.d.ts.map +1 -0
- package/dist/storage/repositories/tool-guard-rules.js +120 -0
- package/dist/storage/repositories/tool-guard-rules.js.map +1 -0
- package/dist/tool-guard/alert.d.ts +30 -0
- package/dist/tool-guard/alert.d.ts.map +1 -0
- package/dist/tool-guard/alert.js +113 -0
- package/dist/tool-guard/alert.js.map +1 -0
- package/dist/tool-guard/extractor.d.ts +10 -0
- package/dist/tool-guard/extractor.d.ts.map +1 -0
- package/dist/tool-guard/extractor.js +309 -0
- package/dist/tool-guard/extractor.js.map +1 -0
- package/dist/tool-guard/rules.d.ts +18 -0
- package/dist/tool-guard/rules.d.ts.map +1 -0
- package/dist/tool-guard/rules.js +255 -0
- package/dist/tool-guard/rules.js.map +1 -0
- package/dist/tool-guard/streaming-guard.d.ts +57 -0
- package/dist/tool-guard/streaming-guard.d.ts.map +1 -0
- package/dist/tool-guard/streaming-guard.js +389 -0
- package/dist/tool-guard/streaming-guard.js.map +1 -0
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +8 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +54 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/timeout.d.ts +5 -0
- package/dist/utils/timeout.d.ts.map +1 -0
- package/dist/utils/timeout.js +26 -0
- package/dist/utils/timeout.js.map +1 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createApiRouter = createApiRouter;
|
|
4
|
+
const requests_js_1 = require("../storage/repositories/requests.js");
|
|
5
|
+
const dlp_events_js_1 = require("../storage/repositories/dlp-events.js");
|
|
6
|
+
const optimizer_events_js_1 = require("../storage/repositories/optimizer-events.js");
|
|
7
|
+
const audit_log_js_1 = require("../storage/repositories/audit-log.js");
|
|
8
|
+
const cache_js_1 = require("../storage/repositories/cache.js");
|
|
9
|
+
const sessions_js_1 = require("../storage/repositories/sessions.js");
|
|
10
|
+
const dlp_patterns_js_1 = require("../storage/repositories/dlp-patterns.js");
|
|
11
|
+
const dlp_config_history_js_1 = require("../storage/repositories/dlp-config-history.js");
|
|
12
|
+
const tool_calls_js_1 = require("../storage/repositories/tool-calls.js");
|
|
13
|
+
const tool_guard_rules_js_1 = require("../storage/repositories/tool-guard-rules.js");
|
|
14
|
+
const alert_js_1 = require("../tool-guard/alert.js");
|
|
15
|
+
const engine_js_1 = require("../dlp/engine.js");
|
|
16
|
+
const semantics_js_1 = require("../dlp/semantics.js");
|
|
17
|
+
const remote_sync_js_1 = require("../dlp/remote-sync.js");
|
|
18
|
+
const version_js_1 = require("../version.js");
|
|
19
|
+
const verify_js_1 = require("../license/verify.js");
|
|
20
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
21
|
+
const log = (0, logger_js_1.createLogger)('api-routes');
|
|
22
|
+
function parseUrl(req) {
|
|
23
|
+
return new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
|
24
|
+
}
|
|
25
|
+
function sendJson(res, data, status = 200) {
|
|
26
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
27
|
+
res.end(JSON.stringify(data));
|
|
28
|
+
}
|
|
29
|
+
function bufferBody(req) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const chunks = [];
|
|
32
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
33
|
+
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
|
34
|
+
req.on('error', reject);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function createApiRouter(db, configManager, pluginManager, getPluginState) {
|
|
38
|
+
const requestsRepo = new requests_js_1.RequestsRepository(db);
|
|
39
|
+
const dlpRepo = new dlp_events_js_1.DlpEventsRepository(db);
|
|
40
|
+
const optimizerRepo = new optimizer_events_js_1.OptimizerEventsRepository(db);
|
|
41
|
+
const auditRepo = new audit_log_js_1.AuditLogRepository(db);
|
|
42
|
+
const cacheRepo = new cache_js_1.CacheRepository(db);
|
|
43
|
+
const sessionsRepo = new sessions_js_1.SessionsRepository(db);
|
|
44
|
+
const dlpPatternsRepo = new dlp_patterns_js_1.DlpPatternsRepository(db);
|
|
45
|
+
const dlpConfigHistory = new dlp_config_history_js_1.DlpConfigHistoryRepository(db);
|
|
46
|
+
const toolCallsRepo = new tool_calls_js_1.ToolCallsRepository(db);
|
|
47
|
+
const toolGuardRulesRepo = new tool_guard_rules_js_1.ToolGuardRulesRepository(db);
|
|
48
|
+
let devUnlocked = false;
|
|
49
|
+
return (req, res) => {
|
|
50
|
+
const url = parseUrl(req);
|
|
51
|
+
const path = url.pathname;
|
|
52
|
+
// GET /api/dev — dev mode check (only true when started with --dev)
|
|
53
|
+
if (req.method === 'GET' && path === '/api/dev') {
|
|
54
|
+
sendJson(res, { dev: process.env.BASTION_DEV === '1' });
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
// POST /api/dev/activate — activate dev unlock with token
|
|
58
|
+
if (req.method === 'POST' && path === '/api/dev/activate') {
|
|
59
|
+
const expected = process.env.BASTION_DEV_TOKEN;
|
|
60
|
+
if (!expected) {
|
|
61
|
+
sendJson(res, { error: 'Dev mode not enabled' }, 403);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
bufferBody(req).then((body) => {
|
|
65
|
+
try {
|
|
66
|
+
const data = JSON.parse(body);
|
|
67
|
+
if (data.token === expected) {
|
|
68
|
+
devUnlocked = true;
|
|
69
|
+
sendJson(res, { ok: true });
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
sendJson(res, { error: 'Invalid token' }, 403);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
sendJson(res, { error: 'Invalid request' }, 400);
|
|
77
|
+
}
|
|
78
|
+
}).catch(() => sendJson(res, { error: 'Internal error' }, 500));
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
// GET /api/stats — Enhanced with filters
|
|
82
|
+
if (req.method === 'GET' && path === '/api/stats') {
|
|
83
|
+
const sessionId = url.searchParams.get('session_id') ?? undefined;
|
|
84
|
+
const apiKeyHash = url.searchParams.get('api_key_hash') ?? undefined;
|
|
85
|
+
const hours = url.searchParams.get('hours');
|
|
86
|
+
const sinceHours = hours ? parseInt(hours, 10) : undefined;
|
|
87
|
+
const stats = requestsRepo.getStats({ sinceHours, sessionId, apiKeyHash });
|
|
88
|
+
const recent = requestsRepo.getRecent(20, sinceHours);
|
|
89
|
+
const cacheStats = cacheRepo.getStats();
|
|
90
|
+
const dlpStats = dlpRepo.getStats();
|
|
91
|
+
sendJson(res, {
|
|
92
|
+
stats,
|
|
93
|
+
recent,
|
|
94
|
+
cache: cacheStats,
|
|
95
|
+
dlp: dlpStats,
|
|
96
|
+
version: (0, version_js_1.getVersion)(),
|
|
97
|
+
uptime: process.uptime(),
|
|
98
|
+
memory: process.memoryUsage().rss,
|
|
99
|
+
});
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
// GET /api/sessions
|
|
103
|
+
if (req.method === 'GET' && path === '/api/sessions') {
|
|
104
|
+
sendJson(res, requestsRepo.getSessions());
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
// GET /api/dlp/recent
|
|
108
|
+
if (req.method === 'GET' && path === '/api/dlp/recent') {
|
|
109
|
+
const limit = parseInt(url.searchParams.get('limit') ?? '50', 10);
|
|
110
|
+
const hours = url.searchParams.get('hours');
|
|
111
|
+
const sinceHours = hours ? parseInt(hours, 10) : undefined;
|
|
112
|
+
sendJson(res, dlpRepo.getRecent(limit, sinceHours));
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
// POST /api/dlp/scan — standalone DLP scan for testing and external integration
|
|
116
|
+
if (req.method === 'POST' && path === '/api/dlp/scan') {
|
|
117
|
+
bufferBody(req).then((body) => {
|
|
118
|
+
try {
|
|
119
|
+
const data = JSON.parse(body);
|
|
120
|
+
const text = data.text;
|
|
121
|
+
if (typeof text !== 'string' || text.length === 0) {
|
|
122
|
+
sendJson(res, { error: 'text field is required' }, 400);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const action = (data.action ?? configManager.get().plugins.dlp.action ?? 'warn');
|
|
126
|
+
const patterns = dlpPatternsRepo.getEnabled();
|
|
127
|
+
const enableTrace = Boolean(data.trace);
|
|
128
|
+
const trace = enableTrace ? { entries: [], totalDurationMs: 0 } : undefined;
|
|
129
|
+
const result = (0, engine_js_1.scanText)(text, patterns, action, trace);
|
|
130
|
+
sendJson(res, {
|
|
131
|
+
action: result.action,
|
|
132
|
+
findings: result.findings.map((f) => ({
|
|
133
|
+
patternName: f.patternName,
|
|
134
|
+
patternCategory: f.patternCategory,
|
|
135
|
+
matchCount: f.matchCount,
|
|
136
|
+
matches: f.matches,
|
|
137
|
+
})),
|
|
138
|
+
redactedText: result.redactedBody ?? null,
|
|
139
|
+
trace: trace ?? null,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
sendJson(res, { error: err.message }, 400);
|
|
144
|
+
}
|
|
145
|
+
}).catch((err) => {
|
|
146
|
+
sendJson(res, { error: err.message }, 500);
|
|
147
|
+
});
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
// GET /api/optimizer/stats
|
|
151
|
+
if (req.method === 'GET' && path === '/api/optimizer/stats') {
|
|
152
|
+
sendJson(res, optimizerRepo.getStats());
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
// GET /api/optimizer/recent
|
|
156
|
+
if (req.method === 'GET' && path === '/api/optimizer/recent') {
|
|
157
|
+
const limit = parseInt(url.searchParams.get('limit') ?? '50', 10);
|
|
158
|
+
const hours = url.searchParams.get('hours');
|
|
159
|
+
const sinceHours = hours ? parseInt(hours, 10) : undefined;
|
|
160
|
+
sendJson(res, optimizerRepo.getRecent(limit, sinceHours));
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
// GET /api/audit/recent
|
|
164
|
+
if (req.method === 'GET' && path === '/api/audit/recent') {
|
|
165
|
+
const limit = parseInt(url.searchParams.get('limit') ?? '50', 10);
|
|
166
|
+
const hours = url.searchParams.get('hours');
|
|
167
|
+
const sinceHours = hours ? parseInt(hours, 10) : undefined;
|
|
168
|
+
sendJson(res, auditRepo.getRecent(limit, sinceHours));
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
// GET /api/audit/sessions — list sessions with audit data
|
|
172
|
+
if (req.method === 'GET' && path === '/api/audit/sessions') {
|
|
173
|
+
const hours = url.searchParams.get('hours');
|
|
174
|
+
const sinceHours = hours ? parseInt(hours, 10) : undefined;
|
|
175
|
+
sendJson(res, auditRepo.getAuditSessions(30, sinceHours));
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
// GET /api/audit/session/:sessionId — full parsed timeline for a session
|
|
179
|
+
if (req.method === 'GET' && path.startsWith('/api/audit/session/')) {
|
|
180
|
+
const sessionId = path.slice('/api/audit/session/'.length);
|
|
181
|
+
if (!sessionId) {
|
|
182
|
+
sendJson(res, { error: 'Missing session ID' }, 400);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
const timeline = auditRepo.getParsedSession(sessionId);
|
|
186
|
+
if (timeline.length === 0) {
|
|
187
|
+
sendJson(res, { error: 'No audit entries for this session' }, 404);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
const session = sessionsRepo.get(sessionId) ?? null;
|
|
191
|
+
sendJson(res, { session, timeline });
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
// GET /api/audit/:requestId — single request parsed
|
|
195
|
+
if (req.method === 'GET' && path.startsWith('/api/audit/') && !path.includes('/session')) {
|
|
196
|
+
const requestId = path.slice('/api/audit/'.length);
|
|
197
|
+
if (!requestId) {
|
|
198
|
+
sendJson(res, { error: 'Missing request ID' }, 400);
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
const parsed = auditRepo.getParsedByRequestId(requestId);
|
|
202
|
+
if (!parsed) {
|
|
203
|
+
// Fallback: raw data may be off — return summary-only
|
|
204
|
+
const meta = auditRepo.getMetaByRequestId(requestId);
|
|
205
|
+
if (!meta) {
|
|
206
|
+
sendJson(res, { error: 'Audit entry not found' }, 404);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
sendJson(res, { summaryOnly: true, summary: meta.summary, meta });
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
// DLP highlight: re-scan raw text with matched patterns to get exact match strings
|
|
213
|
+
if (url.searchParams.get('dlp') === 'true') {
|
|
214
|
+
const dlpFindings = dlpRepo.getByRequestId(requestId);
|
|
215
|
+
if (dlpFindings.length > 0) {
|
|
216
|
+
const patternNames = [...new Set(dlpFindings.map(f => f.pattern_name))];
|
|
217
|
+
const relevantPatterns = dlpPatternsRepo.getByNames(patternNames);
|
|
218
|
+
if (relevantPatterns.length > 0) {
|
|
219
|
+
const allMatches = [];
|
|
220
|
+
try {
|
|
221
|
+
const reqResult = (0, engine_js_1.scanText)(parsed.raw.request, relevantPatterns, 'warn');
|
|
222
|
+
reqResult.findings.forEach(f => allMatches.push(...f.matches));
|
|
223
|
+
const resResult = (0, engine_js_1.scanText)(parsed.raw.response, relevantPatterns, 'warn');
|
|
224
|
+
resResult.findings.forEach(f => allMatches.push(...f.matches));
|
|
225
|
+
}
|
|
226
|
+
catch { /* ignore scan errors */ }
|
|
227
|
+
parsed.dlpHighlights = [...new Set(allMatches)];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Tool Guard: attach tool_calls for this request
|
|
232
|
+
if (url.searchParams.get('tg') === 'true') {
|
|
233
|
+
const toolCalls = toolCallsRepo.getByRequestId(requestId);
|
|
234
|
+
if (toolCalls.length > 0) {
|
|
235
|
+
parsed.toolGuardFindings = toolCalls;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
sendJson(res, parsed);
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
// GET /api/config
|
|
242
|
+
if (req.method === 'GET' && path === '/api/config') {
|
|
243
|
+
const config = configManager.get();
|
|
244
|
+
const pluginStatus = {};
|
|
245
|
+
const pluginInfo = [];
|
|
246
|
+
for (const p of pluginManager.getPlugins()) {
|
|
247
|
+
const enabled = !pluginManager.isDisabled(p.name);
|
|
248
|
+
pluginStatus[p.name] = enabled;
|
|
249
|
+
pluginInfo.push({ name: p.name, enabled, source: p.source ?? 'builtin', version: p.version, packageName: p.packageName, priority: p.priority });
|
|
250
|
+
}
|
|
251
|
+
sendJson(res, { config, pluginStatus, pluginInfo });
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
// PUT /api/config
|
|
255
|
+
if (req.method === 'PUT' && path === '/api/config') {
|
|
256
|
+
bufferBody(req).then((body) => {
|
|
257
|
+
try {
|
|
258
|
+
const update = JSON.parse(body);
|
|
259
|
+
// Handle plugin enable/disable
|
|
260
|
+
if (update.pluginStatus) {
|
|
261
|
+
for (const [name, enabled] of Object.entries(update.pluginStatus)) {
|
|
262
|
+
if (enabled) {
|
|
263
|
+
pluginManager.enable(name);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
pluginManager.disable(name);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
delete update.pluginStatus;
|
|
270
|
+
}
|
|
271
|
+
// Apply remaining config changes
|
|
272
|
+
if (Object.keys(update).length > 0) {
|
|
273
|
+
configManager.update(update);
|
|
274
|
+
}
|
|
275
|
+
const config = configManager.get();
|
|
276
|
+
const pluginStatus = {};
|
|
277
|
+
const pluginInfo = [];
|
|
278
|
+
for (const p of pluginManager.getPlugins()) {
|
|
279
|
+
const enabled = !pluginManager.isDisabled(p.name);
|
|
280
|
+
pluginStatus[p.name] = enabled;
|
|
281
|
+
pluginInfo.push({ name: p.name, enabled, source: p.source ?? 'builtin', version: p.version, packageName: p.packageName, priority: p.priority });
|
|
282
|
+
}
|
|
283
|
+
sendJson(res, { config, pluginStatus, pluginInfo });
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
sendJson(res, { error: err.message }, 400);
|
|
287
|
+
}
|
|
288
|
+
}).catch((err) => {
|
|
289
|
+
sendJson(res, { error: err.message }, 500);
|
|
290
|
+
});
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
// POST /api/dlp/config/apply — batch-apply DLP config and record history
|
|
294
|
+
if (req.method === 'POST' && path === '/api/dlp/config/apply') {
|
|
295
|
+
bufferBody(req).then((body) => {
|
|
296
|
+
try {
|
|
297
|
+
const dlpUpdate = JSON.parse(body);
|
|
298
|
+
// Handle plugin enable/disable
|
|
299
|
+
if (dlpUpdate.enabled !== undefined) {
|
|
300
|
+
if (dlpUpdate.enabled)
|
|
301
|
+
pluginManager.enable('dlp-scanner');
|
|
302
|
+
else
|
|
303
|
+
pluginManager.disable('dlp-scanner');
|
|
304
|
+
delete dlpUpdate.enabled;
|
|
305
|
+
}
|
|
306
|
+
// Apply config changes
|
|
307
|
+
if (Object.keys(dlpUpdate).length > 0) {
|
|
308
|
+
configManager.update({ plugins: { dlp: dlpUpdate } });
|
|
309
|
+
}
|
|
310
|
+
// Record snapshot to history
|
|
311
|
+
const snap = configManager.get().plugins.dlp;
|
|
312
|
+
const dlpEnabled = !pluginManager.isDisabled('dlp-scanner');
|
|
313
|
+
dlpConfigHistory.insert({ ...snap, enabled: dlpEnabled });
|
|
314
|
+
sendJson(res, { ok: true, config: snap, enabled: dlpEnabled });
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
sendJson(res, { error: err.message }, 400);
|
|
318
|
+
}
|
|
319
|
+
}).catch((err) => sendJson(res, { error: err.message }, 500));
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
// GET /api/dlp/config/history — last 10 config changes
|
|
323
|
+
if (req.method === 'GET' && path === '/api/dlp/config/history') {
|
|
324
|
+
sendJson(res, dlpConfigHistory.getRecent());
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
// POST /api/dlp/config/restore/:id — restore a config snapshot
|
|
328
|
+
if (req.method === 'POST' && path.startsWith('/api/dlp/config/restore/')) {
|
|
329
|
+
const id = parseInt(path.slice('/api/dlp/config/restore/'.length), 10);
|
|
330
|
+
if (isNaN(id)) {
|
|
331
|
+
sendJson(res, { error: 'Invalid history ID' }, 400);
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
const entry = dlpConfigHistory.getById(id);
|
|
335
|
+
if (!entry) {
|
|
336
|
+
sendJson(res, { error: 'History entry not found' }, 404);
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const snapshot = JSON.parse(entry.config_json);
|
|
341
|
+
// Restore plugin enabled state
|
|
342
|
+
if (snapshot.enabled !== undefined) {
|
|
343
|
+
if (snapshot.enabled)
|
|
344
|
+
pluginManager.enable('dlp-scanner');
|
|
345
|
+
else
|
|
346
|
+
pluginManager.disable('dlp-scanner');
|
|
347
|
+
}
|
|
348
|
+
// Restore config (exclude non-config fields)
|
|
349
|
+
const { enabled: _, ...configPart } = snapshot;
|
|
350
|
+
if (Object.keys(configPart).length > 0) {
|
|
351
|
+
configManager.update({ plugins: { dlp: configPart } });
|
|
352
|
+
}
|
|
353
|
+
// Record this restore as a new history entry
|
|
354
|
+
const snap = configManager.get().plugins.dlp;
|
|
355
|
+
const dlpEnabled = !pluginManager.isDisabled('dlp-scanner');
|
|
356
|
+
dlpConfigHistory.insert({ ...snap, enabled: dlpEnabled });
|
|
357
|
+
sendJson(res, { ok: true, config: snap, enabled: dlpEnabled });
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
sendJson(res, { error: err.message }, 400);
|
|
361
|
+
}
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
// GET /api/dlp/semantics/builtins — read-only built-in defaults
|
|
365
|
+
if (req.method === 'GET' && path === '/api/dlp/semantics/builtins') {
|
|
366
|
+
sendJson(res, {
|
|
367
|
+
sensitivePatterns: (0, semantics_js_1.getBuiltinSensitivePatterns)(),
|
|
368
|
+
nonSensitiveNames: (0, semantics_js_1.getBuiltinNonSensitiveNames)(),
|
|
369
|
+
});
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
// GET /api/dlp/signature — signature version and update status
|
|
373
|
+
if (req.method === 'GET' && path === '/api/dlp/signature') {
|
|
374
|
+
const remoteConfig = configManager.get().plugins.dlp.remotePatterns;
|
|
375
|
+
const check = url.searchParams.get('check') === 'true';
|
|
376
|
+
if (check && remoteConfig?.url) {
|
|
377
|
+
sendJson(res, (0, remote_sync_js_1.checkForUpdates)(remoteConfig));
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
const local = (0, remote_sync_js_1.getLocalSignatureMeta)();
|
|
381
|
+
sendJson(res, { local, remote: null, updateAvailable: false });
|
|
382
|
+
}
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
// POST /api/dlp/signature/sync — trigger manual sync
|
|
386
|
+
if (req.method === 'POST' && path === '/api/dlp/signature/sync') {
|
|
387
|
+
const remoteConfig = configManager.get().plugins.dlp.remotePatterns;
|
|
388
|
+
if (!remoteConfig?.url) {
|
|
389
|
+
sendJson(res, { error: 'Remote patterns not configured' }, 400);
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
const enabledCategories = configManager.get().plugins.dlp.patterns;
|
|
393
|
+
const count = (0, remote_sync_js_1.syncRemotePatterns)(remoteConfig, dlpPatternsRepo, enabledCategories);
|
|
394
|
+
if (count < 0) {
|
|
395
|
+
sendJson(res, { error: 'Sync failed' }, 500);
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
const local = (0, remote_sync_js_1.getLocalSignatureMeta)();
|
|
399
|
+
sendJson(res, { ok: true, synced: count, signature: local });
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
// GET /api/dlp/patterns — all patterns for UI listing
|
|
403
|
+
if (req.method === 'GET' && path === '/api/dlp/patterns') {
|
|
404
|
+
sendJson(res, dlpPatternsRepo.getAll());
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
// POST /api/dlp/patterns — add custom pattern
|
|
408
|
+
if (req.method === 'POST' && path === '/api/dlp/patterns') {
|
|
409
|
+
bufferBody(req).then((body) => {
|
|
410
|
+
try {
|
|
411
|
+
const data = JSON.parse(body);
|
|
412
|
+
if (!data.name || !data.regex_source) {
|
|
413
|
+
sendJson(res, { error: 'name and regex_source are required' }, 400);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Validate regex
|
|
417
|
+
try {
|
|
418
|
+
new RegExp(data.regex_source, data.regex_flags ?? 'g');
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
sendJson(res, { error: 'Invalid regex' }, 400);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const id = `custom-${crypto.randomUUID()}`;
|
|
425
|
+
dlpPatternsRepo.upsert({
|
|
426
|
+
id,
|
|
427
|
+
name: data.name,
|
|
428
|
+
category: data.category ?? 'custom',
|
|
429
|
+
regex_source: data.regex_source,
|
|
430
|
+
regex_flags: data.regex_flags ?? 'g',
|
|
431
|
+
description: data.description ?? null,
|
|
432
|
+
validator: data.validator ?? null,
|
|
433
|
+
require_context: data.require_context ?? null,
|
|
434
|
+
enabled: data.enabled !== false,
|
|
435
|
+
});
|
|
436
|
+
sendJson(res, { id }, 201);
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
sendJson(res, { error: err.message }, 400);
|
|
440
|
+
}
|
|
441
|
+
}).catch((err) => {
|
|
442
|
+
sendJson(res, { error: err.message }, 500);
|
|
443
|
+
});
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
// PUT /api/dlp/patterns/:id — update pattern (toggle enabled, edit fields)
|
|
447
|
+
if (req.method === 'PUT' && path.startsWith('/api/dlp/patterns/')) {
|
|
448
|
+
const id = decodeURIComponent(path.slice('/api/dlp/patterns/'.length));
|
|
449
|
+
if (!id) {
|
|
450
|
+
sendJson(res, { error: 'Missing pattern ID' }, 400);
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
453
|
+
bufferBody(req).then((body) => {
|
|
454
|
+
try {
|
|
455
|
+
const data = JSON.parse(body);
|
|
456
|
+
// If just toggling enabled
|
|
457
|
+
if (data.enabled !== undefined && Object.keys(data).length === 1) {
|
|
458
|
+
dlpPatternsRepo.toggle(id, Boolean(data.enabled));
|
|
459
|
+
sendJson(res, { ok: true });
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
// Validate regex if provided
|
|
463
|
+
if (data.regex_source) {
|
|
464
|
+
try {
|
|
465
|
+
new RegExp(data.regex_source, data.regex_flags ?? 'g');
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
sendJson(res, { error: 'Invalid regex' }, 400);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
// Full upsert for custom patterns
|
|
473
|
+
if (data.name && data.regex_source) {
|
|
474
|
+
dlpPatternsRepo.upsert({ id, ...data });
|
|
475
|
+
}
|
|
476
|
+
else if (data.enabled !== undefined) {
|
|
477
|
+
dlpPatternsRepo.toggle(id, Boolean(data.enabled));
|
|
478
|
+
}
|
|
479
|
+
sendJson(res, { ok: true });
|
|
480
|
+
}
|
|
481
|
+
catch (err) {
|
|
482
|
+
sendJson(res, { error: err.message }, 400);
|
|
483
|
+
}
|
|
484
|
+
}).catch((err) => {
|
|
485
|
+
sendJson(res, { error: err.message }, 500);
|
|
486
|
+
});
|
|
487
|
+
return true;
|
|
488
|
+
}
|
|
489
|
+
// DELETE /api/dlp/patterns/:id — delete custom pattern only
|
|
490
|
+
if (req.method === 'DELETE' && path.startsWith('/api/dlp/patterns/')) {
|
|
491
|
+
const id = decodeURIComponent(path.slice('/api/dlp/patterns/'.length));
|
|
492
|
+
if (!id) {
|
|
493
|
+
sendJson(res, { error: 'Missing pattern ID' }, 400);
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
dlpPatternsRepo.remove(id);
|
|
498
|
+
sendJson(res, { ok: true });
|
|
499
|
+
}
|
|
500
|
+
catch (err) {
|
|
501
|
+
sendJson(res, { error: err.message }, 400);
|
|
502
|
+
}
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
// GET /api/tool-guard/alerts — recent alerts with unack count
|
|
506
|
+
if (req.method === 'GET' && path === '/api/tool-guard/alerts') {
|
|
507
|
+
sendJson(res, {
|
|
508
|
+
alerts: (0, alert_js_1.getRecentAlerts)(),
|
|
509
|
+
unacknowledged: (0, alert_js_1.getUnacknowledgedCount)(),
|
|
510
|
+
});
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
// POST /api/tool-guard/alerts/ack — acknowledge all alerts
|
|
514
|
+
if (req.method === 'POST' && path === '/api/tool-guard/alerts/ack') {
|
|
515
|
+
(0, alert_js_1.acknowledgeAlerts)();
|
|
516
|
+
sendJson(res, { ok: true });
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
// GET /api/tool-guard/recent — recent tool calls
|
|
520
|
+
if (req.method === 'GET' && path === '/api/tool-guard/recent') {
|
|
521
|
+
const limit = parseInt(url.searchParams.get('limit') ?? '50', 10);
|
|
522
|
+
const hours = url.searchParams.get('hours');
|
|
523
|
+
const sinceHours = hours ? parseInt(hours, 10) : undefined;
|
|
524
|
+
sendJson(res, toolCallsRepo.getRecent(limit, sinceHours));
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
// GET /api/tool-guard/stats — counts by severity, category, top tool names
|
|
528
|
+
if (req.method === 'GET' && path === '/api/tool-guard/stats') {
|
|
529
|
+
sendJson(res, toolCallsRepo.getStats());
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
// GET /api/tool-guard/session/:id — tool calls for a specific session
|
|
533
|
+
if (req.method === 'GET' && path.startsWith('/api/tool-guard/session/')) {
|
|
534
|
+
const sessionId = path.slice('/api/tool-guard/session/'.length);
|
|
535
|
+
if (!sessionId) {
|
|
536
|
+
sendJson(res, { error: 'Missing session ID' }, 400);
|
|
537
|
+
return true;
|
|
538
|
+
}
|
|
539
|
+
sendJson(res, toolCallsRepo.getBySession(sessionId));
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
// GET /api/tool-guard/rules — list all rules
|
|
543
|
+
if (req.method === 'GET' && path === '/api/tool-guard/rules') {
|
|
544
|
+
sendJson(res, toolGuardRulesRepo.getAll());
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
// POST /api/tool-guard/rules — add custom rule
|
|
548
|
+
if (req.method === 'POST' && path === '/api/tool-guard/rules') {
|
|
549
|
+
bufferBody(req).then(raw => {
|
|
550
|
+
try {
|
|
551
|
+
const body = JSON.parse(raw);
|
|
552
|
+
if (!body.name || !body.input_pattern) {
|
|
553
|
+
sendJson(res, { error: 'name and input_pattern are required' }, 400);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
// Validate regex
|
|
557
|
+
try {
|
|
558
|
+
new RegExp(body.input_pattern, body.input_flags ?? 'i');
|
|
559
|
+
}
|
|
560
|
+
catch {
|
|
561
|
+
sendJson(res, { error: 'Invalid input_pattern regex' }, 400);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (body.tool_name_pattern) {
|
|
565
|
+
try {
|
|
566
|
+
new RegExp(body.tool_name_pattern, body.tool_name_flags ?? '');
|
|
567
|
+
}
|
|
568
|
+
catch {
|
|
569
|
+
sendJson(res, { error: 'Invalid tool_name_pattern regex' }, 400);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
const id = body.id ?? `custom-${Date.now()}`;
|
|
574
|
+
toolGuardRulesRepo.upsert({ ...body, id });
|
|
575
|
+
sendJson(res, { ok: true, id });
|
|
576
|
+
}
|
|
577
|
+
catch {
|
|
578
|
+
sendJson(res, { error: 'Invalid JSON' }, 400);
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
// PUT /api/tool-guard/rules/:id — update or toggle rule
|
|
584
|
+
if (req.method === 'PUT' && path.startsWith('/api/tool-guard/rules/')) {
|
|
585
|
+
const id = decodeURIComponent(path.slice('/api/tool-guard/rules/'.length));
|
|
586
|
+
if (!id) {
|
|
587
|
+
sendJson(res, { error: 'Missing rule ID' }, 400);
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
bufferBody(req).then(raw => {
|
|
591
|
+
try {
|
|
592
|
+
const body = JSON.parse(raw);
|
|
593
|
+
// Toggle shortcut: { enabled: true/false }
|
|
594
|
+
if ('enabled' in body && Object.keys(body).length === 1) {
|
|
595
|
+
toolGuardRulesRepo.toggle(id, body.enabled);
|
|
596
|
+
sendJson(res, { ok: true });
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
// Full update (custom rules only)
|
|
600
|
+
if (body.input_pattern) {
|
|
601
|
+
try {
|
|
602
|
+
new RegExp(body.input_pattern, body.input_flags ?? 'i');
|
|
603
|
+
}
|
|
604
|
+
catch {
|
|
605
|
+
sendJson(res, { error: 'Invalid input_pattern regex' }, 400);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (body.tool_name_pattern) {
|
|
610
|
+
try {
|
|
611
|
+
new RegExp(body.tool_name_pattern, body.tool_name_flags ?? '');
|
|
612
|
+
}
|
|
613
|
+
catch {
|
|
614
|
+
sendJson(res, { error: 'Invalid tool_name_pattern regex' }, 400);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
toolGuardRulesRepo.upsert({ ...body, id });
|
|
619
|
+
sendJson(res, { ok: true });
|
|
620
|
+
}
|
|
621
|
+
catch {
|
|
622
|
+
sendJson(res, { error: 'Invalid JSON' }, 400);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
// DELETE /api/tool-guard/rules/:id — delete custom rule
|
|
628
|
+
if (req.method === 'DELETE' && path.startsWith('/api/tool-guard/rules/')) {
|
|
629
|
+
const id = decodeURIComponent(path.slice('/api/tool-guard/rules/'.length));
|
|
630
|
+
if (!id) {
|
|
631
|
+
sendJson(res, { error: 'Missing rule ID' }, 400);
|
|
632
|
+
return true;
|
|
633
|
+
}
|
|
634
|
+
try {
|
|
635
|
+
toolGuardRulesRepo.remove(id);
|
|
636
|
+
sendJson(res, { ok: true });
|
|
637
|
+
}
|
|
638
|
+
catch (err) {
|
|
639
|
+
sendJson(res, { error: err.message }, 400);
|
|
640
|
+
}
|
|
641
|
+
return true;
|
|
642
|
+
}
|
|
643
|
+
// GET /api/license — Pro license status
|
|
644
|
+
if (req.method === 'GET' && path === '/api/license') {
|
|
645
|
+
// Dev token unlock — all features available for debugging
|
|
646
|
+
if (devUnlocked) {
|
|
647
|
+
sendJson(res, { pro: true, plan: 'dev', expiresAt: '', features: ['ai-injection', 'budget', 'ratelimit'] });
|
|
648
|
+
return true;
|
|
649
|
+
}
|
|
650
|
+
const proPlugin = pluginManager.getPlugins().find(p => p.source === 'external' && p.packageName?.match(/bastion-pro|@bastion\/pro/));
|
|
651
|
+
if (!proPlugin || pluginManager.isDisabled(proPlugin.name)) {
|
|
652
|
+
sendJson(res, { pro: false });
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
// The Pro plugin stores a signed token — we verify the signature
|
|
656
|
+
// so a forged plugin cannot simply claim valid: true.
|
|
657
|
+
const licenseState = getPluginState ? getPluginState(proPlugin.name, 'license') : undefined;
|
|
658
|
+
const token = licenseState?.token;
|
|
659
|
+
const result = (0, verify_js_1.verifyLicenseToken)(token);
|
|
660
|
+
if (result.valid && result.payload) {
|
|
661
|
+
sendJson(res, { pro: true, plan: result.payload.plan, expiresAt: result.payload.expiresAt, features: result.payload.features });
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
sendJson(res, { pro: false, installed: true, reason: result.reason });
|
|
665
|
+
}
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
return false;
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
//# sourceMappingURL=api-routes.js.map
|