@cybedefend/vibedefend 1.5.0 → 1.7.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 (264) hide show
  1. package/README.md +71 -2
  2. package/dist/api/gateway-request.js +49 -0
  3. package/dist/api/gateway-request.js.map +1 -0
  4. package/dist/api/projects.js +67 -0
  5. package/dist/api/projects.js.map +1 -1
  6. package/dist/api/repository-link.js +157 -0
  7. package/dist/api/repository-link.js.map +1 -0
  8. package/dist/auth/auth-store.js +107 -25
  9. package/dist/auth/auth-store.js.map +1 -1
  10. package/dist/auth/auth.js +21 -0
  11. package/dist/auth/auth.js.map +1 -1
  12. package/dist/clients/cursor.js +5 -1
  13. package/dist/clients/cursor.js.map +1 -1
  14. package/dist/clients/vscode.js +38 -29
  15. package/dist/clients/vscode.js.map +1 -1
  16. package/dist/commands/mcp/allow.js +219 -0
  17. package/dist/commands/mcp/allow.js.map +1 -0
  18. package/dist/commands/mcp/connect.js +337 -0
  19. package/dist/commands/mcp/connect.js.map +1 -0
  20. package/dist/commands/mcp/index.js +170 -0
  21. package/dist/commands/mcp/index.js.map +1 -0
  22. package/dist/commands/mcp/proxy.js +320 -0
  23. package/dist/commands/mcp/proxy.js.map +1 -0
  24. package/dist/commands/mcp/scan.js +349 -0
  25. package/dist/commands/mcp/scan.js.map +1 -0
  26. package/dist/commands/mcp/sync.js +215 -0
  27. package/dist/commands/mcp/sync.js.map +1 -0
  28. package/dist/config.js +6 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/diagnostics.js +78 -12
  31. package/dist/diagnostics.js.map +1 -1
  32. package/dist/doctor.js +19 -0
  33. package/dist/doctor.js.map +1 -1
  34. package/dist/guards-evaluator/analysis-types.js +27 -0
  35. package/dist/guards-evaluator/analysis-types.js.map +1 -0
  36. package/dist/guards-evaluator/command-analysis.js +572 -0
  37. package/dist/guards-evaluator/command-analysis.js.map +1 -0
  38. package/dist/guards-evaluator/command-view.js +586 -0
  39. package/dist/guards-evaluator/command-view.js.map +1 -0
  40. package/dist/guards-evaluator/env.js +11 -0
  41. package/dist/guards-evaluator/env.js.map +1 -0
  42. package/dist/guards-evaluator/evaluate.js +91 -41
  43. package/dist/guards-evaluator/evaluate.js.map +1 -1
  44. package/dist/guards-evaluator/index.js +2 -1
  45. package/dist/guards-evaluator/index.js.map +1 -1
  46. package/dist/guards-evaluator/inline-code.js +259 -0
  47. package/dist/guards-evaluator/inline-code.js.map +1 -0
  48. package/dist/guards-evaluator/normalize.js +716 -0
  49. package/dist/guards-evaluator/normalize.js.map +1 -0
  50. package/dist/guards-evaluator/preprocess.js +13 -5
  51. package/dist/guards-evaluator/preprocess.js.map +1 -1
  52. package/dist/guards-evaluator/redact.js +19 -0
  53. package/dist/guards-evaluator/redact.js.map +1 -1
  54. package/dist/guards-evaluator/regex.js +25 -3
  55. package/dist/guards-evaluator/regex.js.map +1 -1
  56. package/dist/guards-evaluator/safe-commands.js +155 -0
  57. package/dist/guards-evaluator/safe-commands.js.map +1 -0
  58. package/dist/guards-evaluator/triage.js +315 -0
  59. package/dist/guards-evaluator/triage.js.map +1 -0
  60. package/dist/hook-runner.js +24679 -5079
  61. package/dist/hooks/install.js +38 -0
  62. package/dist/hooks/install.js.map +1 -1
  63. package/dist/hooks/runtime/config.js +38 -0
  64. package/dist/hooks/runtime/config.js.map +1 -1
  65. package/dist/hooks/runtime/emit.js +94 -61
  66. package/dist/hooks/runtime/emit.js.map +1 -1
  67. package/dist/hooks/runtime/fetch-rules.js +22 -7
  68. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  69. package/dist/hooks/runtime/gateway-http-error.js +34 -0
  70. package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
  71. package/dist/hooks/runtime/guard-rules-cache.js +139 -17
  72. package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
  73. package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
  74. package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
  75. package/dist/hooks/runtime/judge-cache.js +6 -0
  76. package/dist/hooks/runtime/judge-cache.js.map +1 -1
  77. package/dist/hooks/runtime/judge-triage.js +193 -0
  78. package/dist/hooks/runtime/judge-triage.js.map +1 -0
  79. package/dist/hooks/runtime/judge.js +7 -1
  80. package/dist/hooks/runtime/judge.js.map +1 -1
  81. package/dist/hooks/runtime/pre-compact.js +12 -6
  82. package/dist/hooks/runtime/pre-compact.js.map +1 -1
  83. package/dist/hooks/runtime/resolve.js +90 -8
  84. package/dist/hooks/runtime/resolve.js.map +1 -1
  85. package/dist/hooks/runtime/retry-policy.js +57 -0
  86. package/dist/hooks/runtime/retry-policy.js.map +1 -0
  87. package/dist/hooks/runtime/review-sessions.js +74 -0
  88. package/dist/hooks/runtime/review-sessions.js.map +1 -0
  89. package/dist/hooks/runtime/script-resolve.js +695 -0
  90. package/dist/hooks/runtime/script-resolve.js.map +1 -0
  91. package/dist/hooks/runtime/session-activation.js +5 -1
  92. package/dist/hooks/runtime/session-activation.js.map +1 -1
  93. package/dist/hooks/runtime/session-review.js +163 -45
  94. package/dist/hooks/runtime/session-review.js.map +1 -1
  95. package/dist/hooks/runtime/session-start.js +2 -1
  96. package/dist/hooks/runtime/session-start.js.map +1 -1
  97. package/dist/hooks/runtime/session-writes.js +232 -0
  98. package/dist/hooks/runtime/session-writes.js.map +1 -0
  99. package/dist/hooks/runtime/sniff.js +26 -7
  100. package/dist/hooks/runtime/sniff.js.map +1 -1
  101. package/dist/hooks/runtime/target-resolve.js +336 -0
  102. package/dist/hooks/runtime/target-resolve.js.map +1 -0
  103. package/dist/hooks/runtime/unmapped-tools.js +93 -0
  104. package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
  105. package/dist/hooks/runtime/usage-block.js +4 -0
  106. package/dist/hooks/runtime/usage-block.js.map +1 -1
  107. package/dist/hooks/runtime/user-prompt-submit.js +2 -1
  108. package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
  109. package/dist/hooks/runtime/wire-text.js +41 -0
  110. package/dist/hooks/runtime/wire-text.js.map +1 -0
  111. package/dist/hooks/runtime/work-dir.js +84 -0
  112. package/dist/hooks/runtime/work-dir.js.map +1 -0
  113. package/dist/index.js +45 -12
  114. package/dist/index.js.map +1 -1
  115. package/dist/install.js +174 -11
  116. package/dist/install.js.map +1 -1
  117. package/dist/link.js +74 -48
  118. package/dist/link.js.map +1 -1
  119. package/dist/login.js +77 -11
  120. package/dist/login.js.map +1 -1
  121. package/dist/mcp/auth/agent-sign-ins.js +174 -0
  122. package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
  123. package/dist/mcp/auth/callback.js +200 -0
  124. package/dist/mcp/auth/callback.js.map +1 -0
  125. package/dist/mcp/auth/connect.js +392 -0
  126. package/dist/mcp/auth/connect.js.map +1 -0
  127. package/dist/mcp/auth/discovery.js +399 -0
  128. package/dist/mcp/auth/discovery.js.map +1 -0
  129. package/dist/mcp/auth/oauth.js +326 -0
  130. package/dist/mcp/auth/oauth.js.map +1 -0
  131. package/dist/mcp/auth/probe.js +128 -0
  132. package/dist/mcp/auth/probe.js.map +1 -0
  133. package/dist/mcp/auth/secrets.js +446 -0
  134. package/dist/mcp/auth/secrets.js.map +1 -0
  135. package/dist/mcp/auth/store.js +260 -0
  136. package/dist/mcp/auth/store.js.map +1 -0
  137. package/dist/mcp/auth/tokenSource.js +55 -0
  138. package/dist/mcp/auth/tokenSource.js.map +1 -0
  139. package/dist/mcp/config/atomicWrite.js +98 -0
  140. package/dist/mcp/config/atomicWrite.js.map +1 -0
  141. package/dist/mcp/config/clients.js +171 -0
  142. package/dist/mcp/config/clients.js.map +1 -0
  143. package/dist/mcp/config/cybedefend-servers.js +48 -0
  144. package/dist/mcp/config/cybedefend-servers.js.map +1 -0
  145. package/dist/mcp/config/discover.js +114 -0
  146. package/dist/mcp/config/discover.js.map +1 -0
  147. package/dist/mcp/config/hook.js +123 -0
  148. package/dist/mcp/config/hook.js.map +1 -0
  149. package/dist/mcp/config/index.js +11 -0
  150. package/dist/mcp/config/index.js.map +1 -0
  151. package/dist/mcp/config/install.js +132 -0
  152. package/dist/mcp/config/install.js.map +1 -0
  153. package/dist/mcp/config/installed.js +37 -0
  154. package/dist/mcp/config/installed.js.map +1 -0
  155. package/dist/mcp/config/jsonEdit.js +119 -0
  156. package/dist/mcp/config/jsonEdit.js.map +1 -0
  157. package/dist/mcp/config/lock.js +102 -0
  158. package/dist/mcp/config/lock.js.map +1 -0
  159. package/dist/mcp/config/proxyBinary.js +211 -0
  160. package/dist/mcp/config/proxyBinary.js.map +1 -0
  161. package/dist/mcp/config/rewrite.js +388 -0
  162. package/dist/mcp/config/rewrite.js.map +1 -0
  163. package/dist/mcp/config/types.js +34 -0
  164. package/dist/mcp/config/types.js.map +1 -0
  165. package/dist/mcp/proxy/audit.js +83 -0
  166. package/dist/mcp/proxy/audit.js.map +1 -0
  167. package/dist/mcp/proxy/authInterceptor.js +119 -0
  168. package/dist/mcp/proxy/authInterceptor.js.map +1 -0
  169. package/dist/mcp/proxy/expand.js +93 -0
  170. package/dist/mcp/proxy/expand.js.map +1 -0
  171. package/dist/mcp/proxy/inject.js +412 -0
  172. package/dist/mcp/proxy/inject.js.map +1 -0
  173. package/dist/mcp/proxy/intercept.js +63 -0
  174. package/dist/mcp/proxy/intercept.js.map +1 -0
  175. package/dist/mcp/proxy/jsonrpc.js +153 -0
  176. package/dist/mcp/proxy/jsonrpc.js.map +1 -0
  177. package/dist/mcp/proxy/log.js +109 -0
  178. package/dist/mcp/proxy/log.js.map +1 -0
  179. package/dist/mcp/proxy/paths.js +57 -0
  180. package/dist/mcp/proxy/paths.js.map +1 -0
  181. package/dist/mcp/proxy/proxy.js +520 -0
  182. package/dist/mcp/proxy/proxy.js.map +1 -0
  183. package/dist/mcp/proxy/serverCheckTimer.js +75 -0
  184. package/dist/mcp/proxy/serverCheckTimer.js.map +1 -0
  185. package/dist/mcp/proxy/sessionLifecycle.js +29 -0
  186. package/dist/mcp/proxy/sessionLifecycle.js.map +1 -0
  187. package/dist/mcp/proxy/spec.js +203 -0
  188. package/dist/mcp/proxy/spec.js.map +1 -0
  189. package/dist/mcp/proxy/sse.js +77 -0
  190. package/dist/mcp/proxy/sse.js.map +1 -0
  191. package/dist/mcp/proxy/upstream.js +2 -0
  192. package/dist/mcp/proxy/upstream.js.map +1 -0
  193. package/dist/mcp/proxy/upstreamHttp.js +499 -0
  194. package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
  195. package/dist/mcp/proxy/upstreamStdio.js +188 -0
  196. package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
  197. package/dist/mcp/proxy/upstreams.js +143 -0
  198. package/dist/mcp/proxy/upstreams.js.map +1 -0
  199. package/dist/mcp/proxy/verifyInterceptor.js +718 -0
  200. package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
  201. package/dist/mcp/proxy/windowsCommand.js +99 -0
  202. package/dist/mcp/proxy/windowsCommand.js.map +1 -0
  203. package/dist/mcp/report/buffer.js +351 -0
  204. package/dist/mcp/report/buffer.js.map +1 -0
  205. package/dist/mcp/report/coalesce.js +165 -0
  206. package/dist/mcp/report/coalesce.js.map +1 -0
  207. package/dist/mcp/report/constants.js +51 -0
  208. package/dist/mcp/report/constants.js.map +1 -0
  209. package/dist/mcp/report/project.js +83 -0
  210. package/dist/mcp/report/project.js.map +1 -0
  211. package/dist/mcp/report/reporter.js +443 -0
  212. package/dist/mcp/report/reporter.js.map +1 -0
  213. package/dist/mcp/report/types.js +3 -0
  214. package/dist/mcp/report/types.js.map +1 -0
  215. package/dist/mcp/report/validate.js +179 -0
  216. package/dist/mcp/report/validate.js.map +1 -0
  217. package/dist/mcp/scan/args.js +228 -0
  218. package/dist/mcp/scan/args.js.map +1 -0
  219. package/dist/mcp/scan/results.js +253 -0
  220. package/dist/mcp/scan/results.js.map +1 -0
  221. package/dist/mcp/scan/types.js +40 -0
  222. package/dist/mcp/scan/types.js.map +1 -0
  223. package/dist/mcp/verify/api.js +514 -0
  224. package/dist/mcp/verify/api.js.map +1 -0
  225. package/dist/mcp/verify/backend.js +143 -0
  226. package/dist/mcp/verify/backend.js.map +1 -0
  227. package/dist/mcp/verify/cache.js +200 -0
  228. package/dist/mcp/verify/cache.js.map +1 -0
  229. package/dist/mcp/verify/contract-errors.js +198 -0
  230. package/dist/mcp/verify/contract-errors.js.map +1 -0
  231. package/dist/mcp/verify/digest.js +91 -0
  232. package/dist/mcp/verify/digest.js.map +1 -0
  233. package/dist/mcp/verify/factory.js +56 -0
  234. package/dist/mcp/verify/factory.js.map +1 -0
  235. package/dist/mcp/verify/identity.js +286 -0
  236. package/dist/mcp/verify/identity.js.map +1 -0
  237. package/dist/mcp/verify/policy-store.js +63 -0
  238. package/dist/mcp/verify/policy-store.js.map +1 -0
  239. package/dist/mcp/verify/policy.js +160 -0
  240. package/dist/mcp/verify/policy.js.map +1 -0
  241. package/dist/mcp/verify/pool.js +27 -0
  242. package/dist/mcp/verify/pool.js.map +1 -0
  243. package/dist/mcp/verify/token-refresh.js +44 -0
  244. package/dist/mcp/verify/token-refresh.js.map +1 -0
  245. package/dist/mcp/verify/token.js +67 -0
  246. package/dist/mcp/verify/token.js.map +1 -0
  247. package/dist/mcp/verify/verifier.js +1166 -0
  248. package/dist/mcp/verify/verifier.js.map +1 -0
  249. package/dist/org-gate.js +1 -1
  250. package/dist/org-gate.js.map +1 -1
  251. package/dist/org.js +146 -0
  252. package/dist/org.js.map +1 -0
  253. package/dist/project-create.js +129 -0
  254. package/dist/project-create.js.map +1 -0
  255. package/dist/prompts.js +21 -0
  256. package/dist/prompts.js.map +1 -1
  257. package/dist/re2.wasm +0 -0
  258. package/dist/status.js +61 -0
  259. package/dist/status.js.map +1 -1
  260. package/dist/uninstall.js +49 -4
  261. package/dist/uninstall.js.map +1 -1
  262. package/dist/utils.js +62 -6
  263. package/dist/utils.js.map +1 -1
  264. package/package.json +10 -3
