@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.
Files changed (123) hide show
  1. package/bin/.generated +25 -25
  2. package/bin/dev/run-v2-torture.js +30 -30
  3. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
  4. package/bin/runners/lib/api-client.js +269 -0
  5. package/bin/runners/lib/auth-truth.js +193 -193
  6. package/bin/runners/lib/backup.js +62 -62
  7. package/bin/runners/lib/billing.js +107 -107
  8. package/bin/runners/lib/claims.js +118 -118
  9. package/bin/runners/lib/cli-ui.js +540 -540
  10. package/bin/runners/lib/contracts/auth-contract.js +202 -202
  11. package/bin/runners/lib/contracts/env-contract.js +181 -181
  12. package/bin/runners/lib/contracts/external-contract.js +206 -206
  13. package/bin/runners/lib/contracts/guard.js +168 -168
  14. package/bin/runners/lib/contracts/index.js +89 -89
  15. package/bin/runners/lib/contracts/plan-validator.js +311 -311
  16. package/bin/runners/lib/contracts/route-contract.js +199 -199
  17. package/bin/runners/lib/contracts.js +804 -804
  18. package/bin/runners/lib/detect.js +89 -89
  19. package/bin/runners/lib/doctor/autofix.js +254 -254
  20. package/bin/runners/lib/doctor/index.js +37 -37
  21. package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
  22. package/bin/runners/lib/doctor/modules/index.js +46 -46
  23. package/bin/runners/lib/doctor/modules/network.js +250 -250
  24. package/bin/runners/lib/doctor/modules/project.js +312 -312
  25. package/bin/runners/lib/doctor/modules/runtime.js +224 -224
  26. package/bin/runners/lib/doctor/modules/security.js +348 -348
  27. package/bin/runners/lib/doctor/modules/system.js +213 -213
  28. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
  29. package/bin/runners/lib/doctor/reporter.js +262 -262
  30. package/bin/runners/lib/doctor/service.js +262 -262
  31. package/bin/runners/lib/doctor/types.js +113 -113
  32. package/bin/runners/lib/doctor/ui.js +263 -263
  33. package/bin/runners/lib/doctor-v2.js +608 -608
  34. package/bin/runners/lib/drift.js +425 -425
  35. package/bin/runners/lib/enforcement.js +72 -72
  36. package/bin/runners/lib/enterprise-detect.js +603 -603
  37. package/bin/runners/lib/enterprise-init.js +942 -942
  38. package/bin/runners/lib/env-resolver.js +417 -417
  39. package/bin/runners/lib/env-template.js +66 -66
  40. package/bin/runners/lib/env.js +189 -189
  41. package/bin/runners/lib/extractors/client-calls.js +990 -990
  42. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
  43. package/bin/runners/lib/extractors/fastify-routes.js +426 -426
  44. package/bin/runners/lib/extractors/index.js +363 -363
  45. package/bin/runners/lib/extractors/next-routes.js +524 -524
  46. package/bin/runners/lib/extractors/proof-graph.js +431 -431
  47. package/bin/runners/lib/extractors/route-matcher.js +451 -451
  48. package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
  49. package/bin/runners/lib/extractors/ui-bindings.js +547 -547
  50. package/bin/runners/lib/findings-schema.js +281 -281
  51. package/bin/runners/lib/firewall-prompt.js +50 -50
  52. package/bin/runners/lib/graph/graph-builder.js +265 -265
  53. package/bin/runners/lib/graph/html-renderer.js +413 -413
  54. package/bin/runners/lib/graph/index.js +32 -32
  55. package/bin/runners/lib/graph/runtime-collector.js +215 -215
  56. package/bin/runners/lib/graph/static-extractor.js +518 -518
  57. package/bin/runners/lib/html-report.js +650 -650
  58. package/bin/runners/lib/llm.js +75 -75
  59. package/bin/runners/lib/meter.js +61 -61
  60. package/bin/runners/lib/missions/evidence.js +126 -126
  61. package/bin/runners/lib/patch.js +40 -40
  62. package/bin/runners/lib/permissions/auth-model.js +213 -213
  63. package/bin/runners/lib/permissions/idor-prover.js +205 -205
  64. package/bin/runners/lib/permissions/index.js +45 -45
  65. package/bin/runners/lib/permissions/matrix-builder.js +198 -198
  66. package/bin/runners/lib/pkgjson.js +28 -28
  67. package/bin/runners/lib/policy.js +295 -295
  68. package/bin/runners/lib/preflight.js +142 -142
  69. package/bin/runners/lib/reality/correlation-detectors.js +359 -359
  70. package/bin/runners/lib/reality/index.js +318 -318
  71. package/bin/runners/lib/reality/request-hashing.js +416 -416
  72. package/bin/runners/lib/reality/request-mapper.js +453 -453
  73. package/bin/runners/lib/reality/safety-rails.js +463 -463
  74. package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
  75. package/bin/runners/lib/reality/toast-detector.js +393 -393
  76. package/bin/runners/lib/reality-findings.js +84 -84
  77. package/bin/runners/lib/receipts.js +179 -179
  78. package/bin/runners/lib/redact.js +29 -29
  79. package/bin/runners/lib/replay/capsule-manager.js +154 -154
  80. package/bin/runners/lib/replay/index.js +263 -263
  81. package/bin/runners/lib/replay/player.js +348 -348
  82. package/bin/runners/lib/replay/recorder.js +331 -331
  83. package/bin/runners/lib/report.js +135 -135
  84. package/bin/runners/lib/route-detection.js +1140 -1140
  85. package/bin/runners/lib/sandbox/index.js +59 -59
  86. package/bin/runners/lib/sandbox/proof-chain.js +399 -399
  87. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
  88. package/bin/runners/lib/sandbox/worktree.js +174 -174
  89. package/bin/runners/lib/schema-validator.js +350 -350
  90. package/bin/runners/lib/schemas/contracts.schema.json +160 -160
  91. package/bin/runners/lib/schemas/finding.schema.json +100 -100
  92. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
  93. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
  94. package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
  95. package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
  96. package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
  97. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
  98. package/bin/runners/lib/schemas/validator.js +438 -438
  99. package/bin/runners/lib/score-history.js +282 -282
  100. package/bin/runners/lib/share-pack.js +239 -239
  101. package/bin/runners/lib/snippets.js +67 -67
  102. package/bin/runners/lib/upsell.js +510 -510
  103. package/bin/runners/lib/usage.js +153 -153
  104. package/bin/runners/lib/validate-patch.js +156 -156
  105. package/bin/runners/lib/verdict-engine.js +628 -628
  106. package/bin/runners/reality/engine.js +917 -917
  107. package/bin/runners/reality/flows.js +122 -122
  108. package/bin/runners/reality/report.js +378 -378
  109. package/bin/runners/reality/session.js +193 -193
  110. package/bin/runners/runAgent.d.ts +5 -0
  111. package/bin/runners/runFirewall.d.ts +5 -0
  112. package/bin/runners/runFirewallHook.d.ts +5 -0
  113. package/bin/runners/runGuard.js +168 -168
  114. package/bin/runners/runScan.js +82 -0
  115. package/bin/runners/runTruth.d.ts +5 -0
  116. package/bin/vibecheck.js +45 -20
  117. package/mcp-server/index.js +85 -0
  118. package/mcp-server/lib/api-client.js +269 -0
  119. package/mcp-server/package.json +1 -1
  120. package/mcp-server/tier-auth.js +173 -113
  121. package/mcp-server/tools/index.js +72 -72
  122. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  123. 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
