@delegance/claude-autopilot 5.0.1 → 5.0.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 (412) hide show
  1. package/dist/src/adapters/review-engine/codex.js +13 -1
  2. package/dist/src/cli/index.js +39 -1
  3. package/dist/src/cli/preflight.js +17 -4
  4. package/dist/src/cli/scan.js +12 -0
  5. package/package.json +4 -3
  6. package/dist/presets/go/rules/go-sql-injection.d.ts.map +0 -1
  7. package/dist/presets/go/rules/go-sql-injection.js.map +0 -1
  8. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.d.ts.map +0 -1
  9. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.js.map +0 -1
  10. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.d.ts.map +0 -1
  11. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.js.map +0 -1
  12. package/dist/presets/rails-postgres/rules/rails-sql-injection.d.ts.map +0 -1
  13. package/dist/presets/rails-postgres/rules/rails-sql-injection.js.map +0 -1
  14. package/dist/presets/t3/rules/t3-server-only.d.ts.map +0 -1
  15. package/dist/presets/t3/rules/t3-server-only.js.map +0 -1
  16. package/dist/src/adapters/base.d.ts.map +0 -1
  17. package/dist/src/adapters/base.js.map +0 -1
  18. package/dist/src/adapters/council/claude.d.ts.map +0 -1
  19. package/dist/src/adapters/council/claude.js.map +0 -1
  20. package/dist/src/adapters/council/openai.d.ts.map +0 -1
  21. package/dist/src/adapters/council/openai.js.map +0 -1
  22. package/dist/src/adapters/council/types.d.ts.map +0 -1
  23. package/dist/src/adapters/council/types.js.map +0 -1
  24. package/dist/src/adapters/loader.d.ts.map +0 -1
  25. package/dist/src/adapters/loader.js.map +0 -1
  26. package/dist/src/adapters/migration-runner/supabase.d.ts.map +0 -1
  27. package/dist/src/adapters/migration-runner/supabase.js.map +0 -1
  28. package/dist/src/adapters/migration-runner/types.d.ts.map +0 -1
  29. package/dist/src/adapters/migration-runner/types.js.map +0 -1
  30. package/dist/src/adapters/review-bot-parser/cursor.d.ts.map +0 -1
  31. package/dist/src/adapters/review-bot-parser/cursor.js.map +0 -1
  32. package/dist/src/adapters/review-bot-parser/declarative-base.d.ts.map +0 -1
  33. package/dist/src/adapters/review-bot-parser/declarative-base.js.map +0 -1
  34. package/dist/src/adapters/review-bot-parser/types.d.ts.map +0 -1
  35. package/dist/src/adapters/review-bot-parser/types.js.map +0 -1
  36. package/dist/src/adapters/review-engine/auto.d.ts.map +0 -1
  37. package/dist/src/adapters/review-engine/auto.js.map +0 -1
  38. package/dist/src/adapters/review-engine/claude.d.ts.map +0 -1
  39. package/dist/src/adapters/review-engine/claude.js.map +0 -1
  40. package/dist/src/adapters/review-engine/codex.d.ts.map +0 -1
  41. package/dist/src/adapters/review-engine/codex.js.map +0 -1
  42. package/dist/src/adapters/review-engine/gemini.d.ts.map +0 -1
  43. package/dist/src/adapters/review-engine/gemini.js.map +0 -1
  44. package/dist/src/adapters/review-engine/openai-compatible.d.ts.map +0 -1
  45. package/dist/src/adapters/review-engine/openai-compatible.js.map +0 -1
  46. package/dist/src/adapters/review-engine/parse-output.d.ts.map +0 -1
  47. package/dist/src/adapters/review-engine/parse-output.js.map +0 -1
  48. package/dist/src/adapters/review-engine/prompt-builder.d.ts.map +0 -1
  49. package/dist/src/adapters/review-engine/prompt-builder.js.map +0 -1
  50. package/dist/src/adapters/review-engine/types.d.ts.map +0 -1
  51. package/dist/src/adapters/review-engine/types.js.map +0 -1
  52. package/dist/src/adapters/vcs-host/commit-status.d.ts.map +0 -1
  53. package/dist/src/adapters/vcs-host/commit-status.js.map +0 -1
  54. package/dist/src/adapters/vcs-host/github.d.ts.map +0 -1
  55. package/dist/src/adapters/vcs-host/github.js.map +0 -1
  56. package/dist/src/adapters/vcs-host/types.d.ts.map +0 -1
  57. package/dist/src/adapters/vcs-host/types.js.map +0 -1
  58. package/dist/src/cli/_pkg-root.d.ts.map +0 -1
  59. package/dist/src/cli/_pkg-root.js.map +0 -1
  60. package/dist/src/cli/autoregress-bridge.d.ts.map +0 -1
  61. package/dist/src/cli/autoregress-bridge.js.map +0 -1
  62. package/dist/src/cli/baseline.d.ts.map +0 -1
  63. package/dist/src/cli/baseline.js.map +0 -1
  64. package/dist/src/cli/ci.d.ts.map +0 -1
  65. package/dist/src/cli/ci.js.map +0 -1
  66. package/dist/src/cli/costs.d.ts.map +0 -1
  67. package/dist/src/cli/costs.js.map +0 -1
  68. package/dist/src/cli/council.d.ts.map +0 -1
  69. package/dist/src/cli/council.js.map +0 -1
  70. package/dist/src/cli/detector.d.ts.map +0 -1
  71. package/dist/src/cli/detector.js.map +0 -1
  72. package/dist/src/cli/explain.d.ts.map +0 -1
  73. package/dist/src/cli/explain.js.map +0 -1
  74. package/dist/src/cli/fix.d.ts.map +0 -1
  75. package/dist/src/cli/fix.js.map +0 -1
  76. package/dist/src/cli/hook.d.ts.map +0 -1
  77. package/dist/src/cli/hook.js.map +0 -1
  78. package/dist/src/cli/ignore-helper.d.ts.map +0 -1
  79. package/dist/src/cli/ignore-helper.js.map +0 -1
  80. package/dist/src/cli/index.d.ts.map +0 -1
  81. package/dist/src/cli/index.js.map +0 -1
  82. package/dist/src/cli/lsp.d.ts.map +0 -1
  83. package/dist/src/cli/lsp.js.map +0 -1
  84. package/dist/src/cli/mcp.d.ts.map +0 -1
  85. package/dist/src/cli/mcp.js.map +0 -1
  86. package/dist/src/cli/migrate-v4.d.ts.map +0 -1
  87. package/dist/src/cli/migrate-v4.js.map +0 -1
  88. package/dist/src/cli/pr-comment.d.ts.map +0 -1
  89. package/dist/src/cli/pr-comment.js.map +0 -1
  90. package/dist/src/cli/pr-desc.d.ts.map +0 -1
  91. package/dist/src/cli/pr-desc.js.map +0 -1
  92. package/dist/src/cli/pr-review-comments.d.ts.map +0 -1
  93. package/dist/src/cli/pr-review-comments.js.map +0 -1
  94. package/dist/src/cli/pr.d.ts.map +0 -1
  95. package/dist/src/cli/pr.js.map +0 -1
  96. package/dist/src/cli/preflight.d.ts.map +0 -1
  97. package/dist/src/cli/preflight.js.map +0 -1
  98. package/dist/src/cli/report.d.ts.map +0 -1
  99. package/dist/src/cli/report.js.map +0 -1
  100. package/dist/src/cli/run.d.ts.map +0 -1
  101. package/dist/src/cli/run.js.map +0 -1
  102. package/dist/src/cli/scan.d.ts.map +0 -1
  103. package/dist/src/cli/scan.js.map +0 -1
  104. package/dist/src/cli/setup.d.ts.map +0 -1
  105. package/dist/src/cli/setup.js.map +0 -1
  106. package/dist/src/cli/test-gen.d.ts.map +0 -1
  107. package/dist/src/cli/test-gen.js.map +0 -1
  108. package/dist/src/cli/triage.d.ts.map +0 -1
  109. package/dist/src/cli/triage.js.map +0 -1
  110. package/dist/src/cli/watch.d.ts.map +0 -1
  111. package/dist/src/cli/watch.js.map +0 -1
  112. package/dist/src/cli/worker.d.ts.map +0 -1
  113. package/dist/src/cli/worker.js.map +0 -1
  114. package/dist/src/core/cache/cached-engine.d.ts.map +0 -1
  115. package/dist/src/core/cache/cached-engine.js.map +0 -1
  116. package/dist/src/core/cache/review-cache.d.ts.map +0 -1
  117. package/dist/src/core/cache/review-cache.js.map +0 -1
  118. package/dist/src/core/chunking/index.d.ts.map +0 -1
  119. package/dist/src/core/chunking/index.js.map +0 -1
  120. package/dist/src/core/chunking/risk-ranker.d.ts.map +0 -1
  121. package/dist/src/core/chunking/risk-ranker.js.map +0 -1
  122. package/dist/src/core/config/loader.d.ts.map +0 -1
  123. package/dist/src/core/config/loader.js.map +0 -1
  124. package/dist/src/core/config/preset-resolver.d.ts.map +0 -1
  125. package/dist/src/core/config/preset-resolver.js.map +0 -1
  126. package/dist/src/core/config/schema.d.ts.map +0 -1
  127. package/dist/src/core/config/schema.js.map +0 -1
  128. package/dist/src/core/config/types.d.ts.map +0 -1
  129. package/dist/src/core/config/types.js.map +0 -1
  130. package/dist/src/core/council/config.d.ts.map +0 -1
  131. package/dist/src/core/council/config.js.map +0 -1
  132. package/dist/src/core/council/context.d.ts.map +0 -1
  133. package/dist/src/core/council/context.js.map +0 -1
  134. package/dist/src/core/council/runner.d.ts.map +0 -1
  135. package/dist/src/core/council/runner.js.map +0 -1
  136. package/dist/src/core/council/types.d.ts.map +0 -1
  137. package/dist/src/core/council/types.js.map +0 -1
  138. package/dist/src/core/detect/git-context.d.ts.map +0 -1
  139. package/dist/src/core/detect/git-context.js.map +0 -1
  140. package/dist/src/core/detect/llm-key.d.ts.map +0 -1
  141. package/dist/src/core/detect/llm-key.js.map +0 -1
  142. package/dist/src/core/detect/protected-paths.d.ts.map +0 -1
  143. package/dist/src/core/detect/protected-paths.js.map +0 -1
  144. package/dist/src/core/detect/provider-usage.d.ts.map +0 -1
  145. package/dist/src/core/detect/provider-usage.js.map +0 -1
  146. package/dist/src/core/detect/stack.d.ts.map +0 -1
  147. package/dist/src/core/detect/stack.js.map +0 -1
  148. package/dist/src/core/detect/workspaces.d.ts.map +0 -1
  149. package/dist/src/core/detect/workspaces.js.map +0 -1
  150. package/dist/src/core/errors.d.ts.map +0 -1
  151. package/dist/src/core/errors.js.map +0 -1
  152. package/dist/src/core/findings/dedup.d.ts.map +0 -1
  153. package/dist/src/core/findings/dedup.js.map +0 -1
  154. package/dist/src/core/findings/types.d.ts.map +0 -1
  155. package/dist/src/core/findings/types.js.map +0 -1
  156. package/dist/src/core/fix/generator.d.ts.map +0 -1
  157. package/dist/src/core/fix/generator.js.map +0 -1
  158. package/dist/src/core/git/diff-hunks.d.ts.map +0 -1
  159. package/dist/src/core/git/diff-hunks.js.map +0 -1
  160. package/dist/src/core/git/touched-files.d.ts.map +0 -1
  161. package/dist/src/core/git/touched-files.js.map +0 -1
  162. package/dist/src/core/ignore/index.d.ts.map +0 -1
  163. package/dist/src/core/ignore/index.js.map +0 -1
  164. package/dist/src/core/index.d.ts.map +0 -1
  165. package/dist/src/core/index.js.map +0 -1
  166. package/dist/src/core/logging/ndjson-writer.d.ts.map +0 -1
  167. package/dist/src/core/logging/ndjson-writer.js.map +0 -1
  168. package/dist/src/core/logging/redaction.d.ts.map +0 -1
  169. package/dist/src/core/logging/redaction.js.map +0 -1
  170. package/dist/src/core/mcp/concurrency.d.ts.map +0 -1
  171. package/dist/src/core/mcp/concurrency.js.map +0 -1
  172. package/dist/src/core/mcp/handlers/fix-finding.d.ts.map +0 -1
  173. package/dist/src/core/mcp/handlers/fix-finding.js.map +0 -1
  174. package/dist/src/core/mcp/handlers/get-capabilities.d.ts.map +0 -1
  175. package/dist/src/core/mcp/handlers/get-capabilities.js.map +0 -1
  176. package/dist/src/core/mcp/handlers/get-findings.d.ts.map +0 -1
  177. package/dist/src/core/mcp/handlers/get-findings.js.map +0 -1
  178. package/dist/src/core/mcp/handlers/review-diff.d.ts.map +0 -1
  179. package/dist/src/core/mcp/handlers/review-diff.js.map +0 -1
  180. package/dist/src/core/mcp/handlers/scan-files.d.ts.map +0 -1
  181. package/dist/src/core/mcp/handlers/scan-files.js.map +0 -1
  182. package/dist/src/core/mcp/handlers/validate-fix.d.ts.map +0 -1
  183. package/dist/src/core/mcp/handlers/validate-fix.js.map +0 -1
  184. package/dist/src/core/mcp/run-store.d.ts.map +0 -1
  185. package/dist/src/core/mcp/run-store.js.map +0 -1
  186. package/dist/src/core/mcp/workspace.d.ts.map +0 -1
  187. package/dist/src/core/mcp/workspace.js.map +0 -1
  188. package/dist/src/core/persist/baseline.d.ts.map +0 -1
  189. package/dist/src/core/persist/baseline.js.map +0 -1
  190. package/dist/src/core/persist/cost-log.d.ts.map +0 -1
  191. package/dist/src/core/persist/cost-log.js.map +0 -1
  192. package/dist/src/core/persist/findings-cache.d.ts.map +0 -1
  193. package/dist/src/core/persist/findings-cache.js.map +0 -1
  194. package/dist/src/core/persist/triage.d.ts.map +0 -1
  195. package/dist/src/core/persist/triage.js.map +0 -1
  196. package/dist/src/core/phases/static-rules.d.ts.map +0 -1
  197. package/dist/src/core/phases/static-rules.js.map +0 -1
  198. package/dist/src/core/phases/tests.d.ts.map +0 -1
  199. package/dist/src/core/phases/tests.js.map +0 -1
  200. package/dist/src/core/pipeline/review-phase.d.ts.map +0 -1
  201. package/dist/src/core/pipeline/review-phase.js.map +0 -1
  202. package/dist/src/core/pipeline/run.d.ts.map +0 -1
  203. package/dist/src/core/pipeline/run.js.map +0 -1
  204. package/dist/src/core/runtime/idempotency.d.ts.map +0 -1
  205. package/dist/src/core/runtime/idempotency.js.map +0 -1
  206. package/dist/src/core/runtime/lock.d.ts.map +0 -1
  207. package/dist/src/core/runtime/lock.js.map +0 -1
  208. package/dist/src/core/runtime/state.d.ts.map +0 -1
  209. package/dist/src/core/runtime/state.js.map +0 -1
  210. package/dist/src/core/schema-alignment/detector.d.ts.map +0 -1
  211. package/dist/src/core/schema-alignment/detector.js.map +0 -1
  212. package/dist/src/core/schema-alignment/extractor/index.d.ts.map +0 -1
  213. package/dist/src/core/schema-alignment/extractor/index.js.map +0 -1
  214. package/dist/src/core/schema-alignment/extractor/prisma.d.ts.map +0 -1
  215. package/dist/src/core/schema-alignment/extractor/prisma.js.map +0 -1
  216. package/dist/src/core/schema-alignment/extractor/sql.d.ts.map +0 -1
  217. package/dist/src/core/schema-alignment/extractor/sql.js.map +0 -1
  218. package/dist/src/core/schema-alignment/llm-check.d.ts.map +0 -1
  219. package/dist/src/core/schema-alignment/llm-check.js.map +0 -1
  220. package/dist/src/core/schema-alignment/scanner.d.ts.map +0 -1
  221. package/dist/src/core/schema-alignment/scanner.js.map +0 -1
  222. package/dist/src/core/schema-alignment/types.d.ts.map +0 -1
  223. package/dist/src/core/schema-alignment/types.js.map +0 -1
  224. package/dist/src/core/shell.d.ts.map +0 -1
  225. package/dist/src/core/shell.js.map +0 -1
  226. package/dist/src/core/static-rules/registry.d.ts.map +0 -1
  227. package/dist/src/core/static-rules/registry.js.map +0 -1
  228. package/dist/src/core/static-rules/rules/brand-tokens.d.ts.map +0 -1
  229. package/dist/src/core/static-rules/rules/brand-tokens.js.map +0 -1
  230. package/dist/src/core/static-rules/rules/console-log.d.ts.map +0 -1
  231. package/dist/src/core/static-rules/rules/console-log.js.map +0 -1
  232. package/dist/src/core/static-rules/rules/hardcoded-secrets.d.ts.map +0 -1
  233. package/dist/src/core/static-rules/rules/hardcoded-secrets.js.map +0 -1
  234. package/dist/src/core/static-rules/rules/insecure-redirect.d.ts.map +0 -1
  235. package/dist/src/core/static-rules/rules/insecure-redirect.js.map +0 -1
  236. package/dist/src/core/static-rules/rules/large-file.d.ts.map +0 -1
  237. package/dist/src/core/static-rules/rules/large-file.js.map +0 -1
  238. package/dist/src/core/static-rules/rules/missing-auth.d.ts.map +0 -1
  239. package/dist/src/core/static-rules/rules/missing-auth.js.map +0 -1
  240. package/dist/src/core/static-rules/rules/missing-tests.d.ts.map +0 -1
  241. package/dist/src/core/static-rules/rules/missing-tests.js.map +0 -1
  242. package/dist/src/core/static-rules/rules/npm-audit.d.ts.map +0 -1
  243. package/dist/src/core/static-rules/rules/npm-audit.js.map +0 -1
  244. package/dist/src/core/static-rules/rules/package-lock-sync.d.ts.map +0 -1
  245. package/dist/src/core/static-rules/rules/package-lock-sync.js.map +0 -1
  246. package/dist/src/core/static-rules/rules/schema-alignment.d.ts.map +0 -1
  247. package/dist/src/core/static-rules/rules/schema-alignment.js.map +0 -1
  248. package/dist/src/core/static-rules/rules/sql-injection.d.ts.map +0 -1
  249. package/dist/src/core/static-rules/rules/sql-injection.js.map +0 -1
  250. package/dist/src/core/static-rules/rules/ssrf.d.ts.map +0 -1
  251. package/dist/src/core/static-rules/rules/ssrf.js.map +0 -1
  252. package/dist/src/core/static-rules/rules/todo-fixme.d.ts.map +0 -1
  253. package/dist/src/core/static-rules/rules/todo-fixme.js.map +0 -1
  254. package/dist/src/core/static-rules/tailwind-extractor.d.ts.map +0 -1
  255. package/dist/src/core/static-rules/tailwind-extractor.js.map +0 -1
  256. package/dist/src/core/test-gen/coverage-analyzer.d.ts.map +0 -1
  257. package/dist/src/core/test-gen/coverage-analyzer.js.map +0 -1
  258. package/dist/src/core/test-gen/framework-detector.d.ts.map +0 -1
  259. package/dist/src/core/test-gen/framework-detector.js.map +0 -1
  260. package/dist/src/core/test-gen/test-writer.d.ts.map +0 -1
  261. package/dist/src/core/test-gen/test-writer.js.map +0 -1
  262. package/dist/src/core/ui/design-context-loader.d.ts.map +0 -1
  263. package/dist/src/core/ui/design-context-loader.js.map +0 -1
  264. package/dist/src/core/worker/client.d.ts.map +0 -1
  265. package/dist/src/core/worker/client.js.map +0 -1
  266. package/dist/src/core/worker/lockfile.d.ts.map +0 -1
  267. package/dist/src/core/worker/lockfile.js.map +0 -1
  268. package/dist/src/core/worker/server.d.ts.map +0 -1
  269. package/dist/src/core/worker/server.js.map +0 -1
  270. package/dist/src/formatters/github-annotations.d.ts.map +0 -1
  271. package/dist/src/formatters/github-annotations.js.map +0 -1
  272. package/dist/src/formatters/index.d.ts.map +0 -1
  273. package/dist/src/formatters/index.js.map +0 -1
  274. package/dist/src/formatters/junit.d.ts.map +0 -1
  275. package/dist/src/formatters/junit.js.map +0 -1
  276. package/dist/src/formatters/sarif.d.ts.map +0 -1
  277. package/dist/src/formatters/sarif.js.map +0 -1
  278. package/dist/src/index.d.ts.map +0 -1
  279. package/dist/src/index.js.map +0 -1
  280. package/src/adapters/base.ts +0 -19
  281. package/src/adapters/council/claude.ts +0 -41
  282. package/src/adapters/council/openai.ts +0 -40
  283. package/src/adapters/council/types.ts +0 -7
  284. package/src/adapters/loader.ts +0 -108
  285. package/src/adapters/migration-runner/supabase.ts +0 -56
  286. package/src/adapters/migration-runner/types.ts +0 -36
  287. package/src/adapters/review-bot-parser/cursor.ts +0 -13
  288. package/src/adapters/review-bot-parser/declarative-base.ts +0 -64
  289. package/src/adapters/review-bot-parser/types.ts +0 -9
  290. package/src/adapters/review-engine/auto.ts +0 -94
  291. package/src/adapters/review-engine/claude.ts +0 -100
  292. package/src/adapters/review-engine/codex.ts +0 -82
  293. package/src/adapters/review-engine/gemini.ts +0 -105
  294. package/src/adapters/review-engine/openai-compatible.ts +0 -100
  295. package/src/adapters/review-engine/parse-output.ts +0 -74
  296. package/src/adapters/review-engine/prompt-builder.ts +0 -19
  297. package/src/adapters/review-engine/types.ts +0 -19
  298. package/src/adapters/vcs-host/commit-status.ts +0 -39
  299. package/src/adapters/vcs-host/github.ts +0 -77
  300. package/src/adapters/vcs-host/types.ts +0 -44
  301. package/src/cli/_pkg-root.ts +0 -85
  302. package/src/cli/autoregress-bridge.ts +0 -30
  303. package/src/cli/baseline.ts +0 -125
  304. package/src/cli/ci.ts +0 -45
  305. package/src/cli/costs.ts +0 -80
  306. package/src/cli/council.ts +0 -96
  307. package/src/cli/detector.ts +0 -92
  308. package/src/cli/explain.ts +0 -197
  309. package/src/cli/fix.ts +0 -249
  310. package/src/cli/hook.ts +0 -124
  311. package/src/cli/ignore-helper.ts +0 -116
  312. package/src/cli/index.ts +0 -612
  313. package/src/cli/lsp.ts +0 -200
  314. package/src/cli/mcp.ts +0 -206
  315. package/src/cli/migrate-v4.ts +0 -388
  316. package/src/cli/pr-comment.ts +0 -139
  317. package/src/cli/pr-desc.ts +0 -168
  318. package/src/cli/pr-review-comments.ts +0 -92
  319. package/src/cli/pr.ts +0 -76
  320. package/src/cli/preflight.ts +0 -235
  321. package/src/cli/report.ts +0 -186
  322. package/src/cli/run.ts +0 -425
  323. package/src/cli/scan.ts +0 -233
  324. package/src/cli/setup.ts +0 -191
  325. package/src/cli/test-gen.ts +0 -125
  326. package/src/cli/triage.ts +0 -137
  327. package/src/cli/watch.ts +0 -190
  328. package/src/cli/worker.ts +0 -109
  329. package/src/core/.gitkeep +0 -0
  330. package/src/core/cache/cached-engine.ts +0 -32
  331. package/src/core/cache/review-cache.ts +0 -70
  332. package/src/core/chunking/index.ts +0 -113
  333. package/src/core/chunking/risk-ranker.ts +0 -56
  334. package/src/core/config/loader.ts +0 -53
  335. package/src/core/config/preset-resolver.ts +0 -46
  336. package/src/core/config/schema.ts +0 -181
  337. package/src/core/config/types.ts +0 -98
  338. package/src/core/council/config.ts +0 -71
  339. package/src/core/council/context.ts +0 -17
  340. package/src/core/council/runner.ts +0 -83
  341. package/src/core/council/types.ts +0 -45
  342. package/src/core/detect/git-context.ts +0 -27
  343. package/src/core/detect/llm-key.ts +0 -89
  344. package/src/core/detect/protected-paths.ts +0 -63
  345. package/src/core/detect/provider-usage.ts +0 -74
  346. package/src/core/detect/stack.ts +0 -153
  347. package/src/core/detect/workspaces.ts +0 -103
  348. package/src/core/errors.ts +0 -37
  349. package/src/core/findings/dedup.ts +0 -14
  350. package/src/core/findings/types.ts +0 -39
  351. package/src/core/fix/generator.ts +0 -149
  352. package/src/core/git/diff-hunks.ts +0 -86
  353. package/src/core/git/touched-files.ts +0 -73
  354. package/src/core/ignore/index.ts +0 -54
  355. package/src/core/index.ts +0 -1
  356. package/src/core/logging/ndjson-writer.ts +0 -37
  357. package/src/core/logging/redaction.ts +0 -19
  358. package/src/core/mcp/concurrency.ts +0 -16
  359. package/src/core/mcp/handlers/fix-finding.ts +0 -126
  360. package/src/core/mcp/handlers/get-capabilities.ts +0 -62
  361. package/src/core/mcp/handlers/get-findings.ts +0 -36
  362. package/src/core/mcp/handlers/review-diff.ts +0 -65
  363. package/src/core/mcp/handlers/scan-files.ts +0 -65
  364. package/src/core/mcp/handlers/validate-fix.ts +0 -41
  365. package/src/core/mcp/run-store.ts +0 -85
  366. package/src/core/mcp/workspace.ts +0 -35
  367. package/src/core/persist/baseline.ts +0 -112
  368. package/src/core/persist/cost-log.ts +0 -30
  369. package/src/core/persist/findings-cache.ts +0 -43
  370. package/src/core/persist/triage.ts +0 -112
  371. package/src/core/phases/static-rules.ts +0 -93
  372. package/src/core/phases/tests.ts +0 -51
  373. package/src/core/pipeline/review-phase.ts +0 -182
  374. package/src/core/pipeline/run.ts +0 -116
  375. package/src/core/runtime/idempotency.ts +0 -6
  376. package/src/core/runtime/lock.ts +0 -29
  377. package/src/core/runtime/state.ts +0 -97
  378. package/src/core/schema-alignment/detector.ts +0 -59
  379. package/src/core/schema-alignment/extractor/index.ts +0 -24
  380. package/src/core/schema-alignment/extractor/prisma.ts +0 -21
  381. package/src/core/schema-alignment/extractor/sql.ts +0 -99
  382. package/src/core/schema-alignment/llm-check.ts +0 -91
  383. package/src/core/schema-alignment/scanner.ts +0 -107
  384. package/src/core/schema-alignment/types.ts +0 -43
  385. package/src/core/shell.ts +0 -48
  386. package/src/core/static-rules/registry.ts +0 -59
  387. package/src/core/static-rules/rules/brand-tokens.ts +0 -145
  388. package/src/core/static-rules/rules/console-log.ts +0 -42
  389. package/src/core/static-rules/rules/hardcoded-secrets.ts +0 -83
  390. package/src/core/static-rules/rules/insecure-redirect.ts +0 -67
  391. package/src/core/static-rules/rules/large-file.ts +0 -37
  392. package/src/core/static-rules/rules/missing-auth.ts +0 -70
  393. package/src/core/static-rules/rules/missing-tests.ts +0 -57
  394. package/src/core/static-rules/rules/npm-audit.ts +0 -38
  395. package/src/core/static-rules/rules/package-lock-sync.ts +0 -54
  396. package/src/core/static-rules/rules/schema-alignment.ts +0 -132
  397. package/src/core/static-rules/rules/sql-injection.ts +0 -71
  398. package/src/core/static-rules/rules/ssrf.ts +0 -63
  399. package/src/core/static-rules/rules/todo-fixme.ts +0 -40
  400. package/src/core/static-rules/tailwind-extractor.ts +0 -38
  401. package/src/core/test-gen/coverage-analyzer.ts +0 -93
  402. package/src/core/test-gen/framework-detector.ts +0 -21
  403. package/src/core/test-gen/test-writer.ts +0 -33
  404. package/src/core/ui/design-context-loader.ts +0 -87
  405. package/src/core/worker/client.ts +0 -46
  406. package/src/core/worker/lockfile.ts +0 -38
  407. package/src/core/worker/server.ts +0 -81
  408. package/src/formatters/github-annotations.ts +0 -36
  409. package/src/formatters/index.ts +0 -3
  410. package/src/formatters/junit.ts +0 -52
  411. package/src/formatters/sarif.ts +0 -103
  412. package/src/index.ts +0 -3
