@vaultcompass/vault-guard 1.0.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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/integration/proxy-test-helpers.d.ts +47 -0
  3. package/dist/__tests__/integration/proxy-test-helpers.d.ts.map +1 -0
  4. package/dist/__tests__/integration/proxy-test-helpers.js +146 -0
  5. package/dist/__tests__/integration/proxy-test-helpers.js.map +1 -0
  6. package/dist/cli-entry.d.ts +3 -0
  7. package/dist/cli-entry.d.ts.map +1 -0
  8. package/dist/cli-entry.js +15 -0
  9. package/dist/cli-entry.js.map +1 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +241 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/commands/check.d.ts +2 -0
  15. package/dist/commands/check.d.ts.map +1 -0
  16. package/dist/commands/check.js +40 -0
  17. package/dist/commands/check.js.map +1 -0
  18. package/dist/commands/config.d.ts +6 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +57 -0
  21. package/dist/commands/config.js.map +1 -0
  22. package/dist/commands/data.d.ts +67 -0
  23. package/dist/commands/data.d.ts.map +1 -0
  24. package/dist/commands/data.js +294 -0
  25. package/dist/commands/data.js.map +1 -0
  26. package/dist/commands/fix.d.ts +2 -0
  27. package/dist/commands/fix.d.ts.map +1 -0
  28. package/dist/commands/fix.js +80 -0
  29. package/dist/commands/fix.js.map +1 -0
  30. package/dist/commands/index.d.ts +11 -0
  31. package/dist/commands/index.d.ts.map +1 -0
  32. package/dist/commands/index.js +26 -0
  33. package/dist/commands/index.js.map +1 -0
  34. package/dist/commands/install-hook.d.ts +3 -0
  35. package/dist/commands/install-hook.d.ts.map +1 -0
  36. package/dist/commands/install-hook.js +31 -0
  37. package/dist/commands/install-hook.js.map +1 -0
  38. package/dist/commands/monitor.d.ts +2 -0
  39. package/dist/commands/monitor.d.ts.map +1 -0
  40. package/dist/commands/monitor.js +23 -0
  41. package/dist/commands/monitor.js.map +1 -0
  42. package/dist/commands/proxy.d.ts +68 -0
  43. package/dist/commands/proxy.d.ts.map +1 -0
  44. package/dist/commands/proxy.js +445 -0
  45. package/dist/commands/proxy.js.map +1 -0
  46. package/dist/commands/scan.d.ts +3 -0
  47. package/dist/commands/scan.d.ts.map +1 -0
  48. package/dist/commands/scan.js +156 -0
  49. package/dist/commands/scan.js.map +1 -0
  50. package/dist/commands/statusline.d.ts +2 -0
  51. package/dist/commands/statusline.d.ts.map +1 -0
  52. package/dist/commands/statusline.js +34 -0
  53. package/dist/commands/statusline.js.map +1 -0
  54. package/dist/commands/suggest-model.d.ts +6 -0
  55. package/dist/commands/suggest-model.d.ts.map +1 -0
  56. package/dist/commands/suggest-model.js +38 -0
  57. package/dist/commands/suggest-model.js.map +1 -0
  58. package/dist/commands/tokens.d.ts +2 -0
  59. package/dist/commands/tokens.d.ts.map +1 -0
  60. package/dist/commands/tokens.js +22 -0
  61. package/dist/commands/tokens.js.map +1 -0
  62. package/dist/index.d.ts +3 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +21 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/utils/index.d.ts +2 -0
  67. package/dist/utils/index.d.ts.map +1 -0
  68. package/dist/utils/index.js +18 -0
  69. package/dist/utils/index.js.map +1 -0
  70. package/dist/utils/scan-utils.d.ts +65 -0
  71. package/dist/utils/scan-utils.d.ts.map +1 -0
  72. package/dist/utils/scan-utils.js +333 -0
  73. package/dist/utils/scan-utils.js.map +1 -0
  74. package/package.json +56 -0
