@vibecheckai/cli 3.5.1 → 3.5.3

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 (272) hide show
  1. package/bin/registry.js +406 -154
  2. package/bin/runners/context/analyzer.js +52 -1
  3. package/bin/runners/context/generators/mcp.js +15 -13
  4. package/bin/runners/context/git-context.js +3 -1
  5. package/bin/runners/context/proof-context.js +248 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  8. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  9. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  10. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  11. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  12. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  13. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  14. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  15. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  16. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  17. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  18. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  19. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  20. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  21. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  22. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  23. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  24. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  25. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  26. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  27. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  28. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  29. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  30. package/bin/runners/lib/agent-firewall/interceptor/base.js +304 -0
  31. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  32. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  33. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  34. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  35. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  36. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  37. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  38. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  39. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  40. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  41. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  42. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  43. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  44. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  45. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +86 -0
  46. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +162 -0
  47. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +189 -0
  48. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  49. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  50. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  51. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  52. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  53. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  54. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  55. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  56. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  57. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  58. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  59. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  60. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  61. package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
  62. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  63. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  64. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  65. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  66. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  67. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  68. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  69. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  70. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  71. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  72. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  73. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  74. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  75. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  76. package/bin/runners/lib/analysis-core.js +220 -182
  77. package/bin/runners/lib/analyzers.js +2145 -224
  78. package/bin/runners/lib/api-client.js +269 -0
  79. package/bin/runners/lib/authority-badge.js +425 -0
  80. package/bin/runners/lib/cli-output.js +242 -210
  81. package/bin/runners/lib/default-config.js +127 -0
  82. package/bin/runners/lib/detectors-v2.js +547 -785
  83. package/bin/runners/lib/doctor/modules/security.js +3 -1
  84. package/bin/runners/lib/engine/ast-cache.js +210 -0
  85. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  86. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  87. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  88. package/bin/runners/lib/engine/env-extractor.js +207 -0
  89. package/bin/runners/lib/engine/express-extractor.js +208 -0
  90. package/bin/runners/lib/engine/extractors.js +849 -0
  91. package/bin/runners/lib/engine/index.js +207 -0
  92. package/bin/runners/lib/engine/repo-index.js +514 -0
  93. package/bin/runners/lib/engine/types.js +124 -0
  94. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  95. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  96. package/bin/runners/lib/engines/ast-cache.js +99 -0
  97. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  98. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  99. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  100. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  101. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  102. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  103. package/bin/runners/lib/engines/file-filter.js +131 -0
  104. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  105. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  106. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  107. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  108. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  109. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  110. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  111. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  112. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  113. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  114. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  115. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  116. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  117. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  118. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  119. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  120. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  121. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  122. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  123. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  124. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  125. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  126. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  127. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  128. package/bin/runners/lib/entitlements-v2.js +152 -446
  129. package/bin/runners/lib/error-handler.js +60 -12
  130. package/bin/runners/lib/error-messages.js +289 -0
  131. package/bin/runners/lib/evidence-pack.js +7 -1
  132. package/bin/runners/lib/exit-codes.js +275 -0
  133. package/bin/runners/lib/finding-id.js +69 -0
  134. package/bin/runners/lib/finding-sorter.js +89 -0
  135. package/bin/runners/lib/fingerprint.js +377 -0
  136. package/bin/runners/lib/global-flags.js +37 -0
  137. package/bin/runners/lib/help-formatter.js +413 -0
  138. package/bin/runners/lib/logger.js +38 -0
  139. package/bin/runners/lib/next-action.js +560 -0
  140. package/bin/runners/lib/prerequisites.js +149 -0
  141. package/bin/runners/lib/route-detection.js +137 -68
  142. package/bin/runners/lib/route-truth.js +1167 -322
  143. package/bin/runners/lib/scan-output.js +504 -463
  144. package/bin/runners/lib/scan-runner.js +135 -0
  145. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  146. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  147. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  148. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  149. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  150. package/bin/runners/lib/schemas/validator.js +27 -0
  151. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  152. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  153. package/bin/runners/lib/ship-output.js +328 -31
  154. package/bin/runners/lib/terminal-ui.js +234 -731
  155. package/bin/runners/lib/truth.js +1332 -308
  156. package/bin/runners/lib/unified-cli-output.js +604 -0
  157. package/bin/runners/lib/unified-output.js +163 -155
  158. package/bin/runners/lib/upsell.js +104 -204
  159. package/bin/runners/runAgent.d.ts +5 -0
  160. package/bin/runners/runAgent.js +161 -0
  161. package/bin/runners/runAllowlist.js +166 -101
  162. package/bin/runners/runApprove.js +1200 -0
  163. package/bin/runners/runAuth.js +373 -95
  164. package/bin/runners/runCheckpoint.js +59 -21
  165. package/bin/runners/runClassify.js +926 -0
  166. package/bin/runners/runContext.d.ts +4 -0
  167. package/bin/runners/runContext.js +136 -24
  168. package/bin/runners/runDoctor.js +115 -67
  169. package/bin/runners/runEvidencePack.js +239 -96
  170. package/bin/runners/runFirewall.d.ts +5 -0
  171. package/bin/runners/runFirewall.js +134 -0
  172. package/bin/runners/runFirewallHook.d.ts +5 -0
  173. package/bin/runners/runFirewallHook.js +56 -0
  174. package/bin/runners/runFix.js +6 -5
  175. package/bin/runners/runGuard.js +212 -118
  176. package/bin/runners/runInit.js +66 -21
  177. package/bin/runners/runLabs.js +204 -121
  178. package/bin/runners/runMcp.js +131 -60
  179. package/bin/runners/runPolish.d.ts +4 -0
  180. package/bin/runners/runPolish.js +43 -20
  181. package/bin/runners/runProof.zip +0 -0
  182. package/bin/runners/runProve.js +15 -5
  183. package/bin/runners/runQuickstart.js +531 -0
  184. package/bin/runners/runReality.js +14 -0
  185. package/bin/runners/runReport.js +36 -4
  186. package/bin/runners/runScan.js +689 -91
  187. package/bin/runners/runShip.js +96 -40
  188. package/bin/runners/runTruth.d.ts +5 -0
  189. package/bin/runners/runTruth.js +101 -0
  190. package/bin/runners/runValidate.js +21 -4
  191. package/bin/runners/runWatch.js +118 -54
  192. package/bin/scan.js +6 -1
  193. package/bin/vibecheck.js +297 -52
  194. package/mcp-server/HARDENING_SUMMARY.md +299 -0
  195. package/mcp-server/agent-firewall-interceptor.js +500 -0
  196. package/mcp-server/authority-tools.js +569 -0
  197. package/mcp-server/conductor/conflict-resolver.js +588 -0
  198. package/mcp-server/conductor/execution-planner.js +544 -0
  199. package/mcp-server/conductor/index.js +377 -0
  200. package/mcp-server/conductor/lock-manager.js +615 -0
  201. package/mcp-server/conductor/request-queue.js +550 -0
  202. package/mcp-server/conductor/session-manager.js +500 -0
  203. package/mcp-server/conductor/tools.js +510 -0
  204. package/mcp-server/deprecation-middleware.js +282 -0
  205. package/mcp-server/handlers/index.ts +15 -0
  206. package/mcp-server/handlers/tool-handler.ts +474 -591
  207. package/mcp-server/index.js +1748 -1099
  208. package/mcp-server/lib/api-client.cjs +13 -0
  209. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  210. package/mcp-server/lib/error-envelope.js +138 -0
  211. package/mcp-server/lib/executor.ts +428 -721
  212. package/mcp-server/lib/index.ts +19 -0
  213. package/mcp-server/lib/logger.cjs +30 -0
  214. package/mcp-server/lib/rate-limiter.js +166 -0
  215. package/mcp-server/lib/sandbox.test.ts +519 -0
  216. package/mcp-server/lib/sandbox.ts +342 -284
  217. package/mcp-server/lib/types.ts +267 -0
  218. package/mcp-server/logger.js +173 -0
  219. package/mcp-server/package.json +11 -27
  220. package/mcp-server/premium-tools.js +2 -2
  221. package/mcp-server/registry/tool-registry.js +794 -0
  222. package/mcp-server/registry/tools.json +507 -378
  223. package/mcp-server/registry.test.ts +334 -0
  224. package/mcp-server/tests/tier-gating.test.js +297 -0
  225. package/mcp-server/tier-auth.js +492 -347
  226. package/mcp-server/tools-v3.js +950 -0
  227. package/mcp-server/truth-context.js +131 -90
  228. package/mcp-server/truth-firewall-tools.js +1612 -1001
  229. package/mcp-server/tsconfig.json +8 -5
  230. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  231. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  232. package/mcp-server/vibecheck-tools.js +2 -2
  233. package/package.json +4 -3
  234. package/bin/runners/runInstall.js +0 -281
  235. package/mcp-server/ARCHITECTURE.md +0 -339
  236. package/mcp-server/__tests__/cache.test.ts +0 -313
  237. package/mcp-server/__tests__/executor.test.ts +0 -239
  238. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +0 -1
  239. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +0 -3
  240. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +0 -3
  241. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +0 -3
  242. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +0 -3
  243. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +0 -5
  244. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +0 -5
  245. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +0 -4
  246. package/mcp-server/__tests__/ids.test.ts +0 -345
  247. package/mcp-server/__tests__/integration/tools.test.ts +0 -410
  248. package/mcp-server/__tests__/registry.test.ts +0 -365
  249. package/mcp-server/__tests__/sandbox.test.ts +0 -323
  250. package/mcp-server/__tests__/schemas.test.ts +0 -372
  251. package/mcp-server/benchmarks/run-benchmarks.ts +0 -304
  252. package/mcp-server/examples/doctor.request.json +0 -14
  253. package/mcp-server/examples/doctor.response.json +0 -53
  254. package/mcp-server/examples/error.response.json +0 -15
  255. package/mcp-server/examples/scan.request.json +0 -14
  256. package/mcp-server/examples/scan.response.json +0 -108
  257. package/mcp-server/index-v3.ts +0 -293
  258. package/mcp-server/index.old.js +0 -4137
  259. package/mcp-server/lib/cache.ts +0 -341
  260. package/mcp-server/lib/errors.ts +0 -346
  261. package/mcp-server/lib/ids.ts +0 -238
  262. package/mcp-server/lib/logger.ts +0 -368
  263. package/mcp-server/lib/metrics.ts +0 -365
  264. package/mcp-server/lib/validator.ts +0 -229
  265. package/mcp-server/package-lock.json +0 -165
  266. package/mcp-server/schemas/error-envelope.schema.json +0 -125
  267. package/mcp-server/schemas/finding.schema.json +0 -167
  268. package/mcp-server/schemas/report-artifact.schema.json +0 -88
  269. package/mcp-server/schemas/run-request.schema.json +0 -75
  270. package/mcp-server/schemas/verdict.schema.json +0 -168
  271. package/mcp-server/tier-auth.d.ts +0 -71
  272. package/mcp-server/vitest.config.ts +0 -16