@@ -1,43 +0,0 @@
1
- // src/core/schema-alignment/types.ts
2
-
3
- export interface SchemaEntity {
4
- table: string;
5
- column?: string;
6
- operation: 'create_table' | 'add_column' | 'drop_column' | 'rename_column' | 'create_type';
7
- oldName?: string; // rename_column only: the previous column name
8
- }
9
-
10
- export interface Evidence {
11
- file: string;
12
- line: number;
13
- snippet: string;
14
- confidence: 'high' | 'medium' | 'low';
15
- }
16
-
17
- export interface LayerScanResult {
18
- entity: SchemaEntity;
19
- typeLayer: Evidence | null;
20
- apiLayer: Evidence | null;
21
- uiLayer: Evidence | null;
22
- }
23
-
24
- export interface AlignmentFinding {
25
- entity: SchemaEntity;
26
- layer: 'type' | 'api' | 'ui';
27
- message: string;
28
- file?: string;
29
- severity: 'warning' | 'error';
30
- confidence: 'high' | 'medium' | 'low';
31
- }
32
-
33
- export interface SchemaAlignmentConfig {
34
- enabled?: boolean;
35
- migrationGlobs?: string[];
36
- layerRoots?: {
37
- types?: string[];
38
- api?: string[];
39
- ui?: string[];
40
- };
41
- llmCheck?: boolean;
42
- severity?: 'warning' | 'error';
43
- }
package/src/core/shell.ts DELETED
@@ -1,48 +0,0 @@
1
- // src/core/shell.ts
2
-
3
- import { execFileSync } from 'node:child_process';
4
- import { GuardrailError, type ErrorCode } from './errors.ts';
5
-
6
- export interface RunOptions {
7
- timeout?: number;
8
- input?: string;
9
- cwd?: string;
10
- env?: NodeJS.ProcessEnv;
11
- }
12
-
13
- /** Run a command; return stdout on success, null on any failure. Never throws. */
14
- export function runSafe(cmd: string, args: string[], options: RunOptions = {}): string | null {
15
- try {
16
- const result = execFileSync(cmd, args, {
17
- encoding: 'utf8',
18
- stdio: options.input ? ['pipe', 'pipe', 'pipe'] : ['ignore', 'pipe', 'pipe'],
19
- timeout: options.timeout ?? 60000,
20
- input: options.input,
21
- cwd: options.cwd,
22
- env: options.env,
23
- });
24
- return result.toString();
25
- } catch {
26
- return null;
27
- }
28
- }
29
-
30
- /** Run a command; throw GuardrailError on failure. */
31
- export function runThrowing(cmd: string, args: string[], options: RunOptions & { errorCode?: ErrorCode; provider?: string } = {}): string {
32
- try {
33
- return execFileSync(cmd, args, {
34
- encoding: 'utf8',
35
- stdio: options.input ? ['pipe', 'pipe', 'pipe'] : ['ignore', 'pipe', 'pipe'],
36
- timeout: options.timeout ?? 60000,
37
- input: options.input,
38
- cwd: options.cwd,
39
- env: options.env,
40
- }).toString();
41
- } catch (err) {
42
- throw new GuardrailError(`Command failed: ${cmd} ${args.join(' ')}`, {
43
- code: options.errorCode ?? 'transient_network',
44
- provider: options.provider,
45
- details: { cmd, args, cause: err instanceof Error ? err.message : String(err) },
46
- });
47
- }
48
- }
@@ -1,59 +0,0 @@
1
- import type { StaticRule } from '../phases/static-rules.ts';
2
- import type { StaticRuleReference } from '../config/types.ts';
3
- import { resolveSiblingModule } from '../../cli/_pkg-root.ts';
4
-
5
- // Dynamic-import string literals that end in `.ts` are NOT rewritten by tsc's
6
- // `rewriteRelativeImportExtensions`. resolveSiblingModule swaps `.ts` → `.js`
7
- // when the caller is itself compiled, so these imports resolve correctly under
8
- // both source (`tsx`) and compiled (`node dist/...`) layouts.
9
- const importRule = <T>(ref: string, exportName: string): Promise<StaticRule> =>
10
- import(resolveSiblingModule(ref, import.meta.url)).then((m: Record<string, T>) => m[exportName] as unknown as StaticRule);
11
-
12
- // Built-in cross-stack rules
13
- const BUILTIN: Record<string, () => Promise<StaticRule>> = {
14
- 'hardcoded-secrets': () => importRule('./rules/hardcoded-secrets.ts', 'hardcodedSecretsRule'),
15
- 'npm-audit': () => importRule('./rules/npm-audit.ts', 'npmAuditRule'),
16
- 'package-lock-sync': () => importRule('./rules/package-lock-sync.ts', 'packageLockSyncRule'),
17
- 'console-log': () => importRule('./rules/console-log.ts', 'consoleLogRule'),
18
- 'todo-fixme': () => importRule('./rules/todo-fixme.ts', 'todoFixmeRule'),
19
- 'large-file': () => importRule('./rules/large-file.ts', 'largeFileRule'),
20
- 'missing-tests': () => importRule('./rules/missing-tests.ts', 'missingTestsRule'),
21
- // Security rules
22
- 'sql-injection': () => importRule('./rules/sql-injection.ts', 'sqlInjectionRule'),
23
- 'missing-auth': () => importRule('./rules/missing-auth.ts', 'missingAuthRule'),
24
- 'ssrf': () => importRule('./rules/ssrf.ts', 'ssrfRule'),
25
- 'insecure-redirect': () => importRule('./rules/insecure-redirect.ts', 'insecureRedirectRule'),
26
- // Brand rules
27
- 'brand-tokens': () => importRule('./rules/brand-tokens.ts', 'brandTokensRule'),
28
- // Schema alignment
29
- 'schema-alignment': () => importRule('./rules/schema-alignment.ts', 'schemaAlignmentRule'),
30
- };
31
-
32
- // Preset-specific rules registered by name
33
- const PRESET: Record<string, () => Promise<StaticRule>> = {
34
- 'supabase-rls-bypass': () => importRule('../../../presets/nextjs-supabase/rules/supabase-rls-bypass.ts', 'supabaseRlsBypassRule'),
35
- 'go-sql-injection': () => importRule('../../../presets/go/rules/go-sql-injection.ts', 'goSqlInjectionRule'),
36
- 'fastapi-missing-auth': () => importRule('../../../presets/python-fastapi/rules/fastapi-missing-auth.ts', 'fastapiMissingAuthRule'),
37
- 't3-server-only': () => importRule('../../../presets/t3/rules/t3-server-only.ts', 't3ServerOnlyRule'),
38
- 'rails-sql-injection': () => importRule('../../../presets/rails-postgres/rules/rails-sql-injection.ts', 'railsSqlInjectionRule'),
39
- };
40
-
41
- const ALL = { ...BUILTIN, ...PRESET };
42
-
43
- export async function loadRulesFromConfig(refs: StaticRuleReference[]): Promise<StaticRule[]> {
44
- const rules: StaticRule[] = [];
45
- for (const ref of refs) {
46
- const name = typeof ref === 'string' ? ref : ref.adapter;
47
- const loader = ALL[name];
48
- if (loader) {
49
- rules.push(await loader());
50
- } else {
51
- process.stderr.write(`[guardrail] Unknown static rule: "${name}" — skipping\n`);
52
- }
53
- }
54
- return rules;
55
- }
56
-
57
- export function listAvailableRules(): string[] {
58
- return Object.keys(ALL);
59
- }
@@ -1,145 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import type { StaticRule } from '../../phases/static-rules.ts';
4
- import type { Finding } from '../../findings/types.ts';
5
- import { extractTailwindColors } from '../tailwind-extractor.ts';
6
-
7
- const UI_EXTS = new Set(['.tsx', '.jsx', '.ts', '.js', '.css', '.scss', '.sass', '.less', '.html', '.vue', '.svelte']);
8
- const HEX_RE = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})\b/g;
9
- const TAILWIND_ARBITRARY_HEX = /(?:bg|text|border|ring|fill|stroke|from|to|via)-\[#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})\]/g;
10
- // Matches the hex portion inside a Tailwind arbitrary color bracket so we can strip it before plain HEX_RE scan
11
- const TAILWIND_ARBITRARY_HEX_STRIP = /(?:bg|text|border|ring|fill|stroke|from|to|via)-\[#[0-9a-fA-F]{3,6}\]/g;
12
- const FONT_FAMILY_RE = /font-family\s*:\s*([^;}\n]+)/g;
13
- const CSS_EXTS = new Set(['.css', '.scss', '.sass', '.less']);
14
-
15
- function normalizeHex(hex: string): string {
16
- const h = hex.toLowerCase();
17
- if (h.length === 4) {
18
- const r = h[1]!, g = h[2]!, b = h[3]!;
19
- return `#${r}${r}${g}${g}${b}${b}`;
20
- }
21
- return h;
22
- }
23
-
24
- function buildPalette(
25
- brandCfg: { colorsFrom?: string; colors?: string[] },
26
- cwd: string,
27
- ): Set<string> | null {
28
- const hasColorsFrom = !!brandCfg.colorsFrom;
29
- const hasColors = Array.isArray(brandCfg.colors) && brandCfg.colors.length > 0;
30
- if (!hasColorsFrom && !hasColors) return null;
31
-
32
- const palette = new Set<string>();
33
- if (hasColorsFrom) {
34
- const cfgPath = path.isAbsolute(brandCfg.colorsFrom!)
35
- ? brandCfg.colorsFrom!
36
- : path.resolve(cwd, brandCfg.colorsFrom!);
37
- for (const c of extractTailwindColors(cfgPath)) palette.add(normalizeHex(c));
38
- }
39
- for (const c of brandCfg.colors ?? []) palette.add(normalizeHex(c));
40
- return palette;
41
- }
42
-
43
- export const brandTokensRule: StaticRule = {
44
- name: 'brand-tokens',
45
- severity: 'warning',
46
-
47
- async check(touchedFiles: string[], config: Record<string, unknown> = {}): Promise<Finding[]> {
48
- const brandCfg = config.brand as
49
- | { colorsFrom?: string; colors?: string[]; fonts?: string[] }
50
- | undefined;
51
-
52
- if (!brandCfg) return [];
53
-
54
- const cwd = process.cwd();
55
- const palette = buildPalette(brandCfg, cwd);
56
- const canonicalFonts = brandCfg.fonts?.map(f => f.toLowerCase()) ?? [];
57
- const findings: Finding[] = [];
58
-
59
- for (const file of touchedFiles) {
60
- const ext = path.extname(file);
61
- if (!UI_EXTS.has(ext)) continue;
62
-
63
- let content: string;
64
- try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }
65
-
66
- const lines = content.split('\n');
67
- for (let i = 0; i < lines.length; i++) {
68
- const line = lines[i]!;
69
- const trimmed = line.trim();
70
- if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) continue;
71
-
72
- if (palette && palette.size > 0) {
73
- // Check Tailwind arbitrary color classes first, then scan remaining line for plain hex
74
- TAILWIND_ARBITRARY_HEX.lastIndex = 0;
75
- let m: RegExpExecArray | null;
76
- while ((m = TAILWIND_ARBITRARY_HEX.exec(line)) !== null) {
77
- const hex = normalizeHex(`#${m[1]!}`);
78
- if (!palette.has(hex)) {
79
- findings.push({
80
- id: `brand-tokens:tailwind:${file}:${i + 1}`,
81
- source: 'static-rules',
82
- severity: 'warning',
83
- category: 'brand-tokens',
84
- file,
85
- line: i + 1,
86
- message: `Off-brand Tailwind arbitrary color ${hex} is not in the canonical palette`,
87
- suggestion: `Replace with a Tailwind token from your brand palette (e.g. bg-primary, text-brand)`,
88
- protectedPath: false,
89
- createdAt: new Date().toISOString(),
90
- });
91
- }
92
- }
93
-
94
- // Strip Tailwind arbitrary color brackets before plain hex scan to avoid double-reporting
95
- const lineWithoutTailwindArbitrary = line.replace(TAILWIND_ARBITRARY_HEX_STRIP, '');
96
- HEX_RE.lastIndex = 0;
97
- while ((m = HEX_RE.exec(lineWithoutTailwindArbitrary)) !== null) {
98
- const hex = normalizeHex(m[0]!);
99
- if (!palette.has(hex)) {
100
- const palettePreview = [...palette].slice(0, 5).join(', ');
101
- findings.push({
102
- id: `brand-tokens:${file}:${i + 1}`,
103
- source: 'static-rules',
104
- severity: 'warning',
105
- category: 'brand-tokens',
106
- file,
107
- line: i + 1,
108
- message: `Off-brand color ${hex} is not in the canonical palette`,
109
- suggestion: `Use a brand token. Canonical colors: ${palettePreview}${palette.size > 5 ? ` (+${palette.size - 5} more)` : ''}`,
110
- protectedPath: false,
111
- createdAt: new Date().toISOString(),
112
- });
113
- }
114
- }
115
- }
116
-
117
- if (canonicalFonts.length > 0 && CSS_EXTS.has(ext)) {
118
- FONT_FAMILY_RE.lastIndex = 0;
119
- let fm: RegExpExecArray | null;
120
- while ((fm = FONT_FAMILY_RE.exec(line)) !== null) {
121
- const declaration = fm[1]!;
122
- const declared = declaration.split(',').map(f => f.trim().replace(/['"]/g, '').toLowerCase());
123
- const hasCanonical = declared.some(f => canonicalFonts.some(cf => f.includes(cf)));
124
- if (!hasCanonical) {
125
- findings.push({
126
- id: `brand-tokens:font:${file}:${i + 1}`,
127
- source: 'static-rules',
128
- severity: 'warning',
129
- category: 'brand-tokens',
130
- file,
131
- line: i + 1,
132
- message: `Off-brand font-family "${declaration.trim()}" — not in canonical fonts list`,
133
- suggestion: `Use one of the canonical fonts: ${canonicalFonts.join(', ')}`,
134
- protectedPath: false,
135
- createdAt: new Date().toISOString(),
136
- });
137
- }
138
- }
139
- }
140
- }
141
- }
142
-
143
- return findings;
144
- },
145
- };
@@ -1,42 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import type { StaticRule } from '../../phases/static-rules.ts';
3
- import type { Finding } from '../../findings/types.ts';
4
-
5
- const CONSOLE_CALLS = /\bconsole\.(log|debug|info)\s*\(/;
6
- const CODE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts', '.mjs', '.cjs']);
7
- const TEST_PATH = /(?:__tests__|\.test\.|\.spec\.|\/test\/|\/tests\/)/;
8
-
9
- export const consoleLogRule: StaticRule = {
10
- name: 'console-log',
11
- severity: 'warning',
12
-
13
- async check(touchedFiles: string[]): Promise<Finding[]> {
14
- const findings: Finding[] = [];
15
- for (const file of touchedFiles) {
16
- const ext = file.slice(file.lastIndexOf('.'));
17
- if (!CODE_EXTS.has(ext) || TEST_PATH.test(file)) continue;
18
- let content: string;
19
- try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }
20
- const lines = content.split('\n');
21
- for (let i = 0; i < lines.length; i++) {
22
- const line = lines[i]!;
23
- if (line.trim().startsWith('//')) continue;
24
- if (CONSOLE_CALLS.test(line)) {
25
- findings.push({
26
- id: `console-log:${file}:${i + 1}`,
27
- source: 'static-rules',
28
- severity: 'warning',
29
- category: 'console-log',
30
- file,
31
- line: i + 1,
32
- message: 'console.log/debug/info left in production code',
33
- suggestion: 'Remove or replace with a structured logger',
34
- protectedPath: false,
35
- createdAt: new Date().toISOString(),
36
- });
37
- }
38
- }
39
- }
40
- return findings;
41
- },
42
- };
@@ -1,83 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import type { StaticRule } from '../../phases/static-rules.ts';
3
- import type { Finding } from '../../findings/types.ts';
4
-
5
- const SECRET_PATTERNS: { regex: RegExp; label: string }[] = [
6
- // Cloud provider keys
7
- { regex: /\bAKIA[0-9A-Z]{16}\b/, label: 'AWS Access Key ID' },
8
- { regex: /\b(?:aws|AWS)_?(?:secret|SECRET)_?(?:key|KEY|access|ACCESS)\s*[:=]\s*['"][A-Za-z0-9/+]{40}['"]/, label: 'AWS Secret Access Key' },
9
-
10
- // LLM / AI providers
11
- { regex: /\bsk-ant-[a-zA-Z0-9\-_]{20,}\b/, label: 'Anthropic API key' },
12
- { regex: /\bsk-[a-zA-Z0-9]{20,}\b(?!.*placeholder)/, label: 'OpenAI API key' },
13
- { regex: /\bgsk_[a-zA-Z0-9]{20,}\b/, label: 'Groq API key' },
14
-
15
- // Payment
16
- { regex: /\bsk_live_[a-zA-Z0-9]{24,}\b/, label: 'Stripe secret key (live)' },
17
- { regex: /\brk_live_[a-zA-Z0-9]{24,}\b/, label: 'Stripe restricted key (live)' },
18
-
19
- // Source control / CI
20
- { regex: /\bghp_[a-zA-Z0-9]{36}\b/, label: 'GitHub personal access token' },
21
- { regex: /\bghs_[a-zA-Z0-9]{36}\b/, label: 'GitHub Actions token' },
22
- { regex: /\bgithub_pat_[a-zA-Z0-9_]{82}\b/, label: 'GitHub fine-grained PAT' },
23
-
24
- // Communication
25
- { regex: /\bSG\.[a-zA-Z0-9\-_]{22,}\.[a-zA-Z0-9\-_]{43,}\b/, label: 'SendGrid API key' },
26
- { regex: /\bAC[a-f0-9]{32}\b/, label: 'Twilio Account SID' },
27
-
28
- // Database / BaaS
29
- { regex: /\bservice_role\b.*\beyJ[a-zA-Z0-9._-]{100,}\b/, label: 'Supabase service role JWT' },
30
- { regex: /\beyJ[a-zA-Z0-9._-]{150,}\b/, label: 'Long JWT (possible service key)' },
31
-
32
- // Generic patterns
33
- { regex: /(?:^|[^a-z])(?:password|passwd|pwd)\s*[:=]\s*['"](?!\/)[^'"]{6,}['"]/, label: 'Hardcoded password' },
34
- { regex: /(?:api_key|apikey|api-key)\s*[:=]\s*['"][^'"]{8,}['"]/, label: 'Hardcoded API key' },
35
- { regex: /(?:secret|secret_key|secretkey)\s*[:=]\s*['"][^'"]{8,}['"]/, label: 'Hardcoded secret' },
36
- { regex: /(?:access_token|accesstoken)\s*[:=]\s*['"][^'"]{8,}['"]/, label: 'Hardcoded access token' },
37
- { regex: /(?:private_key|privatekey)\s*[:=]\s*['"][^'"]{8,}['"]/, label: 'Hardcoded private key' },
38
- { regex: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, label: 'Private key block' },
39
- ];
40
-
41
- // Patterns that indicate a placeholder, not a real secret
42
- const PLACEHOLDER = /(?:your[-_]?|xxx|placeholder|example|test|fake|dummy|changeme|<[^>]+>|process\.env|import\.meta\.env|\$\{)/i;
43
- const SKIP_EXTS = new Set(['.md', '.txt', '.yaml', '.yml', '.json', '.lock', '.snap']);
44
- const TEST_PATH = /(?:__tests__|\.test\.|\.spec\.|\/test\/|\/tests\/)/;
45
-
46
- export const hardcodedSecretsRule: StaticRule = {
47
- name: 'hardcoded-secrets',
48
- severity: 'critical',
49
-
50
- async check(touchedFiles: string[]): Promise<Finding[]> {
51
- const findings: Finding[] = [];
52
- for (const file of touchedFiles) {
53
- const ext = file.slice(file.lastIndexOf('.'));
54
- if (SKIP_EXTS.has(ext) || TEST_PATH.test(file)) continue;
55
- let content: string;
56
- try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }
57
- const lines = content.split('\n');
58
- for (let i = 0; i < lines.length; i++) {
59
- const line = lines[i]!;
60
- if (line.trim().startsWith('//') || line.trim().startsWith('#')) continue;
61
- for (const { regex, label } of SECRET_PATTERNS) {
62
- const match = line.match(regex);
63
- if (match && !PLACEHOLDER.test(match[0])) {
64
- findings.push({
65
- id: `hardcoded-secrets:${file}:${i + 1}`,
66
- source: 'static-rules',
67
- severity: 'critical',
68
- category: 'hardcoded-secrets',
69
- file,
70
- line: i + 1,
71
- message: `${label} appears hardcoded`,
72
- suggestion: 'Move to environment variable and load via process.env',
73
- protectedPath: false,
74
- createdAt: new Date().toISOString(),
75
- });
76
- break;
77
- }
78
- }
79
- }
80
- }
81
- return findings;
82
- },
83
- };
@@ -1,67 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import type { StaticRule } from '../../phases/static-rules.ts';
3
- import type { Finding } from '../../findings/types.ts';
4
-
5
- // Redirect calls in Next.js / Express / Node
6
- const REDIRECT_CALL = /(?:\bredirect\s*\(|NextResponse\.redirect\s*\(|res\.redirect\s*\(|router\.push\s*\()/;
7
-
8
- // User-controlled input sources
9
- const USER_INPUT_SOURCES = /(?:req\.|request\.|params\.|query\.|body\.|searchParams\.|headers\.|getParam|getQuery|getSearchParam)/;
10
-
11
- // Template interpolation of user input into redirect target
12
- const TAINTED_REDIRECT_TEMPLATE = /`[^`]*\$\{[^}]*(?:url|redirect|return|next|callback|target|to|from|path|href|location)[^}]*\}`/i;
13
- const TAINTED_REDIRECT_VAR = /(?:url|redirect|returnUrl|returnTo|next|callbackUrl|target|to|from|path|href|location)\b/;
14
-
15
- const CODE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts', '.mjs', '.cjs']);
16
- const TEST_PATH = /(?:__tests__|\.test\.|\.spec\.|\/test\/|\/tests\/)/;
17
-
18
- export const insecureRedirectRule: StaticRule = {
19
- name: 'insecure-redirect',
20
- severity: 'warning',
21
-
22
- async check(touchedFiles: string[]): Promise<Finding[]> {
23
- const findings: Finding[] = [];
24
- for (const file of touchedFiles) {
25
- const ext = file.slice(file.lastIndexOf('.'));
26
- if (!CODE_EXTS.has(ext) || TEST_PATH.test(file)) continue;
27
- let content: string;
28
- try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }
29
- const lines = content.split('\n');
30
-
31
- for (let i = 0; i < lines.length; i++) {
32
- const line = lines[i]!;
33
- if (line.trim().startsWith('//') || line.trim().startsWith('*')) continue;
34
-
35
- if (!REDIRECT_CALL.test(line)) continue;
36
-
37
- // Check if the redirect target is user-controlled
38
- const hasTaint = TAINTED_REDIRECT_TEMPLATE.test(line) || USER_INPUT_SOURCES.test(line);
39
- if (!hasTaint) {
40
- // Check if a variable with a suspicious name is passed
41
- const argStr = line.replace(REDIRECT_CALL, '');
42
- const hasRedirectVar = TAINTED_REDIRECT_VAR.test(line) && !/['"`]/.test(argStr);
43
- if (!hasRedirectVar) continue;
44
- }
45
-
46
- // Skip if there's obvious validation nearby (startsWith, URL constructor, allowlist)
47
- const context = lines.slice(Math.max(0, i - 5), i + 1).join('\n');
48
- const hasValidation = /(?:startsWith\s*\(\s*['"]\/|new\s+URL|allowedRedirects|trustedOrigins|encodeURIComponent)/.test(context);
49
- if (hasValidation) continue;
50
-
51
- findings.push({
52
- id: `insecure-redirect:${file}:${i + 1}`,
53
- source: 'static-rules',
54
- severity: 'warning',
55
- category: 'insecure-redirect',
56
- file,
57
- line: i + 1,
58
- message: 'Possible open redirect: redirect target may be user-controlled',
59
- suggestion: 'Validate redirect targets — allow only relative paths (startsWith("/")) or an explicit allowlist of trusted origins',
60
- protectedPath: false,
61
- createdAt: new Date().toISOString(),
62
- });
63
- }
64
- }
65
- return findings;
66
- },
67
- };
@@ -1,37 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import type { StaticRule } from '../../phases/static-rules.ts';
3
- import type { Finding } from '../../findings/types.ts';
4
-
5
- const DEFAULT_THRESHOLD = 500;
6
- const SKIP_EXTS = new Set(['.lock', '.snap', '.map', '.min.js', '.min.css']);
7
-
8
- export const largeFileRule: StaticRule = {
9
- name: 'large-file',
10
- severity: 'note',
11
-
12
- async check(touchedFiles: string[]): Promise<Finding[]> {
13
- const threshold = parseInt(process.env.AUTOPILOT_LARGE_FILE_LINES ?? '', 10) || DEFAULT_THRESHOLD;
14
- const findings: Finding[] = [];
15
- for (const file of touchedFiles) {
16
- const ext = file.slice(file.lastIndexOf('.'));
17
- if (SKIP_EXTS.has(ext)) continue;
18
- let content: string;
19
- try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }
20
- const lines = content.split('\n').length;
21
- if (lines > threshold) {
22
- findings.push({
23
- id: `large-file:${file}`,
24
- source: 'static-rules',
25
- severity: 'note',
26
- category: 'large-file',
27
- file,
28
- message: `File is ${lines} lines (threshold: ${threshold})`,
29
- suggestion: 'Consider splitting into smaller, focused modules',
30
- protectedPath: false,
31
- createdAt: new Date().toISOString(),
32
- });
33
- }
34
- }
35
- return findings;
36
- },
37
- };
@@ -1,70 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import type { StaticRule } from '../../phases/static-rules.ts';
4
- import type { Finding } from '../../findings/types.ts';
5
-
6
- // Next.js App Router API routes and pages with data mutations
7
- const API_ROUTE_PATTERN = /(?:app[/\\]api[/\\].*route\.[tj]sx?|pages[/\\]api[/\\].*\.[tj]sx?)$/;
8
-
9
- // Auth function signatures — any of these indicate auth is checked
10
- const AUTH_PATTERNS = [
11
- /getServerSession\s*\(/,
12
- /\bauth\s*\(\s*\)/, // next-auth v5 auth()
13
- /createServerSupabase\s*\(/,
14
- /createServerClient\s*\(/,
15
- /getSession\s*\(/,
16
- /verifyToken\s*\(/,
17
- /authenticate\s*\(/,
18
- /requireAuth\s*\(/,
19
- /currentUser\s*\(/,
20
- /withAuth\s*\(/,
21
- /checkAuth\s*\(/,
22
- /isAuthenticated\s*\(/,
23
- /useServerSession\s*\(/,
24
- /jwtVerify\s*\(/,
25
- /verify\s*\(.*token/i,
26
- /clerkClient/,
27
- /getAuth\s*\(/, // Clerk
28
- /session\s*\.\s*user/,
29
- /req\s*\.\s*user\b/,
30
- ];
31
-
32
- // Mutation handler exports — GET-only routes are less critical
33
- const MUTATION_EXPORT = /export\s+(?:async\s+)?function\s+(?:POST|PUT|PATCH|DELETE)\b/;
34
- const MUTATION_HANDLER = /(?:POST|PUT|PATCH|DELETE)\s*\(/;
35
-
36
- export const missingAuthRule: StaticRule = {
37
- name: 'missing-auth',
38
- severity: 'critical',
39
-
40
- async check(touchedFiles: string[]): Promise<Finding[]> {
41
- const findings: Finding[] = [];
42
- for (const file of touchedFiles) {
43
- if (!API_ROUTE_PATTERN.test(file)) continue;
44
- let content: string;
45
- try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }
46
-
47
- // Only flag mutation handlers
48
- if (!MUTATION_EXPORT.test(content) && !MUTATION_HANDLER.test(content)) continue;
49
-
50
- // Check if any auth pattern is present in the file
51
- const hasAuth = AUTH_PATTERNS.some(p => p.test(content));
52
- if (hasAuth) continue;
53
-
54
- const rel = path.basename(file);
55
- findings.push({
56
- id: `missing-auth:${file}:1`,
57
- source: 'static-rules',
58
- severity: 'critical',
59
- category: 'missing-auth',
60
- file,
61
- line: 1,
62
- message: `API route ${rel} has mutation handlers (POST/PUT/PATCH/DELETE) with no visible auth check`,
63
- suggestion: 'Add authentication: call getServerSession(), auth(), or equivalent before processing the request body',
64
- protectedPath: false,
65
- createdAt: new Date().toISOString(),
66
- });
67
- }
68
- return findings;
69
- },
70
- };
@@ -1,57 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import type { StaticRule } from '../../phases/static-rules.ts';
4
- import type { Finding } from '../../findings/types.ts';
5
-
6
- const SOURCE_DIRS = ['src/', 'app/', 'lib/', 'utils/'];
7
- const SOURCE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx']);
8
- const TEST_PATH = /(?:__tests__|\.test\.|\.spec\.|\/test\/|\/tests\/)/;
9
- const INDEX_FILE = /(?:^|[/\\])index\.[tj]sx?$/;
10
-
11
- function isSourceFile(f: string): boolean {
12
- const ext = f.slice(f.lastIndexOf('.'));
13
- return SOURCE_EXTS.has(ext) && !TEST_PATH.test(f) && SOURCE_DIRS.some(d => f.startsWith(d));
14
- }
15
-
16
- function hasTestCounterpart(file: string, touchedFiles: Set<string>): boolean {
17
- const base = file.replace(/\.[tj]sx?$/, '');
18
- const candidates = [
19
- `${base}.test.ts`, `${base}.test.tsx`, `${base}.test.js`,
20
- `${base}.spec.ts`, `${base}.spec.tsx`, `${base}.spec.js`,
21
- ];
22
- const dir = path.dirname(file);
23
- const name = path.basename(base);
24
- candidates.push(
25
- `${dir}/__tests__/${name}.test.ts`,
26
- `${dir}/__tests__/${name}.test.tsx`,
27
- `${dir}/__tests__/${name}.test.js`,
28
- );
29
- return candidates.some(c => touchedFiles.has(c) || fs.existsSync(c));
30
- }
31
-
32
- export const missingTestsRule: StaticRule = {
33
- name: 'missing-tests',
34
- severity: 'note',
35
-
36
- async check(touchedFiles: string[]): Promise<Finding[]> {
37
- const touched = new Set(touchedFiles);
38
- const findings: Finding[] = [];
39
- for (const file of touchedFiles) {
40
- if (!isSourceFile(file) || INDEX_FILE.test(file)) continue;
41
- if (!hasTestCounterpart(file, touched)) {
42
- findings.push({
43
- id: `missing-tests:${file}`,
44
- source: 'static-rules',
45
- severity: 'note',
46
- category: 'missing-tests',
47
- file,
48
- message: 'No test file found for this changed source file',
49
- suggestion: `Add tests at ${file.replace(/\.[tj]sx?$/, '.test.ts')}`,
50
- protectedPath: false,
51
- createdAt: new Date().toISOString(),
52
- });
53
- }
54
- }
55
- return findings;
56
- },
57
- };