@@ -0,0 +1,153 @@
1
+ /**
2
+ * JSON-RPC 2.0 framing for the MCP stdio channel.
3
+ *
4
+ * The proxy forwards messages it does not understand, so nothing here parses
5
+ * MCP semantics: a message is an object, and the only questions we ask are
6
+ * "is it a request, a response or a notification" and "what is its id".
7
+ * Everything else stays untouched between `stdin` and the upstream.
8
+ */
9
+ /**
10
+ * Largest single message the framer accepts, in bytes.
11
+ *
12
+ * A tool result carrying a base64 image or a gzipped resource is routinely a
13
+ * few megabytes; 16 MiB leaves room for those while bounding the memory an
14
+ * upstream (or a hostile agent) can make the proxy hold on a line that never
15
+ * ends. Over the limit the framer drops bytes until the next newline and
16
+ * reports an error instead of growing without bound.
17
+ */
18
+ export const MAX_MESSAGE_BYTES = 16 * 1024 * 1024;
19
+ const NEWLINE = 0x0a;
20
+ export function isJsonRpcMessage(value) {
21
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
22
+ }
23
+ /** A request expects a response: it carries both a method and a non-null id. */
24
+ export function isRequest(message) {
25
+ return typeof message.method === 'string' && message.id !== undefined && message.id !== null;
26
+ }
27
+ /** A notification carries a method and no id. */
28
+ export function isNotification(message) {
29
+ return typeof message.method === 'string' && (message.id === undefined || message.id === null);
30
+ }
31
+ /** A response carries an id and either a result or an error, and no method. */
32
+ export function isResponse(message) {
33
+ return (message.method === undefined &&
34
+ message.id !== undefined &&
35
+ ('result' in message || 'error' in message));
36
+ }
37
+ export function methodOf(message) {
38
+ return typeof message.method === 'string' ? message.method : undefined;
39
+ }
40
+ /**
41
+ * A comparable key for an id. JSON-RPC ids are strings or numbers and `1` is
42
+ * not `"1"`, so the type is part of the key.
43
+ */
44
+ export function idKey(id) {
45
+ if (typeof id === 'number')
46
+ return `n:${id}`;
47
+ if (typeof id === 'string')
48
+ return `s:${id}`;
49
+ return undefined;
50
+ }
51
+ /**
52
+ * Serialises one message as a single line. `JSON.stringify` escapes every
53
+ * control character, so the payload can never contain the delimiter.
54
+ */
55
+ export function encodeMessage(message) {
56
+ return `${JSON.stringify(message)}\n`;
57
+ }
58
+ /** Longest fragment of a bad line kept for the log. */
59
+ const SAMPLE_BYTES = 200;
60
+ /**
61
+ * Newline-delimited JSON reader.
62
+ *
63
+ * Chunks are held as a list and only concatenated when a newline shows up, so
64
+ * a multi-megabyte message costs one copy instead of one copy per chunk.
65
+ */
66
+ export class LineFramer {
67
+ maxBytes;
68
+ chunks = [];
69
+ size = 0;
70
+ /** Set when the current line blew the size limit: bytes are dropped until the next newline. */
71
+ discarding = false;
72
+ discarded = 0;
73
+ constructor(maxBytes = MAX_MESSAGE_BYTES) {
74
+ this.maxBytes = maxBytes;
75
+ }
76
+ push(chunk) {
77
+ const out = { messages: [], errors: [] };
78
+ let start = 0;
79
+ for (;;) {
80
+ const newline = chunk.indexOf(NEWLINE, start);
81
+ if (newline === -1) {
82
+ this.append(chunk.subarray(start));
83
+ return out;
84
+ }
85
+ this.append(chunk.subarray(start, newline));
86
+ this.emit(out);
87
+ start = newline + 1;
88
+ }
89
+ }
90
+ /** Decodes whatever is left when the stream ends without a trailing newline. */
91
+ flush() {
92
+ const out = { messages: [], errors: [] };
93
+ if (this.size > 0 || this.discarding)
94
+ this.emit(out);
95
+ return out;
96
+ }
97
+ append(part) {
98
+ if (part.length === 0)
99
+ return;
100
+ if (this.discarding) {
101
+ this.discarded += part.length;
102
+ return;
103
+ }
104
+ if (this.size + part.length > this.maxBytes) {
105
+ this.discarding = true;
106
+ this.discarded = this.size + part.length;
107
+ this.chunks = [];
108
+ this.size = 0;
109
+ return;
110
+ }
111
+ this.chunks.push(part);
112
+ this.size += part.length;
113
+ }
114
+ emit(out) {
115
+ if (this.discarding) {
116
+ out.errors.push({ reason: 'too-large', sample: '', bytes: this.discarded });
117
+ this.discarding = false;
118
+ this.discarded = 0;
119
+ return;
120
+ }
121
+ const line = this.size === 1 ? this.chunks[0] : Buffer.concat(this.chunks, this.size);
122
+ const bytes = this.size;
123
+ this.chunks = [];
124
+ this.size = 0;
125
+ // A bare "\r\n" or a blank line is not an error, it is padding.
126
+ const text = line.toString('utf8').replace(/\r$/, '');
127
+ if (text.trim() === '')
128
+ return;
129
+ let parsed;
130
+ try {
131
+ parsed = JSON.parse(text);
132
+ }
133
+ catch {
134
+ out.errors.push({ reason: 'invalid-json', sample: text.slice(0, SAMPLE_BYTES), bytes });
135
+ return;
136
+ }
137
+ if (!isJsonRpcMessage(parsed)) {
138
+ out.errors.push({ reason: 'not-an-object', sample: text.slice(0, SAMPLE_BYTES), bytes });
139
+ return;
140
+ }
141
+ out.messages.push(parsed);
142
+ }
143
+ }
144
+ /** JSON-RPC error codes used by the proxy itself. */
145
+ export const JSON_RPC_INTERNAL_ERROR = -32603;
146
+ export const JSON_RPC_INVALID_REQUEST = -32600;
147
+ export function errorResponse(id, code, message, data) {
148
+ const error = { code, message };
149
+ if (data !== undefined)
150
+ error.data = data;
151
+ return { jsonrpc: '2.0', id: id === undefined ? null : id, error };
152
+ }
153
+ //# sourceMappingURL=jsonrpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonrpc.js","sourceRoot":"","sources":["../../../src/mcp/proxy/jsonrpc.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAqBH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,CAAC;AAErB,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,OAAuB;IAC/C,OAAO,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI,CAAC;AAC/F,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,OAAuB;IACpD,OAAO,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;AACjG,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAC,OAAuB;IAChD,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,SAAS;QAC5B,OAAO,CAAC,EAAE,KAAK,SAAS;QACxB,CAAC,QAAQ,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,CAC5C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAuB;IAC9C,OAAO,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,EAAW;IAC/B,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,EAAE,EAAE,CAAC;IAC7C,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,EAAE,EAAE,CAAC;IAC7C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAuB;IACnD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;AACxC,CAAC;AAgBD,uDAAuD;AACvD,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IAOQ;IANrB,MAAM,GAAa,EAAE,CAAC;IACtB,IAAI,GAAG,CAAC,CAAC;IACjB,+FAA+F;IACvF,UAAU,GAAG,KAAK,CAAC;IACnB,SAAS,GAAG,CAAC,CAAC;IAEtB,YAA6B,WAAmB,iBAAiB;QAApC,aAAQ,GAAR,QAAQ,CAA4B;IAAG,CAAC;IAErE,IAAI,CAAC,KAAa;QAChB,MAAM,GAAG,GAAiB,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACvD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,SAAS,CAAC;YACR,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9C,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnC,OAAO,GAAG,CAAC;YACb,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACf,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,gFAAgF;IAChF,KAAK;QACH,MAAM,GAAG,GAAiB,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,MAAM,CAAC,IAAY;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC9B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;YACzC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;YACd,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEO,IAAI,CAAC,GAAiB;QAC5B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAC5E,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACtF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,gEAAgE;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtD,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO;QAC/B,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACzF,OAAO;QACT,CAAC;QACD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;CACF;AAED,qDAAqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAK,CAAC;AAC9C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAK,CAAC;AAE/C,MAAM,UAAU,aAAa,CAC3B,EAAW,EACX,IAAY,EACZ,OAAe,EACf,IAAc;IAEd,MAAM,KAAK,GAA4B,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACzD,IAAI,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AACrE,CAAC"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * File logger for the proxy.
3
+ *
4
+ * The one rule that shapes this module: `stdout` is the MCP channel, so
5
+ * nothing here may ever write to it. Records go to a JSONL file under
6
+ * `~/.cybedefend/mcp/logs/`, and optionally to `stderr` when the operator
7
+ * asks for it (`VIBEDEFEND_MCP_LOG_STDERR=1`) — a client that spawns us over
8
+ * stdio captures our stderr for debugging, which is the right place for it.
9
+ *
10
+ * Every write is best-effort: a full disk or a read-only home must degrade
11
+ * the logs, never the MCP session.
12
+ */
13
+ import { appendFileSync, mkdirSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { mcpLogsDir, PROXY_ENV_PREFIX } from './paths.js';
16
+ const ORDER = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
17
+ export function parseLogLevel(value, fallback = 'info') {
18
+ if (!value)
19
+ return fallback;
20
+ const normalized = value.trim().toLowerCase();
21
+ return normalized in ORDER ? normalized : fallback;
22
+ }
23
+ /** `proxy-YYYY-MM-DD.log`: one file per day, no rotation logic to get wrong. */
24
+ export function logFileNameFor(date) {
25
+ return `proxy-${date.toISOString().slice(0, 10)}.log`;
26
+ }
27
+ export function createLogger(options = {}) {
28
+ const now = options.now ?? (() => new Date());
29
+ const level = options.level ?? 'info';
30
+ const dir = options.dir ?? mcpLogsDir();
31
+ const mirrorToStderr = options.mirrorToStderr ?? false;
32
+ let target;
33
+ if (level !== 'silent') {
34
+ try {
35
+ mkdirSync(dir, { recursive: true });
36
+ target = join(dir, logFileNameFor(now()));
37
+ }
38
+ catch {
39
+ target = undefined;
40
+ }
41
+ }
42
+ const write = (recordLevel, base) => {
43
+ return (message, fields) => {
44
+ if (ORDER[recordLevel] > ORDER[level])
45
+ return;
46
+ const record = {
47
+ ts: now().toISOString(),
48
+ level: recordLevel,
49
+ msg: message,
50
+ ...base,
51
+ ...fields,
52
+ };
53
+ let line;
54
+ try {
55
+ line = `${JSON.stringify(record)}\n`;
56
+ }
57
+ catch {
58
+ line = `${JSON.stringify({ ts: record.ts, level: recordLevel, msg: message, note: 'fields not serialisable' })}\n`;
59
+ }
60
+ if (target) {
61
+ try {
62
+ appendFileSync(target, line);
63
+ }
64
+ catch {
65
+ // A logger that throws would take the session down with it.
66
+ }
67
+ }
68
+ if (mirrorToStderr) {
69
+ try {
70
+ process.stderr.write(line);
71
+ }
72
+ catch {
73
+ /* ignore */
74
+ }
75
+ }
76
+ };
77
+ };
78
+ const build = (base) => ({
79
+ error: write('error', base),
80
+ warn: write('warn', base),
81
+ info: write('info', base),
82
+ debug: write('debug', base),
83
+ child: (fields) => build({ ...base, ...fields }),
84
+ file: target,
85
+ });
86
+ return build(options.base ?? {});
87
+ }
88
+ /** Drops everything. Used by unit tests that do not assert on logs. */
89
+ export function createNullLogger() {
90
+ const noop = () => { };
91
+ const logger = {
92
+ error: noop,
93
+ warn: noop,
94
+ info: noop,
95
+ debug: noop,
96
+ child: () => logger,
97
+ file: undefined,
98
+ };
99
+ return logger;
100
+ }
101
+ export function loggerFromEnv(base, env = process.env) {
102
+ return createLogger({
103
+ level: parseLogLevel(env[`${PROXY_ENV_PREFIX}LOG_LEVEL`]),
104
+ dir: mcpLogsDir(env),
105
+ base,
106
+ mirrorToStderr: env[`${PROXY_ENV_PREFIX}LOG_STDERR`] === '1',
107
+ });
108
+ }
109
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/mcp/proxy/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Where the proxy keeps its state.
3
+ *
4
+ * Section 0 of docs/PLAN-mcp-proxy.md: everything lives under
5
+ * `~/.cybedefend/mcp/`, no second user directory. `VIBEDEFEND_MCP_DIR` moves
6
+ * the whole tree, which is what the test suite uses instead of rewriting
7
+ * `HOME`.
8
+ */
9
+ import { homedir } from 'node:os';
10
+ import { join } from 'node:path';
11
+ /** Variables the proxy reads for itself; they are stripped from the upstream env. */
12
+ export const PROXY_ENV_PREFIX = 'VIBEDEFEND_MCP_';
13
+ export function mcpHomeDir(env = process.env) {
14
+ const override = env[`${PROXY_ENV_PREFIX}DIR`];
15
+ if (override && override.trim() !== '')
16
+ return override;
17
+ return join(homedir(), '.cybedefend', 'mcp');
18
+ }
19
+ /**
20
+ * Where the clients' own config files are looked for.
21
+ *
22
+ * The home directory — unless `VIBEDEFEND_MCP_DIR` is set, in which case the
23
+ * clients are looked for under it as if it were the home directory. The
24
+ * variable is the root of everything the MCP feature reads and writes: a test
25
+ * or a manual procedure that points it at an empty directory must be certain
26
+ * that no real `~/.claude.json` is discovered, let alone rewritten. Measured
27
+ * on 2026-09-08 before this existed: a proxy started for a throwaway test
28
+ * wrapped twelve real servers across three clients.
29
+ */
30
+ export function clientConfigRoot(env = process.env) {
31
+ const override = env[`${PROXY_ENV_PREFIX}DIR`];
32
+ if (override && override.trim() !== '')
33
+ return override;
34
+ return env.HOME || env.USERPROFILE || homedir();
35
+ }
36
+ /** Is `clientConfigRoot` an override, so platform-specific roots must follow it too? */
37
+ export function clientConfigRootIsOverridden(env = process.env) {
38
+ const override = env[`${PROXY_ENV_PREFIX}DIR`];
39
+ return Boolean(override && override.trim() !== '');
40
+ }
41
+ export function mcpLogsDir(env = process.env) {
42
+ return join(mcpHomeDir(env), 'logs');
43
+ }
44
+ export function mcpCacheDir(env = process.env) {
45
+ return join(mcpHomeDir(env), 'cache');
46
+ }
47
+ export function mcpAuditDir(env = process.env) {
48
+ return join(mcpHomeDir(env), 'audit');
49
+ }
50
+ /** Call reports not yet delivered: `reports.jsonl`, `holds.json`, `flush.lock`. */
51
+ export function mcpReportsDir(env = process.env) {
52
+ return join(mcpHomeDir(env), 'reports');
53
+ }
54
+ export function upstreamsFile(env = process.env) {
55
+ return join(mcpHomeDir(env), 'upstreams.json');
56
+ }
57
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/mcp/proxy/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,qFAAqF;AACrF,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,gBAAgB,KAAK,CAAC,CAAC;IAC/C,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IACxD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACnE,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,gBAAgB,KAAK,CAAC,CAAC;IAC/C,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IACxD,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW,IAAI,OAAO,EAAE,CAAC;AAClD,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,4BAA4B,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC/E,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,gBAAgB,KAAK,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,MAAyB,OAAO,CAAC,GAAG;IAChE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAyB,OAAO,CAAC,GAAG;IAChE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAC,CAAC;AACjD,CAAC"}