@@ -1,25 +1,9 @@
1
1
  /**
2
- * Entitlements v2 - CANONICAL Tier Enforcement
2
+ * VibeCheck Entitlements
3
3
  *
4
- * SINGLE SOURCE OF TRUTH for all tier gating in vibecheck CLI.
5
- * Every command runner MUST use this module for access control.
6
- *
7
- * NO BYPASS ALLOWED:
8
- * - No owner-mode env vars
9
- * - No offline fallback that grants paid features
10
- * - No silent feature access
11
- *
12
- * Exit Codes:
13
- * - 0: Success
14
- * - 2: BLOCK verdict (CI failure)
15
- * - 3: Feature not allowed (upgrade required)
16
- * - 4: Misconfiguration/env error
17
- *
18
- * Tiers:
19
- * - FREE ($0): Basic scanning and validation
20
- * - STARTER ($39/repo/mo): CI/CD gates, PR checks, badges, MCP
21
- * - PRO ($99/repo/mo): Full fix, prove, ai-test, share, advanced reality, permissions, graph, patch apply
22
- * - COMPLIANCE (Enterprise): Advanced compliance packs, audit trails
4
+ * Simple 2-tier model:
5
+ * - FREE ($0): Inspect & Observe
6
+ * - PRO ($69/mo): Fix, Prove & Enforce
23
7
  */
