@vibecheckai/cli 3.5.0 → 3.5.2

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 (224) hide show
  1. package/bin/registry.js +214 -237
  2. package/bin/runners/cli-utils.js +33 -2
  3. package/bin/runners/context/analyzer.js +52 -1
  4. package/bin/runners/context/generators/cursor.js +2 -49
  5. package/bin/runners/context/git-context.js +3 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/analysis-core.js +25 -5
  8. package/bin/runners/lib/analyzers.js +431 -481
  9. package/bin/runners/lib/default-config.js +127 -0
  10. package/bin/runners/lib/doctor/modules/security.js +3 -1
  11. package/bin/runners/lib/engine/ast-cache.js +210 -0
  12. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  13. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  14. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  15. package/bin/runners/lib/engine/env-extractor.js +207 -0
  16. package/bin/runners/lib/engine/express-extractor.js +208 -0
  17. package/bin/runners/lib/engine/extractors.js +849 -0
  18. package/bin/runners/lib/engine/index.js +207 -0
  19. package/bin/runners/lib/engine/repo-index.js +514 -0
  20. package/bin/runners/lib/engine/types.js +124 -0
  21. package/bin/runners/lib/engines/accessibility-engine.js +18 -218
  22. package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
  23. package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
  24. package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
  25. package/bin/runners/lib/engines/mock-data-engine.js +10 -53
  26. package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
  27. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
  28. package/bin/runners/lib/engines/type-aware-engine.js +39 -263
  29. package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
  30. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  31. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  32. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  33. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  34. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  35. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  36. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  37. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
  38. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  39. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  40. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  41. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  42. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  43. package/bin/runners/lib/entitlements-v2.js +73 -97
  44. package/bin/runners/lib/error-handler.js +44 -3
  45. package/bin/runners/lib/error-messages.js +289 -0
  46. package/bin/runners/lib/evidence-pack.js +7 -1
  47. package/bin/runners/lib/finding-id.js +69 -0
  48. package/bin/runners/lib/finding-sorter.js +89 -0
  49. package/bin/runners/lib/html-proof-report.js +700 -350
  50. package/bin/runners/lib/missions/plan.js +6 -46
  51. package/bin/runners/lib/missions/templates.js +0 -232
  52. package/bin/runners/lib/next-action.js +560 -0
  53. package/bin/runners/lib/prerequisites.js +149 -0
  54. package/bin/runners/lib/route-detection.js +137 -68
  55. package/bin/runners/lib/scan-output.js +91 -76
  56. package/bin/runners/lib/scan-runner.js +135 -0
  57. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  58. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  59. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  60. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  61. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  62. package/bin/runners/lib/schemas/validator.js +27 -0
  63. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  64. package/bin/runners/lib/ship-output-enterprise.js +23 -23
  65. package/bin/runners/lib/ship-output.js +75 -31
  66. package/bin/runners/lib/terminal-ui.js +6 -113
  67. package/bin/runners/lib/truth.js +351 -10
  68. package/bin/runners/lib/unified-cli-output.js +430 -603
  69. package/bin/runners/lib/unified-output.js +13 -9
  70. package/bin/runners/runAIAgent.js +10 -5
  71. package/bin/runners/runAgent.js +0 -3
  72. package/bin/runners/runAllowlist.js +389 -0
  73. package/bin/runners/runApprove.js +0 -33
  74. package/bin/runners/runAuth.js +73 -45
  75. package/bin/runners/runCheckpoint.js +51 -11
  76. package/bin/runners/runClassify.js +85 -21
  77. package/bin/runners/runContext.js +0 -3
  78. package/bin/runners/runDoctor.js +41 -28
  79. package/bin/runners/runEvidencePack.js +362 -0
  80. package/bin/runners/runFirewall.js +0 -3
  81. package/bin/runners/runFirewallHook.js +0 -3
  82. package/bin/runners/runFix.js +66 -76
  83. package/bin/runners/runGuard.js +18 -411
  84. package/bin/runners/runInit.js +113 -30
  85. package/bin/runners/runLabs.js +424 -0
  86. package/bin/runners/runMcp.js +19 -25
  87. package/bin/runners/runPolish.js +64 -240
  88. package/bin/runners/runPromptFirewall.js +12 -5
  89. package/bin/runners/runProve.js +57 -22
  90. package/bin/runners/runQuickstart.js +531 -0
  91. package/bin/runners/runReality.js +59 -68
  92. package/bin/runners/runReport.js +38 -33
  93. package/bin/runners/runRuntime.js +8 -5
  94. package/bin/runners/runScan.js +1413 -190
  95. package/bin/runners/runShip.js +113 -719
  96. package/bin/runners/runTruth.js +0 -3
  97. package/bin/runners/runValidate.js +13 -9
  98. package/bin/runners/runWatch.js +23 -14
  99. package/bin/scan.js +6 -1
  100. package/bin/vibecheck.js +204 -185
  101. package/mcp-server/deprecation-middleware.js +282 -0
  102. package/mcp-server/handlers/index.ts +15 -0
  103. package/mcp-server/handlers/tool-handler.ts +554 -0
  104. package/mcp-server/index-v1.js +698 -0
  105. package/mcp-server/index.js +210 -238
  106. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  107. package/mcp-server/lib/error-envelope.js +138 -0
  108. package/mcp-server/lib/executor.ts +499 -0
  109. package/mcp-server/lib/index.ts +19 -0
  110. package/mcp-server/lib/rate-limiter.js +166 -0
  111. package/mcp-server/lib/sandbox.test.ts +519 -0
  112. package/mcp-server/lib/sandbox.ts +395 -0
  113. package/mcp-server/lib/types.ts +267 -0
  114. package/mcp-server/package.json +12 -3
  115. package/mcp-server/registry/tool-registry.js +794 -0
  116. package/mcp-server/registry/tools.json +605 -0
  117. package/mcp-server/registry.test.ts +334 -0
  118. package/mcp-server/tests/tier-gating.test.js +297 -0
  119. package/mcp-server/tier-auth.js +378 -45
  120. package/mcp-server/tools-v3.js +353 -442
  121. package/mcp-server/tsconfig.json +37 -0
  122. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  123. package/package.json +1 -1
  124. package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
  125. package/bin/runners/lib/audit-logger.js +0 -532
  126. package/bin/runners/lib/authority/authorities/architecture.js +0 -364
  127. package/bin/runners/lib/authority/authorities/compliance.js +0 -341
  128. package/bin/runners/lib/authority/authorities/human.js +0 -343
  129. package/bin/runners/lib/authority/authorities/quality.js +0 -420
  130. package/bin/runners/lib/authority/authorities/security.js +0 -228
  131. package/bin/runners/lib/authority/index.js +0 -293
  132. package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
  133. package/bin/runners/lib/cli-charts.js +0 -368
  134. package/bin/runners/lib/cli-config-display.js +0 -405
  135. package/bin/runners/lib/cli-demo.js +0 -275
  136. package/bin/runners/lib/cli-errors.js +0 -438
  137. package/bin/runners/lib/cli-help-formatter.js +0 -439
  138. package/bin/runners/lib/cli-interactive-menu.js +0 -509
  139. package/bin/runners/lib/cli-prompts.js +0 -441
  140. package/bin/runners/lib/cli-scan-cards.js +0 -362
  141. package/bin/runners/lib/compliance-reporter.js +0 -710
  142. package/bin/runners/lib/conductor/index.js +0 -671
  143. package/bin/runners/lib/easy/README.md +0 -123
  144. package/bin/runners/lib/easy/index.js +0 -140
  145. package/bin/runners/lib/easy/interactive-wizard.js +0 -788
  146. package/bin/runners/lib/easy/one-click-firewall.js +0 -564
  147. package/bin/runners/lib/easy/zero-config-reality.js +0 -714
  148. package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
  149. package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
  150. package/bin/runners/lib/engines/confidence-scoring.js +0 -276
  151. package/bin/runners/lib/engines/context-detection.js +0 -264
  152. package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
  153. package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
  154. package/bin/runners/lib/engines/env-variables-engine.js +0 -458
  155. package/bin/runners/lib/engines/error-handling-engine.js +0 -437
  156. package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
  157. package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
  158. package/bin/runners/lib/engines/framework-detection.js +0 -508
  159. package/bin/runners/lib/engines/import-order-engine.js +0 -429
  160. package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
  161. package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
  162. package/bin/runners/lib/engines/orchestrator.js +0 -334
  163. package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
  164. package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
  165. package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
  166. package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
  167. package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
  168. package/bin/runners/lib/enhanced-features/index.js +0 -305
  169. package/bin/runners/lib/enhanced-output.js +0 -631
  170. package/bin/runners/lib/enterprise.js +0 -300
  171. package/bin/runners/lib/firewall/command-validator.js +0 -351
  172. package/bin/runners/lib/firewall/config.js +0 -341
  173. package/bin/runners/lib/firewall/content-validator.js +0 -519
  174. package/bin/runners/lib/firewall/index.js +0 -101
  175. package/bin/runners/lib/firewall/path-validator.js +0 -256
  176. package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
  177. package/bin/runners/lib/mcp-utils.js +0 -425
  178. package/bin/runners/lib/output/index.js +0 -1022
  179. package/bin/runners/lib/policy-engine.js +0 -652
  180. package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
  181. package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
  182. package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
  183. package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
  184. package/bin/runners/lib/polish/autofix/index.js +0 -200
  185. package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
  186. package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
  187. package/bin/runners/lib/polish/backend-checks.js +0 -148
  188. package/bin/runners/lib/polish/documentation-checks.js +0 -111
  189. package/bin/runners/lib/polish/frontend-checks.js +0 -168
  190. package/bin/runners/lib/polish/index.js +0 -71
  191. package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
  192. package/bin/runners/lib/polish/library-detection.js +0 -175
  193. package/bin/runners/lib/polish/performance-checks.js +0 -100
  194. package/bin/runners/lib/polish/security-checks.js +0 -148
  195. package/bin/runners/lib/polish/utils.js +0 -203
  196. package/bin/runners/lib/prompt-builder.js +0 -540
  197. package/bin/runners/lib/proof-certificate.js +0 -634
  198. package/bin/runners/lib/reality/accessibility-audit.js +0 -946
  199. package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
  200. package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
  201. package/bin/runners/lib/reality/performance-tracker.js +0 -1077
  202. package/bin/runners/lib/reality/scenario-generator.js +0 -1404
  203. package/bin/runners/lib/reality/visual-regression.js +0 -852
  204. package/bin/runners/lib/reality-profiler.js +0 -717
  205. package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
  206. package/bin/runners/lib/review/ai-code-review.js +0 -832
  207. package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
  208. package/bin/runners/lib/sbom-generator.js +0 -641
  209. package/bin/runners/lib/scan-output-enhanced.js +0 -512
  210. package/bin/runners/lib/security/owasp-scanner.js +0 -939
  211. package/bin/runners/lib/validators/contract-validator.js +0 -283
  212. package/bin/runners/lib/validators/dead-export-detector.js +0 -279
  213. package/bin/runners/lib/validators/dep-audit.js +0 -245
  214. package/bin/runners/lib/validators/env-validator.js +0 -319
  215. package/bin/runners/lib/validators/index.js +0 -120
  216. package/bin/runners/lib/validators/license-checker.js +0 -252
  217. package/bin/runners/lib/validators/route-validator.js +0 -290
  218. package/bin/runners/runAuthority.js +0 -528
  219. package/bin/runners/runConductor.js +0 -772
  220. package/bin/runners/runContainer.js +0 -366
  221. package/bin/runners/runEasy.js +0 -410
  222. package/bin/runners/runIaC.js +0 -372
  223. package/bin/runners/runVibe.js +0 -791
  224. package/mcp-server/tools.js +0 -495