@@ -0,0 +1,68 @@
1
+ import * as http from 'http';
2
+ import { TelemetryStore } from '@vaultcompass/vault-guard-telemetry';
3
+ export interface ProxyOptions {
4
+ /**
5
+ * Bind address in `host:port` form, e.g. `127.0.0.1:8765`.
6
+ *
7
+ * @remarks
8
+ * Use loopback hosts unless you explicitly want LAN exposure.
9
+ */
10
+ listen: string;
11
+ /**
12
+ * If true, requests with no `x-api-key` header fall back to the
13
+ * `ANTHROPIC_API_KEY` env var on the proxy host.
14
+ *
15
+ * **Security:** Default is `false`. Without this flag any local process
16
+ * that can connect to the proxy (other CLIs, browser fetch from a phishing
17
+ * page, malicious npm postinstall) could spend the operator's Anthropic
18
+ * budget. With it enabled, you accept that risk in exchange for being able
19
+ * to point existing tools at the proxy without rewriting their auth.
20
+ */
21
+ allowEnvFallback?: boolean;
22
+ /**
23
+ * If true, the proxy is allowed to bind a non-loopback address
24
+ * (anything other than `127.0.0.1`, `localhost`, `::1`, `::ffff:127.0.0.1`).
25
+ *
26
+ * **Security:** Default is `false`. Binding `0.0.0.0` or a LAN IP exposes
27
+ * the proxy to anyone reachable on the network — combined with the
28
+ * env-fallback path above, this is a credit-card-draining footgun. Refuse
29
+ * by default and require explicit opt-in.
30
+ */
31
+ allowPublic?: boolean;
32
+ /**
33
+ * Optional cap on forwarded requests per rolling 60-second window (per process).
34
+ * When exceeded, the proxy responds with HTTP 429 until the window slides.
35
+ */
36
+ maxRpm?: number;
37
+ }
38
+ /**
39
+ * Returned from `proxyCommand` so the caller (cli.ts) can register signal
40
+ * handlers and unit tests can drive a clean shutdown without sending real
41
+ * signals.
42
+ */
43
+ export interface ProxyHandle {
44
+ /** Active HTTP server instance backing the proxy. */
45
+ server: http.Server;
46
+ /** Telemetry store used for usage event recording. */
47
+ store: TelemetryStore;
48
+ /**
49
+ * Cleanly stop accepting connections, drain inflight, and checkpoint DB.
50
+ *
51
+ * @param reason - Optional shutdown cause for stderr logs.
52
+ */
53
+ shutdown(reason?: string): Promise<void>;
54
+ }
55
+ /**
56
+ * Minimal opt-in Anthropic forwarder: POST /v1/messages → api.anthropic.com.
57
+ *
58
+ * - Authentication: requires `x-api-key` from the caller. Falls back to
59
+ * `ANTHROPIC_API_KEY` only when `allowEnvFallback === true`.
60
+ * - Bind: refuses non-loopback addresses unless `allowPublic === true`.
61
+ * - Streaming requests: forwarded byte-for-byte; usage logged with token
62
+ * counts of 0 (real SSE usage parsing is a Phase 8 follow-up).
63
+ * - Non-streaming requests: response is **piped** to the client immediately
64
+ * and **teed** (capped at 1 MB) for `usage` parsing into local SQLite.
65
+ * The tee never blocks the wire; on overflow it is silently abandoned.
66
+ */
67
+ export declare function proxyCommand(opts: ProxyOptions | string): Promise<ProxyHandle>;
68
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/commands/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AA4BrE,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,sDAAsD;IACtD,KAAK,EAAE,cAAc,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkHpF"}
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.proxyCommand = proxyCommand;
40
+ const http = __importStar(require("http"));
41
+ const https = __importStar(require("https"));
42
+ const path_1 = __importDefault(require("path"));
43
+ const vault_guard_telemetry_1 = require("@vaultcompass/vault-guard-telemetry");
44
+ /**
45
+ * Bound inbound request buffering. 32 MB is a generous ceiling for
46
+ * Anthropic-shaped JSON bodies (multi-megabyte system prompts, large
47
+ * conversation histories) without enabling trivial OOM amplification.
48
+ */
49
+ const MAX_REQUEST_BYTES = 32 * 1024 * 1024;
50
+ /**
51
+ * Hard cap on the in-memory **tee** of the upstream response body, used only
52
+ * for usage-token parsing on non-streaming responses. The wire response is
53
+ * piped to the client independently and is **not** bounded here — backpressure
54
+ * is handled by the OS pipe.
55
+ *
56
+ * If a response exceeds this cap before `end`, we abandon the tee (the user
57
+ * still gets their full response) and record a `proxy-tee-overflow` telemetry
58
+ * row so the operator can see usage data is missing for that request.
59
+ */
60
+ const MAX_TEE_BYTES = 1 * 1024 * 1024;
61
+ /**
62
+ * Grace period for inflight requests during shutdown. After this, any
63
+ * lingering connections are force-closed via `server.closeAllConnections()`
64
+ * (Node ≥ 18.2).
65
+ */
66
+ const SHUTDOWN_GRACE_MS = 5_000;
67
+ /**
68
+ * Minimal opt-in Anthropic forwarder: POST /v1/messages → api.anthropic.com.
69
+ *
70
+ * - Authentication: requires `x-api-key` from the caller. Falls back to
71
+ * `ANTHROPIC_API_KEY` only when `allowEnvFallback === true`.
72
+ * - Bind: refuses non-loopback addresses unless `allowPublic === true`.
73
+ * - Streaming requests: forwarded byte-for-byte; usage logged with token
74
+ * counts of 0 (real SSE usage parsing is a Phase 8 follow-up).
75
+ * - Non-streaming requests: response is **piped** to the client immediately
76
+ * and **teed** (capped at 1 MB) for `usage` parsing into local SQLite.
77
+ * The tee never blocks the wire; on overflow it is silently abandoned.
78
+ */
79
+ async function proxyCommand(opts) {
80
+ // Backwards-compatible call shape: previous signature accepted a bare
81
+ // `listen` string. Tests and external callers may still pass that.
82
+ const options = typeof opts === 'string' ? { listen: opts } : opts;
83
+ const [host, portStr] = parseListen(options.listen);
84
+ const port = Number(portStr);
85
+ if (!Number.isFinite(port) || port < 0 || port > 65535) {
86
+ throw new Error(`Invalid port in --listen "${options.listen}"`);
87
+ }
88
+ if (!isLoopbackHost(host) && options.allowPublic !== true) {
89
+ throw new Error(`Refusing to bind non-loopback address "${host}". This would expose the proxy ` +
90
+ `to anyone reachable on the network. Re-run with --allow-public to override ` +
91
+ `(see SECURITY.md → "vault-guard proxy" before doing so).`);
92
+ }
93
+ const store = new vault_guard_telemetry_1.TelemetryStore();
94
+ const takeRateSlot = createRollingMinuteLimiter(options.maxRpm);
95
+ // Track inflight requests so shutdown() can drain them before force-closing.
96
+ let inflightCount = 0;
97
+ let drainResolve = null;
98
+ const server = http.createServer((req, res) => {
99
+ inflightCount++;
100
+ let settled = false;
101
+ const onDone = () => {
102
+ if (settled)
103
+ return;
104
+ settled = true;
105
+ inflightCount--;
106
+ if (inflightCount === 0 && drainResolve) {
107
+ drainResolve();
108
+ drainResolve = null;
109
+ }
110
+ };
111
+ res.on('finish', onDone);
112
+ res.on('close', onDone);
113
+ handleRequest(req, res, store, options, takeRateSlot).catch(err => {
114
+ // Defence-in-depth: surface unexpected handler errors as 502 rather than
115
+ // crashing the server. The handler should not throw on its own; if it
116
+ // does, that's a bug we want to know about (logged) but not one that
117
+ // takes down the proxy for other inflight requests.
118
+ try {
119
+ if (!res.headersSent) {
120
+ res.statusCode = 502;
121
+ res.setHeader('content-type', 'text/plain; charset=utf-8');
122
+ }
123
+ }
124
+ catch {
125
+ /* response may already be torn down */
126
+ }
127
+ try {
128
+ res.end(`vault-guard proxy: handler error: ${String(err)}`);
129
+ }
130
+ catch {
131
+ /* same */
132
+ }
133
+ });
134
+ });
135
+ await new Promise((resolve, reject) => {
136
+ server.listen(port, host, () => resolve());
137
+ server.on('error', reject);
138
+ });
139
+ process.stderr.write(`vault-guard proxy listening on http://${host}:${port}\n` +
140
+ `Forward Anthropic traffic here (e.g. ANTHROPIC_BASE_URL=http://${host}:${port}). ` +
141
+ `Non-stream JSON responses log usage to ${path_1.default.join('~', '.vault-guard', 'usage.sqlite')}.\n`);
142
+ if (options.allowEnvFallback) {
143
+ process.stderr.write(`⚠️ --allow-env-fallback is active: requests without x-api-key will use ` +
144
+ `ANTHROPIC_API_KEY from the proxy host's environment.\n`);
145
+ }
146
+ let shuttingDown = false;
147
+ const shutdown = async (reason) => {
148
+ if (shuttingDown)
149
+ return;
150
+ shuttingDown = true;
151
+ if (reason) {
152
+ process.stderr.write(`\nvault-guard proxy: ${reason} received, shutting down...\n`);
153
+ }
154
+ // Stop accepting new connections immediately.
155
+ server.close();
156
+ // Wait for inflight requests to drain, up to the grace window.
157
+ await new Promise(resolve => {
158
+ if (inflightCount === 0) {
159
+ resolve();
160
+ return;
161
+ }
162
+ drainResolve = resolve;
163
+ setTimeout(() => {
164
+ drainResolve = null;
165
+ // Force-close any connections still open after the grace window.
166
+ const closer = server.closeAllConnections;
167
+ if (typeof closer === 'function')
168
+ closer.call(server);
169
+ resolve();
170
+ }, SHUTDOWN_GRACE_MS).unref();
171
+ });
172
+ try {
173
+ store.closeAndCheckpoint();
174
+ }
175
+ catch {
176
+ /* best-effort */
177
+ }
178
+ };
179
+ return { server, store, shutdown };
180
+ }
181
+ function createRollingMinuteLimiter(maxRpm) {
182
+ if (maxRpm === undefined || !Number.isFinite(maxRpm) || maxRpm < 1) {
183
+ return () => true;
184
+ }
185
+ const cap = Math.floor(maxRpm);
186
+ const windowMs = 60_000;
187
+ const stamps = [];
188
+ return () => {
189
+ const now = Date.now();
190
+ while (stamps.length > 0) {
191
+ const head = stamps[0];
192
+ if (head === undefined || now - head < windowMs)
193
+ break;
194
+ stamps.shift();
195
+ }
196
+ if (stamps.length >= cap)
197
+ return false;
198
+ stamps.push(now);
199
+ return true;
200
+ };
201
+ }
202
+ async function handleRequest(req, res, store, options, takeRateSlot) {
203
+ const u = req.url ?? '/';
204
+ if (req.method !== 'POST' || !u.startsWith('/v1/messages')) {
205
+ res.statusCode = 404;
206
+ res.setHeader('content-type', 'text/plain; charset=utf-8');
207
+ res.end('vault-guard proxy (MVP): only POST /v1/messages is forwarded to https://api.anthropic.com\n');
208
+ return;
209
+ }
210
+ if (!takeRateSlot()) {
211
+ res.statusCode = 429;
212
+ res.setHeader('content-type', 'application/json; charset=utf-8');
213
+ res.end(JSON.stringify({
214
+ error: 'rate_limited',
215
+ message: `Exceeded --max-rpm (${options.maxRpm}) for the rolling 60s window`,
216
+ }));
217
+ return;
218
+ }
219
+ const bodyBuf = await readRequestBody(req, res);
220
+ if (bodyBuf === null)
221
+ return; // 413 already sent
222
+ let bodyJson = {};
223
+ try {
224
+ bodyJson = JSON.parse(bodyBuf.toString('utf8'));
225
+ }
226
+ catch {
227
+ /* forward raw body; some Anthropic endpoints accept non-JSON bodies */
228
+ }
229
+ // ----- Authentication ----------------------------------------------------
230
+ // Caller-provided x-api-key always wins. Env fallback is opt-in.
231
+ const callerKey = typeof req.headers['x-api-key'] === 'string' ? req.headers['x-api-key'] : undefined;
232
+ let apiKey = callerKey;
233
+ if (!apiKey && options.allowEnvFallback) {
234
+ apiKey = process.env.ANTHROPIC_API_KEY ?? undefined;
235
+ }
236
+ if (!apiKey) {
237
+ res.statusCode = 401;
238
+ res.setHeader('content-type', 'application/json');
239
+ res.end(JSON.stringify({
240
+ error: 'missing_api_key',
241
+ message: options.allowEnvFallback
242
+ ? 'send x-api-key, or set ANTHROPIC_API_KEY in the proxy host environment'
243
+ : 'send x-api-key, or restart proxy with --allow-env-fallback to use ANTHROPIC_API_KEY',
244
+ }));
245
+ return;
246
+ }
247
+ const anthropicVersion = (typeof req.headers['anthropic-version'] === 'string'
248
+ ? req.headers['anthropic-version']
249
+ : undefined) ?? '2023-06-01';
250
+ const cwd = process.cwd();
251
+ const upstreamOpts = {
252
+ hostname: 'api.anthropic.com',
253
+ port: 443,
254
+ path: u.startsWith('/') ? u : `/${u}`,
255
+ method: 'POST',
256
+ headers: {
257
+ 'content-type': req.headers['content-type'] ?? 'application/json',
258
+ 'x-api-key': apiKey,
259
+ 'anthropic-version': anthropicVersion,
260
+ 'content-length': String(bodyBuf.length),
261
+ },
262
+ };
263
+ await new Promise(resolve => {
264
+ const preq = https.request(upstreamOpts, pres => {
265
+ const stream = Boolean(bodyJson.stream);
266
+ const headers = { ...pres.headers };
267
+ res.writeHead(pres.statusCode ?? 502, headers);
268
+ if (stream) {
269
+ pres.pipe(res);
270
+ pres.on('end', () => {
271
+ store.recordUsage({
272
+ provider: 'anthropic',
273
+ model: typeof bodyJson.model === 'string' ? bodyJson.model : null,
274
+ cwd,
275
+ inputTokens: 0,
276
+ outputTokens: 0,
277
+ estCostUsd: 0,
278
+ source: 'proxy-stream',
279
+ });
280
+ resolve();
281
+ });
282
+ pres.on('error', () => resolve());
283
+ return;
284
+ }
285
+ // ----- Non-streaming path ------------------------------------------
286
+ // Pipe upstream -> client immediately so memory use is bounded by the
287
+ // OS pipe, not by us. Tee a *separate* PassThrough for usage parsing,
288
+ // capped at MAX_TEE_BYTES. If the tee overflows, drop it: the wire
289
+ // pipe is not affected.
290
+ const isJsonResponse = typeof pres.headers['content-type'] === 'string' &&
291
+ pres.headers['content-type'].includes('application/json');
292
+ pres.pipe(res);
293
+ if (!isJsonResponse) {
294
+ // Non-JSON response (e.g. error HTML) — no usage to extract.
295
+ pres.on('end', () => {
296
+ store.recordUsage({
297
+ provider: 'anthropic',
298
+ model: typeof bodyJson.model === 'string' ? bodyJson.model : null,
299
+ cwd,
300
+ inputTokens: 0,
301
+ outputTokens: 0,
302
+ source: 'proxy-non-json',
303
+ });
304
+ resolve();
305
+ });
306
+ pres.on('error', () => resolve());
307
+ return;
308
+ }
309
+ const teeChunks = [];
310
+ let teeLen = 0;
311
+ let teeAbandoned = false;
312
+ pres.on('data', chunk => {
313
+ if (teeAbandoned)
314
+ return;
315
+ const b = chunk;
316
+ teeLen += b.length;
317
+ if (teeLen > MAX_TEE_BYTES) {
318
+ teeAbandoned = true;
319
+ // Drop accumulated chunks so we release the memory immediately.
320
+ teeChunks.length = 0;
321
+ return;
322
+ }
323
+ teeChunks.push(b);
324
+ });
325
+ pres.on('end', () => {
326
+ if (teeAbandoned) {
327
+ store.recordUsage({
328
+ provider: 'anthropic',
329
+ model: typeof bodyJson.model === 'string' ? bodyJson.model : null,
330
+ cwd,
331
+ inputTokens: 0,
332
+ outputTokens: 0,
333
+ source: 'proxy-tee-overflow',
334
+ });
335
+ resolve();
336
+ return;
337
+ }
338
+ try {
339
+ const raw = Buffer.concat(teeChunks);
340
+ const parsed = JSON.parse(raw.toString('utf8'));
341
+ const input = parsed.usage?.input_tokens ?? 0;
342
+ const output = parsed.usage?.output_tokens ?? 0;
343
+ const model = parsed.model ?? (typeof bodyJson.model === 'string' ? bodyJson.model : null);
344
+ store.recordUsage({
345
+ provider: 'anthropic',
346
+ model,
347
+ cwd,
348
+ inputTokens: input,
349
+ outputTokens: output,
350
+ source: 'proxy',
351
+ });
352
+ }
353
+ catch {
354
+ store.recordUsage({
355
+ provider: 'anthropic',
356
+ model: typeof bodyJson.model === 'string' ? bodyJson.model : null,
357
+ cwd,
358
+ inputTokens: 0,
359
+ outputTokens: 0,
360
+ source: 'proxy-parse-failed',
361
+ });
362
+ }
363
+ resolve();
364
+ });
365
+ pres.on('error', () => resolve());
366
+ });
367
+ preq.on('error', e => {
368
+ if (!res.headersSent) {
369
+ res.statusCode = 502;
370
+ res.setHeader('content-type', 'text/plain; charset=utf-8');
371
+ }
372
+ try {
373
+ res.end(String(e));
374
+ }
375
+ catch {
376
+ /* response may already be torn down */
377
+ }
378
+ resolve();
379
+ });
380
+ preq.write(bodyBuf);
381
+ preq.end();
382
+ });
383
+ }
384
+ /**
385
+ * Read the inbound request body up to `MAX_REQUEST_BYTES`. Returns `null` if
386
+ * the cap was exceeded (a 413 has already been written to `res`).
387
+ */
388
+ function readRequestBody(req, res) {
389
+ return new Promise((resolve, reject) => {
390
+ const chunks = [];
391
+ let received = 0;
392
+ let aborted = false;
393
+ req.on('data', c => {
394
+ if (aborted)
395
+ return;
396
+ const b = c;
397
+ received += b.length;
398
+ if (received > MAX_REQUEST_BYTES) {
399
+ aborted = true;
400
+ res.statusCode = 413;
401
+ res.setHeader('content-type', 'application/json');
402
+ res.end(JSON.stringify({ error: 'payload_too_large', max_bytes: MAX_REQUEST_BYTES }));
403
+ // Drain the remaining body bytes so the connection isn't torn down
404
+ // abruptly before the client receives the 413 response.
405
+ req.resume();
406
+ resolve(null);
407
+ return;
408
+ }
409
+ chunks.push(b);
410
+ });
411
+ req.on('end', () => {
412
+ if (aborted)
413
+ return;
414
+ resolve(Buffer.concat(chunks));
415
+ });
416
+ req.on('error', reject);
417
+ });
418
+ }
419
+ function parseListen(listen) {
420
+ const m = /^(.*):(\d+)$/.exec(listen.trim());
421
+ if (!m) {
422
+ throw new Error(`Invalid --listen "${listen}" (expected host:port, e.g. 127.0.0.1:8765)`);
423
+ }
424
+ return [m[1], m[2]];
425
+ }
426
+ /**
427
+ * Loopback host detector. Recognises:
428
+ * - `127.0.0.1`, `localhost`
429
+ * - `::1`, `[::1]`
430
+ * - `::ffff:127.0.0.1` (IPv4-mapped IPv6 loopback — Linux/macOS dual-stack
431
+ * sockets sometimes report this)
432
+ *
433
+ * Anything else (including `0.0.0.0`, `::`, the empty string, LAN IPs) is
434
+ * treated as non-loopback and refused unless `--allow-public` is set.
435
+ */
436
+ function isLoopbackHost(host) {
437
+ const h = host.toLowerCase().trim();
438
+ return (h === '127.0.0.1' ||
439
+ h === 'localhost' ||
440
+ h === '::1' ||
441
+ h === '[::1]' ||
442
+ h === '::ffff:127.0.0.1' ||
443
+ h === '[::ffff:127.0.0.1]');
444
+ }
445
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/commands/proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type OutputFormat = 'text' | 'json' | 'sarif';
2
+ export declare function scanCommand(targetPath: string, format?: OutputFormat, staged?: boolean): Promise<number>;
3
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,YAAqB,EAC7B,MAAM,UAAQ,GACb,OAAO,CAAC,MAAM,CAAC,CA2LjB"}