@guardbee/mcp-security-proxy 1.1.0 → 1.2.0

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 (44) hide show
  1. package/README.md +45 -1
  2. package/TR.md +45 -1
  3. package/ZH.md +233 -0
  4. package/dist/audit/dashboard-sink.d.ts +26 -0
  5. package/dist/audit/dashboard-sink.d.ts.map +1 -0
  6. package/dist/audit/dashboard-sink.js +88 -0
  7. package/dist/audit/dashboard-sink.js.map +1 -0
  8. package/dist/audit/logger.d.ts +4 -2
  9. package/dist/audit/logger.d.ts.map +1 -1
  10. package/dist/audit/logger.js +12 -4
  11. package/dist/audit/logger.js.map +1 -1
  12. package/dist/gateway/config.d.ts +15 -2
  13. package/dist/gateway/config.d.ts.map +1 -1
  14. package/dist/gateway/config.js +70 -12
  15. package/dist/gateway/config.js.map +1 -1
  16. package/dist/gateway/gateway.d.ts +12 -1
  17. package/dist/gateway/gateway.d.ts.map +1 -1
  18. package/dist/gateway/gateway.js +25 -4
  19. package/dist/gateway/gateway.js.map +1 -1
  20. package/dist/gateway/upstream.d.ts +9 -3
  21. package/dist/gateway/upstream.d.ts.map +1 -1
  22. package/dist/gateway/upstream.js +23 -1
  23. package/dist/gateway/upstream.js.map +1 -1
  24. package/dist/http-server.d.ts +20 -0
  25. package/dist/http-server.d.ts.map +1 -0
  26. package/dist/http-server.js +146 -0
  27. package/dist/http-server.js.map +1 -0
  28. package/dist/index.d.ts +6 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +7 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/init.d.ts +3 -2
  33. package/dist/init.d.ts.map +1 -1
  34. package/dist/init.js +21 -6
  35. package/dist/init.js.map +1 -1
  36. package/dist/proxy.d.ts +3 -1
  37. package/dist/proxy.d.ts.map +1 -1
  38. package/dist/proxy.js +64 -6
  39. package/dist/proxy.js.map +1 -1
  40. package/dist/types.d.ts +21 -0
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/types.js +4 -0
  43. package/dist/types.js.map +1 -1
  44. package/package.json +4 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @guardbee/mcp-security-proxy
2
2
 