+ };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibecheck-mcp-server",
3
- "version": "3.1.8",
3
+ "version": "3.2.6",
4
4
  "description": "Professional MCP server for vibecheck - Intelligent development environment vibechecks",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -1,157 +1,162 @@
1
1
  /**
2
2
  * MCP Server Tier Authentication & Authorization
3
3
  *
4
- * Provides tier checking for MCP tools based on API keys
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
- // Tier definitions - MUST MATCH CLI entitlements-v2.js
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
- features: [
18
- // Core commands
19
- 'scan', 'ship', 'ship.static',
20
- // Setup
21
- 'init', 'init.local', 'doctor', 'status', 'install', 'preflight', 'watch', 'watch.local',
22
- // AI Truth
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: 50,
37
- shipChecks: 20,
40
+ scans: -1, // Unlimited scans
38
41
  realityMaxPages: 5,
39
42
  realityMaxClicks: 20,
40
- fixApplyPatches: false,
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, // Updated pricing
54
+ price: 39,
54
55
  order: 1,
55
- features: [
56
- // All FREE features plus...
57
- // Init connect
58
- 'init.connect',
59
- // Scan autofix
60
- 'scan.autofix',
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
- shipChecks: -1,
77
- realityMaxPages: 50,
78
- realityMaxClicks: 200,
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 (curated)
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
- features: [
100
- // All STARTER features plus...
101
- // Prove
102
- 'prove',
103
- // Fix apply
104
- 'fix.apply_patches', 'fix.loop',
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
- shipChecks: -1,
117
- realityMaxPages: -1,
118
- realityMaxClicks: -1,
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 allowed on PRO (curated)
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
- compliance: {
136
- name: 'COMPLIANCE',
137
- price: 0, // Enterprise/on-prem
101
+ enterprise: {
102
+ name: 'ENTERPRISE',
103
+ price: 0, // Custom pricing
138
104
  order: 3,
139
- features: [
140
- // All PRO features plus...
141
- 'report.compliance_packs',
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
- shipChecks: -1,
146
- realityMaxPages: -1,
147
- realityMaxClicks: -1,
148
- fixApplyPatches: true,
112
+ scans: -1,
113
+ realityMaxPages: -1,
114
+ realityMaxClicks: -1,
149
115
  mcpRateLimit: -1,
150
116
  },
151
- mcpTools: ['*'], // All tools
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 'free';
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('gr_compliance_') || apiKey.startsWith('gr_ent_')) return 'compliance';
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 fetch from API (same as CLI)
182
- // For now, default to free - API lookup would happen in production
183
- return 'free'; // default for unknown keys
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 checkFeatureAccess(featureName, providedApiKey = null) {
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: 'free',
199
- reason: 'No API key provided. Run: vibecheck auth --key YOUR_API_KEY',
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 checkMcpToolAccess(toolName, providedApiKey = null) {
317
+ export async function getMcpToolAccess(toolName, providedApiKey = null) {
277
318
  const userConfig = await loadUserConfig();
278
319
  const apiKey = providedApiKey || userConfig?.apiKey;
279
320
 
280
- const currentTier = getTierFromApiKey(apiKey);
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