@vibecheckai/cli 3.2.4 → 3.2.6
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/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/api-client.js +269 -0
- package/bin/runners/lib/auth-truth.js +193 -193
- 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-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/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/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/html-report.js +650 -650
- package/bin/runners/lib/llm.js +75 -75
- 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/upsell.js +510 -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/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runScan.js +82 -0
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/vibecheck.js +45 -20
- package/mcp-server/index.js +85 -0
- package/mcp-server/lib/api-client.js +269 -0
- package/mcp-server/package.json +1 -1
- package/mcp-server/tier-auth.js +173 -113
- package/mcp-server/tools/index.js +72 -72
- package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,269 @@
|
|
|
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");
|
|
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
|
+
* Create a new scan record
|
|
151
|
+
*/
|
|
152
|
+
async function createScan(options) {
|
|
153
|
+
const {
|
|
154
|
+
repositoryId,
|
|
155
|
+
repositoryUrl,
|
|
156
|
+
localPath,
|
|
157
|
+
branch = "main",
|
|
158
|
+
enableLLM = false,
|
|
159
|
+
} = options;
|
|
160
|
+
|
|
161
|
+
const response = await makeRequest("/api/scans", {
|
|
162
|
+
body: {
|
|
163
|
+
repositoryId,
|
|
164
|
+
repositoryUrl,
|
|
165
|
+
localPath,
|
|
166
|
+
branch,
|
|
167
|
+
enableLLM,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
if (!response.ok) {
|
|
172
|
+
throw new Error(`Failed to create scan: ${response.data?.error || response.error}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return response.data.data;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Update scan progress
|
|
180
|
+
*/
|
|
181
|
+
async function updateScanProgress(scanId, progress, status = null) {
|
|
182
|
+
const response = await makeRequest(`/api/scans/${scanId}/progress`, {
|
|
183
|
+
body: {
|
|
184
|
+
progress,
|
|
185
|
+
status,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
logger.debug(`Failed to update scan progress: ${response.data?.error || response.error}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return response.data;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Submit scan results
|
|
198
|
+
*/
|
|
199
|
+
async function submitScanResults(scanId, results) {
|
|
200
|
+
const {
|
|
201
|
+
verdict,
|
|
202
|
+
score,
|
|
203
|
+
findings,
|
|
204
|
+
filesScanned,
|
|
205
|
+
linesScanned,
|
|
206
|
+
durationMs,
|
|
207
|
+
metadata = {},
|
|
208
|
+
} = results;
|
|
209
|
+
|
|
210
|
+
const response = await makeRequest(`/api/scans/${scanId}/complete`, {
|
|
211
|
+
body: {
|
|
212
|
+
verdict,
|
|
213
|
+
score,
|
|
214
|
+
findings,
|
|
215
|
+
filesScanned,
|
|
216
|
+
linesScanned,
|
|
217
|
+
durationMs,
|
|
218
|
+
metadata,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (!response.ok) {
|
|
223
|
+
throw new Error(`Failed to submit scan results: ${response.data?.error || response.error}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return response.data;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Report scan error
|
|
231
|
+
*/
|
|
232
|
+
async function reportScanError(scanId, error) {
|
|
233
|
+
const response = await makeRequest(`/api/scans/${scanId}/error`, {
|
|
234
|
+
body: {
|
|
235
|
+
error: error.message || String(error),
|
|
236
|
+
stack: error.stack,
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
if (!response.ok) {
|
|
241
|
+
logger.debug(`Failed to report scan error: ${response.data?.error || response.error}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return response.data;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Check if API is available
|
|
249
|
+
*/
|
|
250
|
+
async function isApiAvailable() {
|
|
251
|
+
try {
|
|
252
|
+
const response = await makeRequest("/api/health", {
|
|
253
|
+
method: "GET",
|
|
254
|
+
timeout: 5000,
|
|
255
|
+
});
|
|
256
|
+
return response.ok;
|
|
257
|
+
} catch (err) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
module.exports = {
|
|
263
|
+
createScan,
|
|
264
|
+
updateScanProgress,
|
|
265
|
+
submitScanResults,
|
|
266
|
+
reportScanError,
|
|
267
|
+
isApiAvailable,
|
|
268
|
+
getApiKey,
|
|
269
|
+
};
|
package/mcp-server/package.json
CHANGED
package/mcp-server/tier-auth.js
CHANGED
|
@@ -1,157 +1,162 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Server Tier Authentication & Authorization
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* UNIFIED AUTHORITY SYSTEM for MCP tools.
|
|
5
|
+
*
|
|
6
|
+
* Authority Rules:
|
|
7
|
+
* - FREE: May see problems, never resolve certainty. Read-only context tools.
|
|
8
|
+
* - STARTER: May fix, but not prove. Read tools + advisory actions.
|
|
9
|
+
* - PRO: May enforce reality. Full MCP access with proof generation.
|
|
10
|
+
* - ENTERPRISE: All features + compliance tools.
|
|
11
|
+
*
|
|
12
|
+
* Verdict authority is paid. Evidence beats explanations.
|
|
5
13
|
*/
|
|
6
14
|
|
|
7
15
|
import fs from "fs/promises";
|
|
8
16
|
import path from "path";
|
|
9
17
|
import os from "os";
|
|
10
18
|
|
|
11
|
-
//
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
20
|
+
// TIER DEFINITIONS - UNIFIED AUTHORITY SYSTEM
|
|
21
|
+
// Synchronized with packages/core/src/tier-config.ts
|
|
22
|
+
//
|
|
23
|
+
// Authority Rules:
|
|
24
|
+
// - FREE: May see problems, never resolve certainty
|
|
25
|
+
// - STARTER: May fix, but not prove (Advisory verdicts only)
|
|
26
|
+
// - PRO: May enforce reality (Full verdict authority)
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
12
28
|
export const TIERS = {
|
|
13
29
|
free: {
|
|
14
30
|
name: 'FREE',
|
|
15
31
|
price: 0,
|
|
16
32
|
order: 0,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
'ctx', 'guard', 'context', 'mdc', 'contracts',
|
|
24
|
-
// Quality
|
|
25
|
-
'verify', 'quality', 'polish', 'checkpoint', 'checkpoint.basic',
|
|
26
|
-
// Fix (plan only)
|
|
27
|
-
'fix', 'fix.plan_only',
|
|
28
|
-
// Reality (preview)
|
|
29
|
-
'reality', 'reality.preview',
|
|
30
|
-
// MCP (help only)
|
|
31
|
-
'mcp.help_only',
|
|
32
|
-
// Report (html/md only)
|
|
33
|
-
'report', 'report.html_md',
|
|
34
|
-
],
|
|
33
|
+
// Verdict authority
|
|
34
|
+
verdictAuthority: 'NONE',
|
|
35
|
+
canIssueVerdicts: false,
|
|
36
|
+
canEnforceCI: false,
|
|
37
|
+
canGenerateProof: false,
|
|
38
|
+
// Limits
|
|
35
39
|
limits: {
|
|
36
|
-
scans:
|
|
37
|
-
shipChecks: 20,
|
|
40
|
+
scans: -1, // Unlimited scans
|
|
38
41
|
realityMaxPages: 5,
|
|
39
42
|
realityMaxClicks: 20,
|
|
40
|
-
|
|
41
|
-
mcpRateLimit: 10, // requests per minute
|
|
43
|
+
mcpRateLimit: 10,
|
|
42
44
|
},
|
|
43
|
-
// MCP tools allowed on FREE
|
|
45
|
+
// MCP tools allowed on FREE (read-only context only)
|
|
44
46
|
mcpTools: [
|
|
45
47
|
'vibecheck.get_truthpack',
|
|
46
|
-
'vibecheck.validate_claim',
|
|
47
48
|
'vibecheck.compile_context',
|
|
48
49
|
'vibecheck.search_evidence',
|
|
49
50
|
],
|
|
50
51
|
},
|
|
51
52
|
starter: {
|
|
52
53
|
name: 'STARTER',
|
|
53
|
-
price: 39,
|
|
54
|
+
price: 39,
|
|
54
55
|
order: 1,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// CI/CD
|
|
62
|
-
'gate', 'pr', 'badge', 'launch', 'dashboard_sync',
|
|
63
|
-
// Watch PR
|
|
64
|
-
'watch.pr',
|
|
65
|
-
// Report formats
|
|
66
|
-
'report.sarif_csv',
|
|
67
|
-
// Reality basic
|
|
68
|
-
'reality.basic',
|
|
69
|
-
// MCP read-only
|
|
70
|
-
'mcp', 'mcp.read_only',
|
|
71
|
-
// Ship full
|
|
72
|
-
'ship.full',
|
|
73
|
-
],
|
|
56
|
+
// Verdict authority - ADVISORY (verdicts not enforced)
|
|
57
|
+
verdictAuthority: 'ADVISORY',
|
|
58
|
+
canIssueVerdicts: true, // SHIP, WARN only
|
|
59
|
+
canEnforceCI: false, // Cannot block builds
|
|
60
|
+
canGenerateProof: false, // Cannot generate proof
|
|
61
|
+
// Limits
|
|
74
62
|
limits: {
|
|
75
|
-
scans: -1,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
fixApplyPatches: false,
|
|
80
|
-
mcpRateLimit: 60, // requests per minute
|
|
63
|
+
scans: -1, // Unlimited scans
|
|
64
|
+
realityMaxPages: -1, // Unlimited browser testing
|
|
65
|
+
realityMaxClicks: -1,
|
|
66
|
+
mcpRateLimit: 60,
|
|
81
67
|
},
|
|
82
|
-
// MCP tools allowed on STARTER (
|
|
68
|
+
// MCP tools allowed on STARTER (read + advisory actions)
|
|
83
69
|
mcpTools: [
|
|
84
70
|
'vibecheck.ctx',
|
|
85
71
|
'vibecheck.scan',
|
|
86
|
-
'vibecheck.ship',
|
|
72
|
+
'vibecheck.ship', // Advisory verdicts only
|
|
87
73
|
'vibecheck.get_truthpack',
|
|
88
74
|
'vibecheck.validate_claim',
|
|
89
75
|
'vibecheck.compile_context',
|
|
90
76
|
'vibecheck.search_evidence',
|
|
91
77
|
'vibecheck.find_counterexamples',
|
|
92
78
|
'vibecheck.check_invariants',
|
|
79
|
+
'vibecheck.fix', // Plan mode only
|
|
93
80
|
],
|
|
94
81
|
},
|
|
95
82
|
pro: {
|
|
96
83
|
name: 'PRO',
|
|
97
84
|
price: 99,
|
|
98
85
|
order: 2,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// Checkpoint advanced
|
|
106
|
-
'checkpoint.hallucination',
|
|
107
|
-
// Reality advanced
|
|
108
|
-
'reality.full', 'reality.advanced_auth_boundary',
|
|
109
|
-
// Premium
|
|
110
|
-
'replay', 'share', 'ai-test', 'permissions', 'graph',
|
|
111
|
-
// MCP full
|
|
112
|
-
'mcp.full',
|
|
113
|
-
],
|
|
86
|
+
// Verdict authority - ENFORCED (verdicts block CI/PRs)
|
|
87
|
+
verdictAuthority: 'ENFORCED',
|
|
88
|
+
canIssueVerdicts: true, // SHIP, WARN, BLOCK
|
|
89
|
+
canEnforceCI: true, // Can block builds
|
|
90
|
+
canGenerateProof: true, // Can generate cryptographic proof
|
|
91
|
+
// Limits
|
|
114
92
|
limits: {
|
|
115
|
-
scans: -1,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
fixApplyPatches: true,
|
|
120
|
-
mcpRateLimit: -1, // unlimited
|
|
93
|
+
scans: -1,
|
|
94
|
+
realityMaxPages: -1,
|
|
95
|
+
realityMaxClicks: -1,
|
|
96
|
+
mcpRateLimit: -1, // Unlimited
|
|
121
97
|
},
|
|
122
|
-
// MCP tools
|
|
123
|
-
mcpTools: [
|
|
124
|
-
'vibecheck.ctx',
|
|
125
|
-
'vibecheck.scan',
|
|
126
|
-
'vibecheck.ship',
|
|
127
|
-
'vibecheck.get_truthpack',
|
|
128
|
-
'vibecheck.validate_claim',
|
|
129
|
-
'vibecheck.compile_context',
|
|
130
|
-
'vibecheck.search_evidence',
|
|
131
|
-
'vibecheck.find_counterexamples',
|
|
132
|
-
'vibecheck.check_invariants',
|
|
133
|
-
],
|
|
98
|
+
// MCP tools - FULL ACCESS
|
|
99
|
+
mcpTools: ['*'], // All tools unlocked
|
|
134
100
|
},
|
|
135
|
-
|
|
136
|
-
name: '
|
|
137
|
-
price: 0, //
|
|
101
|
+
enterprise: {
|
|
102
|
+
name: 'ENTERPRISE',
|
|
103
|
+
price: 0, // Custom pricing
|
|
138
104
|
order: 3,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
105
|
+
// Verdict authority - ENFORCED + Compliance
|
|
106
|
+
verdictAuthority: 'ENFORCED',
|
|
107
|
+
canIssueVerdicts: true,
|
|
108
|
+
canEnforceCI: true,
|
|
109
|
+
canGenerateProof: true,
|
|
110
|
+
// Limits
|
|
143
111
|
limits: {
|
|
144
|
-
scans: -1,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
realityMaxClicks: -1,
|
|
148
|
-
fixApplyPatches: true,
|
|
112
|
+
scans: -1,
|
|
113
|
+
realityMaxPages: -1,
|
|
114
|
+
realityMaxClicks: -1,
|
|
149
115
|
mcpRateLimit: -1,
|
|
150
116
|
},
|
|
151
|
-
|
|
117
|
+
// MCP tools - FULL ACCESS + Compliance
|
|
118
|
+
mcpTools: ['*'],
|
|
152
119
|
}
|
|
153
120
|
};
|
|
154
121
|
|
|
122
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
123
|
+
// MCP TOOL → TIER MAPPING (Unified Authority System)
|
|
124
|
+
// Aligned with packages/core/src/features.ts
|
|
125
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
126
|
+
export const MCP_TOOL_TIERS = {
|
|
127
|
+
// FREE - Read-only context tools ONLY
|
|
128
|
+
// Free users may see problems, never resolve certainty
|
|
129
|
+
'vibecheck.get_truthpack': 'free',
|
|
130
|
+
'vibecheck.compile_context': 'free',
|
|
131
|
+
'vibecheck.search_evidence': 'free',
|
|
132
|
+
|
|
133
|
+
// STARTER - Advisory verdict authority
|
|
134
|
+
// Starter users may fix, but not prove
|
|
135
|
+
'vibecheck.ctx': 'starter',
|
|
136
|
+
'vibecheck.scan': 'starter',
|
|
137
|
+
'vibecheck.ship': 'starter', // SHIP/WARN (advisory, not enforced)
|
|
138
|
+
'vibecheck.fix': 'starter', // Plan mode only (no apply)
|
|
139
|
+
'vibecheck.validate_claim': 'starter',
|
|
140
|
+
'vibecheck.find_counterexamples': 'starter',
|
|
141
|
+
'vibecheck.check_invariants': 'starter',
|
|
142
|
+
'vibecheck.gate': 'starter', // Advisory gates
|
|
143
|
+
'vibecheck.badge': 'starter', // Unverified badges
|
|
144
|
+
|
|
145
|
+
// PRO - Full verdict authority & enforcement
|
|
146
|
+
// Pro users may enforce reality
|
|
147
|
+
'vibecheck.prove': 'pro', // Cryptographic proof generation
|
|
148
|
+
'vibecheck.fix.apply': 'pro', // Apply fixes
|
|
149
|
+
'vibecheck.fix.verify': 'pro', // Verify fixes with proof
|
|
150
|
+
'vibecheck.reality': 'pro', // Full browser testing
|
|
151
|
+
'vibecheck.reality.prove': 'pro', // Prove runtime behavior
|
|
152
|
+
'vibecheck.enforce': 'pro', // Enforce verdicts in CI
|
|
153
|
+
'vibecheck.ai_test': 'pro', // AI agent testing
|
|
154
|
+
'vibecheck.autopilot': 'pro', // Autonomous protection
|
|
155
|
+
'vibecheck.report': 'pro', // Advanced reporting
|
|
156
|
+
'vibecheck.allowlist': 'pro', // Manage allowlists
|
|
157
|
+
'vibecheck.status': 'pro', // Advanced status
|
|
158
|
+
};
|
|
159
|
+
|
|
155
160
|
/**
|
|
156
161
|
* Load user configuration from ~/.vibecheck/credentials.json
|
|
157
162
|
*/
|
|
@@ -169,25 +174,52 @@ async function loadUserConfig() {
|
|
|
169
174
|
* Determine tier from API key
|
|
170
175
|
* Matches CLI entitlements-v2.js logic
|
|
171
176
|
*/
|
|
172
|
-
function getTierFromApiKey(apiKey) {
|
|
173
|
-
if (!apiKey) return
|
|
177
|
+
async function getTierFromApiKey(apiKey) {
|
|
178
|
+
if (!apiKey) return null; // No API key = no access
|
|
174
179
|
|
|
175
180
|
// Check API key prefix patterns (matches CLI)
|
|
176
181
|
if (apiKey.startsWith('gr_starter_')) return 'starter';
|
|
177
182
|
if (apiKey.startsWith('gr_pro_')) return 'pro';
|
|
178
|
-
if (apiKey.startsWith('
|
|
183
|
+
if (apiKey.startsWith('gr_enterprise_') || apiKey.startsWith('gr_ent_')) return 'enterprise';
|
|
179
184
|
if (apiKey.startsWith('gr_free_')) return 'free';
|
|
180
185
|
|
|
181
|
-
// Try to
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
// Try to validate with API
|
|
187
|
+
try {
|
|
188
|
+
const response = await fetch('https://api.vibecheckai.dev/whoami', {
|
|
189
|
+
headers: {
|
|
190
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
191
|
+
'Content-Type': 'application/json',
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (!response.ok) {
|
|
196
|
+
return null; // Invalid API key
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const data = await response.json();
|
|
200
|
+
|
|
201
|
+
// Map API response to tier
|
|
202
|
+
switch (data.plan?.toLowerCase()) {
|
|
203
|
+
case 'starter':
|
|
204
|
+
return 'starter';
|
|
205
|
+
case 'pro':
|
|
206
|
+
return 'pro';
|
|
207
|
+
case 'enterprise':
|
|
208
|
+
return 'enterprise';
|
|
209
|
+
default:
|
|
210
|
+
return 'free';
|
|
211
|
+
}
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error('API validation failed:', error);
|
|
214
|
+
return null; // On error, deny access
|
|
215
|
+
}
|
|
216
|
+
} // default for unknown keys
|
|
185
217
|
|
|
186
218
|
/**
|
|
187
219
|
* Check if user has access to a specific feature
|
|
188
220
|
* Matches CLI entitlements-v2.js logic
|
|
189
221
|
*/
|
|
190
|
-
export async function
|
|
222
|
+
export async function getFeatureAccessStatus(featureName, providedApiKey = null) {
|
|
191
223
|
// Try to load user config
|
|
192
224
|
const userConfig = await loadUserConfig();
|
|
193
225
|
const apiKey = providedApiKey || userConfig?.apiKey;
|
|
@@ -195,13 +227,22 @@ export async function checkFeatureAccess(featureName, providedApiKey = null) {
|
|
|
195
227
|
if (!apiKey) {
|
|
196
228
|
return {
|
|
197
229
|
hasAccess: false,
|
|
198
|
-
tier:
|
|
199
|
-
reason: 'No API key provided.
|
|
230
|
+
tier: null,
|
|
231
|
+
reason: 'No API key provided. Please set your API key with `vibecheck login`.',
|
|
200
232
|
upgradeUrl: 'https://vibecheckai.dev'
|
|
201
233
|
};
|
|
202
234
|
}
|
|
203
235
|
|
|
204
|
-
const currentTier = getTierFromApiKey(apiKey);
|
|
236
|
+
const currentTier = await getTierFromApiKey(apiKey);
|
|
237
|
+
|
|
238
|
+
if (!currentTier) {
|
|
239
|
+
return {
|
|
240
|
+
hasAccess: false,
|
|
241
|
+
tier: null,
|
|
242
|
+
reason: 'Invalid API key. Please check your API key or get a new one at https://vibecheckai.dev',
|
|
243
|
+
upgradeUrl: 'https://vibecheckai.dev'
|
|
244
|
+
};
|
|
245
|
+
}
|
|
205
246
|
const currentTierConfig = TIERS[currentTier];
|
|
206
247
|
|
|
207
248
|
// Find which tier has this feature
|
|
@@ -273,11 +314,30 @@ export function withTierCheck(featureName, handler) {
|
|
|
273
314
|
* Check if user has access to a specific MCP tool
|
|
274
315
|
* MCP tools have specific tier requirements separate from CLI features
|
|
275
316
|
*/
|
|
276
|
-
export async function
|
|
317
|
+
export async function getMcpToolAccess(toolName, providedApiKey = null) {
|
|
277
318
|
const userConfig = await loadUserConfig();
|
|
278
319
|
const apiKey = providedApiKey || userConfig?.apiKey;
|
|
279
320
|
|
|
280
|
-
|
|
321
|
+
if (!apiKey) {
|
|
322
|
+
return {
|
|
323
|
+
hasAccess: false,
|
|
324
|
+
tier: null,
|
|
325
|
+
reason: 'No API key provided. Please set your API key with `vibecheck login`.',
|
|
326
|
+
upgradeUrl: 'https://vibecheckai.dev'
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const currentTier = await getTierFromApiKey(apiKey);
|
|
331
|
+
|
|
332
|
+
if (!currentTier) {
|
|
333
|
+
return {
|
|
334
|
+
hasAccess: false,
|
|
335
|
+
tier: null,
|
|
336
|
+
reason: 'Invalid API key. Please check your API key or get a new one at https://vibecheckai.dev',
|
|
337
|
+
upgradeUrl: 'https://vibecheckai.dev'
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
281
341
|
const currentTierConfig = TIERS[currentTier];
|
|
282
342
|
|
|
283
343
|
// Check if tool is allowed for current tier
|