sandstream-kit 1.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 (519) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +617 -0
  3. package/dist/adapters/api-key-adapter.d.ts +35 -0
  4. package/dist/adapters/api-key-adapter.js +46 -0
  5. package/dist/adapters/api-key-adapter.js.map +1 -0
  6. package/dist/adapters/clerk-auth.d.ts +6 -0
  7. package/dist/adapters/clerk-auth.js +20 -0
  8. package/dist/adapters/clerk-auth.js.map +1 -0
  9. package/dist/adapters/cloudflare-r2.d.ts +6 -0
  10. package/dist/adapters/cloudflare-r2.js +136 -0
  11. package/dist/adapters/cloudflare-r2.js.map +1 -0
  12. package/dist/adapters/expo-eas.d.ts +6 -0
  13. package/dist/adapters/expo-eas.js +129 -0
  14. package/dist/adapters/expo-eas.js.map +1 -0
  15. package/dist/adapters/flagsmith-flags.d.ts +5 -0
  16. package/dist/adapters/flagsmith-flags.js +20 -0
  17. package/dist/adapters/flagsmith-flags.js.map +1 -0
  18. package/dist/adapters/flyio-hosting.d.ts +2 -0
  19. package/dist/adapters/flyio-hosting.js +143 -0
  20. package/dist/adapters/flyio-hosting.js.map +1 -0
  21. package/dist/adapters/index.d.ts +6 -0
  22. package/dist/adapters/index.js +48 -0
  23. package/dist/adapters/index.js.map +1 -0
  24. package/dist/adapters/inngest-background.d.ts +5 -0
  25. package/dist/adapters/inngest-background.js +19 -0
  26. package/dist/adapters/inngest-background.js.map +1 -0
  27. package/dist/adapters/liveblocks-realtime.d.ts +11 -0
  28. package/dist/adapters/liveblocks-realtime.js +62 -0
  29. package/dist/adapters/liveblocks-realtime.js.map +1 -0
  30. package/dist/adapters/loops-email.d.ts +6 -0
  31. package/dist/adapters/loops-email.js +18 -0
  32. package/dist/adapters/loops-email.js.map +1 -0
  33. package/dist/adapters/neon-db.d.ts +10 -0
  34. package/dist/adapters/neon-db.js +94 -0
  35. package/dist/adapters/neon-db.js.map +1 -0
  36. package/dist/adapters/planetscale-db.d.ts +11 -0
  37. package/dist/adapters/planetscale-db.js +134 -0
  38. package/dist/adapters/planetscale-db.js.map +1 -0
  39. package/dist/adapters/posthog-analytics.d.ts +6 -0
  40. package/dist/adapters/posthog-analytics.js +22 -0
  41. package/dist/adapters/posthog-analytics.js.map +1 -0
  42. package/dist/adapters/railway-hosting.d.ts +2 -0
  43. package/dist/adapters/railway-hosting.js +136 -0
  44. package/dist/adapters/railway-hosting.js.map +1 -0
  45. package/dist/adapters/resend-email.d.ts +35 -0
  46. package/dist/adapters/resend-email.js +109 -0
  47. package/dist/adapters/resend-email.js.map +1 -0
  48. package/dist/adapters/searxng-instance.d.ts +6 -0
  49. package/dist/adapters/searxng-instance.js +240 -0
  50. package/dist/adapters/searxng-instance.js.map +1 -0
  51. package/dist/adapters/sentry-monitoring.d.ts +7 -0
  52. package/dist/adapters/sentry-monitoring.js +27 -0
  53. package/dist/adapters/sentry-monitoring.js.map +1 -0
  54. package/dist/adapters/stripe-payments.d.ts +6 -0
  55. package/dist/adapters/stripe-payments.js +134 -0
  56. package/dist/adapters/stripe-payments.js.map +1 -0
  57. package/dist/adapters/supabase-db.d.ts +6 -0
  58. package/dist/adapters/supabase-db.js +130 -0
  59. package/dist/adapters/supabase-db.js.map +1 -0
  60. package/dist/adapters/tinybird-analytics.d.ts +5 -0
  61. package/dist/adapters/tinybird-analytics.js +20 -0
  62. package/dist/adapters/tinybird-analytics.js.map +1 -0
  63. package/dist/adapters/trigger-background.d.ts +6 -0
  64. package/dist/adapters/trigger-background.js +20 -0
  65. package/dist/adapters/trigger-background.js.map +1 -0
  66. package/dist/adapters/types.d.ts +7 -0
  67. package/dist/adapters/types.js +2 -0
  68. package/dist/adapters/types.js.map +1 -0
  69. package/dist/adapters/upstash-redis.d.ts +6 -0
  70. package/dist/adapters/upstash-redis.js +88 -0
  71. package/dist/adapters/upstash-redis.js.map +1 -0
  72. package/dist/adapters/vercel-hosting.d.ts +6 -0
  73. package/dist/adapters/vercel-hosting.js +112 -0
  74. package/dist/adapters/vercel-hosting.js.map +1 -0
  75. package/dist/agent-adapter-model.d.ts +108 -0
  76. package/dist/agent-adapter-model.js +6 -0
  77. package/dist/agent-adapter-model.js.map +1 -0
  78. package/dist/agent-adapter-service.d.ts +67 -0
  79. package/dist/agent-adapter-service.js +299 -0
  80. package/dist/agent-adapter-service.js.map +1 -0
  81. package/dist/agent-config.d.ts +56 -0
  82. package/dist/agent-config.js +129 -0
  83. package/dist/agent-config.js.map +1 -0
  84. package/dist/agent-governance-model.d.ts +128 -0
  85. package/dist/agent-governance-model.js +6 -0
  86. package/dist/agent-governance-model.js.map +1 -0
  87. package/dist/agent-governance-service.d.ts +101 -0
  88. package/dist/agent-governance-service.js +319 -0
  89. package/dist/agent-governance-service.js.map +1 -0
  90. package/dist/alert-rules-engine.d.ts +102 -0
  91. package/dist/alert-rules-engine.js +210 -0
  92. package/dist/alert-rules-engine.js.map +1 -0
  93. package/dist/analytics-service.d.ts +126 -0
  94. package/dist/analytics-service.js +318 -0
  95. package/dist/analytics-service.js.map +1 -0
  96. package/dist/analyze.d.ts +19 -0
  97. package/dist/analyze.js +311 -0
  98. package/dist/analyze.js.map +1 -0
  99. package/dist/apm-instrumentor.d.ts +119 -0
  100. package/dist/apm-instrumentor.js +225 -0
  101. package/dist/apm-instrumentor.js.map +1 -0
  102. package/dist/approval-model.d.ts +82 -0
  103. package/dist/approval-model.js +6 -0
  104. package/dist/approval-model.js.map +1 -0
  105. package/dist/approval-service.d.ts +39 -0
  106. package/dist/approval-service.js +236 -0
  107. package/dist/approval-service.js.map +1 -0
  108. package/dist/approval.d.ts +22 -0
  109. package/dist/approval.js +148 -0
  110. package/dist/approval.js.map +1 -0
  111. package/dist/audit-logging-model.d.ts +157 -0
  112. package/dist/audit-logging-model.js +6 -0
  113. package/dist/audit-logging-model.js.map +1 -0
  114. package/dist/audit-logging-service.d.ts +89 -0
  115. package/dist/audit-logging-service.js +367 -0
  116. package/dist/audit-logging-service.js.map +1 -0
  117. package/dist/audit-secrets.d.ts +42 -0
  118. package/dist/audit-secrets.js +126 -0
  119. package/dist/audit-secrets.js.map +1 -0
  120. package/dist/audit.d.ts +43 -0
  121. package/dist/audit.js +286 -0
  122. package/dist/audit.js.map +1 -0
  123. package/dist/author-dashboard.d.ts +84 -0
  124. package/dist/author-dashboard.js +204 -0
  125. package/dist/author-dashboard.js.map +1 -0
  126. package/dist/author-notifications.d.ts +130 -0
  127. package/dist/author-notifications.js +261 -0
  128. package/dist/author-notifications.js.map +1 -0
  129. package/dist/author-verification.d.ts +79 -0
  130. package/dist/author-verification.js +257 -0
  131. package/dist/author-verification.js.map +1 -0
  132. package/dist/autonomous-setup-model.d.ts +117 -0
  133. package/dist/autonomous-setup-model.js +6 -0
  134. package/dist/autonomous-setup-model.js.map +1 -0
  135. package/dist/autonomous-setup-service.d.ts +74 -0
  136. package/dist/autonomous-setup-service.js +325 -0
  137. package/dist/autonomous-setup-service.js.map +1 -0
  138. package/dist/badge-system.d.ts +70 -0
  139. package/dist/badge-system.js +210 -0
  140. package/dist/badge-system.js.map +1 -0
  141. package/dist/baseline.d.ts +34 -0
  142. package/dist/baseline.js +78 -0
  143. package/dist/baseline.js.map +1 -0
  144. package/dist/beta-program-service.d.ts +112 -0
  145. package/dist/beta-program-service.js +240 -0
  146. package/dist/beta-program-service.js.map +1 -0
  147. package/dist/budget.d.ts +34 -0
  148. package/dist/budget.js +159 -0
  149. package/dist/budget.js.map +1 -0
  150. package/dist/bumblebee.d.ts +143 -0
  151. package/dist/bumblebee.js +384 -0
  152. package/dist/bumblebee.js.map +1 -0
  153. package/dist/cache-manager.d.ts +97 -0
  154. package/dist/cache-manager.js +244 -0
  155. package/dist/cache-manager.js.map +1 -0
  156. package/dist/cdn-adapter.d.ts +64 -0
  157. package/dist/cdn-adapter.js +263 -0
  158. package/dist/cdn-adapter.js.map +1 -0
  159. package/dist/certification-workflow-model.d.ts +95 -0
  160. package/dist/certification-workflow-model.js +6 -0
  161. package/dist/certification-workflow-model.js.map +1 -0
  162. package/dist/certification-workflow-service.d.ts +72 -0
  163. package/dist/certification-workflow-service.js +305 -0
  164. package/dist/certification-workflow-service.js.map +1 -0
  165. package/dist/check-design.d.ts +38 -0
  166. package/dist/check-design.js +256 -0
  167. package/dist/check-design.js.map +1 -0
  168. package/dist/check-gitignore.d.ts +39 -0
  169. package/dist/check-gitignore.js +156 -0
  170. package/dist/check-gitignore.js.map +1 -0
  171. package/dist/check-hooks.d.ts +15 -0
  172. package/dist/check-hooks.js +72 -0
  173. package/dist/check-hooks.js.map +1 -0
  174. package/dist/check-lock.d.ts +16 -0
  175. package/dist/check-lock.js +94 -0
  176. package/dist/check-lock.js.map +1 -0
  177. package/dist/check-secrets.d.ts +11 -0
  178. package/dist/check-secrets.js +320 -0
  179. package/dist/check-secrets.js.map +1 -0
  180. package/dist/check-security.d.ts +13 -0
  181. package/dist/check-security.js +887 -0
  182. package/dist/check-security.js.map +1 -0
  183. package/dist/check-services.d.ts +10 -0
  184. package/dist/check-services.js +44 -0
  185. package/dist/check-services.js.map +1 -0
  186. package/dist/check-skills.d.ts +8 -0
  187. package/dist/check-skills.js +26 -0
  188. package/dist/check-skills.js.map +1 -0
  189. package/dist/check-tests.d.ts +43 -0
  190. package/dist/check-tests.js +175 -0
  191. package/dist/check-tests.js.map +1 -0
  192. package/dist/check-tools.d.ts +8 -0
  193. package/dist/check-tools.js +42 -0
  194. package/dist/check-tools.js.map +1 -0
  195. package/dist/check-web-search.d.ts +12 -0
  196. package/dist/check-web-search.js +168 -0
  197. package/dist/check-web-search.js.map +1 -0
  198. package/dist/ci-cd-publisher.d.ts +162 -0
  199. package/dist/ci-cd-publisher.js +319 -0
  200. package/dist/ci-cd-publisher.js.map +1 -0
  201. package/dist/cli.d.ts +2 -0
  202. package/dist/cli.js +4074 -0
  203. package/dist/cli.js.map +1 -0
  204. package/dist/clone.d.ts +25 -0
  205. package/dist/clone.js +73 -0
  206. package/dist/clone.js.map +1 -0
  207. package/dist/completions.d.ts +8 -0
  208. package/dist/completions.js +250 -0
  209. package/dist/completions.js.map +1 -0
  210. package/dist/compression-manager.d.ts +107 -0
  211. package/dist/compression-manager.js +250 -0
  212. package/dist/compression-manager.js.map +1 -0
  213. package/dist/config.d.ts +233 -0
  214. package/dist/config.js +255 -0
  215. package/dist/config.js.map +1 -0
  216. package/dist/context.d.ts +38 -0
  217. package/dist/context.js +86 -0
  218. package/dist/context.js.map +1 -0
  219. package/dist/cost-monitor.d.ts +72 -0
  220. package/dist/cost-monitor.js +218 -0
  221. package/dist/cost-monitor.js.map +1 -0
  222. package/dist/create-plugin.d.ts +22 -0
  223. package/dist/create-plugin.js +266 -0
  224. package/dist/create-plugin.js.map +1 -0
  225. package/dist/database.d.ts +123 -0
  226. package/dist/database.js +354 -0
  227. package/dist/database.js.map +1 -0
  228. package/dist/datadog-adapter.d.ts +60 -0
  229. package/dist/datadog-adapter.js +245 -0
  230. package/dist/datadog-adapter.js.map +1 -0
  231. package/dist/doctor.d.ts +15 -0
  232. package/dist/doctor.js +131 -0
  233. package/dist/doctor.js.map +1 -0
  234. package/dist/documentation-generator.d.ts +226 -0
  235. package/dist/documentation-generator.js +348 -0
  236. package/dist/documentation-generator.js.map +1 -0
  237. package/dist/elevation-scopes.d.ts +40 -0
  238. package/dist/elevation-scopes.js +110 -0
  239. package/dist/elevation-scopes.js.map +1 -0
  240. package/dist/elevation.d.ts +102 -0
  241. package/dist/elevation.js +449 -0
  242. package/dist/elevation.js.map +1 -0
  243. package/dist/env-diff.d.ts +27 -0
  244. package/dist/env-diff.js +104 -0
  245. package/dist/env-diff.js.map +1 -0
  246. package/dist/env-inspect.d.ts +28 -0
  247. package/dist/env-inspect.js +81 -0
  248. package/dist/env-inspect.js.map +1 -0
  249. package/dist/env-switch.d.ts +37 -0
  250. package/dist/env-switch.js +102 -0
  251. package/dist/env-switch.js.map +1 -0
  252. package/dist/environment.d.ts +27 -0
  253. package/dist/environment.js +148 -0
  254. package/dist/environment.js.map +1 -0
  255. package/dist/error-tracker.d.ts +92 -0
  256. package/dist/error-tracker.js +206 -0
  257. package/dist/error-tracker.js.map +1 -0
  258. package/dist/escalate.d.ts +11 -0
  259. package/dist/escalate.js +73 -0
  260. package/dist/escalate.js.map +1 -0
  261. package/dist/event-stream.d.ts +81 -0
  262. package/dist/event-stream.js +161 -0
  263. package/dist/event-stream.js.map +1 -0
  264. package/dist/fix.d.ts +42 -0
  265. package/dist/fix.js +419 -0
  266. package/dist/fix.js.map +1 -0
  267. package/dist/governance-middleware.d.ts +22 -0
  268. package/dist/governance-middleware.js +173 -0
  269. package/dist/governance-middleware.js.map +1 -0
  270. package/dist/governance.d.ts +44 -0
  271. package/dist/governance.js +236 -0
  272. package/dist/governance.js.map +1 -0
  273. package/dist/hooks.d.ts +25 -0
  274. package/dist/hooks.js +281 -0
  275. package/dist/hooks.js.map +1 -0
  276. package/dist/id-generator.d.ts +43 -0
  277. package/dist/id-generator.js +47 -0
  278. package/dist/id-generator.js.map +1 -0
  279. package/dist/image-optimizer.d.ts +92 -0
  280. package/dist/image-optimizer.js +202 -0
  281. package/dist/image-optimizer.js.map +1 -0
  282. package/dist/install.d.ts +15 -0
  283. package/dist/install.js +59 -0
  284. package/dist/install.js.map +1 -0
  285. package/dist/lock.d.ts +82 -0
  286. package/dist/lock.js +264 -0
  287. package/dist/lock.js.map +1 -0
  288. package/dist/login.d.ts +23 -0
  289. package/dist/login.js +132 -0
  290. package/dist/login.js.map +1 -0
  291. package/dist/mcp-kit-tools-model.d.ts +195 -0
  292. package/dist/mcp-kit-tools-model.js +6 -0
  293. package/dist/mcp-kit-tools-model.js.map +1 -0
  294. package/dist/mcp-kit-tools-service.d.ts +127 -0
  295. package/dist/mcp-kit-tools-service.js +943 -0
  296. package/dist/mcp-kit-tools-service.js.map +1 -0
  297. package/dist/mcp-orchestrator.d.ts +70 -0
  298. package/dist/mcp-orchestrator.js +175 -0
  299. package/dist/mcp-orchestrator.js.map +1 -0
  300. package/dist/mcp-server.d.ts +3 -0
  301. package/dist/mcp-server.js +722 -0
  302. package/dist/mcp-server.js.map +1 -0
  303. package/dist/middleware/rate-limiter.d.ts +74 -0
  304. package/dist/middleware/rate-limiter.js +342 -0
  305. package/dist/middleware/rate-limiter.js.map +1 -0
  306. package/dist/migration-runner.d.ts +66 -0
  307. package/dist/migration-runner.js +192 -0
  308. package/dist/migration-runner.js.map +1 -0
  309. package/dist/migrations.d.ts +25 -0
  310. package/dist/migrations.js +530 -0
  311. package/dist/migrations.js.map +1 -0
  312. package/dist/moderation-system.d.ts +153 -0
  313. package/dist/moderation-system.js +338 -0
  314. package/dist/moderation-system.js.map +1 -0
  315. package/dist/multi-agent-workflow-model.d.ts +125 -0
  316. package/dist/multi-agent-workflow-model.js +6 -0
  317. package/dist/multi-agent-workflow-model.js.map +1 -0
  318. package/dist/multi-agent-workflow-service.d.ts +102 -0
  319. package/dist/multi-agent-workflow-service.js +452 -0
  320. package/dist/multi-agent-workflow-service.js.map +1 -0
  321. package/dist/onepassword.d.ts +75 -0
  322. package/dist/onepassword.js +140 -0
  323. package/dist/onepassword.js.map +1 -0
  324. package/dist/open.d.ts +30 -0
  325. package/dist/open.js +166 -0
  326. package/dist/open.js.map +1 -0
  327. package/dist/output.d.ts +32 -0
  328. package/dist/output.js +295 -0
  329. package/dist/output.js.map +1 -0
  330. package/dist/partner-service.d.ts +101 -0
  331. package/dist/partner-service.js +191 -0
  332. package/dist/partner-service.js.map +1 -0
  333. package/dist/payout-service.d.ts +136 -0
  334. package/dist/payout-service.js +293 -0
  335. package/dist/payout-service.js.map +1 -0
  336. package/dist/pkg.d.ts +30 -0
  337. package/dist/pkg.js +162 -0
  338. package/dist/pkg.js.map +1 -0
  339. package/dist/plugin-loader.d.ts +16 -0
  340. package/dist/plugin-loader.js +124 -0
  341. package/dist/plugin-loader.js.map +1 -0
  342. package/dist/plugin-registry-model.d.ts +133 -0
  343. package/dist/plugin-registry-model.js +6 -0
  344. package/dist/plugin-registry-model.js.map +1 -0
  345. package/dist/plugin-registry-service.d.ts +109 -0
  346. package/dist/plugin-registry-service.js +361 -0
  347. package/dist/plugin-registry-service.js.map +1 -0
  348. package/dist/plugin-registry.d.ts +58 -0
  349. package/dist/plugin-registry.js +108 -0
  350. package/dist/plugin-registry.js.map +1 -0
  351. package/dist/plugin-updates.d.ts +135 -0
  352. package/dist/plugin-updates.js +326 -0
  353. package/dist/plugin-updates.js.map +1 -0
  354. package/dist/plugins-cli.d.ts +7 -0
  355. package/dist/plugins-cli.js +157 -0
  356. package/dist/plugins-cli.js.map +1 -0
  357. package/dist/plugins.d.ts +88 -0
  358. package/dist/plugins.js +251 -0
  359. package/dist/plugins.js.map +1 -0
  360. package/dist/policy.d.ts +66 -0
  361. package/dist/policy.js +160 -0
  362. package/dist/policy.js.map +1 -0
  363. package/dist/post-pull-audit.d.ts +39 -0
  364. package/dist/post-pull-audit.js +151 -0
  365. package/dist/post-pull-audit.js.map +1 -0
  366. package/dist/provision.d.ts +17 -0
  367. package/dist/provision.js +147 -0
  368. package/dist/provision.js.map +1 -0
  369. package/dist/query-optimizer.d.ts +102 -0
  370. package/dist/query-optimizer.js +199 -0
  371. package/dist/query-optimizer.js.map +1 -0
  372. package/dist/read-only-mode.d.ts +46 -0
  373. package/dist/read-only-mode.js +71 -0
  374. package/dist/read-only-mode.js.map +1 -0
  375. package/dist/redis-adapter.d.ts +71 -0
  376. package/dist/redis-adapter.js +278 -0
  377. package/dist/redis-adapter.js.map +1 -0
  378. package/dist/resilience-tests.d.ts +120 -0
  379. package/dist/resilience-tests.js +293 -0
  380. package/dist/resilience-tests.js.map +1 -0
  381. package/dist/revocation.d.ts +22 -0
  382. package/dist/revocation.js +100 -0
  383. package/dist/revocation.js.map +1 -0
  384. package/dist/run.d.ts +21 -0
  385. package/dist/run.js +80 -0
  386. package/dist/run.js.map +1 -0
  387. package/dist/scan-build.d.ts +18 -0
  388. package/dist/scan-build.js +100 -0
  389. package/dist/scan-build.js.map +1 -0
  390. package/dist/scan-plaintext.d.ts +24 -0
  391. package/dist/scan-plaintext.js +147 -0
  392. package/dist/scan-plaintext.js.map +1 -0
  393. package/dist/scan-staged.d.ts +15 -0
  394. package/dist/scan-staged.js +70 -0
  395. package/dist/scan-staged.js.map +1 -0
  396. package/dist/scan-transcripts.d.ts +23 -0
  397. package/dist/scan-transcripts.js +93 -0
  398. package/dist/scan-transcripts.js.map +1 -0
  399. package/dist/secret-backends.d.ts +50 -0
  400. package/dist/secret-backends.js +510 -0
  401. package/dist/secret-backends.js.map +1 -0
  402. package/dist/secret-expiration.d.ts +46 -0
  403. package/dist/secret-expiration.js +172 -0
  404. package/dist/secret-expiration.js.map +1 -0
  405. package/dist/secrets-migrate.d.ts +75 -0
  406. package/dist/secrets-migrate.js +185 -0
  407. package/dist/secrets-migrate.js.map +1 -0
  408. package/dist/secrets-model.d.ts +77 -0
  409. package/dist/secrets-model.js +6 -0
  410. package/dist/secrets-model.js.map +1 -0
  411. package/dist/secrets-onecli.d.ts +65 -0
  412. package/dist/secrets-onecli.js +113 -0
  413. package/dist/secrets-onecli.js.map +1 -0
  414. package/dist/secrets-propagate.d.ts +48 -0
  415. package/dist/secrets-propagate.js +201 -0
  416. package/dist/secrets-propagate.js.map +1 -0
  417. package/dist/secrets-pull.d.ts +34 -0
  418. package/dist/secrets-pull.js +118 -0
  419. package/dist/secrets-pull.js.map +1 -0
  420. package/dist/secrets-purge-history.d.ts +53 -0
  421. package/dist/secrets-purge-history.js +144 -0
  422. package/dist/secrets-purge-history.js.map +1 -0
  423. package/dist/secrets-rotate-cli.d.ts +54 -0
  424. package/dist/secrets-rotate-cli.js +438 -0
  425. package/dist/secrets-rotate-cli.js.map +1 -0
  426. package/dist/secrets-rotate.d.ts +38 -0
  427. package/dist/secrets-rotate.js +65 -0
  428. package/dist/secrets-rotate.js.map +1 -0
  429. package/dist/secrets-service.d.ts +73 -0
  430. package/dist/secrets-service.js +283 -0
  431. package/dist/secrets-service.js.map +1 -0
  432. package/dist/secrets-set.d.ts +25 -0
  433. package/dist/secrets-set.js +33 -0
  434. package/dist/secrets-set.js.map +1 -0
  435. package/dist/secrets-sync.d.ts +21 -0
  436. package/dist/secrets-sync.js +215 -0
  437. package/dist/secrets-sync.js.map +1 -0
  438. package/dist/secrets-validate.d.ts +41 -0
  439. package/dist/secrets-validate.js +126 -0
  440. package/dist/secrets-validate.js.map +1 -0
  441. package/dist/secrets-vault-migrate.d.ts +71 -0
  442. package/dist/secrets-vault-migrate.js +258 -0
  443. package/dist/secrets-vault-migrate.js.map +1 -0
  444. package/dist/secrets.d.ts +16 -0
  445. package/dist/secrets.js +72 -0
  446. package/dist/secrets.js.map +1 -0
  447. package/dist/security-hardening.d.ts +150 -0
  448. package/dist/security-hardening.js +275 -0
  449. package/dist/security-hardening.js.map +1 -0
  450. package/dist/security-policy.d.ts +89 -0
  451. package/dist/security-policy.js +174 -0
  452. package/dist/security-policy.js.map +1 -0
  453. package/dist/security-prescan.d.ts +117 -0
  454. package/dist/security-prescan.js +566 -0
  455. package/dist/security-prescan.js.map +1 -0
  456. package/dist/sentry-adapter.d.ts +49 -0
  457. package/dist/sentry-adapter.js +227 -0
  458. package/dist/sentry-adapter.js.map +1 -0
  459. package/dist/service-adapter.d.ts +94 -0
  460. package/dist/service-adapter.js +162 -0
  461. package/dist/service-adapter.js.map +1 -0
  462. package/dist/skills.d.ts +13 -0
  463. package/dist/skills.js +17 -0
  464. package/dist/skills.js.map +1 -0
  465. package/dist/sla-monitor.d.ts +107 -0
  466. package/dist/sla-monitor.js +233 -0
  467. package/dist/sla-monitor.js.map +1 -0
  468. package/dist/stack-detector.d.ts +12 -0
  469. package/dist/stack-detector.js +251 -0
  470. package/dist/stack-detector.js.map +1 -0
  471. package/dist/team-model.d.ts +58 -0
  472. package/dist/team-model.js +83 -0
  473. package/dist/team-model.js.map +1 -0
  474. package/dist/team-service.d.ts +54 -0
  475. package/dist/team-service.js +206 -0
  476. package/dist/team-service.js.map +1 -0
  477. package/dist/toml-generator.d.ts +8 -0
  478. package/dist/toml-generator.js +223 -0
  479. package/dist/toml-generator.js.map +1 -0
  480. package/dist/triage-sandbox.d.ts +34 -0
  481. package/dist/triage-sandbox.js +167 -0
  482. package/dist/triage-sandbox.js.map +1 -0
  483. package/dist/triage.d.ts +30 -0
  484. package/dist/triage.js +79 -0
  485. package/dist/triage.js.map +1 -0
  486. package/dist/update-check.d.ts +13 -0
  487. package/dist/update-check.js +91 -0
  488. package/dist/update-check.js.map +1 -0
  489. package/dist/utils/colors.d.ts +14 -0
  490. package/dist/utils/colors.js +15 -0
  491. package/dist/utils/colors.js.map +1 -0
  492. package/dist/utils/didYouMean.d.ts +15 -0
  493. package/dist/utils/didYouMean.js +47 -0
  494. package/dist/utils/didYouMean.js.map +1 -0
  495. package/dist/utils/exec.d.ts +21 -0
  496. package/dist/utils/exec.js +23 -0
  497. package/dist/utils/exec.js.map +1 -0
  498. package/dist/utils/execFileNoThrow.d.ts +14 -0
  499. package/dist/utils/execFileNoThrow.js +29 -0
  500. package/dist/utils/execFileNoThrow.js.map +1 -0
  501. package/dist/utils/flags.d.ts +19 -0
  502. package/dist/utils/flags.js +36 -0
  503. package/dist/utils/flags.js.map +1 -0
  504. package/dist/utils/parseCommand.d.ts +16 -0
  505. package/dist/utils/parseCommand.js +13 -0
  506. package/dist/utils/parseCommand.js.map +1 -0
  507. package/dist/utils/prompt.d.ts +13 -0
  508. package/dist/utils/prompt.js +35 -0
  509. package/dist/utils/prompt.js.map +1 -0
  510. package/dist/utils/promptSelect.d.ts +19 -0
  511. package/dist/utils/promptSelect.js +89 -0
  512. package/dist/utils/promptSelect.js.map +1 -0
  513. package/dist/utils/redactSecrets.d.ts +24 -0
  514. package/dist/utils/redactSecrets.js +134 -0
  515. package/dist/utils/redactSecrets.js.map +1 -0
  516. package/dist/validation/dynamic-schema.d.ts +29 -0
  517. package/dist/validation/dynamic-schema.js +76 -0
  518. package/dist/validation/dynamic-schema.js.map +1 -0
  519. package/package.json +52 -0
