@vibecheckai/cli 2.8.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (454) hide show
  1. package/README.md +8 -8
  2. package/bin/_deprecations.js +35 -0
  3. package/bin/_router.js +46 -0
  4. package/bin/cli-hygiene.js +241 -0
  5. package/bin/guardrail.js +834 -0
  6. package/bin/runners/cli-utils.js +1070 -0
  7. package/bin/runners/context/ai-task-decomposer.js +337 -0
  8. package/bin/runners/context/analyzer.js +462 -0
  9. package/bin/runners/context/api-contracts.js +427 -0
  10. package/bin/runners/context/context-diff.js +342 -0
  11. package/bin/runners/context/context-pruner.js +291 -0
  12. package/bin/runners/context/dependency-graph.js +414 -0
  13. package/bin/runners/context/generators/claude.js +107 -0
  14. package/bin/runners/context/generators/codex.js +108 -0
  15. package/bin/runners/context/generators/copilot.js +119 -0
  16. package/bin/runners/context/generators/cursor.js +514 -0
  17. package/bin/runners/context/generators/mcp.js +151 -0
  18. package/bin/runners/context/generators/windsurf.js +180 -0
  19. package/bin/runners/context/git-context.js +302 -0
  20. package/bin/runners/context/index.js +1042 -0
  21. package/bin/runners/context/insights.js +173 -0
  22. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  23. package/bin/runners/context/mcp-server/index.js +1176 -0
  24. package/bin/runners/context/mcp-server/package.json +24 -0
  25. package/bin/runners/context/memory.js +200 -0
  26. package/bin/runners/context/monorepo.js +215 -0
  27. package/bin/runners/context/multi-repo-federation.js +404 -0
  28. package/bin/runners/context/patterns.js +253 -0
  29. package/bin/runners/context/proof-context.js +972 -0
  30. package/bin/runners/context/security-scanner.js +303 -0
  31. package/bin/runners/context/semantic-search.js +350 -0
  32. package/bin/runners/context/shared.js +264 -0
  33. package/bin/runners/context/team-conventions.js +310 -0
  34. package/bin/runners/lib/ai-bridge.js +416 -0
  35. package/bin/runners/lib/analysis-core.js +271 -0
  36. package/bin/runners/lib/analyzers.js +541 -0
  37. package/bin/runners/lib/audit-bridge.js +391 -0
  38. package/bin/runners/lib/auth-truth.js +193 -0
  39. package/bin/runners/lib/auth.js +215 -0
  40. package/bin/runners/lib/backup.js +62 -0
  41. package/bin/runners/lib/billing.js +107 -0
  42. package/bin/runners/lib/claims.js +118 -0
  43. package/bin/runners/lib/cli-ui.js +540 -0
  44. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  45. package/bin/runners/lib/compliance-bridge.js +165 -0
  46. package/bin/runners/lib/contracts/auth-contract.js +194 -0
  47. package/bin/runners/lib/contracts/env-contract.js +178 -0
  48. package/bin/runners/lib/contracts/external-contract.js +198 -0
  49. package/bin/runners/lib/contracts/guard.js +168 -0
  50. package/bin/runners/lib/contracts/index.js +89 -0
  51. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  52. package/bin/runners/lib/contracts/route-contract.js +192 -0
  53. package/bin/runners/lib/detect.js +89 -0
  54. package/bin/runners/lib/doctor/autofix.js +254 -0
  55. package/bin/runners/lib/doctor/index.js +37 -0
  56. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  57. package/bin/runners/lib/doctor/modules/index.js +46 -0
  58. package/bin/runners/lib/doctor/modules/network.js +250 -0
  59. package/bin/runners/lib/doctor/modules/project.js +312 -0
  60. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  61. package/bin/runners/lib/doctor/modules/security.js +348 -0
  62. package/bin/runners/lib/doctor/modules/system.js +213 -0
  63. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  64. package/bin/runners/lib/doctor/reporter.js +262 -0
  65. package/bin/runners/lib/doctor/service.js +262 -0
  66. package/bin/runners/lib/doctor/types.js +113 -0
  67. package/bin/runners/lib/doctor/ui.js +263 -0
  68. package/bin/runners/lib/doctor-enhanced.js +233 -0
  69. package/bin/runners/lib/doctor-v2.js +608 -0
  70. package/bin/runners/lib/enforcement.js +72 -0
  71. package/bin/runners/lib/enterprise-detect.js +603 -0
  72. package/bin/runners/lib/enterprise-init.js +942 -0
  73. package/bin/runners/lib/entitlements-v2.js +381 -0
  74. package/bin/runners/lib/entitlements.generated.js +0 -0
  75. package/bin/runners/lib/entitlements.js +332 -0
  76. package/bin/runners/lib/env-template.js +66 -0
  77. package/bin/runners/lib/env.js +189 -0
  78. package/bin/runners/lib/error-handler.js +320 -0
  79. package/bin/runners/lib/firewall-prompt.js +50 -0
  80. package/bin/runners/lib/graph/graph-builder.js +265 -0
  81. package/bin/runners/lib/graph/html-renderer.js +413 -0
  82. package/bin/runners/lib/graph/index.js +32 -0
  83. package/bin/runners/lib/graph/runtime-collector.js +215 -0
  84. package/bin/runners/lib/graph/static-extractor.js +518 -0
  85. package/bin/runners/lib/init-wizard.js +308 -0
  86. package/bin/runners/lib/json-output.js +76 -0
  87. package/bin/runners/lib/llm.js +75 -0
  88. package/bin/runners/lib/meter.js +61 -0
  89. package/bin/runners/lib/missions/evidence.js +126 -0
  90. package/bin/runners/lib/missions/plan.js +69 -0
  91. package/bin/runners/lib/missions/templates.js +147 -0
  92. package/bin/runners/lib/patch.js +40 -0
  93. package/bin/runners/lib/permissions/auth-model.js +213 -0
  94. package/bin/runners/lib/permissions/idor-prover.js +205 -0
  95. package/bin/runners/lib/permissions/index.js +45 -0
  96. package/bin/runners/lib/permissions/matrix-builder.js +198 -0
  97. package/bin/runners/lib/pkgjson.js +28 -0
  98. package/bin/runners/lib/preflight.js +142 -0
  99. package/bin/runners/lib/reality-findings.js +84 -0
  100. package/bin/runners/lib/redact.js +29 -0
  101. package/bin/runners/lib/replay/capsule-manager.js +154 -0
  102. package/bin/runners/lib/replay/index.js +263 -0
  103. package/bin/runners/lib/replay/player.js +348 -0
  104. package/bin/runners/lib/replay/recorder.js +331 -0
  105. package/bin/runners/lib/report-engine.js +447 -0
  106. package/bin/runners/lib/report-html.js +1117 -0
  107. package/bin/runners/lib/report-templates.js +964 -0
  108. package/bin/runners/lib/route-detection.js +1140 -0
  109. package/bin/runners/lib/route-truth.js +477 -0
  110. package/bin/runners/lib/sandbox/index.js +59 -0
  111. package/bin/runners/lib/sandbox/proof-chain.js +399 -0
  112. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
  113. package/bin/runners/lib/sandbox/worktree.js +174 -0
  114. package/bin/runners/lib/scan-cache.js +330 -0
  115. package/bin/runners/lib/scan-output-schema.js +344 -0
  116. package/bin/runners/lib/score-history.js +282 -0
  117. package/bin/runners/lib/security-bridge.js +249 -0
  118. package/bin/runners/lib/server-usage.js +513 -0
  119. package/bin/runners/lib/share-pack.js +239 -0
  120. package/bin/runners/lib/snippets.js +67 -0
  121. package/bin/runners/lib/truth.js +667 -0
  122. package/bin/runners/lib/unified-output.js +189 -0
  123. package/bin/runners/lib/validate-patch.js +156 -0
  124. package/bin/runners/lib/verification.js +345 -0
  125. package/bin/runners/reality/engine.js +917 -0
  126. package/bin/runners/reality/flows.js +122 -0
  127. package/bin/runners/reality/report.js +378 -0
  128. package/bin/runners/reality/session.js +193 -0
  129. package/bin/runners/runAIAgent.js +2 -0
  130. package/bin/runners/runAudit.js +2 -0
  131. package/bin/runners/runAuth.js +106 -0
  132. package/bin/runners/runAutopilot.js +2 -0
  133. package/bin/runners/runBadge.js +2 -0
  134. package/bin/runners/runCertify.js +2 -0
  135. package/bin/runners/runClaimVerifier.js +483 -0
  136. package/bin/runners/runContext.js +56 -0
  137. package/bin/runners/runContextCompiler.js +385 -0
  138. package/bin/runners/runCtx.js +187 -0
  139. package/bin/runners/runCtxGuard.js +176 -0
  140. package/bin/runners/runCtxSync.js +116 -0
  141. package/bin/runners/runDashboard.js +10 -0
  142. package/bin/runners/runDoctor.js +245 -0
  143. package/bin/runners/runEnhancedShip.js +2 -0
  144. package/bin/runners/runFix.js +735 -0
  145. package/bin/runners/runFixPacks.js +2 -0
  146. package/bin/runners/runGate.js +17 -0
  147. package/bin/runners/runGraph.js +283 -0
  148. package/bin/runners/runInit.js +260 -0
  149. package/bin/runners/runInitGha.js +101 -0
  150. package/bin/runners/runInstall.js +76 -0
  151. package/bin/runners/runInteractive.js +388 -0
  152. package/bin/runners/runLaunch.js +2 -0
  153. package/bin/runners/runMcp.js +19 -0
  154. package/bin/runners/runMdc.js +2 -0
  155. package/bin/runners/runMissionGenerator.js +282 -0
  156. package/bin/runners/runNaturalLanguage.js +3 -0
  157. package/bin/runners/runPR.js +96 -0
  158. package/bin/runners/runPermissions.js +290 -0
  159. package/bin/runners/runPromptFirewall.js +211 -0
  160. package/bin/runners/runProof.js +2 -0
  161. package/bin/runners/runProve.js +392 -0
  162. package/bin/runners/runReality.js +489 -0
  163. package/bin/runners/runRealitySniff.js +2 -0
  164. package/bin/runners/runReplay.js +469 -0
  165. package/bin/runners/runReport.js +478 -0
  166. package/bin/runners/runScan.js +835 -0
  167. package/bin/runners/runShare.js +34 -0
  168. package/bin/runners/runShip.js +1062 -0
  169. package/bin/runners/runStatus.js +136 -0
  170. package/bin/runners/runTruthpack.js +634 -0
  171. package/bin/runners/runUpgrade.js +2 -0
  172. package/bin/runners/runValidate.js +2 -0
  173. package/bin/runners/runVerifyAgentOutput.js +2 -0
  174. package/bin/runners/runWatch.js +230 -0
  175. package/bin/runners/utils.js +360 -0
  176. package/bin/scan.js +612 -0
  177. package/bin/vibecheck.js +834 -0
  178. package/package.json +11 -11
  179. package/dist/autopatch/verified-autopatch.d.ts +0 -111
  180. package/dist/autopatch/verified-autopatch.d.ts.map +0 -1
  181. package/dist/autopatch/verified-autopatch.js +0 -503
  182. package/dist/autopatch/verified-autopatch.js.map +0 -1
  183. package/dist/bundles/index.js +0 -8
  184. package/dist/bundles/vibecheck-core.js +0 -25799
  185. package/dist/bundles/vibecheck-security.js +0 -208693
  186. package/dist/bundles/vibecheck-ship.js +0 -2318
  187. package/dist/commands/baseline.d.ts +0 -7
  188. package/dist/commands/baseline.d.ts.map +0 -1
  189. package/dist/commands/baseline.js +0 -79
  190. package/dist/commands/baseline.js.map +0 -1
  191. package/dist/commands/cache.d.ts +0 -13
  192. package/dist/commands/cache.d.ts.map +0 -1
  193. package/dist/commands/cache.js +0 -165
  194. package/dist/commands/cache.js.map +0 -1
  195. package/dist/commands/checkpoint.d.ts +0 -8
  196. package/dist/commands/checkpoint.d.ts.map +0 -1
  197. package/dist/commands/checkpoint.js +0 -35
  198. package/dist/commands/checkpoint.js.map +0 -1
  199. package/dist/commands/doctor.d.ts +0 -17
  200. package/dist/commands/doctor.d.ts.map +0 -1
  201. package/dist/commands/doctor.js +0 -226
  202. package/dist/commands/doctor.js.map +0 -1
  203. package/dist/commands/evidence.d.ts +0 -45
  204. package/dist/commands/evidence.d.ts.map +0 -1
  205. package/dist/commands/evidence.js +0 -197
  206. package/dist/commands/evidence.js.map +0 -1
  207. package/dist/commands/explain.d.ts +0 -8
  208. package/dist/commands/explain.d.ts.map +0 -1
  209. package/dist/commands/explain.js +0 -52
  210. package/dist/commands/explain.js.map +0 -1
  211. package/dist/commands/fix-consolidated.d.ts +0 -19
  212. package/dist/commands/fix-consolidated.d.ts.map +0 -1
  213. package/dist/commands/fix-consolidated.js +0 -165
  214. package/dist/commands/fix-consolidated.js.map +0 -1
  215. package/dist/commands/index.d.ts +0 -8
  216. package/dist/commands/index.d.ts.map +0 -1
  217. package/dist/commands/index.js +0 -15
  218. package/dist/commands/index.js.map +0 -1
  219. package/dist/commands/init.d.ts +0 -8
  220. package/dist/commands/init.d.ts.map +0 -1
  221. package/dist/commands/init.js +0 -125
  222. package/dist/commands/init.js.map +0 -1
  223. package/dist/commands/launcher.d.ts +0 -10
  224. package/dist/commands/launcher.d.ts.map +0 -1
  225. package/dist/commands/launcher.js +0 -174
  226. package/dist/commands/launcher.js.map +0 -1
  227. package/dist/commands/on.d.ts +0 -8
  228. package/dist/commands/on.d.ts.map +0 -1
  229. package/dist/commands/on.js +0 -123
  230. package/dist/commands/on.js.map +0 -1
  231. package/dist/commands/replay.d.ts +0 -8
  232. package/dist/commands/replay.d.ts.map +0 -1
  233. package/dist/commands/replay.js +0 -52
  234. package/dist/commands/replay.js.map +0 -1
  235. package/dist/commands/scan-consolidated.d.ts +0 -61
  236. package/dist/commands/scan-consolidated.d.ts.map +0 -1
  237. package/dist/commands/scan-consolidated.js +0 -243
  238. package/dist/commands/scan-consolidated.js.map +0 -1
  239. package/dist/commands/scan-secrets.d.ts +0 -47
  240. package/dist/commands/scan-secrets.d.ts.map +0 -1
  241. package/dist/commands/scan-secrets.js +0 -225
  242. package/dist/commands/scan-secrets.js.map +0 -1
  243. package/dist/commands/scan-vulnerabilities-enhanced.d.ts +0 -41
  244. package/dist/commands/scan-vulnerabilities-enhanced.d.ts.map +0 -1
  245. package/dist/commands/scan-vulnerabilities-enhanced.js +0 -368
  246. package/dist/commands/scan-vulnerabilities-enhanced.js.map +0 -1
  247. package/dist/commands/scan-vulnerabilities-osv.d.ts +0 -58
  248. package/dist/commands/scan-vulnerabilities-osv.d.ts.map +0 -1
  249. package/dist/commands/scan-vulnerabilities-osv.js +0 -722
  250. package/dist/commands/scan-vulnerabilities-osv.js.map +0 -1
  251. package/dist/commands/scan-vulnerabilities.d.ts +0 -32
  252. package/dist/commands/scan-vulnerabilities.d.ts.map +0 -1
  253. package/dist/commands/scan-vulnerabilities.js +0 -283
  254. package/dist/commands/scan-vulnerabilities.js.map +0 -1
  255. package/dist/commands/secrets-allowlist.d.ts +0 -7
  256. package/dist/commands/secrets-allowlist.d.ts.map +0 -1
  257. package/dist/commands/secrets-allowlist.js +0 -85
  258. package/dist/commands/secrets-allowlist.js.map +0 -1
  259. package/dist/commands/ship-consolidated.d.ts +0 -58
  260. package/dist/commands/ship-consolidated.d.ts.map +0 -1
  261. package/dist/commands/ship-consolidated.js +0 -515
  262. package/dist/commands/ship-consolidated.js.map +0 -1
  263. package/dist/commands/stats.d.ts +0 -8
  264. package/dist/commands/stats.d.ts.map +0 -1
  265. package/dist/commands/stats.js +0 -134
  266. package/dist/commands/stats.js.map +0 -1
  267. package/dist/commands/upgrade.d.ts +0 -8
  268. package/dist/commands/upgrade.d.ts.map +0 -1
  269. package/dist/commands/upgrade.js +0 -30
  270. package/dist/commands/upgrade.js.map +0 -1
  271. package/dist/fix/applicator.d.ts +0 -44
  272. package/dist/fix/applicator.d.ts.map +0 -1
  273. package/dist/fix/applicator.js +0 -144
  274. package/dist/fix/applicator.js.map +0 -1
  275. package/dist/fix/backup.d.ts +0 -38
  276. package/dist/fix/backup.d.ts.map +0 -1
  277. package/dist/fix/backup.js +0 -154
  278. package/dist/fix/backup.js.map +0 -1
  279. package/dist/fix/engine.d.ts +0 -55
  280. package/dist/fix/engine.d.ts.map +0 -1
  281. package/dist/fix/engine.js +0 -285
  282. package/dist/fix/engine.js.map +0 -1
  283. package/dist/fix/index.d.ts +0 -5
  284. package/dist/fix/index.d.ts.map +0 -1
  285. package/dist/fix/index.js +0 -12
  286. package/dist/fix/index.js.map +0 -1
  287. package/dist/fix/interactive.d.ts +0 -22
  288. package/dist/fix/interactive.d.ts.map +0 -1
  289. package/dist/fix/interactive.js +0 -172
  290. package/dist/fix/interactive.js.map +0 -1
  291. package/dist/formatters/index.d.ts +0 -6
  292. package/dist/formatters/index.d.ts.map +0 -1
  293. package/dist/formatters/index.js +0 -11
  294. package/dist/formatters/index.js.map +0 -1
  295. package/dist/formatters/sarif-enhanced.d.ts +0 -78
  296. package/dist/formatters/sarif-enhanced.d.ts.map +0 -1
  297. package/dist/formatters/sarif-enhanced.js +0 -144
  298. package/dist/formatters/sarif-enhanced.js.map +0 -1
  299. package/dist/formatters/sarif-v2.d.ts +0 -121
  300. package/dist/formatters/sarif-v2.d.ts.map +0 -1
  301. package/dist/formatters/sarif-v2.js +0 -356
  302. package/dist/formatters/sarif-v2.js.map +0 -1
  303. package/dist/formatters/sarif.d.ts +0 -72
  304. package/dist/formatters/sarif.d.ts.map +0 -1
  305. package/dist/formatters/sarif.js +0 -146
  306. package/dist/formatters/sarif.js.map +0 -1
  307. package/dist/index.d.ts +0 -61
  308. package/dist/index.d.ts.map +0 -1
  309. package/dist/index.js +0 -4388
  310. package/dist/index.js.map +0 -1
  311. package/dist/init/ci-generator.d.ts +0 -18
  312. package/dist/init/ci-generator.d.ts.map +0 -1
  313. package/dist/init/ci-generator.js +0 -317
  314. package/dist/init/ci-generator.js.map +0 -1
  315. package/dist/init/detect-framework.d.ts +0 -15
  316. package/dist/init/detect-framework.d.ts.map +0 -1
  317. package/dist/init/detect-framework.js +0 -301
  318. package/dist/init/detect-framework.js.map +0 -1
  319. package/dist/init/hooks-installer.d.ts +0 -22
  320. package/dist/init/hooks-installer.d.ts.map +0 -1
  321. package/dist/init/hooks-installer.js +0 -310
  322. package/dist/init/hooks-installer.js.map +0 -1
  323. package/dist/init/index.d.ts +0 -8
  324. package/dist/init/index.d.ts.map +0 -1
  325. package/dist/init/index.js +0 -22
  326. package/dist/init/index.js.map +0 -1
  327. package/dist/init/templates.d.ts +0 -402
  328. package/dist/init/templates.d.ts.map +0 -1
  329. package/dist/init/templates.js +0 -240
  330. package/dist/init/templates.js.map +0 -1
  331. package/dist/mcp/server.d.ts +0 -12
  332. package/dist/mcp/server.d.ts.map +0 -1
  333. package/dist/mcp/server.js +0 -42
  334. package/dist/mcp/server.js.map +0 -1
  335. package/dist/mcp/telemetry.d.ts +0 -40
  336. package/dist/mcp/telemetry.d.ts.map +0 -1
  337. package/dist/mcp/telemetry.js +0 -98
  338. package/dist/mcp/telemetry.js.map +0 -1
  339. package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts +0 -32
  340. package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts.map +0 -1
  341. package/dist/reality/no-dead-buttons/button-sweep-generator.js +0 -236
  342. package/dist/reality/no-dead-buttons/button-sweep-generator.js.map +0 -1
  343. package/dist/reality/no-dead-buttons/index.d.ts +0 -11
  344. package/dist/reality/no-dead-buttons/index.d.ts.map +0 -1
  345. package/dist/reality/no-dead-buttons/index.js +0 -18
  346. package/dist/reality/no-dead-buttons/index.js.map +0 -1
  347. package/dist/reality/no-dead-buttons/static-scanner.d.ts +0 -34
  348. package/dist/reality/no-dead-buttons/static-scanner.d.ts.map +0 -1
  349. package/dist/reality/no-dead-buttons/static-scanner.js +0 -230
  350. package/dist/reality/no-dead-buttons/static-scanner.js.map +0 -1
  351. package/dist/reality/reality-graph.d.ts +0 -192
  352. package/dist/reality/reality-graph.d.ts.map +0 -1
  353. package/dist/reality/reality-graph.js +0 -600
  354. package/dist/reality/reality-graph.js.map +0 -1
  355. package/dist/reality/reality-runner.d.ts +0 -89
  356. package/dist/reality/reality-runner.d.ts.map +0 -1
  357. package/dist/reality/reality-runner.js +0 -540
  358. package/dist/reality/reality-runner.js.map +0 -1
  359. package/dist/reality/receipt-generator.d.ts +0 -152
  360. package/dist/reality/receipt-generator.d.ts.map +0 -1
  361. package/dist/reality/receipt-generator.js +0 -495
  362. package/dist/reality/receipt-generator.js.map +0 -1
  363. package/dist/reality/runtime-tracer.d.ts +0 -75
  364. package/dist/reality/runtime-tracer.d.ts.map +0 -1
  365. package/dist/reality/runtime-tracer.js +0 -109
  366. package/dist/reality/runtime-tracer.js.map +0 -1
  367. package/dist/runtime/auth-utils.d.ts +0 -43
  368. package/dist/runtime/auth-utils.d.ts.map +0 -1
  369. package/dist/runtime/auth-utils.js +0 -130
  370. package/dist/runtime/auth-utils.js.map +0 -1
  371. package/dist/runtime/client.d.ts +0 -74
  372. package/dist/runtime/client.d.ts.map +0 -1
  373. package/dist/runtime/client.js +0 -222
  374. package/dist/runtime/client.js.map +0 -1
  375. package/dist/runtime/creds.d.ts +0 -48
  376. package/dist/runtime/creds.d.ts.map +0 -1
  377. package/dist/runtime/creds.js +0 -245
  378. package/dist/runtime/creds.js.map +0 -1
  379. package/dist/runtime/exit-codes.d.ts +0 -49
  380. package/dist/runtime/exit-codes.d.ts.map +0 -1
  381. package/dist/runtime/exit-codes.js +0 -93
  382. package/dist/runtime/exit-codes.js.map +0 -1
  383. package/dist/runtime/index.d.ts +0 -9
  384. package/dist/runtime/index.d.ts.map +0 -1
  385. package/dist/runtime/index.js +0 -25
  386. package/dist/runtime/index.js.map +0 -1
  387. package/dist/runtime/json-output.d.ts +0 -42
  388. package/dist/runtime/json-output.d.ts.map +0 -1
  389. package/dist/runtime/json-output.js +0 -59
  390. package/dist/runtime/json-output.js.map +0 -1
  391. package/dist/runtime/semver.d.ts +0 -37
  392. package/dist/runtime/semver.d.ts.map +0 -1
  393. package/dist/runtime/semver.js +0 -110
  394. package/dist/runtime/semver.js.map +0 -1
  395. package/dist/scan/dead-ui-detector.d.ts +0 -48
  396. package/dist/scan/dead-ui-detector.d.ts.map +0 -1
  397. package/dist/scan/dead-ui-detector.js +0 -170
  398. package/dist/scan/dead-ui-detector.js.map +0 -1
  399. package/dist/scan/playwright-sweep.d.ts +0 -40
  400. package/dist/scan/playwright-sweep.d.ts.map +0 -1
  401. package/dist/scan/playwright-sweep.js +0 -216
  402. package/dist/scan/playwright-sweep.js.map +0 -1
  403. package/dist/scan/proof-bundle.d.ts +0 -25
  404. package/dist/scan/proof-bundle.d.ts.map +0 -1
  405. package/dist/scan/proof-bundle.js +0 -203
  406. package/dist/scan/proof-bundle.js.map +0 -1
  407. package/dist/scan/proof-graph.d.ts +0 -59
  408. package/dist/scan/proof-graph.d.ts.map +0 -1
  409. package/dist/scan/proof-graph.js +0 -64
  410. package/dist/scan/proof-graph.js.map +0 -1
  411. package/dist/scan/reality-sniff.d.ts +0 -56
  412. package/dist/scan/reality-sniff.d.ts.map +0 -1
  413. package/dist/scan/reality-sniff.js +0 -200
  414. package/dist/scan/reality-sniff.js.map +0 -1
  415. package/dist/scan/structural-verifier.d.ts +0 -20
  416. package/dist/scan/structural-verifier.d.ts.map +0 -1
  417. package/dist/scan/structural-verifier.js +0 -112
  418. package/dist/scan/structural-verifier.js.map +0 -1
  419. package/dist/scan/verification-engine.d.ts +0 -47
  420. package/dist/scan/verification-engine.d.ts.map +0 -1
  421. package/dist/scan/verification-engine.js +0 -141
  422. package/dist/scan/verification-engine.js.map +0 -1
  423. package/dist/scanner/baseline.d.ts +0 -52
  424. package/dist/scanner/baseline.d.ts.map +0 -1
  425. package/dist/scanner/baseline.js +0 -85
  426. package/dist/scanner/baseline.js.map +0 -1
  427. package/dist/scanner/incremental.d.ts +0 -30
  428. package/dist/scanner/incremental.d.ts.map +0 -1
  429. package/dist/scanner/incremental.js +0 -82
  430. package/dist/scanner/incremental.js.map +0 -1
  431. package/dist/scanner/parallel.d.ts +0 -43
  432. package/dist/scanner/parallel.d.ts.map +0 -1
  433. package/dist/scanner/parallel.js +0 -99
  434. package/dist/scanner/parallel.js.map +0 -1
  435. package/dist/standalone.d.ts +0 -1
  436. package/dist/standalone.d.ts.map +0 -1
  437. package/dist/standalone.js +0 -1
  438. package/dist/standalone.js.map +0 -1
  439. package/dist/truth-pack/index.d.ts +0 -102
  440. package/dist/truth-pack/index.d.ts.map +0 -1
  441. package/dist/truth-pack/index.js +0 -694
  442. package/dist/truth-pack/index.js.map +0 -1
  443. package/dist/ui/frame.d.ts +0 -68
  444. package/dist/ui/frame.d.ts.map +0 -1
  445. package/dist/ui/frame.js +0 -165
  446. package/dist/ui/frame.js.map +0 -1
  447. package/dist/ui/index.d.ts +0 -5
  448. package/dist/ui/index.d.ts.map +0 -1
  449. package/dist/ui/index.js +0 -16
  450. package/dist/ui/index.js.map +0 -1
  451. package/dist/ui.d.ts +0 -36
  452. package/dist/ui.d.ts.map +0 -1
  453. package/dist/ui.js +0 -45
  454. package/dist/ui.js.map +0 -1
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Mission Generator v1
4
+ *
5
+ * Generates Assist Mission files from ship findings.
6
+ * Each mission is a Markdown file with YAML frontmatter.
7
+ *
8
+ * Usage:
9
+ * generateMissions(findings, projectPath)
10
+ */
11
+
12
+ import fs from 'fs/promises';
13
+ import path from 'path';
14
+ import yaml from 'js-yaml';
15
+
16
+ /**
17
+ * Generate mission files from findings
18
+ *
19
+ * @param {Object[]} findings - Array of findings from vibecheck ship
20
+ * @param {string} projectPath - Project root path
21
+ * @returns {Object} Generated missions info
22
+ */
23
+ export async function generateMissions(findings, projectPath = process.cwd()) {
24
+ const assistDir = path.join(projectPath, '.vibecheck', 'assist');
25
+ const missionsDir = path.join(assistDir, 'missions');
26
+
27
+ await fs.mkdir(missionsDir, { recursive: true });
28
+
29
+ // Group findings by category
30
+ const grouped = groupFindings(findings);
31
+
32
+ // Generate mission files
33
+ const missions = [];
34
+ let missionNumber = 1;
35
+
36
+ for (const [category, categoryFindings] of Object.entries(grouped)) {
37
+ for (const finding of categoryFindings) {
38
+ const mission = createMission(finding, missionNumber, category);
39
+ const filename = `${String(missionNumber).padStart(2, '0')}_${slugify(mission.title)}.md`;
40
+ const filePath = path.join(missionsDir, filename);
41
+
42
+ await fs.writeFile(filePath, formatMission(mission));
43
+
44
+ missions.push({
45
+ id: mission.missionId,
46
+ title: mission.title,
47
+ file: filename,
48
+ severity: mission.severity,
49
+ category: mission.category,
50
+ });
51
+
52
+ missionNumber++;
53
+ }
54
+ }
55
+
56
+ // Write plan.json
57
+ const plan = {
58
+ generatedAt: new Date().toISOString(),
59
+ totalMissions: missions.length,
60
+ byCategory: Object.fromEntries(
61
+ Object.entries(grouped).map(([cat, items]) => [cat, items.length])
62
+ ),
63
+ missions,
64
+ };
65
+
66
+ await fs.writeFile(
67
+ path.join(assistDir, 'plan.json'),
68
+ JSON.stringify(plan, null, 2)
69
+ );
70
+
71
+ console.log(`\n📋 Generated ${missions.length} missions in ${missionsDir}`);
72
+
73
+ return plan;
74
+ }
75
+
76
+ /**
77
+ * Group findings by category
78
+ */
79
+ function groupFindings(findings) {
80
+ const groups = {};
81
+
82
+ for (const finding of findings) {
83
+ const category = finding.category || 'general';
84
+ if (!groups[category]) groups[category] = [];
85
+ groups[category].push(finding);
86
+ }
87
+
88
+ // Sort by severity within each category
89
+ const severityOrder = { BLOCK: 0, WARN: 1, INFO: 2 };
90
+ for (const category of Object.keys(groups)) {
91
+ groups[category].sort((a, b) =>
92
+ (severityOrder[a.severity] || 3) - (severityOrder[b.severity] || 3)
93
+ );
94
+ }
95
+
96
+ return groups;
97
+ }
98
+
99
+ /**
100
+ * Create a mission object from a finding
101
+ */
102
+ function createMission(finding, number, category) {
103
+ const missionId = `M${String(number).padStart(2, '0')}`;
104
+
105
+ // Determine required claims based on finding type
106
+ const dependsOnClaims = [];
107
+ if (finding.type === 'dead_ui' || finding.type === 'route_mismatch') {
108
+ dependsOnClaims.push({
109
+ type: 'route_exists',
110
+ subject: { path: finding.route || finding.expectedRoute },
111
+ });
112
+ }
113
+ if (finding.type === 'auth_gap') {
114
+ dependsOnClaims.push({
115
+ type: 'auth_enforced',
116
+ subject: { path: finding.route },
117
+ });
118
+ }
119
+
120
+ // Determine applicable invariants
121
+ const invariants = [];
122
+ if (category === 'DeadUI' || finding.type === 'dead_ui') {
123
+ invariants.push('INV_NO_FAKE_SUCCESS', 'INV_NO_ROUTE_INVENTION');
124
+ }
125
+ if (category === 'Auth' || finding.type === 'auth_gap') {
126
+ invariants.push('INV_NO_BYPASS_ENTITLEMENTS', 'INV_NO_SILENT_CATCH_AUTH');
127
+ }
128
+ if (category === 'Billing') {
129
+ invariants.push('INV_NO_BYPASS_ENTITLEMENTS');
130
+ }
131
+
132
+ return {
133
+ missionId,
134
+ title: finding.title || `Fix ${category} issue`,
135
+ severity: finding.severity || 'WARN',
136
+ category,
137
+ scopeFiles: finding.files || [],
138
+ dependsOnClaims,
139
+ invariants,
140
+ assumptionBudget: 2,
141
+ finding,
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Format a mission as Markdown with YAML frontmatter
147
+ */
148
+ function formatMission(mission) {
149
+ const frontmatter = {
150
+ missionId: mission.missionId,
151
+ title: mission.title,
152
+ severity: mission.severity,
153
+ category: mission.category,
154
+ scopeFiles: mission.scopeFiles,
155
+ dependsOnClaims: mission.dependsOnClaims,
156
+ invariants: mission.invariants,
157
+ assumptionBudget: mission.assumptionBudget,
158
+ };
159
+
160
+ const finding = mission.finding;
161
+
162
+ const content = `---
163
+ ${yaml.dump(frontmatter, { lineWidth: -1 })}---
164
+
165
+ # Objective
166
+ ${finding.description || finding.title || 'Fix the identified issue.'}
167
+
168
+ # Truth Pack (authoritative)
169
+ Use the provided context slice and do not invent endpoints, env vars, or auth assumptions.
170
+
171
+ # Evidence Pack (must reference when editing)
172
+ - Finding ${finding.id || mission.missionId}:
173
+ ${mission.scopeFiles.map(f => ` - ${f}`).join('\n') || ' - (no specific files identified)'}
174
+ - Reason: ${finding.reason || finding.description || 'See finding details'}
175
+
176
+ # Required tool calls (before making claims)
177
+ ${generateRequiredToolCalls(mission)}
178
+
179
+ # Steps
180
+ ${generateSteps(mission)}
181
+
182
+ # Acceptance tests (must pass)
183
+ - vibecheck ship
184
+ - ${findTestCommand(mission)}
185
+ - No new blockers introduced
186
+
187
+ # Output requirements
188
+ - List changed files
189
+ - Explain each change with evidence refs
190
+ - Provide final ship verdict result
191
+ `;
192
+
193
+ return content;
194
+ }
195
+
196
+ /**
197
+ * Generate required tool calls for the mission
198
+ */
199
+ function generateRequiredToolCalls(mission) {
200
+ const calls = [];
201
+ let callNum = 1;
202
+
203
+ for (const claim of mission.dependsOnClaims) {
204
+ calls.push(`${callNum}) validate_claim(${claim.type} ${JSON.stringify(claim.subject)})`);
205
+ callNum++;
206
+ }
207
+
208
+ if (calls.length === 0) {
209
+ calls.push('1) vibecheck.get_truthpack() - Get current truth state');
210
+ }
211
+
212
+ calls.push(`${callNum}) search_evidence("${mission.category.toLowerCase()}", globs=["src/**","apps/**"])`);
213
+
214
+ return calls.join('\n');
215
+ }
216
+
217
+ /**
218
+ * Generate steps for the mission
219
+ */
220
+ function generateSteps(mission) {
221
+ const steps = [];
222
+ const finding = mission.finding;
223
+
224
+ switch (mission.category) {
225
+ case 'DeadUI':
226
+ steps.push('1) Identify why the UI action is dead (early return / missing handler / missing await).');
227
+ steps.push('2) If route mismatch exists, align client call to an existing proven route (do not invent).');
228
+ steps.push('3) Ensure success UI happens only after response ok.');
229
+ steps.push('4) Ensure errors surface (no empty catch).');
230
+ break;
231
+
232
+ case 'Auth':
233
+ steps.push('1) Verify the auth gap is real by checking middleware/guard configuration.');
234
+ steps.push('2) Add or fix the auth middleware on the affected route.');
235
+ steps.push('3) Ensure auth errors are properly handled (no silent failures).');
236
+ steps.push('4) Test both authenticated and unauthenticated access.');
237
+ break;
238
+
239
+ case 'Billing':
240
+ steps.push('1) Verify the billing gate is missing or bypassable.');
241
+ steps.push('2) Add server-side tier/entitlement check.');
242
+ steps.push('3) Ensure client-side checks match server-side enforcement.');
243
+ steps.push('4) Remove any bypass flags or dev-only overrides.');
244
+ break;
245
+
246
+ case 'Security':
247
+ steps.push('1) Identify the security vulnerability.');
248
+ steps.push('2) Apply the appropriate fix without breaking functionality.');
249
+ steps.push('3) Add validation/sanitization as needed.');
250
+ steps.push('4) Verify the fix does not introduce new vulnerabilities.');
251
+ break;
252
+
253
+ default:
254
+ steps.push('1) Analyze the finding to understand the root cause.');
255
+ steps.push('2) Identify the minimal change needed to fix the issue.');
256
+ steps.push('3) Implement the fix with proper error handling.');
257
+ steps.push('4) Verify the fix resolves the finding.');
258
+ }
259
+
260
+ return steps.join('\n');
261
+ }
262
+
263
+ /**
264
+ * Find the appropriate test command
265
+ */
266
+ function findTestCommand(mission) {
267
+ // This would ideally come from the truth pack's project.scripts
268
+ return 'pnpm test OR npm test (if present)';
269
+ }
270
+
271
+ /**
272
+ * Convert title to slug
273
+ */
274
+ function slugify(text) {
275
+ return text
276
+ .toLowerCase()
277
+ .replace(/[^a-z0-9]+/g, '_')
278
+ .replace(/^_+|_+$/g, '')
279
+ .slice(0, 40);
280
+ }
281
+
282
+ export default { generateMissions };
@@ -0,0 +1,3 @@
1
+ function isNaturalLanguageCommand(s) { return false; }
2
+ async function runNaturalLanguage(s) { return 1; }
3
+ module.exports = { runNaturalLanguage, isNaturalLanguageCommand };
@@ -0,0 +1,96 @@
1
+ // bin/runners/runPR.js
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const { shipCore } = require("./runShip");
5
+
6
+ function ensureDir(p) {
7
+ fs.mkdirSync(p, { recursive: true });
8
+ }
9
+
10
+ function severityCounts(findings) {
11
+ const c = { BLOCK: 0, WARN: 0, INFO: 0 };
12
+ for (const f of findings || []) {
13
+ if (f.severity === "BLOCK") c.BLOCK++;
14
+ else if (f.severity === "WARN") c.WARN++;
15
+ else c.INFO++;
16
+ }
17
+ return c;
18
+ }
19
+
20
+ function toEmojiVerdict(v) {
21
+ if (v === "SHIP") return "✅ SHIP";
22
+ if (v === "WARN") return "⚠️ WARN";
23
+ return "🛑 BLOCK";
24
+ }
25
+
26
+ function buildPrMarkdown({ report, maxFindings = 12 } = {}) {
27
+ const verdict = report?.meta?.verdict || "unknown";
28
+ const findings = report?.findings || [];
29
+ const counts = severityCounts(findings);
30
+
31
+ const top = findings
32
+ .filter(f => f.severity === "BLOCK" || f.severity === "WARN")
33
+ .slice(0, maxFindings);
34
+
35
+ const lines = [];
36
+ lines.push(`## vibecheck — ${toEmojiVerdict(verdict)}`);
37
+ lines.push(``);
38
+ lines.push(`**Reality summary:** BLOCK=${counts.BLOCK} • WARN=${counts.WARN}`);
39
+ lines.push(``);
40
+
41
+ if (!top.length) {
42
+ lines.push(`✅ No blockers. Ship it.`);
43
+ return lines.join("\n");
44
+ }
45
+
46
+ lines.push(`### Top findings`);
47
+ for (const f of top) {
48
+ lines.push(`- **${f.severity}** \`${f.id}\` — ${f.title}`);
49
+ const ev = (f.evidence || [])[0];
50
+ if (ev?.file) {
51
+ lines.push(` - Evidence: \`${ev.file}:${ev.lines}\` (${ev.reason})`);
52
+ if (ev.snippetHash) lines.push(` - SnipHash: \`${ev.snippetHash}\``);
53
+ }
54
+ const hint = (f.fixHints || [])[0];
55
+ if (hint) lines.push(` - Fix: ${hint}`);
56
+ }
57
+
58
+ if (findings.length > top.length) {
59
+ lines.push(``);
60
+ lines.push(`_…and ${findings.length - top.length} more finding(s). See \`.vibecheck/last_ship.json\` for full details._`);
61
+ }
62
+
63
+ return lines.join("\n");
64
+ }
65
+
66
+ function exitCodeForVerdict(verdict, { failOnWarn = false } = {}) {
67
+ if (verdict === "SHIP") return 0;
68
+ if (verdict === "WARN") return failOnWarn ? 1 : 0;
69
+ return 2; // BLOCK
70
+ }
71
+
72
+ async function runPR({
73
+ repoRoot,
74
+ fastifyEntry,
75
+ out,
76
+ failOnWarn = false,
77
+ maxFindings = 12
78
+ } = {}) {
79
+ const root = repoRoot || process.cwd();
80
+
81
+ const { report, verdict } = await shipCore({ repoRoot: root, fastifyEntry, noWrite: false });
82
+
83
+ const md = buildPrMarkdown({ report, maxFindings });
84
+
85
+ if (out) {
86
+ const outAbs = path.isAbsolute(out) ? out : path.join(root, out);
87
+ ensureDir(path.dirname(outAbs));
88
+ fs.writeFileSync(outAbs, md, "utf8");
89
+ }
90
+
91
+ console.log(md);
92
+
93
+ process.exitCode = exitCodeForVerdict(verdict, { failOnWarn });
94
+ }
95
+
96
+ module.exports = { runPR };
@@ -0,0 +1,290 @@
1
+ /**
2
+ * vibecheck permissions - AuthZ Matrix & IDOR Detection
3
+ *
4
+ * Verifies authorization is correct, not just present:
5
+ * - Which roles can hit which routes
6
+ * - Which UI actions leak data cross-user (IDOR)
7
+ * - Which admin endpoints are accidentally public
8
+ */
9
+
10
+ "use strict";
11
+
12
+ const path = require("path");
13
+ const fs = require("fs");
14
+ const { buildTruthpack, loadTruthpack } = require("./lib/truth");
15
+ const {
16
+ extractAuthModel,
17
+ buildAuthZMatrix,
18
+ formatMatrix,
19
+ detectIDORCandidates,
20
+ buildIDORTestPlan,
21
+ formatIDORPlan
22
+ } = require("./lib/permissions");
23
+
24
+ const c = {
25
+ reset: '\x1b[0m',
26
+ bold: '\x1b[1m',
27
+ dim: '\x1b[2m',
28
+ green: '\x1b[32m',
29
+ yellow: '\x1b[33m',
30
+ cyan: '\x1b[36m',
31
+ red: '\x1b[31m',
32
+ blue: '\x1b[34m',
33
+ };
34
+
35
+ function ensureDir(p) {
36
+ fs.mkdirSync(p, { recursive: true });
37
+ }
38
+
39
+ async function runPermissions(args) {
40
+ const opts = parseArgs(args);
41
+
42
+ if (opts.help) {
43
+ printHelp();
44
+ return 0;
45
+ }
46
+
47
+ const root = path.resolve(opts.path || process.cwd());
48
+ const outDir = path.join(root, ".vibecheck", "permissions");
49
+ ensureDir(outDir);
50
+
51
+ console.log(`\n${c.cyan}${c.bold}🔐 vibecheck permissions${c.reset}`);
52
+
53
+ // Load or build truthpack
54
+ let truthpack = loadTruthpack(root);
55
+ if (!truthpack) {
56
+ console.log(`${c.dim}Building truthpack...${c.reset}`);
57
+ truthpack = await buildTruthpack({ repoRoot: root, fastifyEntry: opts.fastifyEntry });
58
+ }
59
+
60
+ // Extract auth model
61
+ console.log(`${c.dim}Extracting auth model...${c.reset}`);
62
+ const authModel = await extractAuthModel(root, truthpack);
63
+
64
+ // Save auth model
65
+ fs.writeFileSync(
66
+ path.join(outDir, "auth-model.json"),
67
+ JSON.stringify(authModel, null, 2),
68
+ "utf8"
69
+ );
70
+
71
+ if (opts.learn) {
72
+ // Learning mode - just extract and display
73
+ console.log(`\n${c.bold}Auth Model${c.reset}`);
74
+ console.log(` Roles: ${authModel.roles.map(r => r.name).join(", ")}`);
75
+ console.log(` Protected patterns: ${authModel.protectedPatterns?.length || 0}`);
76
+ console.log(` Routes: ${authModel.routes.length}`);
77
+ console.log(` RBAC patterns: ${authModel.rbacPatterns.length}`);
78
+
79
+ if (authModel.roles.length > 0) {
80
+ console.log(`\n${c.bold}Detected Roles${c.reset}`);
81
+ for (const role of authModel.roles) {
82
+ console.log(` - ${role.name} (${role.evidence.length} references)`);
83
+ }
84
+ }
85
+
86
+ console.log(`\n${c.dim}Auth model saved to: .vibecheck/permissions/auth-model.json${c.reset}`);
87
+ console.log(`${c.dim}Run 'vibecheck permissions --prove' to verify at runtime${c.reset}\n`);
88
+ return 0;
89
+ }
90
+
91
+ if (opts.prove) {
92
+ // Runtime verification mode
93
+ if (!opts.url) {
94
+ console.log(`${c.red}Error: --prove requires --url${c.reset}`);
95
+ return 1;
96
+ }
97
+
98
+ console.log(`${c.dim}Running permission verification against ${opts.url}...${c.reset}`);
99
+
100
+ // This would run actual browser tests
101
+ // For now, show what would be tested
102
+ const matrix = buildAuthZMatrix(authModel, null);
103
+
104
+ console.log(`\n${c.bold}AuthZ Matrix${c.reset}`);
105
+ console.log(` Routes to verify: ${matrix.routes.length}`);
106
+ console.log(` Roles to test: ${matrix.roles.join(", ")}`);
107
+
108
+ // Save matrix
109
+ fs.writeFileSync(
110
+ path.join(outDir, "authz-matrix.json"),
111
+ JSON.stringify(matrix, null, 2),
112
+ "utf8"
113
+ );
114
+
115
+ fs.writeFileSync(
116
+ path.join(outDir, "authz-matrix.md"),
117
+ formatMatrix(matrix),
118
+ "utf8"
119
+ );
120
+
121
+ const blocks = matrix.violations.filter(v => v.severity === "BLOCK").length;
122
+ const warns = matrix.violations.filter(v => v.severity === "WARN").length;
123
+
124
+ if (matrix.violations.length > 0) {
125
+ console.log(`\n${c.bold}Violations${c.reset}`);
126
+ for (const v of matrix.violations.slice(0, 10)) {
127
+ const icon = v.severity === "BLOCK" ? `${c.red}✗` : `${c.yellow}⚠`;
128
+ console.log(` ${icon} ${v.message}${c.reset}`);
129
+ }
130
+ } else {
131
+ console.log(`\n${c.green}✓ No violations detected${c.reset}`);
132
+ }
133
+
134
+ console.log(`\n${c.dim}Matrix saved to: .vibecheck/permissions/authz-matrix.json${c.reset}`);
135
+ console.log(`\n${c.bold}Verdict:${c.reset} ${blocks ? `${c.red}🛑 BLOCK${c.reset}` : warns ? `${c.yellow}⚠️ WARN${c.reset}` : `${c.green}✅ CLEAN${c.reset}`}`);
136
+
137
+ return blocks ? 2 : warns ? 1 : 0;
138
+ }
139
+
140
+ if (opts.matrix) {
141
+ // Output matrix mode
142
+ const matrix = buildAuthZMatrix(authModel, null);
143
+ console.log("\n" + formatMatrix(matrix));
144
+
145
+ fs.writeFileSync(
146
+ path.join(outDir, "authz-matrix.json"),
147
+ JSON.stringify(matrix, null, 2),
148
+ "utf8"
149
+ );
150
+
151
+ fs.writeFileSync(
152
+ path.join(outDir, "authz-matrix.md"),
153
+ formatMatrix(matrix),
154
+ "utf8"
155
+ );
156
+
157
+ return 0;
158
+ }
159
+
160
+ if (opts.idor) {
161
+ // IDOR detection mode
162
+ console.log(`${c.dim}Detecting IDOR candidates...${c.reset}`);
163
+
164
+ const candidates = detectIDORCandidates(authModel);
165
+ const plan = buildIDORTestPlan(candidates, { safe: opts.safe });
166
+
167
+ console.log(`\n${c.bold}IDOR Candidates${c.reset}`);
168
+ console.log(` Detected: ${candidates.length}`);
169
+
170
+ if (candidates.length > 0) {
171
+ for (const c of candidates.slice(0, 10)) {
172
+ console.log(` - ${c.resourceType}: ${c.path}`);
173
+ }
174
+ }
175
+
176
+ // Save plan
177
+ fs.writeFileSync(
178
+ path.join(outDir, "idor-plan.json"),
179
+ JSON.stringify(plan, null, 2),
180
+ "utf8"
181
+ );
182
+
183
+ fs.writeFileSync(
184
+ path.join(outDir, "idor-plan.md"),
185
+ formatIDORPlan(plan),
186
+ "utf8"
187
+ );
188
+
189
+ console.log(`\n${c.dim}IDOR plan saved to: .vibecheck/permissions/idor-plan.json${c.reset}`);
190
+
191
+ if (!opts.safe) {
192
+ console.log(`\n${c.yellow}⚠️ IDOR tests require --safe flag for first-party testing${c.reset}`);
193
+ }
194
+
195
+ return 0;
196
+ }
197
+
198
+ // Default: show summary
199
+ console.log(`\n${c.bold}Summary${c.reset}`);
200
+ console.log(` Roles: ${authModel.roles.length}`);
201
+ console.log(` Routes: ${authModel.routes.length}`);
202
+ console.log(` Protected patterns: ${authModel.protectedPatterns?.length || 0}`);
203
+
204
+ console.log(`\n${c.bold}Run one of:${c.reset}`);
205
+ console.log(` ${c.cyan}vibecheck permissions --learn${c.reset} Extract auth model from code`);
206
+ console.log(` ${c.cyan}vibecheck permissions --prove${c.reset} Runtime verification`);
207
+ console.log(` ${c.cyan}vibecheck permissions --matrix${c.reset} Output AuthZ matrix`);
208
+ console.log(` ${c.cyan}vibecheck permissions --idor${c.reset} Detect IDOR candidates\n`);
209
+
210
+ return 0;
211
+ }
212
+
213
+ function parseArgs(args) {
214
+ const opts = {
215
+ path: process.cwd(),
216
+ url: null,
217
+ learn: false,
218
+ prove: false,
219
+ matrix: false,
220
+ idor: false,
221
+ safe: false,
222
+ fastifyEntry: null,
223
+ help: false,
224
+ };
225
+
226
+ for (let i = 0; i < args.length; i++) {
227
+ const arg = args[i];
228
+ if (arg === "--learn") opts.learn = true;
229
+ else if (arg === "--prove") opts.prove = true;
230
+ else if (arg === "--matrix") opts.matrix = true;
231
+ else if (arg === "--idor") opts.idor = true;
232
+ else if (arg === "--safe") opts.safe = true;
233
+ else if (arg === "--url") opts.url = args[++i];
234
+ else if (arg === "--fastify-entry") opts.fastifyEntry = args[++i];
235
+ else if (arg === "--path" || arg === "-p") opts.path = args[++i];
236
+ else if (arg === "--help" || arg === "-h") opts.help = true;
237
+ }
238
+
239
+ return opts;
240
+ }
241
+
242
+ function printHelp() {
243
+ console.log(`
244
+ ${c.cyan}${c.bold}🔐 vibecheck permissions${c.reset} - AuthZ Matrix & IDOR Detection
245
+
246
+ Verify authorization is correct, not just present.
247
+
248
+ ${c.bold}USAGE${c.reset}
249
+ vibecheck permissions --learn ${c.dim}# Extract auth model from code${c.reset}
250
+ vibecheck permissions --prove --url ${c.dim}# Runtime verification${c.reset}
251
+ vibecheck permissions --matrix ${c.dim}# Output full AuthZ matrix${c.reset}
252
+ vibecheck permissions --idor --safe ${c.dim}# IDOR detection (first-party)${c.reset}
253
+
254
+ ${c.bold}OPTIONS${c.reset}
255
+ --learn Extract auth model from code
256
+ --prove Runtime verification of permissions
257
+ --matrix Output AuthZ matrix
258
+ --idor Detect IDOR candidates
259
+ --safe Enable safe mode for IDOR testing (required)
260
+ --url <url> Target URL for runtime testing
261
+ --fastify-entry Fastify entry file (e.g. src/server.ts)
262
+ --path, -p Project path (default: current directory)
263
+ --help, -h Show this help
264
+
265
+ ${c.bold}FINDINGS${c.reset}
266
+ ${c.red}BLOCK${c.reset} Endpoint accessible as anon that should require auth
267
+ ${c.red}BLOCK${c.reset} User A can access User B's resource (IDOR)
268
+ ${c.red}BLOCK${c.reset} Role mismatch between UI + server
269
+ ${c.yellow}WARN${c.reset} Admin endpoint missing role check (static)
270
+
271
+ ${c.bold}OUTPUT${c.reset}
272
+ .vibecheck/permissions/
273
+ auth-model.json Extracted auth model
274
+ authz-matrix.json Full authorization matrix
275
+ authz-matrix.md Human-readable matrix
276
+ idor-plan.json IDOR test plan
277
+
278
+ ${c.bold}SAFETY${c.reset}
279
+ IDOR tests only run with --idor --safe flag
280
+ Only use on local dev/staging with explicit consent
281
+ Configure test users in .vibecheck/config.json
282
+
283
+ ${c.bold}EXAMPLES${c.reset}
284
+ vibecheck permissions --learn ${c.dim}# Extract model${c.reset}
285
+ vibecheck permissions --prove --url http://localhost:3000
286
+ vibecheck permissions --idor --safe ${c.dim}# IDOR detection${c.reset}
287
+ `);
288
+ }
289
+
290
+ module.exports = { runPermissions };