3
- **🇬🇧 English** | [🇹🇷 Türkçe](TR.md)
3
+ **🇬🇧 English** | [🇹🇷 Türkçe](TR.md) | [🇨🇳 中文](ZH.md)
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@guardbee/mcp-security-proxy.svg)](https://www.npmjs.com/package/@guardbee/mcp-security-proxy)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@guardbee/mcp-security-proxy.svg)](https://www.npmjs.com/package/@guardbee/mcp-security-proxy)
@@ -132,6 +132,50 @@ The single-server `--` form above keeps its 0.x behavior: tool names are not pre
132
132
 
133
133
  ---
134
134
 
135
+ ## Remote Mode (HTTP)
136
+
137
+ The proxy can run as a shared network service instead of a subprocess of one client. Agents connect over Streamable HTTP, and upstreams can be remote Streamable HTTP servers too.
138
+
139
+ ```yaml
140
+ version: 1
141
+ listen:
142
+ transport: http # stdio (default) | http
143
+ host: 0.0.0.0 # 0.0.0.0 in a container; 127.0.0.1 on a laptop
144
+ port: 8787
145
+ path: /mcp
146
+ apiKeys: ["${GUARDBEE_PROXY_KEY}"] # agents send Authorization: Bearer <key>
147
+ maxSessions: 100
148
+ upstreams:
149
+ github:
150
+ command: npx
151
+ args: ["-y", "@modelcontextprotocol/server-github"]
152
+ linear:
153
+ url: https://mcp.linear.app/mcp # a Streamable HTTP upstream
154
+ headers: { Authorization: "Bearer ${LINEAR_TOKEN}" }
155
+ audit:
156
+ sink: file
157
+ filePath: /var/log/guardbee/audit.jsonl
158
+ dashboard:
159
+ url: https://app.guardbee.ai/api/v1/gateway/events
160
+ apiKeyEnv: GUARDBEE_API_KEY # workspace API key with the gateway.write scope
161
+ ```
162
+
163
+ - **Sessions are isolated.** Each MCP session gets its own taint state, PII tokens and tool pins, so one agent's toxic flow never blocks another. All sessions share the upstream connections. Audit events carry the `sessionId`.
164
+ - **No key, no network.** Listening on anything other than loopback without `listen.apiKeys` is a config error. Keys are compared in constant time, and a wrong or missing key gets `401`.
165
+ - `GET /healthz` returns `{"ok": true, "sessions": N}`. Sessions above `maxSessions` get `503`.
166
+ - **Dashboard:** `audit.dashboard` sends every audit event, batched, to the GuardBee dashboard with a workspace API key taken from `apiKeyEnv`. The key never sits in the file. If the dashboard is unreachable, events wait in memory (up to 10,000) and go out later. A rejected key is reported once on stderr. Tool calls never wait for the dashboard.
167
+ - `init` now also moves Streamable HTTP servers (`url` + `headers`) behind the proxy. Legacy SSE servers stay in the client config and are reported.
168
+
169
+ Docker:
170
+
171
+ ```bash
172
+ docker build -t guardbee/mcp-security-proxy packages/security-proxy
173
+ docker run -p 8787:8787 -e GUARDBEE_PROXY_KEY=... -e GUARDBEE_API_KEY=... \
174
+ -v "$PWD/guardbee-proxy.yaml:/etc/guardbee/guardbee-proxy.yaml:ro" guardbee/mcp-security-proxy
175
+ ```
176
+
177
+ ---
178
+
135
179
  ## MCP Tools
136
180
 
137
181
  The proxy does not register tools of its own. It forwards the target server's tools and applies the interceptor chain on every call.
package/TR.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @guardbee/mcp-security-proxy
2
2
 
3
- [🇬🇧 English](README.md) | **🇹🇷 Türkçe**
3
+ [🇬🇧 English](README.md) | **🇹🇷 Türkçe** | [🇨🇳 中文](ZH.md)
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@guardbee/mcp-security-proxy.svg)](https://www.npmjs.com/package/@guardbee/mcp-security-proxy)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@guardbee/mcp-security-proxy.svg)](https://www.npmjs.com/package/@guardbee/mcp-security-proxy)
@@ -132,6 +132,50 @@ Yukarıdaki tek sunuculu `--` kullanımı 0.x davranışını korur: tool adlar
132
132
 
133
133
  ---
134
134
 
135
+ ## Remote Mod (HTTP)
136
+
137
+ Proxy, tek bir istemcinin alt süreci olmak yerine paylaşılan bir ağ servisi olarak da çalışabilir. Ajanlar Streamable HTTP ile bağlanır; upstream'ler de uzak Streamable HTTP server'lar olabilir.
138
+
139
+ ```yaml
140
+ version: 1
141
+ listen:
142
+ transport: http # stdio (default) | http
143
+ host: 0.0.0.0 # konteynerde 0.0.0.0; dizüstünde 127.0.0.1
144
+ port: 8787
145
+ path: /mcp
146
+ apiKeys: ["${GUARDBEE_PROXY_KEY}"] # ajanlar Authorization: Bearer <key> gönderir
147
+ maxSessions: 100
148
+ upstreams:
149
+ github:
150
+ command: npx
151
+ args: ["-y", "@modelcontextprotocol/server-github"]
152
+ linear:
153
+ url: https://mcp.linear.app/mcp # bir Streamable HTTP upstream
154
+ headers: { Authorization: "Bearer ${LINEAR_TOKEN}" }
155
+ audit:
156
+ sink: file
157
+ filePath: /var/log/guardbee/audit.jsonl
158
+ dashboard:
159
+ url: https://app.guardbee.ai/api/v1/gateway/events
160
+ apiKeyEnv: GUARDBEE_API_KEY # gateway.write scope'lu workspace API key'i
161
+ ```
162
+
163
+ - **Oturumlar birbirinden ayrık.** Her MCP oturumunun kendi taint durumu, PII token'ları ve tool pin'leri vardır; bir ajanın toxic flow'u başka bir ajanı asla engellemez. Tüm oturumlar upstream bağlantılarını paylaşır. Audit olayları `sessionId` taşır.
164
+ - **Key yoksa ağ da yok.** `listen.apiKeys` olmadan loopback dışında dinlemek config hatasıdır. Key'ler sabit zamanda karşılaştırılır; yanlış veya eksik key `401` alır.
165
+ - `GET /healthz` `{"ok": true, "sessions": N}` döner. `maxSessions` üstündeki oturumlar `503` alır.
166
+ - **Dashboard:** `audit.dashboard` her audit olayını toplu halde, `apiKeyEnv`'den alınan workspace API key'iyle GuardBee dashboard'una gönderir; key dosyada durmaz. Dashboard'a ulaşılamazsa olaylar bellekte bekler (en fazla 10.000) ve sonra gönderilir. Reddedilen key stderr'e bir kez raporlanır. Tool çağrıları dashboard'u asla beklemez.
167
+ - `init` artık Streamable HTTP server'ları (`url` + `headers`) da proxy'nin arkasına taşır. Eski SSE server'lar istemci config'inde kalır ve raporlanır.
168
+
169
+ Docker:
170
+
171
+ ```bash
172
+ docker build -t guardbee/mcp-security-proxy packages/security-proxy
173
+ docker run -p 8787:8787 -e GUARDBEE_PROXY_KEY=... -e GUARDBEE_API_KEY=... \
174
+ -v "$PWD/guardbee-proxy.yaml:/etc/guardbee/guardbee-proxy.yaml:ro" guardbee/mcp-security-proxy
175
+ ```
176
+
177
+ ---
178
+
135
179
  ## MCP Tools
136
180
 
137
181
  Proxy kendi tool'unu kaydetmez. Hedef sunucunun tool'larını iletir ve her çağrıda interceptor zincirini uygular.
package/ZH.md ADDED
@@ -0,0 +1,233 @@
1
+ # @guardbee/mcp-security-proxy
2
+
3
+ [🇬🇧 English](README.md) | [🇹🇷 Türkçe](TR.md) | **🇨🇳 中文**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@guardbee/mcp-security-proxy.svg)](https://www.npmjs.com/package/@guardbee/mcp-security-proxy)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@guardbee/mcp-security-proxy.svg)](https://www.npmjs.com/package/@guardbee/mcp-security-proxy)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
8
+
9
+ 一个透明的安全层,放在任何 MCP 服务器前面。它拦截 prompt 注入攻击,对响应中的 PII 进行脱敏,并把每个请求写入不可篡改的审计日志。
10
+
11
+ > 本包默认向 GuardBee 发送使用遥测(工具名 + 较短的参数,见 [`@guardbee/mcp-telemetry`](../telemetry/README.md)),这与它自己的本地审计日志相互独立。设置 `GUARDBEE_TELEMETRY=0` 即可关闭。
12
+
13
+ ```
14
+ Claude ──► MCP Security Proxy ──► 任意 MCP 服务器
15
+ │
16
+ ├─ Prompt 注入检测 (27 条规则,英文 + 土耳其语)
17
+ ├─ PII + 密钥脱敏 (TC、VKN、IBAN、银行卡、电话、22 种密钥格式)
18
+ ├─ 拦截或警告模式
19
+ ├─ 有毒数据流(lethal trifecta)拦截
20
+ └─ 哈希链审计日志
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 功能
26
+
27
+ - **Prompt 注入防护** —— 27 条英文和土耳其语规则;精确规则会拦截,通用短语只发出警告
28
+ - **工具结果注入** —— 同一套规则也作用于工具结果,标记为 MCP06:2025。拦截模式会替换结果;警告模式会在结果前加上一条警告
29
+ - **会话工具固定(pin)** —— 固定第一次 `tools/list` 的结果。之后描述或 schema 的变化即视为 rug pull(MCP03:2025)。拦截模式继续提供固定的定义,并拒绝已漂移的调用
30
+ - **PII 脱敏** —— 对响应中的土耳其身份证号(TC Kimlik No)、税号(VKN)、IBAN、银行卡号和电话号码(均经校验和验证)、电子邮件、22 种服务商密钥格式、私钥和数据库连接串进行脱敏
31
+ - **拦截 / 警告模式** —— 每个拦截器都可以独立运行在拦截或警告模式
32
+ - **审计日志** —— 可配置,写入控制台或文件
33
+ - **网关模式** —— 多个 MCP 服务器置于同一个代理之后,使用一份 YAML 策略(allow / deny / mask / warn)
34
+ - **有毒数据流拦截** —— 跨服务器追踪 lethal trifecta,并拦截会使其成立的外发(egress)调用
35
+ - **无需改代码** —— 直接挂在任何现有 MCP 服务器前面
36
+
37
+ ---
38
+
39
+ ## 快速开始
40
+
41
+ ```bash
42
+ npm install -g @guardbee/mcp-security-proxy
43
+ ```
44
+
45
+ 添加到 `claude_desktop_config.json`:
46
+
47
+ ```json
48
+ {
49
+ "mcpServers": {
50
+ "secure-filesystem": {
51
+ "command": "npx",
52
+ "args": [
53
+ "-y", "@guardbee/mcp-security-proxy",
54
+ "--", "npx", "-y",
55
+ "@modelcontextprotocol/server-filesystem", "/tmp"
56
+ ]
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ > 代理会把 `--` 之后的内容作为目标 MCP 服务器启动。
63
+
64
+ ---
65
+
66
+ ## 网关模式:多个服务器,一份策略
67
+
68
+ 用一个 `guardbee-proxy.yaml` 把所有 MCP 服务器放到同一个代理后面。`init` 可以帮你完成迁移:
69
+
70
+ ```bash
71
+ npx -y @guardbee/mcp-security-proxy@^1 init --client claude-desktop # 或 cursor、claude-code、--file ./mcp.json
72
+ ```
73
+
74
+ 它会把每个 stdio 服务器移入 `~/.guardbee/guardbee-proxy.yaml`(权限 0600),备份客户端配置,并把配置指向代理。HTTP 服务器保持不变并会被报告出来,因为它们会绕过策略。`--dry-run` 只打印两个文件而不写入。也可以手动配置:
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "guardbee": {
80
+ "command": "npx",
81
+ "args": ["-y", "@guardbee/mcp-security-proxy@^1", "--config", "/path/to/guardbee-proxy.yaml"]
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ ```yaml
88
+ version: 1
89
+ upstreams:
90
+ github:
91
+ command: npx
92
+ args: ["-y", "@modelcontextprotocol/server-github"]
93
+ env: { GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}" } # 从环境变量读取
94
+ postgres:
95
+ command: npx
96
+ args: ["-y", "@guardbee/mcp-db-gateway"]
97
+
98
+ labels: # 覆盖启发式标签
99
+ github__get_issue: [untrusted]
100
+ github__create_pull_request: [egress]
101
+
102
+ rules: # 第一条匹配的规则生效
103
+ - id: no-deletes
104
+ match: { tool: "postgres__delete_*" }
105
+ action: deny # allow | deny | mask | warn | approve
106
+ - match: { tool: "postgres__query", args: { table: "salaries" } } # 点分路径 → 值,字符串为 glob
107
+ action: mask
108
+ mask: { fields: [salary, iban] } # 清空这些 JSON 键
109
+ - match: { label: destructive }
110
+ action: approve # 先征求用户同意
111
+
112
+ taint:
113
+ mode: strict # strict | approve | warn | off
114
+
115
+ audit:
116
+ sink: file
117
+ filePath: ./guardbee-audit.jsonl
118
+ ```
119
+
120
+ - 工具和 prompt 以 `<upstream>__<tool>` 的名称出现。
121
+ - **有毒数据流(lethal trifecta):** 每个工具会被标记为 `untrusted`、`sensitive`、`egress` 或 `destructive`(基于名称/描述的启发式,可在 `labels` 中覆盖)。当一个会话既读取过不可信内容(`untrusted` 工具或任何 resource),又读取过敏感数据(`sensitive` 工具,或结果中出现任何 PII)之后,`egress` 调用在 `strict` 模式下会被拦截,在 `warn` 模式下只记录日志。该检查跨服务器生效:从 GitHub 读取的 issue 加上从 CRM 读取的客户记录,会拦截第三个服务器上的 webhook 调用。
122
+ - **规则**可按 `tool`(glob)、`upstream`、`label`、`session`(`clean` | `tainted`)和 `args` 匹配。即使全局脱敏关闭,`mask` 也会对该工具强制进行 PII 脱敏;`mask.fields` 还会清空文本和 `structuredContent` 中指定的 JSON 键。规则中的 `allow` 不会跳过有毒数据流检查;如需放行,请修改该工具的标签。
123
+ - **审批:** `approve`(规则动作,或针对有毒数据流的 `taint.mode: approve`)会通过 MCP elicitation 向用户展示一个是/否表单,其中包含工具、原因和参数。除明确的"是"之外的任何回答——拒绝、取消、在 `approval.timeoutSeconds`(默认 120 秒)内未作答——都会拦截该调用。不支持 elicitation 的客户端无法审批,调用会被拦截并附带说明。
124
+ - **令牌化(Tokenize):** 设置 `interceptors.piiMasking.mode: tokenize` 后,模型看到的是 `<pii:tc_kimlik:7f3a9b21>` 而不是真实值,并且仍然可以把它传给另一个工具:代理会在发往该服务器时把真实值放回去。令牌只在会话期间保存在内存中;除非设置 `piiMasking.detokenizeForEgress: true`,否则不会为 `egress` 工具还原成真实值。
125
+ - **Prompt**(`prompts/get`)与工具结果一样,经过注入扫描和 PII 脱敏。
126
+ - `interceptors.definitionDrift.recheck: on-change` 会跳过每次调用前的 `tools/list`,只在服务器发送 `tools/list_changed` 后重新检查;代理也会把该通知转发给智能体。
127
+ - **审计日志**采用哈希链。默认只保存参数的 SHA-256,而不保存参数本身,也不保存结果;设置 `audit.includePayloads: true` 可记录它们。用 `guardbee-proxy verify-audit ./guardbee-audit.jsonl` 校验日志。
128
+ - `guardbee-proxy validate --config guardbee-proxy.yaml` 在不启动任何服务器的情况下检查配置。
129
+ - 未指定 `--config` 时,代理也会读取 `./guardbee-proxy.yaml` 或 `GUARDBEE_PROXY_CONFIG=<file>.yaml`。
130
+
131
+ 上面的单服务器 `--` 用法保持 0.x 的行为:工具名不加前缀,记录完整载荷,有毒数据流只记为警告。
132
+
133
+ ---
134
+
135
+ ## 远程模式(HTTP)
136
+
137
+ 代理也可以作为共享的网络服务运行,而不只是某个客户端的子进程。智能体通过 Streamable HTTP 连接;上游也可以是远程的 Streamable HTTP 服务器。
138
+
139
+ ```yaml
140
+ version: 1
141
+ listen:
142
+ transport: http # stdio (default) | http
143
+ host: 0.0.0.0 # 容器中用 0.0.0.0;笔记本上用 127.0.0.1
144
+ port: 8787
145
+ path: /mcp
146
+ apiKeys: ["${GUARDBEE_PROXY_KEY}"] # 智能体发送 Authorization: Bearer <key>
147
+ maxSessions: 100
148
+ upstreams:
149
+ github:
150
+ command: npx
151
+ args: ["-y", "@modelcontextprotocol/server-github"]
152
+ linear:
153
+ url: https://mcp.linear.app/mcp # 一个 Streamable HTTP 上游
154
+ headers: { Authorization: "Bearer ${LINEAR_TOKEN}" }
155
+ audit:
156
+ sink: file
157
+ filePath: /var/log/guardbee/audit.jsonl
158
+ dashboard:
159
+ url: https://app.guardbee.ai/api/v1/gateway/events
160
+ apiKeyEnv: GUARDBEE_API_KEY # 带 gateway.write 权限的工作区 API 密钥
161
+ ```
162
+
163
+ - **会话相互隔离。** 每个 MCP 会话都有自己的污点状态、PII 令牌和工具固定;一个智能体的有毒数据流绝不会拦截另一个智能体。所有会话共享上游连接。审计事件带有 `sessionId`。
164
+ - **没有密钥就不能监听网络。** 未配置 `listen.apiKeys` 就在回环地址以外监听属于配置错误。密钥以恒定时间比较;错误或缺失的密钥返回 `401`。
165
+ - `GET /healthz` 返回 `{"ok": true, "sessions": N}`。超过 `maxSessions` 的会话返回 `503`。
166
+ - **仪表盘:** `audit.dashboard` 会用从 `apiKeyEnv` 读取的工作区 API 密钥,把每个审计事件批量发送到 GuardBee 仪表盘;密钥不写在文件中。仪表盘不可达时,事件会在内存中等待(最多 10,000 条)并稍后发送。被拒绝的密钥只会在 stderr 报告一次。工具调用从不等待仪表盘。
167
+ - `init` 现在也会把 Streamable HTTP 服务器(`url` + `headers`)移到代理之后。旧的 SSE 服务器保留在客户端配置中并会被报告。
168
+
169
+ Docker:
170
+
171
+ ```bash
172
+ docker build -t guardbee/mcp-security-proxy packages/security-proxy
173
+ docker run -p 8787:8787 -e GUARDBEE_PROXY_KEY=... -e GUARDBEE_API_KEY=... \
174
+ -v "$PWD/guardbee-proxy.yaml:/etc/guardbee/guardbee-proxy.yaml:ro" guardbee/mcp-security-proxy
175
+ ```
176
+
177
+ ---
178
+
179
+ ## MCP 工具
180
+
181
+ 代理本身不注册任何工具。它转发目标服务器的工具,并在每次调用时应用拦截器链。
182
+
183
+ ---
184
+
185
+ ## 拦截器
186
+
187
+ ### Prompt 注入检测
188
+
189
+ 来自 [`@guardbee/guard-core`](../guard-core/README.md) 的 27 条规则,作用于工具参数、工具结果、resource 和 prompt:
190
+
191
+ - **拦截**(13 条精确规则,high/critical):英文和土耳其语的指令覆盖("ignore all previous instructions"、"önceki talimatları yok say")、`DAN mode`、"bypass your safety guardrails"、聊天模板标记(`<|im_start|>`、`[INST]`)、`<system>` 标签、藏在 Unicode tag 字符中的文本、CSS 隐藏元素或 HTML 注释中的指令、markdown 图片外泄信标、索要系统提示词的请求(英文和土耳其语)、"send the user's data to https://…"。
192
+ - **仅警告**(14 条):在普通文本中也会出现的通用短语——"act as"、"you are now"、"developer mode"、"jailbreak"、"override policy"、"sen artık"——以及中等严重度的信号,如零宽字符或双向(bidi)控制字符、行首的 `System:` 标签。
193
+ - **Base64:** 能解码为可读文本的片段会被解码,并用拦截规则检查,因此指令无法藏在编码的数据块里。
194
+
195
+ 从 1.1 开始,单独出现的通用短语不再触发拦截:在 1.0 中,工具结果里的 "use jailbreak mode" 或 "act as a reverse proxy" 会被拦截;现在只记录日志,并在结果中附上一条警告。
196
+
197
+ ### PII 脱敏
198
+
199
+ | 数据类型 | 校验 | 输入示例 | 输出 |
200
+ |-----------|-------|---------------|--------|
201
+ | 土耳其身份证号(TC Kimlik No) | 官方校验算法 | `10000000146` | `[TC-KİMLİK]` |
202
+ | IBAN(TR) | mod-97 | `TR330006100519786457841326` | `TR**[IBAN]` |
203
+ | 银行卡号 | Luhn | `4111 1111 1111 1111` | `****-****-****-[KART]` |
204
+ | 电子邮件 | — | `ahmet@example.com` | `***@[EMAIL]` |
205
+ | 电话(土耳其) | 手机 / 座机 / 850 前缀 | `0532 123 45 67` | `+90-***-***-**[TELEFON]` |
206
+ | 税号(VKN) | 校验位,且需带 `VKN` / `Vergi No` 标签 | `VKN: 1234567890` | `VKN: [VKN]` |
207
+ | 服务商密钥 | 来自 secret-scanner 的 22 种密钥和令牌格式(AWS、GitHub、Stripe、OpenAI、Anthropic、Slack 等) | `ghp_…`、`AKIA…` | `[API-KEY]` |
208
+ | 其他 API 密钥 | `sk_`/`api_`/`token_` 等前缀,同时含字母和数字 | `api_k3y9x8…` | `[API-KEY]` |
209
+ | 私钥 | 完整的 BEGIN…END 块 | `-----BEGIN … PRIVATE KEY-----` | `[PRIVATE-KEY]` |
210
+ | 数据库连接串 | URL 中的 用户名:密码(排除 localhost) | `postgres://app:pw@db/prod` | `[CONNECTION-STRING]` |
211
+ | JWT | — | `eyJhbGc...` | `[JWT-TOKEN]` |
212
+
213
+ 未通过校验和的数字(订单号、快递单号)保持原样。
214
+
215
+ ---
216
+
217
+ ## 配置
218
+
219
+ 可通过环境变量配置:
220
+
221
+ | 变量 | 默认值 | 说明 |
222
+ |----------|-----------|----------|
223
+ | `PROXY_MODE` | `block` | `block` 或 `warn` |
224
+ | `PROXY_LOG` | `console` | `console` 或 `file` |
225
+ | `PROXY_LOG_PATH` | `./proxy-audit.jsonl` | 日志文件路径 |
226
+ | `PROXY_PII_MASK` | `true` | 启用 PII 脱敏 |
227
+ | `PROXY_INJECTION_CHECK` | `true` | 启用注入检查 |
228
+
229
+ ---
230
+
231
+ ## 许可证
232
+
233
+ MIT — [GuardBee](https://guardbee.ai)
@@ -0,0 +1,26 @@
1
+ import type { AuditEvent, DashboardSinkConfig } from "../types.js";
2
+ type Fetch = typeof fetch;
3
+ /**
4
+ * Sends audit events to the GuardBee dashboard in batches, off the request
5
+ * path: a tool call never waits for it. Events that could not be sent stay
6
+ * queued (up to MAX_QUEUE, oldest dropped first) and go out with the next flush.
7
+ */
8
+ export declare class DashboardSink {
9
+ private readonly config;
10
+ private readonly fetchImpl;
11
+ private queue;
12
+ private inFlight;
13
+ private readonly timer;
14
+ private dropped;
15
+ private warnedStatus;
16
+ constructor(config: DashboardSinkConfig, fetchImpl?: Fetch);
17
+ private get batchSize();
18
+ push(event: AuditEvent): void;
19
+ /** Send everything queued; resolves when done or when the endpoint is unreachable. */
20
+ flush(): Promise<void>;
21
+ private drain;
22
+ get pending(): number;
23
+ close(): Promise<void>;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=dashboard-sink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-sink.d.ts","sourceRoot":"","sources":["../../src/audit/dashboard-sink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAOnE,KAAK,KAAK,GAAG,OAAO,KAAK,CAAC;AAE1B;;;;GAIG;AACH,qBAAa,aAAa;IAQtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAR5B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,YAAY,CAAuB;gBAGxB,MAAM,EAAE,mBAAmB,EAC3B,SAAS,GAAE,KAAa;IAM3C,OAAO,KAAK,SAAS,GAEpB;IAED,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAU7B,sFAAsF;IACtF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAOR,KAAK;IAqCnB,IAAI,OAAO,IAAI,MAAM,CAEpB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DashboardSink = void 0;
4
+ const MAX_QUEUE = 10000;
5
+ const REQUEST_TIMEOUT_MS = 10000;
6
+ /** Retrying these cannot succeed: a bad payload or a bad / under-scoped key. */
7
+ const PERMANENT = new Set([400, 401, 403, 404, 413, 422]);
8
+ /**
9
+ * Sends audit events to the GuardBee dashboard in batches, off the request
10
+ * path: a tool call never waits for it. Events that could not be sent stay
11
+ * queued (up to MAX_QUEUE, oldest dropped first) and go out with the next flush.
12
+ */
13
+ class DashboardSink {
14
+ constructor(config, fetchImpl = fetch) {
15
+ this.config = config;
16
+ this.fetchImpl = fetchImpl;
17
+ this.queue = [];
18
+ this.inFlight = null;
19
+ this.dropped = 0;
20
+ this.warnedStatus = null;
21
+ this.timer = setInterval(() => void this.flush(), config.flushIntervalMs ?? 5000);
22
+ this.timer.unref?.();
23
+ }
24
+ get batchSize() {
25
+ return this.config.batchSize ?? 100;
26
+ }
27
+ push(event) {
28
+ this.queue.push(event);
29
+ if (this.queue.length > MAX_QUEUE) {
30
+ const overflow = this.queue.length - MAX_QUEUE;
31
+ this.queue.splice(0, overflow);
32
+ this.dropped += overflow;
33
+ }
34
+ if (this.queue.length >= this.batchSize)
35
+ void this.flush();
36
+ }
37
+ /** Send everything queued; resolves when done or when the endpoint is unreachable. */
38
+ flush() {
39
+ this.inFlight ?? (this.inFlight = this.drain().finally(() => {
40
+ this.inFlight = null;
41
+ }));
42
+ return this.inFlight;
43
+ }
44
+ async drain() {
45
+ while (this.queue.length > 0) {
46
+ const batch = this.queue.slice(0, this.batchSize);
47
+ let status;
48
+ try {
49
+ const response = await this.fetchImpl(this.config.url, {
50
+ method: "POST",
51
+ headers: { authorization: `Bearer ${this.config.apiKey}`, "content-type": "application/json" },
52
+ body: JSON.stringify({ source: this.config.source, dropped: this.dropped, events: batch }),
53
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
54
+ });
55
+ status = response.status;
56
+ }
57
+ catch {
58
+ return; // offline or timed out: keep the batch for the next flush
59
+ }
60
+ if (status >= 200 && status < 300) {
61
+ this.queue.splice(0, batch.length);
62
+ this.dropped = 0;
63
+ continue;
64
+ }
65
+ if (PERMANENT.has(status)) {
66
+ this.queue.splice(0, batch.length);
67
+ this.dropped += batch.length;
68
+ if (this.warnedStatus !== status) {
69
+ this.warnedStatus = status;
70
+ process.stderr.write(`[guardbee-proxy] dashboard rejected audit events with HTTP ${status}` +
71
+ (status === 401 || status === 403 ? " — check the API key and its gateway.write scope" : "") +
72
+ "; those events stay only in the local audit log\n");
73
+ }
74
+ continue;
75
+ }
76
+ return; // 429 / 5xx: try again later
77
+ }
78
+ }
79
+ get pending() {
80
+ return this.queue.length;
81
+ }
82
+ async close() {
83
+ clearInterval(this.timer);
84
+ await this.flush();
85
+ }
86
+ }
87
+ exports.DashboardSink = DashboardSink;
88
+ //# sourceMappingURL=dashboard-sink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-sink.js","sourceRoot":"","sources":["../../src/audit/dashboard-sink.ts"],"names":[],"mappings":"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"}
@@ -3,9 +3,11 @@ export declare class AuditLogger {
3
3
  private config;
4
4
  private stream;
5
5
  private lastHash;
6
- constructor(config: AuditConfig);
6
+ private readonly dashboard;
7
+ constructor(config: AuditConfig, fetchImpl?: typeof fetch);
7
8
  log(event: AuditEvent): void;
8
- close(): void;
9
+ /** Flush the dashboard queue and close the file. */
10
+ close(): Promise<void>;
9
11
  private redact;
10
12
  }
11
13
  export type ChainVerification = {
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAiC3D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,QAAQ,CAAW;gBAEf,MAAM,EAAE,WAAW;IAQ/B,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAa5B,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,MAAM;CAKf;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAwBjE"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAkC3D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8B;gBAE5C,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK;IASzD,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAe5B,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,OAAO,CAAC,MAAM;CAKf;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAwBjE"}
@@ -8,6 +8,7 @@ exports.verifyAuditChain = verifyAuditChain;
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const crypto_1 = require("crypto");
10
10
  const definition_drift_js_1 = require("../interceptors/definition-drift.js");
11
+ const dashboard_sink_js_1 = require("./dashboard-sink.js");
11
12
  const GENESIS = "";
12
13
  function sha256(text) {
13
14
  return (0, crypto_1.createHash)("sha256").update(text).digest("hex");
@@ -38,14 +39,17 @@ function lastHashIn(filePath) {
38
39
  }
39
40
  }
40
41
  class AuditLogger {
41
- constructor(config) {
42
+ constructor(config, fetchImpl) {
42
43
  this.stream = null;
43
44
  this.lastHash = GENESIS;
45
+ this.dashboard = null;
44
46
  this.config = config;
45
47
  if (config.sink === "file" && config.filePath) {
46
48
  this.lastHash = lastHashIn(config.filePath);
47
49
  this.stream = fs_1.default.createWriteStream(config.filePath, { flags: "a" });
48
50
  }
51
+ if (config.enabled && config.dashboard)
52
+ this.dashboard = new dashboard_sink_js_1.DashboardSink(config.dashboard, fetchImpl);
49
53
  }
50
54
  log(event) {
51
55
  if (!this.config.enabled)
@@ -53,7 +57,9 @@ class AuditLogger {
53
57
  const unhashed = { ...this.redact(event), prevHash: this.lastHash };
54
58
  const hash = chainHash(unhashed);
55
59
  this.lastHash = hash;
56
- const line = JSON.stringify({ ...unhashed, hash });
60
+ const hashed = { ...unhashed, hash };
61
+ this.dashboard?.push(hashed);
62
+ const line = JSON.stringify(hashed);
57
63
  if (this.config.sink === "file" && this.stream) {
58
64
  this.stream.write(line + "\n");
59
65
  }
@@ -61,8 +67,10 @@ class AuditLogger {
61
67
  process.stderr.write("[guardbee-proxy] " + line + "\n");
62
68
  }
63
69
  }
64
- close() {
65
- this.stream?.end();
70
+ /** Flush the dashboard queue and close the file. */
71
+ async close() {
72
+ await this.dashboard?.close();
73
+ await new Promise((resolve) => (this.stream ? this.stream.end(resolve) : resolve()));
66
74
  }
67
75
  redact(event) {
68
76
  if (this.config.includePayloads !== false)
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":";;;;;;AA6EA,4CAwBC;AArGD,4CAAoB;AACpB,mCAAoC;AAEpC,6EAA6D;AAE7D,MAAM,OAAO,GAAG,EAAE,CAAC;AAEnB,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,iFAAiF;AACjF,SAAS,SAAS,CAAC,QAAkC;IACnD,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,uFAAuF;AACvF,SAAS,UAAU,CAAC,QAAgB;IAClC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,IAAI,GAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC,IAAI,CAAC;QACnD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAa,WAAW;IAKtB,YAAY,MAAmB;QAHvB,WAAM,GAA0B,IAAI,CAAC;QACrC,aAAQ,GAAG,OAAO,CAAC;QAGzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,GAAG,YAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,GAAG,CAAC,KAAiB;QACnB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO;QACjC,MAAM,QAAQ,GAA6B,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9F,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;IACrB,CAAC;IAEO,MAAM,CAAC,KAAiB;QAC9B,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QACxD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAClD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,IAAA,4BAAM,EAAC,KAAK,CAAC,CAAC,EAAE,CAAC;IACpF,CAAC;CACF;AAnCD,kCAmCC;AAMD,mGAAmG;AACnG,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,YAAY,GAAG,OAAO,CAAC;IAC3B,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,SAAS;QACjC,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC;QACzB,IAAI,KAAiB,CAAC;QACtB,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QAC/D,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC;QACpC,IAAI,QAAQ,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YACvC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,8EAA8E,EAAE,CAAC;QAC7H,CAAC;QACD,IAAI,IAAI,KAAK,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,8DAA8D,EAAE,CAAC;QAC7G,CAAC;QACD,YAAY,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,CAAC;IACX,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,22 @@
1
- import type { AuditConfig, McpServerConfig, ProxyConfig } from "../types.js";
1
+ import type { AuditConfig, ProxyConfig, UpstreamConfig } from "../types.js";
2
2
  import { type Label } from "./labels.js";
3
3
  import type { PolicyAction, PolicyRule } from "./policy.js";
4
4
  import type { TaintMode } from "./taint.js";
5
+ /** How the agent reaches the proxy. */
6
+ export type ListenConfig = {
7
+ transport: "stdio";
8
+ } | {
9
+ transport: "http";
10
+ host: string;
11
+ port: number;
12
+ path: string;
13
+ /** Accepted Bearer keys; required unless the host is loopback. */
14
+ apiKeys: string[];
15
+ maxSessions: number;
16
+ };
5
17
  export interface GatewayConfig {
6
- upstreams: Record<string, McpServerConfig>;
18
+ upstreams: Record<string, UpstreamConfig>;
19
+ listen: ListenConfig;
7
20
  /** Prefix tool and prompt names with `<upstream>__`. Off only for the legacy single-server config. */
8
21
  namespaced: boolean;
9
22
  /** Label overrides by the tool name the agent sees; replaces the heuristic labels entirely. */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAU,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC3C,sGAAsG;IACtG,UAAU,EAAE,OAAO,CAAC;IACpB,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAChC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,EAAE;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,QAAQ,EAAE;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;IACnC,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,WAAW,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;CACxD;AAyHD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAwB,GAAG,aAAa,CAuBjG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,aAAa,CAYnE;AAgBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAM,EAAiB,EAAE,GAAG,GAAE,MAAsB,GAAG,aAAa,CAmB3G"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAmB,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAU,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,uCAAuC;AACvC,MAAM,MAAM,YAAY,GACpB;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GACtB;IACE,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,MAAM,EAAE,YAAY,CAAC;IACrB,sGAAsG;IACtG,UAAU,EAAE,OAAO,CAAC;IACpB,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAChC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,EAAE;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,QAAQ,EAAE;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;IACnC,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,WAAW,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;CACxD;AAmLD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAwB,GAAG,aAAa,CAwBjG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,aAAa,CAanE;AAgBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAM,EAAiB,EAAE,GAAG,GAAE,MAAsB,GAAG,aAAa,CAmB3G"}