@@ -0,0 +1,887 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { readFile, access } from "node:fs/promises";
4
+ import { resolve } from "node:path";
5
+ import { execFileNoThrow } from "./utils/execFileNoThrow.js";
6
+ import { ensureBumblebee, runScan, maxSeverity, newestCatalogMtime, isCatalogStale, } from "./bumblebee.js";
7
+ const exec = promisify(execFile);
8
+ function envFlagDisabled(value) {
9
+ if (!value)
10
+ return false;
11
+ return ["0", "false", "off", "no"].includes(value.toLowerCase());
12
+ }
13
+ function envFlagEnabled(value) {
14
+ if (!value)
15
+ return false;
16
+ return ["1", "true", "on", "yes"].includes(value.toLowerCase());
17
+ }
18
+ /** Map a bumblebee severity label to the SecurityCheckResult severity scale. */
19
+ function toResultSeverity(label) {
20
+ switch ((label ?? "").toLowerCase()) {
21
+ case "critical":
22
+ return "critical";
23
+ case "high":
24
+ return "high";
25
+ case "medium":
26
+ return "medium";
27
+ case "low":
28
+ return "low";
29
+ default:
30
+ // A known-compromise match with an unrecognized label is still serious.
31
+ return "high";
32
+ }
33
+ }
34
+ /**
35
+ * Run npm audit and check for high/critical vulnerabilities
36
+ */
37
+ async function checkNpmAudit() {
38
+ try {
39
+ // Check if package.json exists
40
+ await access(resolve(process.cwd(), "package.json"));
41
+ }
42
+ catch {
43
+ return {
44
+ category: "dependency",
45
+ name: "npm audit",
46
+ status: "skip",
47
+ detail: "no package.json found",
48
+ };
49
+ }
50
+ try {
51
+ await exec("npm", ["audit", "--audit-level=high", "--json"], {
52
+ timeout: 30_000,
53
+ });
54
+ return {
55
+ category: "dependency",
56
+ name: "npm audit",
57
+ status: "pass",
58
+ detail: "no high/critical vulnerabilities",
59
+ };
60
+ }
61
+ catch (error) {
62
+ if (error && typeof error === "object" && "stdout" in error) {
63
+ try {
64
+ const auditResult = JSON.parse(error.stdout);
65
+ const vulnerabilities = auditResult.metadata?.vulnerabilities || {};
66
+ const high = vulnerabilities.high || 0;
67
+ const critical = vulnerabilities.critical || 0;
68
+ if (high > 0 || critical > 0) {
69
+ return {
70
+ category: "dependency",
71
+ name: "npm audit",
72
+ status: "fail",
73
+ detail: `${critical} critical, ${high} high vulnerabilities`,
74
+ severity: critical > 0 ? "critical" : "high",
75
+ };
76
+ }
77
+ }
78
+ catch {
79
+ // JSON parse failed, treat as fail
80
+ }
81
+ }
82
+ return {
83
+ category: "dependency",
84
+ name: "npm audit",
85
+ status: "fail",
86
+ detail: "audit check failed",
87
+ severity: "high",
88
+ };
89
+ }
90
+ }
91
+ /**
92
+ * Run pip-audit for Python dependencies
93
+ */
94
+ async function checkPipAudit() {
95
+ try {
96
+ // Check if requirements.txt exists
97
+ await access(resolve(process.cwd(), "requirements.txt"));
98
+ }
99
+ catch {
100
+ return {
101
+ category: "dependency",
102
+ name: "pip-audit",
103
+ status: "skip",
104
+ detail: "no requirements.txt found",
105
+ };
106
+ }
107
+ try {
108
+ // Check if pip-audit is installed
109
+ await exec("pip-audit", ["--version"], { timeout: 5_000 });
110
+ }
111
+ catch {
112
+ return {
113
+ category: "dependency",
114
+ name: "pip-audit",
115
+ status: "warn",
116
+ detail: "pip-audit not installed (run: pip install pip-audit)",
117
+ severity: "medium",
118
+ };
119
+ }
120
+ try {
121
+ const { stdout } = await exec("pip-audit", ["--format=json"], {
122
+ timeout: 30_000,
123
+ });
124
+ const result = JSON.parse(stdout);
125
+ const vulns = result.dependencies || [];
126
+ if (vulns.length === 0) {
127
+ return {
128
+ category: "dependency",
129
+ name: "pip-audit",
130
+ status: "pass",
131
+ detail: "no vulnerabilities found",
132
+ };
133
+ }
134
+ const highSeverity = vulns.filter((v) => v.vulnerabilities?.some(vuln => vuln.severity === "high" || vuln.severity === "critical")).length;
135
+ return {
136
+ category: "dependency",
137
+ name: "pip-audit",
138
+ status: highSeverity > 0 ? "fail" : "warn",
139
+ detail: `${vulns.length} vulnerable dependencies`,
140
+ severity: highSeverity > 0 ? "high" : "medium",
141
+ };
142
+ }
143
+ catch {
144
+ return {
145
+ category: "dependency",
146
+ name: "pip-audit",
147
+ status: "fail",
148
+ detail: "audit check failed",
149
+ severity: "high",
150
+ };
151
+ }
152
+ }
153
+ /**
154
+ * Check if .env files are in .gitignore
155
+ */
156
+ async function checkEnvGitignored() {
157
+ try {
158
+ const gitignoreContent = await readFile(resolve(process.cwd(), ".gitignore"), "utf-8");
159
+ const envPatterns = [".env", ".env.local", ".env.*.local"];
160
+ const missingPatterns = envPatterns.filter(pattern => !gitignoreContent.includes(pattern));
161
+ if (missingPatterns.length === 0) {
162
+ return {
163
+ category: "secrets",
164
+ name: ".env gitignored",
165
+ status: "pass",
166
+ detail: "all .env patterns in .gitignore",
167
+ };
168
+ }
169
+ return {
170
+ category: "secrets",
171
+ name: ".env gitignored",
172
+ status: "warn",
173
+ detail: `missing patterns: ${missingPatterns.join(", ")}`,
174
+ severity: "high",
175
+ };
176
+ }
177
+ catch {
178
+ return {
179
+ category: "secrets",
180
+ name: ".env gitignored",
181
+ status: "warn",
182
+ detail: ".gitignore not found",
183
+ severity: "medium",
184
+ };
185
+ }
186
+ }
187
+ /**
188
+ * Check if package-lock.json or requirements.txt are committed
189
+ */
190
+ async function checkLockfilesCommitted() {
191
+ const results = [];
192
+ // Check package-lock.json
193
+ try {
194
+ await access(resolve(process.cwd(), "package.json"));
195
+ try {
196
+ const { stdout } = await exec("git", ["ls-files", "package-lock.json"], {
197
+ timeout: 5_000,
198
+ });
199
+ if (stdout.trim()) {
200
+ results.push({
201
+ category: "supply-chain",
202
+ name: "package-lock.json",
203
+ status: "pass",
204
+ detail: "committed to git",
205
+ });
206
+ }
207
+ else {
208
+ results.push({
209
+ category: "supply-chain",
210
+ name: "package-lock.json",
211
+ status: "fail",
212
+ detail: "not committed to git",
213
+ severity: "high",
214
+ });
215
+ }
216
+ }
217
+ catch {
218
+ results.push({
219
+ category: "supply-chain",
220
+ name: "package-lock.json",
221
+ status: "warn",
222
+ detail: "git check failed (not in a git repo?)",
223
+ severity: "low",
224
+ });
225
+ }
226
+ }
227
+ catch {
228
+ // No package.json, skip
229
+ }
230
+ // Check requirements.txt
231
+ try {
232
+ await access(resolve(process.cwd(), "requirements.txt"));
233
+ try {
234
+ const { stdout } = await exec("git", ["ls-files", "requirements.txt"], {
235
+ timeout: 5_000,
236
+ });
237
+ if (stdout.trim()) {
238
+ results.push({
239
+ category: "supply-chain",
240
+ name: "requirements.txt",
241
+ status: "pass",
242
+ detail: "committed to git",
243
+ });
244
+ }
245
+ else {
246
+ results.push({
247
+ category: "supply-chain",
248
+ name: "requirements.txt",
249
+ status: "fail",
250
+ detail: "not committed to git",
251
+ severity: "high",
252
+ });
253
+ }
254
+ }
255
+ catch {
256
+ results.push({
257
+ category: "supply-chain",
258
+ name: "requirements.txt",
259
+ status: "warn",
260
+ detail: "git check failed (not in a git repo?)",
261
+ severity: "low",
262
+ });
263
+ }
264
+ }
265
+ catch {
266
+ // No requirements.txt, skip
267
+ }
268
+ return results;
269
+ }
270
+ /**
271
+ * Check if local services are exposed to internet
272
+ */
273
+ async function checkServiceExposure() {
274
+ const results = [];
275
+ // Check Ollama (common port 11434)
276
+ try {
277
+ const { stdout: ollamaCheck } = await exec("sh", ["-c", "command -v ollama && ollama ps 2>/dev/null || echo 'not running'"], { timeout: 5_000 });
278
+ if (ollamaCheck.includes("not running")) {
279
+ results.push({
280
+ category: "exposure",
281
+ name: "Ollama",
282
+ status: "skip",
283
+ detail: "not running",
284
+ });
285
+ }
286
+ else {
287
+ // Check if listening on 0.0.0.0 (exposed) or 127.0.0.1 (localhost only)
288
+ try {
289
+ const { stdout: netstat } = await exec("sh", ["-c", "ss -tlnp 2>/dev/null | grep :11434 || netstat -tlnp 2>/dev/null | grep :11434 || echo 'no listener'"], { timeout: 5_000 });
290
+ if (netstat.includes("0.0.0.0:11434") || netstat.includes(":::11434")) {
291
+ results.push({
292
+ category: "exposure",
293
+ name: "Ollama",
294
+ status: "warn",
295
+ detail: "exposed on all interfaces (0.0.0.0)",
296
+ severity: "medium",
297
+ });
298
+ }
299
+ else if (netstat.includes("127.0.0.1:11434")) {
300
+ results.push({
301
+ category: "exposure",
302
+ name: "Ollama",
303
+ status: "pass",
304
+ detail: "localhost only",
305
+ });
306
+ }
307
+ else {
308
+ results.push({
309
+ category: "exposure",
310
+ name: "Ollama",
311
+ status: "skip",
312
+ detail: "could not determine exposure",
313
+ });
314
+ }
315
+ }
316
+ catch {
317
+ results.push({
318
+ category: "exposure",
319
+ name: "Ollama",
320
+ status: "skip",
321
+ detail: "could not check network exposure",
322
+ });
323
+ }
324
+ }
325
+ }
326
+ catch {
327
+ results.push({
328
+ category: "exposure",
329
+ name: "Ollama",
330
+ status: "skip",
331
+ detail: "not installed",
332
+ });
333
+ }
334
+ // Check Remote API (common port 3199)
335
+ try {
336
+ const { stdout: netstat } = await exec("sh", ["-c", "ss -tlnp 2>/dev/null | grep :3199 || netstat -tlnp 2>/dev/null | grep :3199 || echo 'no listener'"], { timeout: 5_000 });
337
+ if (netstat.includes("no listener")) {
338
+ results.push({
339
+ category: "exposure",
340
+ name: "Remote API",
341
+ status: "skip",
342
+ detail: "not running on port 3199",
343
+ });
344
+ }
345
+ else if (netstat.includes("0.0.0.0:3199") || netstat.includes(":::3199")) {
346
+ results.push({
347
+ category: "exposure",
348
+ name: "Remote API",
349
+ status: "warn",
350
+ detail: "exposed on all interfaces (verify firewall)",
351
+ severity: "medium",
352
+ });
353
+ }
354
+ else {
355
+ results.push({
356
+ category: "exposure",
357
+ name: "Remote API",
358
+ status: "pass",
359
+ detail: "localhost only",
360
+ });
361
+ }
362
+ }
363
+ catch {
364
+ results.push({
365
+ category: "exposure",
366
+ name: "Remote API",
367
+ status: "skip",
368
+ detail: "could not check network exposure",
369
+ });
370
+ }
371
+ return results;
372
+ }
373
+ /**
374
+ * Check if dependencies use pinned versions
375
+ */
376
+ async function checkPinnedVersions() {
377
+ const unpinned = [];
378
+ // Check package.json
379
+ try {
380
+ const packageJsonContent = await readFile(resolve(process.cwd(), "package.json"), "utf-8");
381
+ const packageJson = JSON.parse(packageJsonContent);
382
+ const checkDeps = (deps) => {
383
+ if (!deps)
384
+ return;
385
+ for (const [name, version] of Object.entries(deps)) {
386
+ // Check for range specifiers: ^, ~, >, <, >=, <=, *, x
387
+ if (/^[~^><=*x]|[*x]$/.test(version)) {
388
+ unpinned.push(`${name}@${version}`);
389
+ }
390
+ }
391
+ };
392
+ checkDeps(packageJson.dependencies);
393
+ checkDeps(packageJson.devDependencies);
394
+ }
395
+ catch {
396
+ // No package.json or parse error
397
+ }
398
+ // Check requirements.txt
399
+ try {
400
+ const requirementsContent = await readFile(resolve(process.cwd(), "requirements.txt"), "utf-8");
401
+ for (const line of requirementsContent.split("\n")) {
402
+ const trimmed = line.trim();
403
+ if (!trimmed || trimmed.startsWith("#"))
404
+ continue;
405
+ // Check for range specifiers: >=, >, ~=, !=
406
+ if (/[>~!]=?/.test(trimmed)) {
407
+ unpinned.push(trimmed.split(/\s+/)[0]);
408
+ }
409
+ }
410
+ }
411
+ catch {
412
+ // No requirements.txt or read error
413
+ }
414
+ if (unpinned.length > 0) {
415
+ return {
416
+ category: "supply-chain",
417
+ name: "pinned versions",
418
+ status: "warn",
419
+ detail: `${unpinned.length} unpinned dependencies`,
420
+ severity: "medium",
421
+ };
422
+ }
423
+ return {
424
+ category: "supply-chain",
425
+ name: "pinned versions",
426
+ status: "pass",
427
+ detail: "all dependencies pinned",
428
+ };
429
+ }
430
+ /**
431
+ * Scan for secrets in code using trufflehog or basic pattern matching
432
+ */
433
+ async function checkSecretsInCode() {
434
+ try {
435
+ // Check if we're in a git repo
436
+ await exec("git", ["rev-parse", "--git-dir"], { timeout: 5_000 });
437
+ }
438
+ catch {
439
+ return {
440
+ category: "secrets",
441
+ name: "secrets scan",
442
+ status: "skip",
443
+ detail: "not a git repository",
444
+ };
445
+ }
446
+ // Try trufflehog first
447
+ try {
448
+ await exec("trufflehog", ["--version"], { timeout: 5_000 });
449
+ try {
450
+ const { stdout } = await exec("trufflehog", ["filesystem", ".", "--json", "--no-update"], { timeout: 60_000 });
451
+ const findings = stdout.trim().split("\n").filter(Boolean);
452
+ if (findings.length > 0) {
453
+ return {
454
+ category: "secrets",
455
+ name: "secrets scan",
456
+ status: "fail",
457
+ detail: `${findings.length} potential secret(s) found`,
458
+ severity: "critical",
459
+ };
460
+ }
461
+ return {
462
+ category: "secrets",
463
+ name: "secrets scan",
464
+ status: "pass",
465
+ detail: "no secrets detected (trufflehog)",
466
+ };
467
+ }
468
+ catch {
469
+ return {
470
+ category: "secrets",
471
+ name: "secrets scan",
472
+ status: "warn",
473
+ detail: "trufflehog scan failed",
474
+ severity: "medium",
475
+ };
476
+ }
477
+ }
478
+ catch {
479
+ // Trufflehog not installed, use basic pattern matching
480
+ try {
481
+ const { stdout } = await exec("git", [
482
+ "grep",
483
+ "-n",
484
+ "-iE",
485
+ "(api[_-]?key|secret[_-]?key|password|token|credential)[\"']?\\s*[:=]\\s*[\"'][^\"']{20,}",
486
+ ], { timeout: 10_000 });
487
+ if (stdout.trim()) {
488
+ const lines = stdout.trim().split("\n");
489
+ const matches = lines.length;
490
+ // Extract unique filenames
491
+ const files = new Set();
492
+ for (const line of lines) {
493
+ const match = line.match(/^([^:]+):/);
494
+ if (match) {
495
+ files.add(match[1]);
496
+ }
497
+ }
498
+ const fileArray = Array.from(files);
499
+ return {
500
+ category: "secrets",
501
+ name: "secrets scan",
502
+ status: "warn",
503
+ detail: `${matches} potential secret(s) in ${files.size} file(s)`,
504
+ severity: "high",
505
+ files: fileArray,
506
+ suggestion: "Install trufflehog for better detection:\n • macOS/Linux: brew install trufflehog\n • Go: go install github.com/trufflesecurity/trufflehog/v3@latest\n • Or download from: https://github.com/trufflesecurity/trufflehog/releases",
507
+ };
508
+ }
509
+ }
510
+ catch {
511
+ // No matches or git grep failed
512
+ }
513
+ return {
514
+ category: "secrets",
515
+ name: "secrets scan",
516
+ status: "pass",
517
+ detail: "basic scan passed (install trufflehog for better detection: brew install trufflehog)",
518
+ };
519
+ }
520
+ }
521
+ /**
522
+ * Check for supply chain attacks using Socket CLI.
523
+ * Detects behavioral anomalies (obfuscated files, unexpected network calls, install scripts)
524
+ * that npm audit misses -catches intentional malware like node-ipc and compromised packages.
525
+ */
526
+ async function checkSocket() {
527
+ try {
528
+ await access(resolve(process.cwd(), "package.json"));
529
+ }
530
+ catch {
531
+ return { category: "supply-chain", name: "socket scan", status: "skip", detail: "no package.json found" };
532
+ }
533
+ const versionCheck = await execFileNoThrow("socket", ["--version"], { timeout: 5_000 });
534
+ if (!versionCheck.ok) {
535
+ return {
536
+ category: "supply-chain",
537
+ name: "socket scan",
538
+ status: "warn",
539
+ detail: "socket not installed -supply chain malware undetected",
540
+ severity: "medium",
541
+ suggestion: "npm install -g @socketsecurity/cli",
542
+ };
543
+ }
544
+ const result = await execFileNoThrow("socket", ["check", "--json"], { timeout: 60_000 });
545
+ const raw = result.stdout || result.stderr;
546
+ try {
547
+ const parsed = JSON.parse(raw);
548
+ const issues = parsed.issues ?? parsed.alerts ?? [];
549
+ const critical = issues.filter((i) => i.severity === "critical" || i.severity === "high");
550
+ if (critical.length > 0) {
551
+ return {
552
+ category: "supply-chain",
553
+ name: "socket scan",
554
+ status: "fail",
555
+ detail: `${critical.length} critical/high supply chain issue(s) -run: socket check`,
556
+ severity: "critical",
557
+ };
558
+ }
559
+ if (issues.length > 0) {
560
+ return {
561
+ category: "supply-chain",
562
+ name: "socket scan",
563
+ status: "warn",
564
+ detail: `${issues.length} supply chain warning(s) -run: socket check`,
565
+ severity: "medium",
566
+ };
567
+ }
568
+ }
569
+ catch {
570
+ // Non-JSON output: socket check passed (exit 0, human-readable)
571
+ }
572
+ if (!result.ok) {
573
+ return {
574
+ category: "supply-chain",
575
+ name: "socket scan",
576
+ status: "warn",
577
+ detail: "socket check failed -verify installation or run: socket login",
578
+ severity: "medium",
579
+ suggestion: "socket login",
580
+ };
581
+ }
582
+ return { category: "supply-chain", name: "socket scan", status: "pass", detail: "no supply chain issues detected" };
583
+ }
584
+ /**
585
+ * Scan Dockerfile and filesystem for CVEs using Trivy.
586
+ * Catches OS-level vulnerabilities that npm audit misses.
587
+ */
588
+ async function checkTrivy() {
589
+ const hasDockerfile = await access(resolve(process.cwd(), "Dockerfile")).then(() => true).catch(() => false);
590
+ if (!hasDockerfile) {
591
+ return { category: "supply-chain", name: "trivy container scan", status: "skip", detail: "no Dockerfile found" };
592
+ }
593
+ const versionCheck = await execFileNoThrow("trivy", ["--version"], { timeout: 5_000 });
594
+ if (!versionCheck.ok) {
595
+ return {
596
+ category: "supply-chain",
597
+ name: "trivy container scan",
598
+ status: "warn",
599
+ detail: "trivy not installed -container CVEs undetected",
600
+ severity: "medium",
601
+ suggestion: "brew install trivy",
602
+ };
603
+ }
604
+ const result = await execFileNoThrow("trivy", ["fs", ".", "--format", "json", "--severity", "HIGH,CRITICAL", "--quiet"], { timeout: 120_000 });
605
+ if (!result.ok && !result.stdout) {
606
+ return { category: "supply-chain", name: "trivy container scan", status: "warn", detail: "trivy scan failed", severity: "medium" };
607
+ }
608
+ try {
609
+ const parsed = JSON.parse(result.stdout);
610
+ const vulns = (parsed.Results ?? []).flatMap((r) => r.Vulnerabilities ?? []);
611
+ if (vulns.length === 0) {
612
+ return { category: "supply-chain", name: "trivy container scan", status: "pass", detail: "no high/critical container vulnerabilities" };
613
+ }
614
+ return {
615
+ category: "supply-chain",
616
+ name: "trivy container scan",
617
+ status: "fail",
618
+ detail: `${vulns.length} high/critical vulnerability(ies) in container`,
619
+ severity: "high",
620
+ };
621
+ }
622
+ catch {
623
+ return { category: "supply-chain", name: "trivy container scan", status: "warn", detail: "trivy scan failed", severity: "medium" };
624
+ }
625
+ }
626
+ /**
627
+ * Check dependency licenses for GPL/AGPL that create legal obligations.
628
+ */
629
+ async function checkLicenses() {
630
+ try {
631
+ await access(resolve(process.cwd(), "package.json"));
632
+ }
633
+ catch {
634
+ return { category: "supply-chain", name: "license check", status: "skip", detail: "no package.json found" };
635
+ }
636
+ // Try direct binary first (fast). If absent, fall back to `npx --yes
637
+ // license-checker` so we don't force users to `npm install -g`.
638
+ // npx first-run can fetch the package, so allow generous timeout.
639
+ let runner = null;
640
+ const direct = await execFileNoThrow("license-checker", ["--version"], { timeout: 5_000 });
641
+ if (direct.ok) {
642
+ runner = { cmd: "license-checker", baseArgs: [] };
643
+ }
644
+ else {
645
+ const npxAvailable = await execFileNoThrow("npx", ["--version"], { timeout: 5_000 });
646
+ if (npxAvailable.ok) {
647
+ runner = { cmd: "npx", baseArgs: ["--yes", "license-checker"] };
648
+ }
649
+ }
650
+ if (!runner) {
651
+ return {
652
+ category: "supply-chain",
653
+ name: "license check",
654
+ status: "warn",
655
+ detail: "license-checker not installed (npx also unavailable)",
656
+ severity: "low",
657
+ suggestion: "npm install -g license-checker",
658
+ };
659
+ }
660
+ const PROBLEMATIC = ["GPL", "AGPL", "LGPL", "CPAL", "OSL", "EUPL"];
661
+ const result = await execFileNoThrow(runner.cmd, [...runner.baseArgs, "--json", "--production"], { timeout: 120_000 });
662
+ if (!result.ok && !result.stdout) {
663
+ return { category: "supply-chain", name: "license check", status: "warn", detail: "license check failed", severity: "low" };
664
+ }
665
+ try {
666
+ const packages = JSON.parse(result.stdout);
667
+ const violations = [];
668
+ for (const [pkg, info] of Object.entries(packages)) {
669
+ const license = info.licenses ?? "";
670
+ if (PROBLEMATIC.some((l) => license.toUpperCase().includes(l))) {
671
+ violations.push(`${pkg} (${license})`);
672
+ }
673
+ }
674
+ if (violations.length > 0) {
675
+ return {
676
+ category: "supply-chain",
677
+ name: "license check",
678
+ status: "warn",
679
+ detail: `${violations.length} copyleft license(s): ${violations.slice(0, 3).join(", ")}${violations.length > 3 ? ` +${violations.length - 3} more` : ""}`,
680
+ severity: "medium",
681
+ };
682
+ }
683
+ return { category: "supply-chain", name: "license check", status: "pass", detail: "no problematic licenses found" };
684
+ }
685
+ catch {
686
+ return { category: "supply-chain", name: "license check", status: "warn", detail: "license check failed", severity: "low" };
687
+ }
688
+ }
689
+ /**
690
+ * Run static analysis using Semgrep to catch security anti-patterns in source code.
691
+ */
692
+ async function checkSemgrep() {
693
+ const versionCheck = await execFileNoThrow("semgrep", ["--version"], { timeout: 5_000 });
694
+ if (!versionCheck.ok) {
695
+ return {
696
+ category: "supply-chain",
697
+ name: "semgrep SAST",
698
+ status: "skip",
699
+ detail: "semgrep not installed (brew install semgrep)",
700
+ };
701
+ }
702
+ const result = await execFileNoThrow("semgrep", ["scan", "--config", "auto", "--json", "--quiet", "--no-rewrite-rule-ids"], { timeout: 120_000 });
703
+ const raw = result.stdout || result.stderr;
704
+ try {
705
+ const parsed = JSON.parse(raw);
706
+ const findings = parsed.results ?? [];
707
+ const high = findings.filter((f) => f.extra?.severity === "ERROR" || f.extra?.severity === "WARNING");
708
+ if (high.length === 0) {
709
+ return { category: "supply-chain", name: "semgrep SAST", status: "pass", detail: "no security issues found" };
710
+ }
711
+ return {
712
+ category: "supply-chain",
713
+ name: "semgrep SAST",
714
+ status: high.some((f) => f.extra?.severity === "ERROR") ? "fail" : "warn",
715
+ detail: `${high.length} security finding(s) -run: semgrep scan --config auto`,
716
+ severity: high.some((f) => f.extra?.severity === "ERROR") ? "high" : "medium",
717
+ };
718
+ }
719
+ catch {
720
+ return { category: "supply-chain", name: "semgrep SAST", status: "warn", detail: "semgrep scan failed", severity: "low" };
721
+ }
722
+ }
723
+ /**
724
+ * Scan for installed packages matching known supply-chain compromise catalogs
725
+ * using bumblebee. Unlike npm/pip audit (known CVEs), this flags packages that
726
+ * exactly match curated incident catalogs (shai-hulud, typosquats, credential
727
+ * stealers, malicious editor/browser extensions, etc.).
728
+ *
729
+ * Zero-config by default; tunable via environment:
730
+ * KIT_BUMBLEBEE set to 0/false to skip the check entirely
731
+ * KIT_NO_DOWNLOAD set to 1 to never fetch the scanner binary
732
+ * KIT_BUMBLEBEE_PROFILE baseline (default) | project | deep
733
+ * KIT_BUMBLEBEE_ROOTS comma-separated roots (e.g. "." for the repo; required for deep)
734
+ * KIT_BUMBLEBEE_BIN use a pre-installed bumblebee instead of downloading
735
+ * KIT_BUMBLEBEE_CATALOG override the exposure-catalog directory
736
+ */
737
+ async function checkBumblebee() {
738
+ const name = "bumblebee (supply-chain)";
739
+ const category = "supply-chain";
740
+ if (envFlagDisabled(process.env.KIT_BUMBLEBEE)) {
741
+ return { category, name, status: "skip", detail: "disabled via KIT_BUMBLEBEE" };
742
+ }
743
+ const { install, reason, kind } = await ensureBumblebee({
744
+ allowDownload: !envFlagEnabled(process.env.KIT_NO_DOWNLOAD),
745
+ });
746
+ if (!install) {
747
+ // A failed integrity check (checksum mismatch) is a potential tampering
748
+ // event — escalate to a hard failure rather than failing open to a warn.
749
+ if (kind === "integrity") {
750
+ return {
751
+ category,
752
+ name,
753
+ status: "fail",
754
+ detail: `scanner ${reason}`,
755
+ severity: "high",
756
+ suggestion: "The downloaded scanner did not match its pinned checksum. Do NOT trust it. Investigate for tampering (network MITM, compromised mirror), clear ~/.kit/tools/bumblebee, and retry from a trusted network.",
757
+ };
758
+ }
759
+ return {
760
+ category,
761
+ name,
762
+ status: "warn",
763
+ detail: `scanner unavailable: ${reason}`,
764
+ severity: "low",
765
+ suggestion: "Provide a binary with KIT_BUMBLEBEE_BIN, or allow downloads (unset KIT_NO_DOWNLOAD). Manual install: go install github.com/perplexityai/bumblebee/cmd/bumblebee@latest",
766
+ };
767
+ }
768
+ const profile = process.env.KIT_BUMBLEBEE_PROFILE || "baseline";
769
+ const roots = (process.env.KIT_BUMBLEBEE_ROOTS || "")
770
+ .split(",")
771
+ .map((s) => s.trim())
772
+ .filter(Boolean);
773
+ const { outcome, error } = await runScan({ install, profile, roots });
774
+ if (error || !outcome) {
775
+ return {
776
+ category,
777
+ name,
778
+ status: "warn",
779
+ detail: `scan failed: ${error ?? "no output"}`,
780
+ severity: "medium",
781
+ };
782
+ }
783
+ if (outcome.findings.length > 0) {
784
+ const catalogs = describeFindings(outcome.findings);
785
+ // F9: persist every catalog match to the local audit log so the find
786
+ // survives the next CI run and shows up in `kit audit`.
787
+ await logSupplyChainFindings(outcome.findings, profile).catch(() => { });
788
+ return {
789
+ category,
790
+ name,
791
+ status: "fail",
792
+ detail: `${outcome.findings.length} known supply-chain exposure(s): ${catalogs}`,
793
+ severity: toResultSeverity(maxSeverity(outcome.findings)),
794
+ files: Array.from(new Set(outcome.findings.map((f) => f.sourceFile).filter(Boolean))),
795
+ suggestion: "Remove or downgrade the flagged packages immediately — they match curated known-compromise catalogs. Verify on the source advisory before trusting any replacement.",
796
+ };
797
+ }
798
+ if (!outcome.summarySeen || outcome.status !== "complete" || outcome.timedOut) {
799
+ return {
800
+ category,
801
+ name,
802
+ status: "warn",
803
+ detail: `scan incomplete (status=${outcome.status}${outcome.timedOut ? ", timed out" : ""})`,
804
+ severity: "low",
805
+ };
806
+ }
807
+ // Clean scan — but a frozen catalog set silently loses coverage over time.
808
+ const newest = await newestCatalogMtime(install.catalogDir);
809
+ if (newest !== null) {
810
+ const { stale, ageDays } = isCatalogStale(newest, Date.now());
811
+ if (stale) {
812
+ return {
813
+ category,
814
+ name,
815
+ status: "warn",
816
+ severity: "low",
817
+ detail: `no known exposures (${outcome.packagesScanned} packages), but threat-intel catalogs are ${ageDays} days old`,
818
+ suggestion: "Bump BUMBLEBEE_VERSION (and TARBALL_CHECKSUMS) in src/bumblebee.ts to refresh the exposure catalogs.",
819
+ };
820
+ }
821
+ }
822
+ return {
823
+ category,
824
+ name,
825
+ status: "pass",
826
+ detail: `no known exposures (${outcome.packagesScanned} packages, profile=${profile})`,
827
+ };
828
+ }
829
+ /** Short, human-readable summary of the catalogs matched by findings. */
830
+ function describeFindings(findings) {
831
+ const labels = Array.from(new Set(findings.map((f) => f.catalogName || f.catalogId).filter(Boolean)));
832
+ const shown = labels.slice(0, 3).join("; ");
833
+ return labels.length > 3 ? `${shown}; +${labels.length - 3} more` : shown;
834
+ }
835
+ /**
836
+ * Run all security checks
837
+ */
838
+ export async function checkSecurity() {
839
+ const results = [];
840
+ const [npmResult, pipResult, envResult, pinnedResult, secretsScan, socketResult, trivyResult, licenseResult, semgrepResult, bumblebeeResult, ...lockfileResults] = await Promise.all([
841
+ checkNpmAudit(),
842
+ checkPipAudit(),
843
+ checkEnvGitignored(),
844
+ checkPinnedVersions(),
845
+ checkSecretsInCode(),
846
+ checkSocket(),
847
+ checkTrivy(),
848
+ checkLicenses(),
849
+ checkSemgrep(),
850
+ checkBumblebee(),
851
+ ...await checkLockfilesCommitted(),
852
+ ]);
853
+ results.push(npmResult, pipResult, envResult, pinnedResult, secretsScan, socketResult, trivyResult, licenseResult, semgrepResult, bumblebeeResult);
854
+ results.push(...lockfileResults);
855
+ const exposureResults = await checkServiceExposure();
856
+ results.push(...exposureResults);
857
+ return results;
858
+ }
859
+ /**
860
+ * F9 — append bumblebee supply-chain findings to the local audit JSONL.
861
+ * Bypasses the governance config so the trail is captured even when
862
+ * `kit check` is run without `.kit.toml`. One JSON line per finding.
863
+ */
864
+ async function logSupplyChainFindings(findings, profile) {
865
+ const { appendFile } = await import("node:fs/promises");
866
+ const path = resolve(process.cwd(), ".kit-audit.jsonl");
867
+ const lines = findings
868
+ .map((f) => JSON.stringify({
869
+ timestamp: new Date().toISOString(),
870
+ event_type: "supply_chain_finding",
871
+ source: "bumblebee",
872
+ profile,
873
+ catalog_id: f.catalogId,
874
+ catalog_name: f.catalogName,
875
+ severity: f.severity,
876
+ package: f.packageName || "unknown",
877
+ version: f.version || null,
878
+ ecosystem: f.ecosystem || null,
879
+ source_file: f.sourceFile || null,
880
+ evidence: f.evidence || null,
881
+ }))
882
+ .join("\n");
883
+ if (lines) {
884
+ await appendFile(path, lines + "\n", "utf-8");
885
+ }
886
+ }
887
+ //# sourceMappingURL=check-security.js.map