@@ -1,14 +1,42 @@
1
1
  /**
2
2
  * MCP Server Tier Authentication
3
3
  *
4
+ * ═══════════════════════════════════════════════════════════════════════════
5
+ * TIER MODEL - Aligned with CLI entitlements-v2.js
6
+ * ═══════════════════════════════════════════════════════════════════════════
7
+ *
4
8
  * Simple 2-tier model:
5
9
  * - FREE ($0): Inspect & Observe
6
10
  * - PRO ($69/mo): Fix, Prove & Enforce
7
11
  *
8
- * PRO includes:
9
- * - Authority System (verdicts, approvals)
10
- * - Agent Conductor (multi-agent coordination)
11
- * - Agent Firewall (enforce mode)
12
+ * ┌────────────────────────────────────────────────────────────────────────┐
13
+ * MCP Tool │ Tier │ CLI Equivalent │
14
+ * ├────────────────────────────────────────────────────────────────────────┤
15
+ * vibecheck.scan │ FREE scan │
16
+ * │ vibecheck.scan (--autofix) │ PRO │ scan.autofix │
17
+ * │ vibecheck.ctx │ FREE │ ctx │
18
+ * │ vibecheck.verify │ FREE │ verify │
19
+ * │ vibecheck.report │ FREE │ report │
20
+ * │ vibecheck.status │ FREE │ status │
21
+ * │ vibecheck.doctor │ FREE │ doctor │
22
+ * │ vibecheck.firewall (observe) │ FREE │ firewall.observe │
23
+ * │ vibecheck.firewall (enforce) │ PRO │ firewall.enforce │
24
+ * │ vibecheck.ship │ PRO │ ship │
25
+ * │ vibecheck.fix │ PRO │ fix │
26
+ * │ vibecheck.fix (--apply) │ PRO │ fix.apply │
27
+ * │ vibecheck.prove │ PRO │ prove │
28
+ * │ vibecheck.gate │ PRO │ gate │
29
+ * │ vibecheck.badge │ PRO │ badge │
30
+ * │ vibecheck.reality │ PRO │ reality.full │
31
+ * │ vibecheck.ai_test │ PRO │ ai-test │
32
+ * │ vibecheck.share │ PRO │ share │
33
+ * │ authority.list │ FREE │ (read-only authority) │
34
+ * │ authority.classify │ FREE │ (inventory analysis) │
35
+ * │ authority.approve │ PRO │ (execute authority) │
36
+ * │ vibecheck_conductor_status │ FREE │ (status only) │
37
+ * │ vibecheck_conductor_* │ PRO │ (full coordination) │
38
+ * │ vibecheck_agent_firewall_* │ PRO │ (enforce mode) │
39
+ * └────────────────────────────────────────────────────────────────────────┘
12
40
  */