24
8
 
25
9
  "use strict";
@@ -27,254 +11,120 @@
27
11
  const fs = require("fs");
28
12
  const path = require("path");
29
13
  const os = require("os");
30
- const crypto = require("crypto");
31
14
 
32
- // ═══════════════════════════════════════════════════════════════════════════════
15
+ // ============================================================================
33
16
  // EXIT CODES
34
- // ═══════════════════════════════════════════════════════════════════════════════
17
+ // ============================================================================
35
18
  const EXIT_SUCCESS = 0;
36
- const EXIT_BLOCK_VERDICT = 2;
37
19
  const EXIT_FEATURE_NOT_ALLOWED = 3;
38
- const EXIT_MISCONFIG = 4;
39
20
 
40
- // ═══════════════════════════════════════════════════════════════════════════════
41
- // TIER DEFINITIONS - SOURCE OF TRUTH
42
- // ═══════════════════════════════════════════════════════════════════════════════
21
+ // ============================================================================
22
+ // TIERS
23
+ // ============================================================================
43
24
  const TIERS = {
44
- free: { name: "FREE", price: 0, order: 0 },
45
- starter: { name: "STARTER", price: 39, order: 1 }, // Updated pricing
46
- pro: { name: "PRO", price: 99, order: 2 },
47
- compliance: { name: "COMPLIANCE", price: 0, order: 3 }, // Enterprise/on-prem
48
- };
49
-
50
- // ═══════════════════════════════════════════════════════════════════════════════
51
- // ENTITLEMENTS MATRIX - SOURCE OF TRUTH
52
- // Format: feature -> { minTier, caps?, downgrade? }
53
- // ═══════════════════════════════════════════════════════════════════════════════
54
- const ENTITLEMENTS = {
55
- // ─────────────────────────────────────────────────────────────────────────────
56
- // CORE COMMANDS
57
- // ─────────────────────────────────────────────────────────────────────────────
58
- "scan": { minTier: "free" },
59
- "scan.autofix": { minTier: "starter" }, // Apply safe fixes + missions
60
- "ship": { minTier: "free", caps: { free: "static-only" } },
61
- "ship.static": { minTier: "free" },
62
- "ship.full": { minTier: "pro" },
63
-
64
- // ─────────────────────────────────────────────────────────────────────────────
65
- // INIT MODES
66
- // ─────────────────────────────────────────────────────────────────────────────
67
- "init": { minTier: "free" },
68
- "init.local": { minTier: "free" }, // Full local setup
69
- "init.connect": { minTier: "starter" }, // GitHub Actions + PR comments
70
-
71
- // ─────────────────────────────────────────────────────────────────────────────
72
- // CHECKPOINT
73
- // ─────────────────────────────────────────────────────────────────────────────
74
- "checkpoint": { minTier: "free", downgrade: "checkpoint.basic" },
75
- "checkpoint.basic": { minTier: "free" }, // Basic diff comparison
76
- "checkpoint.hallucination": { minTier: "pro" }, // Hallucination scoring
77
-
78
- // ─────────────────────────────────────────────────────────────────────────────
79
- // REALITY TESTING
80
- // ─────────────────────────────────────────────────────────────────────────────
81
- "reality": { minTier: "free", downgrade: "reality.preview" },
82
- "reality.preview": { minTier: "free", caps: { free: { maxPages: 5, maxClicks: 20, noAuthBoundary: true } } },
83
- "reality.basic": { minTier: "starter", caps: { starter: { maxPages: 50, maxClicks: 200, basicAuthVerify: true } } },
84
- "reality.full": { minTier: "pro" },
85
- "reality.advanced_auth_boundary": { minTier: "pro" },
86
-
87
- // ─────────────────────────────────────────────────────────────────────────────
88
- // PROVE COMMAND
89
- // ─────────────────────────────────────────────────────────────────────────────
90
- "prove": { minTier: "pro" },
91
-
92
- // ─────────────────────────────────────────────────────────────────────────────
93
- // FIX COMMAND
94
- // ─────────────────────────────────────────────────────────────────────────────
95
- "fix": { minTier: "free", downgrade: "fix.plan_only" },
96
- "fix.plan_only": { minTier: "free" }, // Generate missions, don't apply
97
- "fix.apply_patches": { minTier: "pro" }, // Apply patches automatically
98
- "fix.loop": { minTier: "pro" }, // Continuous fix loop
99
-
100
- // ─────────────────────────────────────────────────────────────────────────────
101
- // REPORT FORMATS
102
- // ─────────────────────────────────────────────────────────────────────────────
103
- "report": { minTier: "free", downgrade: "report.html_md" },
104
- "report.html_md": { minTier: "free" },
105
- "report.sarif_csv": { minTier: "starter" }, // SARIF/CSV at STARTER
106
- "report.compliance_packs": { minTier: "compliance" },
107
-
108
- // ─────────────────────────────────────────────────────────────────────────────
109
- // SETUP & DX
110
- // ─────────────────────────────────────────────────────────────────────────────
111
- "install": { minTier: "free" },
112
- "doctor": { minTier: "free" },
113
- "status": { minTier: "free" },
114
- "watch": { minTier: "free", downgrade: "watch.local" },
115
- "watch.local": { minTier: "free" }, // Local-only file watching
116
- "watch.pr": { minTier: "starter" }, // PR updates on changes
117
- "preflight": { minTier: "free" },
118
- "polish": { minTier: "free" },
119
-
120
- // ─────────────────────────────────────────────────────────────────────────────
121
- // AI TRUTH
122
- // ─────────────────────────────────────────────────────────────────────────────
123
- "ctx": { minTier: "free" },
124
- "guard": { minTier: "free" },
125
- "context": { minTier: "free" },
126
- "mdc": { minTier: "free" },
127
- "contracts": { minTier: "free" },
128
-
129
- // ─────────────────────────────────────────────────────────────────────────────
130
- // EXPORT COMMAND (subcommands gate individually)
131
- // ─────────────────────────────────────────────────────────────────────────────
132
- "export": { minTier: "free" }, // Base export command is free, subcommands gate themselves
133
-
134
- // ─────────────────────────────────────────────────────────────────────────────
135
- // RUNTIME COMMAND (browser-based verification)
136
- // ─────────────────────────────────────────────────────────────────────────────
137
- "runtime": { minTier: "free", downgrade: "reality.preview" }, // Same as reality
138
-
139
- // ─────────────────────────────────────────────────────────────────────────────
140
- // SECURITY COMMAND (AuthZ & IDOR)
141
- // ─────────────────────────────────────────────────────────────────────────────
142
- "security": { minTier: "pro" },
143
-
144
- // ─────────────────────────────────────────────────────────────────────────────
145
- // PRO ONLY
146
- // ─────────────────────────────────────────────────────────────────────────────
147
- "replay": { minTier: "pro" },
148
- "share": { minTier: "pro" },
149
- "ai-test": { minTier: "pro" },
150
- "permissions": { minTier: "pro" },
151
- "graph": { minTier: "pro" },
152
-
153
- // ─────────────────────────────────────────────────────────────────────────────
154
- // STARTER AND ABOVE
155
- // ─────────────────────────────────────────────────────────────────────────────
156
- "gate": { minTier: "starter" },
157
- "pr": { minTier: "starter" },
158
- "badge": { minTier: "starter" },
159
- "launch": { minTier: "starter" },
160
- "dashboard_sync": { minTier: "starter" },
161
-
162
- // MCP Server
163
- "mcp": { minTier: "starter", downgrade: "mcp.help_only" },
164
- "mcp.help_only": { minTier: "free", caps: { free: "help and print-config only" } },
165
- "mcp.read_only": { minTier: "starter", caps: { starter: "read-only safe tools, rate limited" } },
166
- "mcp.full": { minTier: "pro", caps: { pro: "full tools, audit logs, higher limits" } },
167
-
168
- // ─────────────────────────────────────────────────────────────────────────────
169
- // ACCOUNT (ALWAYS FREE)
170
- // ─────────────────────────────────────────────────────────────────────────────
171
- "login": { minTier: "free" },
172
- "logout": { minTier: "free" },
173
- "whoami": { minTier: "free" },
174
-
175
- // Labs/experimental
176
- "labs": { minTier: "free" },
25
+ free: { name: "FREE", price: 0 },
26
+ pro: { name: "PRO", price: 69 },
177
27
  };
