@vibecheckai/cli 3.2.5 → 3.3.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.
- package/bin/.generated +25 -25
- package/bin/dev/run-v2-torture.js +30 -30
- package/bin/registry.js +192 -5
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/analyzers.js +81 -18
- package/bin/runners/lib/api-client.js +269 -0
- package/bin/runners/lib/auth-truth.js +193 -193
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/backup.js +62 -62
- package/bin/runners/lib/billing.js +107 -107
- package/bin/runners/lib/claims.js +118 -118
- package/bin/runners/lib/cli-output.js +7 -1
- package/bin/runners/lib/cli-ui.js +540 -540
- package/bin/runners/lib/contracts/auth-contract.js +202 -202
- package/bin/runners/lib/contracts/env-contract.js +181 -181
- package/bin/runners/lib/contracts/external-contract.js +206 -206
- package/bin/runners/lib/contracts/guard.js +168 -168
- package/bin/runners/lib/contracts/index.js +89 -89
- package/bin/runners/lib/contracts/plan-validator.js +311 -311
- package/bin/runners/lib/contracts/route-contract.js +199 -199
- package/bin/runners/lib/contracts.js +804 -804
- package/bin/runners/lib/detect.js +89 -89
- package/bin/runners/lib/doctor/autofix.js +254 -254
- package/bin/runners/lib/doctor/index.js +37 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
- package/bin/runners/lib/doctor/modules/index.js +46 -46
- package/bin/runners/lib/doctor/modules/network.js +250 -250
- package/bin/runners/lib/doctor/modules/project.js +312 -312
- package/bin/runners/lib/doctor/modules/runtime.js +224 -224
- package/bin/runners/lib/doctor/modules/security.js +348 -348
- package/bin/runners/lib/doctor/modules/system.js +213 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
- package/bin/runners/lib/doctor/reporter.js +262 -262
- package/bin/runners/lib/doctor/service.js +262 -262
- package/bin/runners/lib/doctor/types.js +113 -113
- package/bin/runners/lib/doctor/ui.js +263 -263
- package/bin/runners/lib/doctor-v2.js +608 -608
- package/bin/runners/lib/drift.js +425 -425
- package/bin/runners/lib/enforcement.js +72 -72
- package/bin/runners/lib/enterprise-detect.js +603 -603
- package/bin/runners/lib/enterprise-init.js +942 -942
- package/bin/runners/lib/env-resolver.js +417 -417
- package/bin/runners/lib/env-template.js +66 -66
- package/bin/runners/lib/env.js +189 -189
- package/bin/runners/lib/error-handler.js +16 -9
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/extractors/client-calls.js +990 -990
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
- package/bin/runners/lib/extractors/fastify-routes.js +426 -426
- package/bin/runners/lib/extractors/index.js +363 -363
- package/bin/runners/lib/extractors/next-routes.js +524 -524
- package/bin/runners/lib/extractors/proof-graph.js +431 -431
- package/bin/runners/lib/extractors/route-matcher.js +451 -451
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
- package/bin/runners/lib/extractors/ui-bindings.js +547 -547
- package/bin/runners/lib/findings-schema.js +281 -281
- package/bin/runners/lib/firewall-prompt.js +50 -50
- package/bin/runners/lib/global-flags.js +37 -0
- package/bin/runners/lib/graph/graph-builder.js +265 -265
- package/bin/runners/lib/graph/html-renderer.js +413 -413
- package/bin/runners/lib/graph/index.js +32 -32
- package/bin/runners/lib/graph/runtime-collector.js +215 -215
- package/bin/runners/lib/graph/static-extractor.js +518 -518
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/html-report.js +650 -650
- package/bin/runners/lib/llm.js +75 -75
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/meter.js +61 -61
- package/bin/runners/lib/missions/evidence.js +126 -126
- package/bin/runners/lib/patch.js +40 -40
- package/bin/runners/lib/permissions/auth-model.js +213 -213
- package/bin/runners/lib/permissions/idor-prover.js +205 -205
- package/bin/runners/lib/permissions/index.js +45 -45
- package/bin/runners/lib/permissions/matrix-builder.js +198 -198
- package/bin/runners/lib/pkgjson.js +28 -28
- package/bin/runners/lib/policy.js +295 -295
- package/bin/runners/lib/preflight.js +142 -142
- package/bin/runners/lib/reality/correlation-detectors.js +359 -359
- package/bin/runners/lib/reality/index.js +318 -318
- package/bin/runners/lib/reality/request-hashing.js +416 -416
- package/bin/runners/lib/reality/request-mapper.js +453 -453
- package/bin/runners/lib/reality/safety-rails.js +463 -463
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
- package/bin/runners/lib/reality/toast-detector.js +393 -393
- package/bin/runners/lib/reality-findings.js +84 -84
- package/bin/runners/lib/receipts.js +179 -179
- package/bin/runners/lib/redact.js +29 -29
- package/bin/runners/lib/replay/capsule-manager.js +154 -154
- package/bin/runners/lib/replay/index.js +263 -263
- package/bin/runners/lib/replay/player.js +348 -348
- package/bin/runners/lib/replay/recorder.js +331 -331
- package/bin/runners/lib/report.js +135 -135
- package/bin/runners/lib/route-detection.js +1140 -1140
- package/bin/runners/lib/sandbox/index.js +59 -59
- package/bin/runners/lib/sandbox/proof-chain.js +399 -399
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
- package/bin/runners/lib/sandbox/worktree.js +174 -174
- package/bin/runners/lib/schema-validator.js +350 -350
- package/bin/runners/lib/schemas/contracts.schema.json +160 -160
- package/bin/runners/lib/schemas/finding.schema.json +100 -100
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
- package/bin/runners/lib/schemas/validator.js +438 -438
- package/bin/runners/lib/score-history.js +282 -282
- package/bin/runners/lib/share-pack.js +239 -239
- package/bin/runners/lib/snippets.js +67 -67
- package/bin/runners/lib/unified-cli-output.js +604 -0
- package/bin/runners/lib/upsell.js +658 -510
- package/bin/runners/lib/usage.js +153 -153
- package/bin/runners/lib/validate-patch.js +156 -156
- package/bin/runners/lib/verdict-engine.js +628 -628
- package/bin/runners/reality/engine.js +917 -917
- package/bin/runners/reality/flows.js +122 -122
- package/bin/runners/reality/report.js +378 -378
- package/bin/runners/reality/session.js +193 -193
- package/bin/runners/runAgent.d.ts +5 -0
- package/bin/runners/runApprove.js +1200 -0
- package/bin/runners/runAuth.js +324 -95
- package/bin/runners/runCheckpoint.js +39 -21
- package/bin/runners/runClassify.js +859 -0
- package/bin/runners/runContext.js +136 -24
- package/bin/runners/runDoctor.js +108 -68
- package/bin/runners/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runFix.js +6 -5
- package/bin/runners/runGuard.js +262 -168
- package/bin/runners/runInit.js +3 -2
- package/bin/runners/runMcp.js +130 -52
- package/bin/runners/runPolish.js +43 -20
- package/bin/runners/runProve.js +1 -2
- package/bin/runners/runReport.js +3 -2
- package/bin/runners/runScan.js +145 -44
- package/bin/runners/runShip.js +3 -4
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/runners/runValidate.js +19 -2
- package/bin/runners/runWatch.js +104 -53
- package/bin/vibecheck.js +106 -19
- package/mcp-server/HARDENING_SUMMARY.md +299 -0
- package/mcp-server/agent-firewall-interceptor.js +367 -31
- package/mcp-server/authority-tools.js +569 -0
- package/mcp-server/conductor/conflict-resolver.js +588 -0
- package/mcp-server/conductor/execution-planner.js +544 -0
- package/mcp-server/conductor/index.js +377 -0
- package/mcp-server/conductor/lock-manager.js +615 -0
- package/mcp-server/conductor/request-queue.js +550 -0
- package/mcp-server/conductor/session-manager.js +500 -0
- package/mcp-server/conductor/tools.js +510 -0
- package/mcp-server/index.js +1199 -208
- package/mcp-server/lib/api-client.cjs +305 -0
- package/mcp-server/lib/logger.cjs +30 -0
- package/mcp-server/logger.js +173 -0
- package/mcp-server/package.json +2 -2
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/tier-auth.js +351 -136
- package/mcp-server/tools/index.js +72 -72
- package/mcp-server/truth-firewall-tools.js +145 -15
- package/mcp-server/vibecheck-tools.js +2 -2
- package/package.json +2 -3
- package/mcp-server/index.old.js +0 -4137
- package/mcp-server/package-lock.json +0 -165
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Client for Vibecheck Dashboard Integration
|
|
3
|
+
*
|
|
4
|
+
* Handles communication with the web dashboard API for:
|
|
5
|
+
* - Creating scan records
|
|
6
|
+
* - Updating scan progress
|
|
7
|
+
* - Submitting scan results
|
|
8
|
+
* - Broadcasting real-time updates
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
13
|
+
const https = require("https");
|
|
14
|
+
const http = require("http");
|
|
15
|
+
const { logger } = require("./logger.cjs");
|
|
16
|
+
|
|
17
|
+
// Configuration
|
|
18
|
+
const API_BASE_URL = process.env.VIBECHECK_API_URL || "https://api.vibecheckai.dev";
|
|
19
|
+
const API_TIMEOUT = 30000; // 30 seconds
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Make HTTP request to API
|
|
23
|
+
*/
|
|
24
|
+
async function makeRequest(path, options = {}) {
|
|
25
|
+
const url = new URL(path, API_BASE_URL);
|
|
26
|
+
const isHttps = url.protocol === "https:";
|
|
27
|
+
const client = isHttps ? https : http;
|
|
28
|
+
|
|
29
|
+
const defaultOptions = {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: {
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
"User-Agent": "vibecheck-cli/3.3.0",
|
|
34
|
+
},
|
|
35
|
+
timeout: API_TIMEOUT,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const requestOptions = {
|
|
39
|
+
...defaultOptions,
|
|
40
|
+
...options,
|
|
41
|
+
hostname: url.hostname,
|
|
42
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
43
|
+
path: url.pathname + url.search,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Add Authorization header if API key is available
|
|
47
|
+
const apiKey = process.env.VIBECHECK_API_KEY || getApiKey();
|
|
48
|
+
if (apiKey) {
|
|
49
|
+
requestOptions.headers.Authorization = `Bearer ${apiKey}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const req = client.request(requestOptions, (res) => {
|
|
54
|
+
let data = "";
|
|
55
|
+
|
|
56
|
+
res.on("data", (chunk) => {
|
|
57
|
+
data += chunk;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
res.on("end", () => {
|
|
61
|
+
try {
|
|
62
|
+
const jsonData = data ? JSON.parse(data) : {};
|
|
63
|
+
resolve({
|
|
64
|
+
ok: res.statusCode >= 200 && res.statusCode < 300,
|
|
65
|
+
status: res.statusCode,
|
|
66
|
+
data: jsonData,
|
|
67
|
+
});
|
|
68
|
+
} catch (err) {
|
|
69
|
+
resolve({
|
|
70
|
+
ok: false,
|
|
71
|
+
status: res.statusCode,
|
|
72
|
+
data: { error: "Invalid JSON response" },
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
req.on("error", (err) => {
|
|
79
|
+
logger.debug(`API request failed: ${err.message}`);
|
|
80
|
+
resolve({
|
|
81
|
+
ok: false,
|
|
82
|
+
error: err.message,
|
|
83
|
+
data: { error: err.message },
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
req.on("timeout", () => {
|
|
88
|
+
req.destroy();
|
|
89
|
+
resolve({
|
|
90
|
+
ok: false,
|
|
91
|
+
error: "Request timeout",
|
|
92
|
+
data: { error: "Request timeout" },
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (options.body) {
|
|
97
|
+
req.write(JSON.stringify(options.body));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
req.end();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get API key from environment or config
|
|
106
|
+
*/
|
|
107
|
+
function getApiKey() {
|
|
108
|
+
// Try various environment variables
|
|
109
|
+
const envVars = [
|
|
110
|
+
"VIBECHECK_API_KEY",
|
|
111
|
+
"VIBECHECK_TOKEN",
|
|
112
|
+
"API_KEY",
|
|
113
|
+
"TOKEN",
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
for (const envVar of envVars) {
|
|
117
|
+
if (process.env[envVar]) {
|
|
118
|
+
return process.env[envVar];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Try to read from config file
|
|
123
|
+
try {
|
|
124
|
+
const fs = require("fs");
|
|
125
|
+
const path = require("path");
|
|
126
|
+
const os = require("os");
|
|
127
|
+
|
|
128
|
+
const configPaths = [
|
|
129
|
+
path.join(os.homedir(), ".vibecheck", "config.json"),
|
|
130
|
+
path.join(process.cwd(), ".vibecheckrc.json"),
|
|
131
|
+
path.join(process.cwd(), "vibecheck.config.json"),
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
for (const configPath of configPaths) {
|
|
135
|
+
if (fs.existsSync(configPath)) {
|
|
136
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
137
|
+
if (config.apiKey || config.token) {
|
|
138
|
+
return config.apiKey || config.token;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
// Ignore config file errors
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// =============================================================================
|
|
150
|
+
// SECURITY: Input Validation
|
|
151
|
+
// =============================================================================
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Validate scanId format to prevent path injection.
|
|
155
|
+
*
|
|
156
|
+
* SECURITY FIX: scanId is interpolated into URLs like `/api/scans/${scanId}/progress`.
|
|
157
|
+
* Without validation, an attacker could inject path segments:
|
|
158
|
+
* scanId = "../../admin/delete"
|
|
159
|
+
* → URL becomes "/api/scans/../../admin/delete/progress"
|
|
160
|
+
*
|
|
161
|
+
* @param {string} scanId - The scan ID to validate
|
|
162
|
+
* @returns {string} - The validated scanId
|
|
163
|
+
* @throws {Error} - If scanId is invalid
|
|
164
|
+
*/
|
|
165
|
+
function validateScanId(scanId) {
|
|
166
|
+
if (!scanId || typeof scanId !== 'string') {
|
|
167
|
+
throw new Error('scanId is required and must be a string');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Only allow alphanumeric, hyphens, underscores (no dots, slashes, etc.)
|
|
171
|
+
// Max length 64 to prevent abuse
|
|
172
|
+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(scanId)) {
|
|
173
|
+
throw new Error('Invalid scanId format - must be alphanumeric with hyphens/underscores only, max 64 chars');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return scanId;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Create a new scan record
|
|
181
|
+
*/
|
|
182
|
+
async function createScan(options) {
|
|
183
|
+
const {
|
|
184
|
+
repositoryId,
|
|
185
|
+
repositoryUrl,
|
|
186
|
+
localPath,
|
|
187
|
+
branch = "main",
|
|
188
|
+
enableLLM = false,
|
|
189
|
+
} = options;
|
|
190
|
+
|
|
191
|
+
const response = await makeRequest("/api/scans", {
|
|
192
|
+
body: {
|
|
193
|
+
repositoryId,
|
|
194
|
+
repositoryUrl,
|
|
195
|
+
localPath,
|
|
196
|
+
branch,
|
|
197
|
+
enableLLM,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
if (!response.ok) {
|
|
202
|
+
throw new Error(`Failed to create scan: ${response.data?.error || response.error}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return response.data.data;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Update scan progress
|
|
210
|
+
*/
|
|
211
|
+
async function updateScanProgress(scanId, progress, status = null) {
|
|
212
|
+
const validatedId = validateScanId(scanId);
|
|
213
|
+
|
|
214
|
+
const response = await makeRequest(`/api/scans/${validatedId}/progress`, {
|
|
215
|
+
body: {
|
|
216
|
+
progress,
|
|
217
|
+
status,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if (!response.ok) {
|
|
222
|
+
logger.debug(`Failed to update scan progress: ${response.data?.error || response.error}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return response.data;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Submit scan results
|
|
230
|
+
*/
|
|
231
|
+
async function submitScanResults(scanId, results) {
|
|
232
|
+
const validatedId = validateScanId(scanId);
|
|
233
|
+
|
|
234
|
+
const {
|
|
235
|
+
verdict,
|
|
236
|
+
score,
|
|
237
|
+
findings,
|
|
238
|
+
filesScanned,
|
|
239
|
+
linesScanned,
|
|
240
|
+
durationMs,
|
|
241
|
+
metadata = {},
|
|
242
|
+
} = results;
|
|
243
|
+
|
|
244
|
+
const response = await makeRequest(`/api/scans/${validatedId}/complete`, {
|
|
245
|
+
body: {
|
|
246
|
+
verdict,
|
|
247
|
+
score,
|
|
248
|
+
findings,
|
|
249
|
+
filesScanned,
|
|
250
|
+
linesScanned,
|
|
251
|
+
durationMs,
|
|
252
|
+
metadata,
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
if (!response.ok) {
|
|
257
|
+
throw new Error(`Failed to submit scan results: ${response.data?.error || response.error}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return response.data;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Report scan error
|
|
265
|
+
*/
|
|
266
|
+
async function reportScanError(scanId, error) {
|
|
267
|
+
const validatedId = validateScanId(scanId);
|
|
268
|
+
|
|
269
|
+
const response = await makeRequest(`/api/scans/${validatedId}/error`, {
|
|
270
|
+
body: {
|
|
271
|
+
error: error.message || String(error),
|
|
272
|
+
stack: error.stack,
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (!response.ok) {
|
|
277
|
+
logger.debug(`Failed to report scan error: ${response.data?.error || response.error}`);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return response.data;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Check if API is available
|
|
285
|
+
*/
|
|
286
|
+
async function isApiAvailable() {
|
|
287
|
+
try {
|
|
288
|
+
const response = await makeRequest("/api/health", {
|
|
289
|
+
method: "GET",
|
|
290
|
+
timeout: 5000,
|
|
291
|
+
});
|
|
292
|
+
return response.ok;
|
|
293
|
+
} catch (err) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
module.exports = {
|
|
299
|
+
createScan,
|
|
300
|
+
updateScanProgress,
|
|
301
|
+
submitScanResults,
|
|
302
|
+
reportScanError,
|
|
303
|
+
isApiAvailable,
|
|
304
|
+
getApiKey,
|
|
305
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logger for MCP server
|
|
3
|
+
* Outputs to stderr to avoid interfering with MCP stdio protocol
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const DEBUG = process.env.VIBECHECK_DEBUG === "true" || process.env.DEBUG === "true";
|
|
9
|
+
|
|
10
|
+
const logger = {
|
|
11
|
+
debug(...args) {
|
|
12
|
+
if (DEBUG) {
|
|
13
|
+
console.error("[DEBUG]", ...args);
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
info(...args) {
|
|
18
|
+
console.error("[INFO]", ...args);
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
warn(...args) {
|
|
22
|
+
console.error("[WARN]", ...args);
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
error(...args) {
|
|
26
|
+
console.error("[ERROR]", ...args);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports = { logger };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VibeCheck MCP Server Logger
|
|
3
|
+
*
|
|
4
|
+
* Centralized logging utility for all MCP server modules.
|
|
5
|
+
* Avoids console.log/warn/error in production code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Log levels
|
|
12
|
+
*/
|
|
13
|
+
export const LOG_LEVELS = {
|
|
14
|
+
DEBUG: 0,
|
|
15
|
+
INFO: 1,
|
|
16
|
+
WARN: 2,
|
|
17
|
+
ERROR: 3,
|
|
18
|
+
SILENT: 4,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Current log level (can be set via environment)
|
|
23
|
+
*/
|
|
24
|
+
let currentLevel = LOG_LEVELS.INFO;
|
|
25
|
+
|
|
26
|
+
// Set from environment
|
|
27
|
+
if (process.env.VIBECHECK_LOG_LEVEL) {
|
|
28
|
+
const envLevel = process.env.VIBECHECK_LOG_LEVEL.toUpperCase();
|
|
29
|
+
if (LOG_LEVELS[envLevel] !== undefined) {
|
|
30
|
+
currentLevel = LOG_LEVELS[envLevel];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Log buffer for testing/inspection
|
|
36
|
+
*/
|
|
37
|
+
const logBuffer = [];
|
|
38
|
+
const MAX_BUFFER_SIZE = 1000;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Format a log message
|
|
42
|
+
* @param {string} level - Log level
|
|
43
|
+
* @param {string} module - Module name
|
|
44
|
+
* @param {string} message - Log message
|
|
45
|
+
* @returns {string} Formatted message
|
|
46
|
+
*/
|
|
47
|
+
function formatMessage(level, module, message) {
|
|
48
|
+
const timestamp = new Date().toISOString();
|
|
49
|
+
return `[${timestamp}] [${level}] [${module}] ${message}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Write a log entry
|
|
54
|
+
* @param {number} level - Log level number
|
|
55
|
+
* @param {string} levelName - Level name
|
|
56
|
+
* @param {string} module - Module name
|
|
57
|
+
* @param {string} message - Message
|
|
58
|
+
* @param {Error} [error] - Optional error object
|
|
59
|
+
*/
|
|
60
|
+
function writeLog(level, levelName, module, message, error = null) {
|
|
61
|
+
if (level < currentLevel) return;
|
|
62
|
+
|
|
63
|
+
const formatted = formatMessage(levelName, module, message);
|
|
64
|
+
|
|
65
|
+
// Add to buffer
|
|
66
|
+
logBuffer.push({
|
|
67
|
+
timestamp: new Date(),
|
|
68
|
+
level: levelName,
|
|
69
|
+
module,
|
|
70
|
+
message,
|
|
71
|
+
error: error ? { message: error.message, stack: error.stack } : null,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Trim buffer
|
|
75
|
+
if (logBuffer.length > MAX_BUFFER_SIZE) {
|
|
76
|
+
logBuffer.shift();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Write to stderr (MCP servers should write logs to stderr, stdout is for JSON-RPC)
|
|
80
|
+
if (level >= LOG_LEVELS.WARN) {
|
|
81
|
+
process.stderr.write(formatted + '\n');
|
|
82
|
+
} else if (process.env.VIBECHECK_DEBUG || currentLevel === LOG_LEVELS.DEBUG) {
|
|
83
|
+
process.stderr.write(formatted + '\n');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create a logger for a specific module
|
|
89
|
+
* @param {string} moduleName - Module name
|
|
90
|
+
* @returns {Object} Logger instance
|
|
91
|
+
*/
|
|
92
|
+
export function createLogger(moduleName) {
|
|
93
|
+
return {
|
|
94
|
+
debug: (message) => writeLog(LOG_LEVELS.DEBUG, 'DEBUG', moduleName, message),
|
|
95
|
+
info: (message) => writeLog(LOG_LEVELS.INFO, 'INFO', moduleName, message),
|
|
96
|
+
warn: (message, error = null) => writeLog(LOG_LEVELS.WARN, 'WARN', moduleName, message, error),
|
|
97
|
+
error: (message, error = null) => writeLog(LOG_LEVELS.ERROR, 'ERROR', moduleName, message, error),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Set the global log level
|
|
103
|
+
* @param {string|number} level - Level name or number
|
|
104
|
+
*/
|
|
105
|
+
export function setLogLevel(level) {
|
|
106
|
+
if (typeof level === 'string') {
|
|
107
|
+
const upperLevel = level.toUpperCase();
|
|
108
|
+
if (LOG_LEVELS[upperLevel] !== undefined) {
|
|
109
|
+
currentLevel = LOG_LEVELS[upperLevel];
|
|
110
|
+
}
|
|
111
|
+
} else if (typeof level === 'number') {
|
|
112
|
+
currentLevel = level;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get current log level
|
|
118
|
+
* @returns {number} Current level
|
|
119
|
+
*/
|
|
120
|
+
export function getLogLevel() {
|
|
121
|
+
return currentLevel;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get recent log entries
|
|
126
|
+
* @param {number} count - Number of entries
|
|
127
|
+
* @returns {Object[]} Log entries
|
|
128
|
+
*/
|
|
129
|
+
export function getRecentLogs(count = 100) {
|
|
130
|
+
return logBuffer.slice(-count);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Clear log buffer
|
|
135
|
+
*/
|
|
136
|
+
export function clearLogs() {
|
|
137
|
+
logBuffer.length = 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get error message safely from any error type
|
|
142
|
+
* @param {unknown} error - Error object
|
|
143
|
+
* @returns {string} Error message
|
|
144
|
+
*/
|
|
145
|
+
export function getErrorMessage(error) {
|
|
146
|
+
if (error instanceof Error) {
|
|
147
|
+
return error.message;
|
|
148
|
+
}
|
|
149
|
+
if (typeof error === 'string') {
|
|
150
|
+
return error;
|
|
151
|
+
}
|
|
152
|
+
if (error && typeof error === 'object' && 'message' in error) {
|
|
153
|
+
return String(error.message);
|
|
154
|
+
}
|
|
155
|
+
return String(error);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Pre-created loggers for common modules
|
|
159
|
+
export const conductorLogger = createLogger('Conductor');
|
|
160
|
+
export const lawbookLogger = createLogger('Lawbook');
|
|
161
|
+
export const timeMachineLogger = createLogger('TimeMachine');
|
|
162
|
+
export const clearanceLogger = createLogger('Clearance');
|
|
163
|
+
export const firewallLogger = createLogger('Firewall');
|
|
164
|
+
|
|
165
|
+
export default {
|
|
166
|
+
createLogger,
|
|
167
|
+
setLogLevel,
|
|
168
|
+
getLogLevel,
|
|
169
|
+
getRecentLogs,
|
|
170
|
+
clearLogs,
|
|
171
|
+
getErrorMessage,
|
|
172
|
+
LOG_LEVELS,
|
|
173
|
+
};
|
package/mcp-server/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibecheck-mcp-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Professional MCP server for vibecheck - Intelligent development environment vibechecks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=
|
|
27
|
+
"node": ">=20.11"
|
|
28
28
|
},
|
|
29
29
|
"author": "vibecheck",
|
|
30
30
|
"license": "MIT",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import fs from 'fs/promises';
|
|
17
17
|
import path from 'path';
|
|
18
18
|
import { execSync, spawn } from 'child_process';
|
|
19
|
-
import {
|
|
19
|
+
import { getFeatureAccessStatus } from "./tier-auth.js";
|
|
20
20
|
|
|
21
21
|
// State management (in-memory for MCP session, persisted to disk)
|
|
22
22
|
class MCPState {
|
|
@@ -434,7 +434,7 @@ export async function handlePremiumTool(name, args, logger) {
|
|
|
434
434
|
|
|
435
435
|
const requiredFeature = featureMap[name];
|
|
436
436
|
if (requiredFeature) {
|
|
437
|
-
const access = await
|
|
437
|
+
const access = await getFeatureAccessStatus(requiredFeature, args?.apiKey);
|
|
438
438
|
if (!access.hasAccess) {
|
|
439
439
|
return {
|
|
440
440
|
content: [{
|