13
41
 
14
42
  import fs from "fs/promises";
@@ -16,7 +44,17 @@ import path from "path";
16
44
  import os from "os";
17
45
 
18
46
  // ============================================================================
19
- // TIERS
47
+ // ERROR CODES - Standard error envelope codes
48
+ // ============================================================================
49
+ export const ERROR_CODES = {
50
+ NOT_ENTITLED: 'NOT_ENTITLED',
51
+ INVALID_API_KEY: 'INVALID_API_KEY',
52
+ RATE_LIMITED: 'RATE_LIMITED',
53
+ OPTION_NOT_ENTITLED: 'OPTION_NOT_ENTITLED',
54
+ };
55
+
56
+ // ============================================================================
57
+ // TIERS - Simple 2-tier model matching CLI
20
58
  // ============================================================================
21
59
  export const TIERS = {
22
60
  free: { name: 'FREE', price: 0 },
@@ -24,43 +62,68 @@ export const TIERS = {
24
62
  };
25
63
 
26
64
  // ============================================================================
27
- // MCP TOOLS - 15 Core + PRO Features
65
+ // MCP TOOLS - Aligned with CLI entitlements-v2.js
28
66
  // ============================================================================
29
67
 
30
68
  /**
31
- * FREE TOOLS (7) - Inspect & Observe
69
+ * FREE TOOLS - Inspect & Observe
70
+ * Matches CLI FREE_FEATURES: scan, ctx, verify, report, status, doctor, etc.
32
71
  */
33
72
  export const FREE_TOOLS = [
34
- // Core FREE tools
73
+ // Core analysis (CLI: scan, ctx, verify)
35
74
  'vibecheck.scan',
36
75
  'vibecheck.ctx',
37
76
  'vibecheck.verify',
77
+
78
+ // Reports & setup (CLI: report, status, doctor)
38
79
  'vibecheck.report',
39
80
  'vibecheck.status',
40
81
  'vibecheck.doctor',
41
- 'vibecheck.firewall', // Observe mode only
82
+
83
+ // Firewall observe mode (CLI: firewall.observe)
84
+ 'vibecheck.firewall',
85
+
42
86
  // Authority (read-only)
43
87
  'authority.list',
44
88
  'authority.classify',
89
+
45
90
  // Conductor (status only)
46
91
  'vibecheck_conductor_status',
92
+
93
+ // Labs & experimental (CLI: labs, mdc)
94
+ 'vibecheck.labs',
95
+ 'vibecheck.mdc',
96
+
97
+ // Allowlist management
98
+ 'vibecheck.allowlist',
99
+
100
+ // Context generation (basic - CLI: ctx)
101
+ 'vibecheck.context',
102
+
103
+ // Next action recommendation
104
+ 'vibecheck.get_next_action',
47
105
  ];
48
106
 
49
107
  /**
50
- * PRO TOOLS (8 Core + Authority + Conductor + Firewall) - Fix, Prove & Enforce
108
+ * PRO TOOLS - Fix, Prove & Enforce
109
+ * Matches CLI PRO_FEATURES: ship, fix, prove, gate, badge, etc.
51
110
  */
52
111
  export const PRO_TOOLS = [
53
- // Core PRO tools
112
+ // Core PRO (CLI: ship, fix, prove, gate, badge)
54
113
  'vibecheck.ship',
55
114
  'vibecheck.fix',
56
115
  'vibecheck.prove',
57
116
  'vibecheck.gate',
58
117
  'vibecheck.badge',
118
+
119
+ // Runtime verification (CLI: reality.full, ai-test)
59
120
  'vibecheck.reality',
60
121
  'vibecheck.ai_test',
122
+
123
+ // Sharing & PR (CLI: share, pr)
61
124
  'vibecheck.share',
62
125
 
63
- // Authority System (full)
126
+ // Authority System (full - execute verdicts)
64
127
  'authority.approve',
65
128
  'authority.enforce',
66
129
 
@@ -71,31 +134,158 @@ export const PRO_TOOLS = [
71
134
  'vibecheck_conductor_propose',
72
135
  'vibecheck_conductor_terminate',
73
136
 
74
- // Agent Firewall (enforce mode)
137
+ // Agent Firewall (enforce mode - CLI: firewall.enforce)
75
138
  'vibecheck_agent_firewall_intercept',
76
139
  'vibecheck.firewall.enforce',
140
+
141
+ // Advanced features (CLI: checkpoint, polish, guard)
142
+ 'vibecheck.checkpoint',
143
+ 'vibecheck.polish',
144
+ 'vibecheck.guard',
77
145
  ];
78
146
 
79
147
  export const ALL_TOOLS = [...FREE_TOOLS, ...PRO_TOOLS];
80
148
 
149
+ /**
150
+ * OPTION-LEVEL GATES
151
+ * Some tools are FREE at base level but specific options require PRO
152
+ */
153
+ export const OPTION_GATES = {
154
+ 'vibecheck.scan': {
155
+ autofix: 'pro', // scan --autofix requires PRO
156
+ fix: 'pro', // scan --fix requires PRO
157
+ },
158
+ 'vibecheck.fix': {
159
+ apply: 'pro', // fix --apply requires PRO (plan is PRO too)
160
+ loop: 'pro', // fix --loop requires PRO
161
+ },
162
+ 'vibecheck.firewall': {
163
+ enforce: 'pro', // firewall --enforce requires PRO
164
+ mode: { enforce: 'pro' },
165
+ },
166
+ 'vibecheck.reality': {
167
+ full: 'pro', // reality full mode requires PRO
168
+ auth: 'pro', // auth boundary testing requires PRO
169
+ },
170
+ };
171
+
81
172
  // ============================================================================
82
173
  // TIER CACHE
83
174
  // ============================================================================
84
175
  const tierCache = new Map();
85
176
  const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
86
177
 
178
+ /**
179
+ * Check if developer mode bypass is allowed.
180
+ *
181
+ * SECURITY: VIBECHECK_DEV_PRO is ONLY allowed in non-production environments.
182
+ * This prevents environment variable injection from granting PRO access in production.
183
+ *
184
+ * @returns {{ enabled: boolean, tier?: string }} Dev override status
185
+ */
186
+ export function getDevModeOverride() {
187
+ // SECURITY: Never allow dev override in production
188
+ if (process.env.NODE_ENV === 'production') {
189
+ return { enabled: false };
190
+ }
191
+ // Also block in CI environments to prevent pipeline exploitation
192
+ if (process.env.CI === 'true' || process.env.CI === '1') {
193
+ return { enabled: false };
194
+ }
195
+ // Only in development with explicit flag
196
+ if (process.env.VIBECHECK_DEV_PRO === '1' && process.env.NODE_ENV === 'development') {
197
+ console.warn('[DEV] VIBECHECK_DEV_PRO override active - PRO features unlocked');
198
+ return { enabled: true, tier: 'pro' };
199
+ }
200
+ return { enabled: false };
201
+ }
202
+
203
+ /**
204
+ * Check if developer mode bypass is allowed (legacy function for backward compatibility)
205
+ * @returns {boolean} True only if in development AND VIBECHECK_DEV_PRO=1
206
+ */
207
+ function isDevProBypassAllowed() {
208
+ return getDevModeOverride().enabled;
209
+ }
210
+
87
211
  function hashKey(apiKey) {
88
212
  const crypto = require('crypto');
89
213
  return crypto.createHash('sha256').update(apiKey).digest('hex').slice(0, 16);
90
214
  }
91
215
 
216
+ // ============================================================================
217
+ // ERROR ENVELOPE - Standard format for tier errors
218
+ // ============================================================================
219
+
220
+ /**
221
+ * Create a standard ErrorEnvelope for tier-related errors
222
+ * @param {string} code - Error code (NOT_ENTITLED, INVALID_API_KEY, etc.)
223
+ * @param {string} message - Human-readable error message
224
+ * @param {object} extra - Additional properties
225
+ * @returns {object} ErrorEnvelope
226
+ */
227
+ export function createTierErrorEnvelope(code, message, extra = {}) {
228
+ return {
229
+ code,
230
+ message,
231
+ userAction: extra.userAction || 'Open billing',
232
+ retryable: extra.retryable ?? false,
233
+ tier: extra.tier,
234
+ required: extra.required,
235
+ upgradeUrl: 'https://vibecheckai.dev/pricing',
236
+ ...extra,
237
+ };
238
+ }
239
+
240
+ /**
241
+ * Create NOT_ENTITLED error envelope
242
+ */
243
+ export function notEntitledError(toolName, currentTier = 'free', requiredTier = 'pro') {
244
+ return createTierErrorEnvelope(ERROR_CODES.NOT_ENTITLED, `Requires ${requiredTier.toUpperCase()}`, {
245
+ tier: currentTier,
246
+ required: requiredTier,
247
+ tool: toolName,
248
+ userAction: 'Open billing',
249
+ retryable: false,
250
+ nextSteps: [
251
+ `Upgrade to ${requiredTier.toUpperCase()} ($69/mo) to unlock this feature`,
252
+ 'Visit https://vibecheckai.dev/pricing',
253
+ 'Run: vibecheck upgrade',
254
+ ],
255
+ });
256
+ }
257
+
258
+ /**
259
+ * Create OPTION_NOT_ENTITLED error envelope
260
+ */
261
+ export function optionNotEntitledError(toolName, option, currentTier = 'free', requiredTier = 'pro') {
262
+ return createTierErrorEnvelope(ERROR_CODES.OPTION_NOT_ENTITLED, `Option --${option} requires ${requiredTier.toUpperCase()}`, {
263
+ tier: currentTier,
264
+ required: requiredTier,
265
+ tool: toolName,
266
+ option,
267
+ userAction: 'Open billing',
268
+ retryable: false,
269
+ nextSteps: [
270
+ `The --${option} flag requires ${requiredTier.toUpperCase()} subscription`,
271
+ `Base ${toolName} is available on FREE tier`,
272
+ 'Visit https://vibecheckai.dev/pricing to upgrade',
273
+ ],
274
+ });
275
+ }
276
+
92
277
  // ============================================================================
93
278
  // TIER VALIDATION
94
279
  // ============================================================================
95
280
 
96
281
  export async function getTierFromApiKey(apiKey) {
282
+ // Developer mode bypass (blocked in production)
283
+ if (isDevProBypassAllowed()) {
284
+ return 'pro';
285
+ }
286
+
97
287
  if (!apiKey || typeof apiKey !== 'string' || apiKey.length < 10) {
98
- return null;
288
+ return 'free'; // No API key = free tier (not null)
99
289
  }
100
290
 
101
291
  const keyHash = hashKey(apiKey);
@@ -109,28 +299,30 @@ export async function getTierFromApiKey(apiKey) {
109
299
 
110
300
  // Validate with API
111
301
  try {
112
- const response = await fetch('https://api.vibecheckai.dev/whoami', {
302
+ const response = await fetch('https://api.vibecheckai.dev/v1/auth/whoami', {
113
303
  headers: { 'Authorization': `Bearer ${apiKey}` },
114
304
  signal: AbortSignal.timeout(10000),
115
305
  });
116
306
 
117
307
  if (!response.ok) {
118
- return null;
308
+ // Invalid key - default to free
309
+ tierCache.set(keyHash, { tier: 'free', expiresAt: now + 60000 }); // Short cache for invalid
310
+ return 'free';
119
311
  }
120
312
 
121
313
  const data = await response.json();
122
- const plan = data.plan?.toLowerCase() || 'free';
314
+ const plan = data.plan?.toLowerCase() || data.tier?.toLowerCase() || 'free';
123
315
 
124
- // Any paid plan = pro
316
+ // Map any paid plan to 'pro' (STARTER, PRO, ENTERPRISE all = pro)
125
317
  const tier = (plan === 'free') ? 'free' : 'pro';
126
318
 
127
319
  tierCache.set(keyHash, { tier, expiresAt: now + CACHE_TTL });
128
320
  return tier;
129
321
 
130
322
  } catch {
131
- // Network error - check stale cache
323
+ // Network error - check stale cache or default to free
132
324
  if (cached) return cached.tier;
133
- return null;
325
+ return 'free';
134
326
  }
135
327
  }
136
328
 
@@ -139,10 +331,15 @@ export async function getTierFromApiKey(apiKey) {
139
331
  // ============================================================================
140
332
 
141
333
  export function isPro(tier) {
334
+ // Developer mode bypass (blocked in production)
335
+ if (isDevProBypassAllowed()) return true;
142
336
  return tier === 'pro';
143
337
  }
144
338
 
145
339
  export function canAccessTool(tier, toolName) {
340
+ // Developer mode bypass (blocked in production)
341
+ if (isDevProBypassAllowed()) return true;
342
+
146
343
  // PRO gets everything
147
344
  if (tier === 'pro') return true;
148
345
 
@@ -150,59 +347,110 @@ export function canAccessTool(tier, toolName) {
150
347
  return FREE_TOOLS.includes(toolName);
151
348
  }
152
349
 
350
+ /**
351
+ * Check option-level access
352
+ * @param {string} tier - User tier
353
+ * @param {string} toolName - Tool name
354
+ * @param {object} args - Tool arguments
355
+ * @returns {{ allowed: boolean, blockedOption?: string, required?: string }}
356
+ */
357
+ export function checkOptionAccess(tier, toolName, args) {
358
+ // Developer mode (blocked in production) or PRO = full access
359
+ if (isDevProBypassAllowed() || tier === 'pro') {
360
+ return { allowed: true };
361
+ }
362
+
363
+ const gates = OPTION_GATES[toolName];
364
+ if (!gates || !args) {
365
+ return { allowed: true };
366
+ }
367
+
368
+ // Check each gated option
369
+ for (const [option, requiredTier] of Object.entries(gates)) {
370
+ // Handle nested object gates (e.g., mode: { enforce: 'pro' })
371
+ if (typeof requiredTier === 'object') {
372
+ const argValue = args[option];
373
+ if (argValue && requiredTier[argValue] === 'pro') {
374
+ return { allowed: false, blockedOption: `${option}=${argValue}`, required: 'pro' };
375
+ }
376
+ } else if (args[option] === true && requiredTier === 'pro') {
377
+ return { allowed: false, blockedOption: option, required: 'pro' };
378
+ }
379
+ }
380
+
381
+ return { allowed: true };
382
+ }
383
+
153
384
  /**
154
385
  * Get firewall mode based on tier
155
386
  * - FREE: observe (log only)
156
387
  * - PRO: enforce (block violations)
157
388
  */
158
389
  export function getFirewallMode(tier) {
390
+ if (isDevProBypassAllowed()) return 'enforce';
159
391
  return tier === 'pro' ? 'enforce' : 'observe';
160
392
  }
161
393
 
162
394
  /**
163
395
  * Check if user can use full conductor features
164
396
  */
165
- export function canUseCondcutor(tier) {
397
+ export function canUseConductor(tier) {
398
+ if (isDevProBypassAllowed()) return true;
166
399
  return tier === 'pro';
167
400
  }
168
401
 
402
+ // Legacy alias (typo fix)
403
+ export const canUseCondcutor = canUseConductor;
404
+
169
405
  /**
170
406
  * Check if user can approve authorities
171
407
  */
172
408
  export function canApproveAuthority(tier) {
409
+ if (isDevProBypassAllowed()) return true;
173
410
  return tier === 'pro';
174
411
  }
175
412
 
176
- export async function getMcpToolAccess(toolName, apiKey) {
177
- if (!apiKey) {
413
+ /**
414
+ * Get MCP tool access with full ErrorEnvelope support
415
+ *
416
+ * @param {string} toolName - Tool name
417
+ * @param {string} apiKey - API key (optional)
418
+ * @param {object} args - Tool arguments for option-level checks
419
+ * @returns {Promise<{hasAccess: boolean, tier: string, error?: object}>}
420
+ */
421
+ export async function getMcpToolAccess(toolName, apiKey, args = {}) {
422
+ const tier = await getTierFromApiKey(apiKey);
423
+
424
+ // Check tool-level access
425
+ const hasToolAccess = canAccessTool(tier, toolName);
426
+
427
+ if (!hasToolAccess) {
178
428
  return {
179
- hasAccess: FREE_TOOLS.includes(toolName),
180
- tier: 'free',
181
- reason: FREE_TOOLS.includes(toolName)
182
- ? 'Access granted (free tool)'
183
- : 'This tool requires Pro. Set API key with `vibecheck login`.',
429
+ hasAccess: false,
430
+ tier,
431
+ firewallMode: getFirewallMode(tier),
432
+ error: notEntitledError(toolName, tier, 'pro'),
433
+ reason: `${toolName} requires Pro ($69/mo). Upgrade at https://vibecheckai.dev/pricing`,
184
434
  };
185
435
  }
186
436
 
187
- const tier = await getTierFromApiKey(apiKey);
188
-
189
- if (!tier) {
437
+ // Check option-level access
438
+ const optionCheck = checkOptionAccess(tier, toolName, args);
439
+ if (!optionCheck.allowed) {
190
440
  return {
191
441
  hasAccess: false,
192
- tier: null,
193
- reason: 'Invalid API key.',
442
+ tier,
443
+ firewallMode: getFirewallMode(tier),
444
+ error: optionNotEntitledError(toolName, optionCheck.blockedOption, tier, optionCheck.required),
445
+ reason: `Option --${optionCheck.blockedOption} requires Pro`,
194
446
  };
195
447
  }
196
448
 
197
- const hasAccess = canAccessTool(tier, toolName);
198
-
199
449
  return {
200
- hasAccess,
450
+ hasAccess: true,
201
451
  tier,
202
452
  firewallMode: getFirewallMode(tier),
203
- reason: hasAccess
204
- ? 'Access granted'
205
- : `${toolName} requires Pro ($69/mo). Upgrade at https://vibecheckai.dev/pricing`,
453
+ reason: 'Access granted',
206
454
  };
207
455
  }
208
456
 
@@ -210,17 +458,27 @@ export async function getMcpToolAccess(toolName, apiKey) {
210
458
  // MIDDLEWARE
211
459
  // ============================================================================
212
460
 
461
+ /**
462
+ * Middleware that wraps a tool handler with tier checking
463
+ * Returns proper ErrorEnvelope on failure
464
+ */
213
465
  export function withTierCheck(toolName, handler) {
214
466
  return async (args) => {
215
- const access = await getMcpToolAccess(toolName, args?.apiKey);
467
+ const access = await getMcpToolAccess(toolName, args?.apiKey, args);
216
468
 
217
469
  if (!access.hasAccess) {
470
+ // Return proper ErrorEnvelope format
218
471
  return {
219
472
  content: [{
220
473
  type: "text",
221
- text: `This tool requires Pro.\n\n${toolName} is a Pro feature.\n\nUpgrade to Pro ($69/mo) to unlock:\n- Authority System (verdicts & approvals)\n- Agent Conductor (multi-agent coordination)\n- Agent Firewall (enforce mode)\n\nhttps://vibecheckai.dev/pricing`
474
+ text: JSON.stringify({
475
+ ok: false,
476
+ error: access.error,
477
+ }, null, 2)
222
478
  }],
223
- isError: true
479
+ isError: true,
480
+ // Also include error envelope at top level for structured access
481
+ _error: access.error,
224
482
  };
225
483
  }
226
484
 
@@ -230,6 +488,29 @@ export function withTierCheck(toolName, handler) {
230
488
  };
231
489
  }
232
490
 
491
+ /**
492
+ * Create tier gate response for direct use in handlers
493
+ * Returns null if access granted, ErrorEnvelope if denied
494
+ */
495
+ export async function checkTierGate(toolName, apiKey, args = {}) {
496
+ const access = await getMcpToolAccess(toolName, apiKey, args);
497
+
498
+ if (!access.hasAccess) {
499
+ return {
500
+ content: [{
501
+ type: "text",
502
+ text: JSON.stringify({
503
+ ok: false,
504
+ error: access.error,
505
+ }, null, 2)
506
+ }],
507
+ isError: true,
508
+ };
509
+ }
510
+
511
+ return null; // Access granted
512
+ }
513
+
233
514
  // ============================================================================
234
515
  // USER INFO
235
516
  // ============================================================================
@@ -276,11 +557,63 @@ export async function getAvailableMcpTools(apiKey) {
276
557
  };
277
558
  }
278
559
 
279
- // Legacy exports for backward compatibility
280
- export async function getFeatureAccessStatus(featureName, apiKey) {
281
- return getMcpToolAccess(featureName, apiKey);
560
+ // ============================================================================
561
+ // LEGACY EXPORTS - Backward compatibility
562
+ // ============================================================================
563
+
564
+ /**
565
+ * @deprecated Use getMcpToolAccess instead
566
+ */
567
+ export async function getFeatureAccessStatus(featureName, apiKey, args = {}) {
568
+ const result = await getMcpToolAccess(featureName, apiKey, args);
569
+ // Add upgradeUrl for legacy consumers
570
+ return {
571
+ ...result,
572
+ upgradeUrl: 'https://vibecheckai.dev/pricing',
573
+ };
282
574
  }
283
575
 
576
+ /**
577
+ * @deprecated Use withTierCheck instead
578
+ */
284
579
  export function withMcpToolCheck(toolName, handler) {
285
580
  return withTierCheck(toolName, handler);
286
581
  }
582
+
583
+ // ============================================================================
584
+ // TOOL TIER MAPPING - For documentation and testing
585
+ // ============================================================================
586
+
587
+ /**
588
+ * Get the tier requirements table for all MCP tools
589
+ * Used for documentation and test generation
590
+ */
591
+ export function getToolTierTable() {
592
+ const table = [];
593
+
594
+ for (const tool of FREE_TOOLS) {
595
+ table.push({ tool, tier: 'FREE', options: OPTION_GATES[tool] || null });
596
+ }
597
+
598
+ for (const tool of PRO_TOOLS) {
599
+ table.push({ tool, tier: 'PRO', options: null });
600
+ }
601
+
602
+ return table;
603
+ }
604
+
605
+ /**
606
+ * Print formatted tier table (for CLI/debugging)
607
+ */
608
+ export function printTierTable() {
609
+ console.log('┌────────────────────────────────────┬──────┬─────────────────────────┐');
610
+ console.log('│ MCP Tool │ Tier │ Gated Options │');
611
+ console.log('├────────────────────────────────────┼──────┼─────────────────────────┤');
612
+
613
+ for (const { tool, tier, options } of getToolTierTable()) {
614
+ const optStr = options ? Object.keys(options).join(', ') : '-';
615
+ console.log(`│ ${tool.padEnd(34)} │ ${tier.padEnd(4)} │ ${optStr.padEnd(23)} │`);
616
+ }
617
+
618
+ console.log('└────────────────────────────────────┴──────┴─────────────────────────┘');
619
+ }