178
28
 
179
- // ═══════════════════════════════════════════════════════════════════════════════
180
- // LIMITS BY TIER
181
- // ═══════════════════════════════════════════════════════════════════════════════
182
- const LIMITS = {
183
- free: {
184
- realityMaxPages: 5,
185
- realityMaxClicks: 20,
186
- realityAuthBoundary: false,
187
- reportFormats: ["html", "md"],
188
- fixApplyPatches: false,
189
- scansPerMonth: 50,
190
- shipChecksPerMonth: 20,
191
- },
192
- starter: {
193
- realityMaxPages: 50,
194
- realityMaxClicks: 200,
195
- realityAuthBoundary: false,
196
- realityAdvancedAuth: false,
197
- reportFormats: ["html", "md", "sarif", "csv"],
198
- fixApplyPatches: false,
199
- scansPerMonth: 500,
200
- shipChecksPerMonth: 200,
201
- },
202
- pro: {
203
- realityMaxPages: -1, // unlimited
204
- realityMaxClicks: -1,
205
- realityAuthBoundary: true,
206
- realityAdvancedAuth: true,
207
- reportFormats: ["html", "md", "sarif", "csv"],
208
- fixApplyPatches: true,
209
- scansPerMonth: -1, // unlimited
210
- shipChecksPerMonth: -1,
211
- },
212
- compliance: {
213
- realityMaxPages: -1,
214
- realityMaxClicks: -1,
215
- realityAuthBoundary: true,
216
- realityAdvancedAuth: true,
217
- reportFormats: ["html", "md", "sarif", "csv", "compliance"],
218
- fixApplyPatches: true,
219
- scansPerMonth: -1,
220
- shipChecksPerMonth: -1,
221
- },
222
- };
29
+ // ============================================================================
30
+ // GATED FEATURES
31
+ // ============================================================================
32
+ const FREE_FEATURES = [
33
+ // Setup & environment
34
+ "init", "doctor", "install", "status", "watch", "preflight",
35
+ // Scan & analysis
36
+ "scan", "runtime",
37
+ // AI verification
38
+ "ctx", "contracts", "verify",
39
+ // Reports
40
+ "report", "export",
41
+ // Account
42
+ "login", "logout", "whoami",
43
+ // Preview modes
44
+ "reality.preview", "firewall.observe",
45
+ // Misc
46
+ "labs", "mdc",
47
+ ];
223
48
 
224
- const API_BASE_URL = process.env.VIBECHECK_API_URL || "https://api.vibecheckai.dev";
49
+ const PRO_FEATURES = [
50
+ // CI/CD & PR
51
+ "gate", "pr", "badge", "ship",
52
+ // Fixes
53
+ "fix", "fix.apply", "fix.analyze", "fix.diff", "fix.rules", "scan.autofix",
54
+ // Prove & verify
55
+ "prove", "replay", "permissions", "graph", "ai-test", "share",
56
+ // Advanced
57
+ "checkpoint", "polish", "guard", "context",
58
+ // Full modes
59
+ "firewall.enforce", "reality.full", "mcp.full",
60
+ // All FREE features
61
+ ...FREE_FEATURES,
62
+ ];
225
63
 
226
- // ═══════════════════════════════════════════════════════════════════════════════
227
- // CACHE PATHS
228
- // ═══════════════════════════════════════════════════════════════════════════════
229
- function getEntitlementsCachePath(projectPath) {
230
- return path.join(projectPath || process.cwd(), ".vibecheck", ".entitlements.json");
231
- }
232
-
233
- function getGlobalConfigPath() {
234
- const home = os.homedir();
235
- if (process.platform === "win32") {
236
- return path.join(process.env.APPDATA || path.join(home, "AppData", "Roaming"), "vibecheck", "config.json");
64
+ /**
65
+ * Check if developer mode bypass is allowed.
66
+ *
67
+ * SECURITY: VIBECHECK_DEV_PRO is ONLY allowed in non-production environments.
68
+ * This prevents environment variable injection from granting PRO access in production.
69
+ *
70
+ * @returns {boolean} True only if in development AND VIBECHECK_DEV_PRO=1
71
+ */
72
+ function isDevProBypassAllowed() {
73
+ // SECURITY: Never allow dev bypass in production
74
+ if (process.env.NODE_ENV === "production") {
75
+ return false;
76
+ }
77
+ // Also block in CI environments to prevent pipeline exploitation
78
+ if (process.env.CI === "true" || process.env.CI === "1") {
79
+ return false;
237
80
  }
238
- return path.join(home, ".config", "vibecheck", "config.json");
81
+ return process.env.VIBECHECK_DEV_PRO === "1";
239
82
  }
240
83
 
241
- // ═══════════════════════════════════════════════════════════════════════════════
242
- // TIER COMPARISON
243
- // ═══════════════════════════════════════════════════════════════════════════════
244
- function tierMeetsMinimum(currentTier, requiredTier) {
245
- const current = TIERS[currentTier]?.order ?? -1;
246
- const required = TIERS[requiredTier]?.order ?? 999;
247
- return current >= required;
84
+ function isPro(tier) {
85
+ // Developer mode bypass (blocked in production)
86
+ if (isDevProBypassAllowed()) return true;
87
+ return tier === "pro";
248
88
  }
249
89
 
250
- function getTierLabel(tier) {
251
- return TIERS[tier]?.name || tier.toUpperCase();
90
+ function tierHasFeature(tier, feature) {
91
+ // Developer mode bypass - grant all features (blocked in production)
92
+ if (isDevProBypassAllowed()) return true;
93
+ if (tier === "pro") return true; // PRO has everything
94
+ return FREE_FEATURES.includes(feature);
252
95
  }
253
96
 
254
- // ═══════════════════════════════════════════════════════════════════════════════
255
- // CORE API: getTier()
256
- // ═══════════════════════════════════════════════════════════════════════════════
97
+ // ============================================================================
98
+ // API
99
+ // ============================================================================
100
+ const API_BASE_URL = process.env.VIBECHECK_API_URL || "https://api.vibecheckai.dev";
101
+
257
102
  let _cachedTier = null;
258
103
  let _cachedTierExpiry = 0;
259
104
 
260
105
  async function getTier(options = {}) {
261
- const { apiKey, projectPath, forceRefresh = false } = options;
106
+ const { apiKey, forceRefresh = false } = options;
107
+
108
+ // Developer mode: VIBECHECK_DEV_PRO=1 grants pro tier for local development
109
+ // SECURITY: This bypass is blocked in production environments
110
+ if (isDevProBypassAllowed()) {
111
+ _cachedTier = "pro";
112
+ _cachedTierExpiry = Date.now() + 86400000; // 24 hours
113
+ return "pro";
114
+ }
262
115
 
263
- // Check cache (5 minute TTL)
264
116
  if (!forceRefresh && _cachedTier && Date.now() < _cachedTierExpiry) {
265
117
  return _cachedTier;
266
118
  }
267
119
 
268
- // No API key = free tier
269
120
  if (!apiKey) {
270
121
  _cachedTier = "free";
271
122
  _cachedTierExpiry = Date.now() + 300000;
272
123
  return "free";
273
124
  }
274
125
 
275
- // Fetch from API
276
126
  try {
277
- const res = await fetch(`${API_BASE_URL}/v1/entitlements`, {
127
+ const res = await fetch(`${API_BASE_URL}/v1/auth/whoami`, {
278
128
  method: "GET",
279
129
  headers: { "Authorization": `Bearer ${apiKey}` },
280
130
  signal: AbortSignal.timeout(5000),
@@ -282,113 +132,33 @@ async function getTier(options = {}) {
282
132
 
283
133
  if (res.ok) {
284
134
  const data = await res.json();
285
- _cachedTier = data.tier || "free";
135
+ // Map any paid tier to 'pro'
136
+ const plan = data.plan || data.tier || "free";
137
+ _cachedTier = (plan === "free") ? "free" : "pro";
286
138
  _cachedTierExpiry = Date.now() + 300000;
287
-
288
- // Cache locally
289
- try {
290
- const cachePath = getEntitlementsCachePath(projectPath);
291
- const dir = path.dirname(cachePath);
292
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
293
- fs.writeFileSync(cachePath, JSON.stringify({ tier: _cachedTier, fetchedAt: new Date().toISOString() }, null, 2));
294
- } catch {}
295
-
296
139
  return _cachedTier;
297
140
  }
298
-
299
- if (res.status === 401) {
300
- return "free"; // Invalid key = free tier
301
- }
302
141
  } catch {
303
- // Network error - check local cache
304
- try {
305
- const cachePath = getEntitlementsCachePath(projectPath);
306
- if (fs.existsSync(cachePath)) {
307
- const cached = JSON.parse(fs.readFileSync(cachePath, "utf8"));
308
- // Only use cache if less than 24 hours old
309
- const fetchedAt = new Date(cached.fetchedAt).getTime();
310
- if (Date.now() - fetchedAt < 24 * 3600 * 1000) {
311
- return cached.tier || "free";
312
- }
313
- }
314
- } catch {}
142
+ // Network error - default to free
315
143
  }
316
144
 
317
- // Default to free (no offline bypass to paid features)
318
145
  return "free";
319
146
  }
320
147
 
321
- // ═══════════════════════════════════════════════════════════════════════════════
322
- // CORE API: getLimits()
323
- // ═══════════════════════════════════════════════════════════════════════════════
324
- function getLimits(tier) {
325
- return LIMITS[tier] || LIMITS.free;
326
- }
327
-
328
- // ═══════════════════════════════════════════════════════════════════════════════
329
- // CORE API: enforce() - THE GATEKEEPER
330
- // ═══════════════════════════════════════════════════════════════════════════════
331
- /**
332
- * Enforce feature access. Returns enforcement result.
333
- *
334
- * @param {string} feature - Feature key (e.g., "prove", "fix.apply_patches")
335
- * @param {object} options - { apiKey?, projectPath?, silent? }
336
- * @returns {object} - { allowed, tier, downgrade?, exitCode, message }
337
- */
148
+ // ============================================================================
149
+ // ENFORCE
150
+ // ============================================================================
338
151
  async function enforce(feature, options = {}) {
339
- const { apiKey, projectPath, silent = false } = options;
152
+ const { apiKey, silent = false } = options;
153
+ const tier = await getTier({ apiKey });
340
154
 
341
- const tier = await getTier({ apiKey, projectPath });
342
- const entitlement = ENTITLEMENTS[feature];
343
-
344
- if (!entitlement) {
345
- // Unknown feature - block by default
346
- return {
347
- allowed: false,
348
- tier,
349
- exitCode: EXIT_MISCONFIG,
350
- message: `Unknown feature: ${feature}`,
351
- };
352
- }
353
-
354
- const hasAccess = tierMeetsMinimum(tier, entitlement.minTier);
155
+ const hasAccess = tierHasFeature(tier, feature);
355
156
 
356
157
  if (hasAccess) {
357
- // Full access
358
- return {
359
- allowed: true,
360
- tier,
361
- limits: getLimits(tier),
362
- caps: entitlement.caps?.[tier] || null,
363
- };
364
- }
365
-
366
- // Check for downgrade option
367
- if (entitlement.downgrade) {
368
- const downgradeEntitlement = ENTITLEMENTS[entitlement.downgrade];
369
- if (downgradeEntitlement && tierMeetsMinimum(tier, downgradeEntitlement.minTier)) {
370
- // Downgrade allowed
371
- const caps = downgradeEntitlement.caps?.[tier] || null;
372
- const message = formatDowngradeMessage(feature, entitlement.downgrade, tier, entitlement.minTier, caps);
373
-
374
- if (!silent) {
375
- console.log(message);
376
- }
377
-
378
- return {
379
- allowed: true,
380
- tier,
381
- downgrade: entitlement.downgrade,
382
- limits: getLimits(tier),
383
- caps,
384
- message,
385
- };
386
- }
158
+ return { allowed: true, tier };
387
159
  }
388
160
 
389
- // Not allowed - generate upgrade message
390
- const message = formatUpgradeMessage(feature, tier, entitlement.minTier);
391
-
161
+ const message = formatUpgradeMessage(feature);
392
162
  if (!silent) {
393
163
  console.error(message);
394
164
  }
@@ -396,164 +166,100 @@ async function enforce(feature, options = {}) {
396
166
  return {
397
167
  allowed: false,
398
168
  tier,
399
- requiredTier: entitlement.minTier,
400
169
  exitCode: EXIT_FEATURE_NOT_ALLOWED,
401
170
  message,
402
171
  };
403
172
  }
404
173
 
405
- // ═══════════════════════════════════════════════════════════════════════════════
174
+ async function enforceOrExit(feature, options = {}) {
175
+ const result = await enforce(feature, options);
176
+ if (!result.allowed) {
177
+ process.exit(result.exitCode);
178
+ }
179
+ return result;
180
+ }
181
+
182
+ async function checkCommand(command, options = {}) {
183
+ return enforce(command, { ...options, silent: true });
184
+ }
185
+
186
+ // ============================================================================
406
187
  // MESSAGING
407
- // ═══════════════════════════════════════════════════════════════════════════════
188
+ // ============================================================================
408
189
  const c = {
409
190
  reset: "\x1b[0m",
410
191
  bold: "\x1b[1m",
411
- dim: "\x1b[2m",
412
- red: "\x1b[31m",
413
- green: "\x1b[32m",
414
- yellow: "\x1b[33m",
415
192
  cyan: "\x1b[36m",
416
- magenta: "\x1b[35m",
193
+ yellow: "\x1b[33m",
417
194
  };
418
195
 
419
- function formatUpgradeMessage(feature, currentTier, requiredTier) {
420
- const tierColors = { starter: c.cyan, pro: c.magenta, enterprise: c.yellow };
421
- const reqColor = tierColors[requiredTier] || c.yellow;
422
-
196
+ function formatUpgradeMessage(feature) {
423
197
  return `
424
- ${c.red}${c.bold} Feature Not Available${c.reset}
425
-
426
- ${c.yellow}${feature}${c.reset} requires ${reqColor}${getTierLabel(requiredTier)}${c.reset} plan.
427
- Your current plan: ${c.dim}${getTierLabel(currentTier)}${c.reset}
198
+ ${c.bold}This feature requires Pro.${c.reset}
428
199
 
429
- ${c.cyan}Upgrade at:${c.reset} https://vibecheckai.dev/pricing
430
-
431
- ${c.dim}Exit code: ${EXIT_FEATURE_NOT_ALLOWED}${c.reset}
432
- `;
433
- }
200
+ ${c.yellow}${feature}${c.reset} is a Pro feature.
434
201
 
435
- function formatDowngradeMessage(feature, downgradeTo, currentTier, requiredTier, caps) {
436
- const tierColors = { starter: c.cyan, pro: c.magenta, enterprise: c.yellow };
437
- const reqColor = tierColors[requiredTier] || c.yellow;
438
-
439
- let capsStr = "";
440
- if (caps) {
441
- if (typeof caps === "string") {
442
- capsStr = ` ${c.dim}Mode: ${caps}${c.reset}\n`;
443
- } else if (typeof caps === "object") {
444
- const entries = Object.entries(caps).map(([k, v]) => `${k}: ${v}`).join(", ");
445
- capsStr = ` ${c.dim}Limits: ${entries}${c.reset}\n`;
446
- }
447
- }
448
-
449
- return `
450
- ${c.yellow}${c.bold}⚠ Running in Preview Mode${c.reset}
202
+ Upgrade to Pro ($69/mo) to unlock Fix, Prove & Enforce capabilities.
451
203
 
452
- Full ${c.yellow}${feature}${c.reset} requires ${reqColor}${getTierLabel(requiredTier)}${c.reset} plan.
453
- Running ${c.green}${downgradeTo}${c.reset} instead.
454
- ${capsStr}
455
- ${c.cyan}Upgrade for full access:${c.reset} https://vibecheckai.dev/pricing
204
+ vibecheck upgrade
205
+ https://vibecheckai.dev/pricing
456
206
  `;
457
207
  }
458
208
 
459
- // ═══════════════════════════════════════════════════════════════════════════════
460
- // CONVENIENCE HELPERS
461
- // ═══════════════════════════════════════════════════════════════════════════════
462
-
463
- /**
464
- * Check if a command is allowed (does not print messages)
465
- */
466
- async function checkCommand(command, options = {}) {
467
- return enforce(command, { ...options, silent: true });
468
- }
469
-
470
- /**
471
- * Enforce and exit if not allowed
472
- */
473
- async function enforceOrExit(feature, options = {}) {
474
- const result = await enforce(feature, options);
475
- if (!result.allowed) {
476
- process.exit(result.exitCode);
477
- }
478
- return result;
479
- }
480
-
481
- /**
482
- * Get the minimum tier required for a feature
483
- */
484
- function getMinTierForFeature(feature) {
485
- return ENTITLEMENTS[feature]?.minTier || "enterprise";
486
- }
209
+ // ============================================================================
210
+ // TIER LIMITS
211
+ // ============================================================================
212
+ const TIER_LIMITS = {
213
+ free: {
214
+ reportFormats: ["html", "md", "json"],
215
+ maxScansPerMonth: 100,
216
+ maxFilesPerScan: 1000,
217
+ },
218
+ pro: {
219
+ reportFormats: ["html", "md", "json", "sarif", "csv", "pdf"],
220
+ maxScansPerMonth: -1, // unlimited
221
+ maxFilesPerScan: -1, // unlimited
222
+ },
223
+ };
487
224
 
488
225
  /**
489
- * Check if tier has access to feature (sync, for help display)
226
+ * Get limits for a tier
490
227
  */
491
- function tierHasFeature(tier, feature) {
492
- const entitlement = ENTITLEMENTS[feature];
493
- if (!entitlement) return false;
494
- return tierMeetsMinimum(tier, entitlement.minTier);
228
+ function getLimits(tier) {
229
+ return TIER_LIMITS[tier] || TIER_LIMITS.free;
495
230
  }
496
231
 
497
232
  /**
498
- * Get all features for a tier
233
+ * Check if current tier meets minimum required tier
499
234
  */
500
- function getFeaturesForTier(tier) {
501
- const features = [];
502
- for (const [feature, def] of Object.entries(ENTITLEMENTS)) {
503
- if (tierMeetsMinimum(tier, def.minTier)) {
504
- features.push(feature);
505
- }
506
- }
507
- return features;
508
- }
509
-
510
- // ═══════════════════════════════════════════════════════════════════════════════
511
- // COMMAND GROUPING FOR HELP DISPLAY
512
- // ═══════════════════════════════════════════════════════════════════════════════
513
- const COMMAND_GROUPS = {
514
- "Proof Loop": ["scan", "ship", "reality", "prove", "fix", "report"],
515
- "Setup & DX": ["install", "init", "doctor", "status", "watch", "launch"],
516
- "AI Truth": ["ctx", "guard", "context", "mdc"],
517
- "CI & Collaboration": ["gate", "pr", "badge"],
518
- "Reporting": ["report"],
519
- "Automation": ["ai-test", "mcp", "share"],
520
- };
521
-
522
- function getCommandGroup(command) {
523
- for (const [group, commands] of Object.entries(COMMAND_GROUPS)) {
524
- if (commands.includes(command)) return group;
525
- }
526
- return "Other";
235
+ function tierMeetsMinimum(current, required) {
236
+ const tierOrder = ['free', 'pro'];
237
+ const currentIndex = tierOrder.indexOf(current);
238
+ const requiredIndex = tierOrder.indexOf(required);
239
+ return currentIndex >= requiredIndex;
527
240
  }
528
241
 
529
- // ═══════════════════════════════════════════════════════════════════════════════
242
+ // ============================================================================
530
243
  // EXPORTS
531
- // ═══════════════════════════════════════════════════════════════════════════════
244
+ // ============================================================================
532
245
  module.exports = {
533
- // Core API
246
+ // Core
534
247
  getTier,
535
- getLimits,
536
248
  enforce,
537
249
  enforceOrExit,
538
250
  checkCommand,
539
251
 
540
- // Tier helpers
541
- tierMeetsMinimum,
542
- getTierLabel,
543
- getMinTierForFeature,
252
+ // Helpers
253
+ isPro,
544
254
  tierHasFeature,
545
- getFeaturesForTier,
546
-
547
- // Command grouping
548
- COMMAND_GROUPS,
549
- getCommandGroup,
255
+ getLimits,
256
+ tierMeetsMinimum,
550
257
 
551
258
  // Constants
552
259
  TIERS,
553
- ENTITLEMENTS,
554
- LIMITS,
260
+ TIER_LIMITS,
261
+ FREE_FEATURES,
262
+ PRO_FEATURES,
555
263
  EXIT_SUCCESS,
556
- EXIT_BLOCK_VERDICT,
557
264
  EXIT_FEATURE_NOT_ALLOWED,
558
- EXIT_MISCONFIG,
559
265
  };