@zivis/mcp 0.1.8 → 0.1.10

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 (330) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +19 -0
  3. package/dist/api-client.d.ts +2 -24
  4. package/dist/api-client.js +32 -52
  5. package/dist/auth/index.d.ts +1 -22
  6. package/dist/auth/index.js +17 -38
  7. package/dist/auth/jwt.d.ts +0 -16
  8. package/dist/auth/jwt.js +0 -13
  9. package/dist/auth/keychain.d.ts +6 -32
  10. package/dist/auth/keychain.js +83 -114
  11. package/dist/auth/oauth.d.ts +3 -32
  12. package/dist/auth/oauth.js +67 -61
  13. package/dist/auth/sessions.d.ts +5 -25
  14. package/dist/auth/sessions.js +20 -39
  15. package/dist/auth/token-refresh.d.ts +2 -22
  16. package/dist/auth/token-refresh.js +33 -36
  17. package/dist/cli.d.ts +1 -18
  18. package/dist/cli.js +30 -908
  19. package/dist/index.d.ts +0 -6
  20. package/dist/index.js +0 -7
  21. package/dist/lib/inspect-cache.d.ts +10 -0
  22. package/dist/lib/inspect-cache.js +75 -0
  23. package/dist/lib/next-steps.d.ts +27 -0
  24. package/dist/lib/next-steps.js +21 -0
  25. package/dist/matcher/ast-eval.d.ts +8 -0
  26. package/dist/matcher/ast-eval.js +95 -0
  27. package/dist/matcher/finding.d.ts +55 -0
  28. package/dist/matcher/finding.js +1 -0
  29. package/dist/matcher/index.d.ts +8 -0
  30. package/dist/matcher/index.js +202 -0
  31. package/dist/matcher/inference-candidates.d.ts +26 -0
  32. package/dist/matcher/inference-candidates.js +81 -0
  33. package/dist/matcher/walker.d.ts +7 -0
  34. package/dist/matcher/walker.js +71 -0
  35. package/dist/pattern-pack/index.d.ts +125 -0
  36. package/dist/pattern-pack/index.js +189 -0
  37. package/dist/pattern-packs/zivis-public-0.2.0/capsules/agents/privilege-separation.yaml +224 -0
  38. package/dist/pattern-packs/zivis-public-0.2.0/capsules/prompting/self-consistency-no-isolation.yaml +237 -0
  39. package/dist/pattern-packs/zivis-public-0.2.0/capsules/retrieval/context-injection-no-validator.yaml +348 -0
  40. package/dist/pattern-packs/zivis-public-0.2.0/capsules/security/late-org-filter.yaml +266 -0
  41. package/dist/pattern-packs/zivis-public-0.2.0/controls/external_validator_on_facts.yaml +37 -0
  42. package/dist/pattern-packs/zivis-public-0.2.0/controls/fact_validator_present.yaml +68 -0
  43. package/dist/pattern-packs/zivis-public-0.2.0/controls/human_approval_gate.yaml +44 -0
  44. package/dist/pattern-packs/zivis-public-0.2.0/controls/langgraph_state_machine_with_per_node_tools.yaml +35 -0
  45. package/dist/pattern-packs/zivis-public-0.2.0/controls/per_sample_retrieval_diversification.yaml +38 -0
  46. package/dist/pattern-packs/zivis-public-0.2.0/controls/prisma_extension_or_middleware_attaching_org_filter.yaml +31 -0
  47. package/dist/pattern-packs/zivis-public-0.2.0/controls/row_level_security_policy.yaml +37 -0
  48. package/dist/pattern-packs/zivis-public-0.2.0/controls/source_attribution_present.yaml +58 -0
  49. package/dist/pattern-packs/zivis-public-0.2.0/manifest.json +167 -0
  50. package/dist/pattern-packs/zivis-public-0.2.0/prompts/agents/privilege-separation/identify.md +54 -0
  51. package/dist/pattern-packs/zivis-public-0.2.0/prompts/prompting/self-consistency-no-isolation/identify.md +60 -0
  52. package/dist/pattern-packs/zivis-public-0.2.0/prompts/retrieval/context-injection-no-validator/identify.md +109 -0
  53. package/dist/pattern-packs/zivis-public-0.2.0/prompts/security/late-org-filter/identify.md +78 -0
  54. package/dist/project-binding.d.ts +2 -19
  55. package/dist/project-binding.js +38 -21
  56. package/dist/prompts/audit-dependencies.d.ts +2 -0
  57. package/dist/prompts/audit-dependencies.js +47 -0
  58. package/dist/prompts/getting-started.d.ts +2 -0
  59. package/dist/prompts/getting-started.js +37 -0
  60. package/dist/prompts/index.d.ts +2 -0
  61. package/dist/prompts/index.js +6 -0
  62. package/dist/resolve-application-id.d.ts +0 -4
  63. package/dist/resolve-application-id.js +0 -5
  64. package/dist/sanitize.d.ts +1 -21
  65. package/dist/sanitize.js +7 -41
  66. package/dist/server.d.ts +1 -13
  67. package/dist/server.js +142 -265
  68. package/dist/tools/artifacts.d.ts +76 -0
  69. package/dist/tools/artifacts.js +178 -0
  70. package/dist/tools/check-project.d.ts +5 -18
  71. package/dist/tools/check-project.js +122 -110
  72. package/dist/tools/check-repo-trust.d.ts +4 -19
  73. package/dist/tools/check-repo-trust.js +56 -47
  74. package/dist/tools/create-diagram.d.ts +0 -5
  75. package/dist/tools/create-diagram.js +0 -10
  76. package/dist/tools/create-document.d.ts +0 -5
  77. package/dist/tools/create-document.js +3 -9
  78. package/dist/tools/create-finding.d.ts +85 -0
  79. package/dist/tools/create-finding.js +136 -0
  80. package/dist/tools/delete-finding.d.ts +19 -0
  81. package/dist/tools/delete-finding.js +36 -0
  82. package/dist/tools/devx-run.d.ts +88 -0
  83. package/dist/tools/devx-run.js +175 -0
  84. package/dist/tools/discover-local-infra.d.ts +0 -10
  85. package/dist/tools/discover-local-infra.js +3 -73
  86. package/dist/tools/enterprise/get-org-zat.d.ts +0 -5
  87. package/dist/tools/enterprise/get-org-zat.js +0 -6
  88. package/dist/tools/explain-signal-for-diff.d.ts +34 -0
  89. package/dist/tools/explain-signal-for-diff.js +75 -0
  90. package/dist/tools/generate-diagram.d.ts +0 -6
  91. package/dist/tools/generate-diagram.js +21 -13
  92. package/dist/tools/get-application-overview.d.ts +0 -5
  93. package/dist/tools/get-application-overview.js +0 -6
  94. package/dist/tools/get-application.d.ts +0 -5
  95. package/dist/tools/get-application.js +0 -6
  96. package/dist/tools/get-diagram.d.ts +0 -5
  97. package/dist/tools/get-diagram.js +1 -11
  98. package/dist/tools/get-document.d.ts +0 -5
  99. package/dist/tools/get-document.js +0 -6
  100. package/dist/tools/get-oss-zat.d.ts +0 -5
  101. package/dist/tools/get-oss-zat.js +0 -7
  102. package/dist/tools/get-signal.d.ts +24 -0
  103. package/dist/tools/get-signal.js +75 -0
  104. package/dist/tools/get-started.d.ts +18 -0
  105. package/dist/tools/get-started.js +470 -0
  106. package/dist/tools/get-trust-keys.d.ts +0 -5
  107. package/dist/tools/get-trust-keys.js +0 -6
  108. package/dist/tools/import-openapi-endpoints.d.ts +0 -5
  109. package/dist/tools/import-openapi-endpoints.js +0 -6
  110. package/dist/tools/inspect-zat.d.ts +0 -5
  111. package/dist/tools/inspect-zat.js +0 -19
  112. package/dist/tools/inspect.d.ts +21 -0
  113. package/dist/tools/inspect.js +222 -0
  114. package/dist/tools/list-applications.d.ts +1 -6
  115. package/dist/tools/list-applications.js +0 -6
  116. package/dist/tools/list-diagrams.d.ts +0 -5
  117. package/dist/tools/list-diagrams.js +0 -6
  118. package/dist/tools/list-documents.d.ts +0 -5
  119. package/dist/tools/list-documents.js +0 -6
  120. package/dist/tools/list-endpoints.d.ts +1 -6
  121. package/dist/tools/list-endpoints.js +0 -6
  122. package/dist/tools/list-signals.d.ts +37 -0
  123. package/dist/tools/list-signals.js +83 -0
  124. package/dist/tools/manage-application.d.ts +64 -0
  125. package/dist/tools/manage-application.js +129 -0
  126. package/dist/tools/manage-diagram.d.ts +0 -5
  127. package/dist/tools/manage-diagram.js +0 -16
  128. package/dist/tools/manage-endpoint-lifecycle.d.ts +80 -0
  129. package/dist/tools/manage-endpoint-lifecycle.js +180 -0
  130. package/dist/tools/open-in-ide.d.ts +2 -14
  131. package/dist/tools/open-in-ide.js +0 -13
  132. package/dist/tools/review-change.d.ts +34 -0
  133. package/dist/tools/review-change.js +93 -0
  134. package/dist/tools/security-memory.d.ts +76 -0
  135. package/dist/tools/security-memory.js +202 -0
  136. package/dist/tools/security-review.d.ts +1 -21
  137. package/dist/tools/security-review.js +8 -108
  138. package/dist/tools/threat-get-capsule.d.ts +15 -0
  139. package/dist/tools/threat-get-capsule.js +53 -0
  140. package/dist/tools/threat-get-inference-prompt.d.ts +15 -0
  141. package/dist/tools/threat-get-inference-prompt.js +73 -0
  142. package/dist/tools/threat-list-relevant-capsules.d.ts +17 -0
  143. package/dist/tools/threat-list-relevant-capsules.js +158 -0
  144. package/dist/tools/threat-run-matcher.d.ts +17 -0
  145. package/dist/tools/threat-run-matcher.js +145 -0
  146. package/dist/tools/update-document.d.ts +0 -5
  147. package/dist/tools/update-document.js +3 -9
  148. package/dist/tools/update-endpoint.d.ts +1 -6
  149. package/dist/tools/update-endpoint.js +0 -7
  150. package/dist/tools/update-finding.d.ts +61 -0
  151. package/dist/tools/update-finding.js +80 -0
  152. package/dist/tools/update-mermaid-source.d.ts +0 -13
  153. package/dist/tools/update-mermaid-source.js +0 -14
  154. package/dist/tools/verify-trust-mark.d.ts +0 -5
  155. package/dist/tools/verify-trust-mark.js +0 -6
  156. package/dist/types.d.ts +14 -14
  157. package/dist/types.js +22 -28
  158. package/package.json +38 -15
  159. package/dist/api-client.js.map +0 -1
  160. package/dist/auth/index.js.map +0 -1
  161. package/dist/auth/jwt.js.map +0 -1
  162. package/dist/auth/keychain.js.map +0 -1
  163. package/dist/auth/oauth.js.map +0 -1
  164. package/dist/auth/sessions.js.map +0 -1
  165. package/dist/auth/token-refresh.js.map +0 -1
  166. package/dist/cli.js.map +0 -1
  167. package/dist/index.js.map +0 -1
  168. package/dist/project-binding.js.map +0 -1
  169. package/dist/resolve-application-id.js.map +0 -1
  170. package/dist/sanitize.js.map +0 -1
  171. package/dist/server.js.map +0 -1
  172. package/dist/tools/check-project.js.map +0 -1
  173. package/dist/tools/check-repo-trust.js.map +0 -1
  174. package/dist/tools/create-diagram.js.map +0 -1
  175. package/dist/tools/create-document.js.map +0 -1
  176. package/dist/tools/discover-local-infra.js.map +0 -1
  177. package/dist/tools/enterprise/capture-evidence.d.ts +0 -54
  178. package/dist/tools/enterprise/capture-evidence.js +0 -72
  179. package/dist/tools/enterprise/capture-evidence.js.map +0 -1
  180. package/dist/tools/enterprise/create-report-ticket.d.ts +0 -34
  181. package/dist/tools/enterprise/create-report-ticket.js +0 -44
  182. package/dist/tools/enterprise/create-report-ticket.js.map +0 -1
  183. package/dist/tools/enterprise/end-pentest-session.d.ts +0 -33
  184. package/dist/tools/enterprise/end-pentest-session.js +0 -42
  185. package/dist/tools/enterprise/end-pentest-session.js.map +0 -1
  186. package/dist/tools/enterprise/generate-report.d.ts +0 -55
  187. package/dist/tools/enterprise/generate-report.js +0 -111
  188. package/dist/tools/enterprise/generate-report.js.map +0 -1
  189. package/dist/tools/enterprise/get-org-zat.js.map +0 -1
  190. package/dist/tools/enterprise/get-report-status.d.ts +0 -27
  191. package/dist/tools/enterprise/get-report-status.js +0 -38
  192. package/dist/tools/enterprise/get-report-status.js.map +0 -1
  193. package/dist/tools/enterprise/get-threat-model.d.ts +0 -29
  194. package/dist/tools/enterprise/get-threat-model.js +0 -83
  195. package/dist/tools/enterprise/get-threat-model.js.map +0 -1
  196. package/dist/tools/enterprise/list-agents.d.ts +0 -42
  197. package/dist/tools/enterprise/list-agents.js +0 -95
  198. package/dist/tools/enterprise/list-agents.js.map +0 -1
  199. package/dist/tools/enterprise/list-report-issues.d.ts +0 -36
  200. package/dist/tools/enterprise/list-report-issues.js +0 -50
  201. package/dist/tools/enterprise/list-report-issues.js.map +0 -1
  202. package/dist/tools/enterprise/list-threat-models.d.ts +0 -36
  203. package/dist/tools/enterprise/list-threat-models.js +0 -82
  204. package/dist/tools/enterprise/list-threat-models.js.map +0 -1
  205. package/dist/tools/enterprise/manage-actor.d.ts +0 -58
  206. package/dist/tools/enterprise/manage-actor.js +0 -99
  207. package/dist/tools/enterprise/manage-actor.js.map +0 -1
  208. package/dist/tools/enterprise/manage-attack-scenario.d.ts +0 -70
  209. package/dist/tools/enterprise/manage-attack-scenario.js +0 -89
  210. package/dist/tools/enterprise/manage-attack-scenario.js.map +0 -1
  211. package/dist/tools/enterprise/manage-component.d.ts +0 -58
  212. package/dist/tools/enterprise/manage-component.js +0 -90
  213. package/dist/tools/enterprise/manage-component.js.map +0 -1
  214. package/dist/tools/enterprise/manage-data-asset.d.ts +0 -53
  215. package/dist/tools/enterprise/manage-data-asset.js +0 -90
  216. package/dist/tools/enterprise/manage-data-asset.js.map +0 -1
  217. package/dist/tools/enterprise/manage-data-flow.d.ts +0 -57
  218. package/dist/tools/enterprise/manage-data-flow.js +0 -98
  219. package/dist/tools/enterprise/manage-data-flow.js.map +0 -1
  220. package/dist/tools/enterprise/manage-finding.d.ts +0 -69
  221. package/dist/tools/enterprise/manage-finding.js +0 -106
  222. package/dist/tools/enterprise/manage-finding.js.map +0 -1
  223. package/dist/tools/enterprise/manage-security-control.d.ts +0 -59
  224. package/dist/tools/enterprise/manage-security-control.js +0 -96
  225. package/dist/tools/enterprise/manage-security-control.js.map +0 -1
  226. package/dist/tools/enterprise/manage-test-case.d.ts +0 -88
  227. package/dist/tools/enterprise/manage-test-case.js +0 -119
  228. package/dist/tools/enterprise/manage-test-case.js.map +0 -1
  229. package/dist/tools/enterprise/promote-finding-to-issue.d.ts +0 -36
  230. package/dist/tools/enterprise/promote-finding-to-issue.js +0 -65
  231. package/dist/tools/enterprise/promote-finding-to-issue.js.map +0 -1
  232. package/dist/tools/enterprise/publish-report-version.d.ts +0 -34
  233. package/dist/tools/enterprise/publish-report-version.js +0 -75
  234. package/dist/tools/enterprise/publish-report-version.js.map +0 -1
  235. package/dist/tools/enterprise/publish-test-to-library.d.ts +0 -31
  236. package/dist/tools/enterprise/publish-test-to-library.js +0 -40
  237. package/dist/tools/enterprise/publish-test-to-library.js.map +0 -1
  238. package/dist/tools/enterprise/record-test-result.d.ts +0 -67
  239. package/dist/tools/enterprise/record-test-result.js +0 -75
  240. package/dist/tools/enterprise/record-test-result.js.map +0 -1
  241. package/dist/tools/enterprise/start-pentest-session.d.ts +0 -35
  242. package/dist/tools/enterprise/start-pentest-session.js +0 -50
  243. package/dist/tools/enterprise/start-pentest-session.js.map +0 -1
  244. package/dist/tools/enterprise/sync-report-section.d.ts +0 -41
  245. package/dist/tools/enterprise/sync-report-section.js +0 -79
  246. package/dist/tools/enterprise/sync-report-section.js.map +0 -1
  247. package/dist/tools/enterprise/update-report-issue.d.ts +0 -55
  248. package/dist/tools/enterprise/update-report-issue.js +0 -69
  249. package/dist/tools/enterprise/update-report-issue.js.map +0 -1
  250. package/dist/tools/generate-diagram.js.map +0 -1
  251. package/dist/tools/get-agent-test-results.d.ts +0 -41
  252. package/dist/tools/get-agent-test-results.js +0 -86
  253. package/dist/tools/get-agent-test-results.js.map +0 -1
  254. package/dist/tools/get-application-overview.js.map +0 -1
  255. package/dist/tools/get-application.js.map +0 -1
  256. package/dist/tools/get-artifact-content.d.ts +0 -29
  257. package/dist/tools/get-artifact-content.js +0 -86
  258. package/dist/tools/get-artifact-content.js.map +0 -1
  259. package/dist/tools/get-diagram.js.map +0 -1
  260. package/dist/tools/get-document.js.map +0 -1
  261. package/dist/tools/get-finding-details.d.ts +0 -28
  262. package/dist/tools/get-finding-details.js +0 -43
  263. package/dist/tools/get-finding-details.js.map +0 -1
  264. package/dist/tools/get-findings.d.ts +0 -57
  265. package/dist/tools/get-findings.js +0 -103
  266. package/dist/tools/get-findings.js.map +0 -1
  267. package/dist/tools/get-oss-zat.js.map +0 -1
  268. package/dist/tools/get-recon-scan.d.ts +0 -27
  269. package/dist/tools/get-recon-scan.js +0 -46
  270. package/dist/tools/get-recon-scan.js.map +0 -1
  271. package/dist/tools/get-scan-output.d.ts +0 -27
  272. package/dist/tools/get-scan-output.js +0 -64
  273. package/dist/tools/get-scan-output.js.map +0 -1
  274. package/dist/tools/get-scenario-details.d.ts +0 -27
  275. package/dist/tools/get-scenario-details.js +0 -46
  276. package/dist/tools/get-scenario-details.js.map +0 -1
  277. package/dist/tools/get-test-case-results.d.ts +0 -37
  278. package/dist/tools/get-test-case-results.js +0 -66
  279. package/dist/tools/get-test-case-results.js.map +0 -1
  280. package/dist/tools/get-test-details.d.ts +0 -29
  281. package/dist/tools/get-test-details.js +0 -49
  282. package/dist/tools/get-test-details.js.map +0 -1
  283. package/dist/tools/get-trust-keys.js.map +0 -1
  284. package/dist/tools/import-openapi-endpoints.js.map +0 -1
  285. package/dist/tools/inspect-zat.js.map +0 -1
  286. package/dist/tools/list-agent-test-cases.d.ts +0 -41
  287. package/dist/tools/list-agent-test-cases.js +0 -73
  288. package/dist/tools/list-agent-test-cases.js.map +0 -1
  289. package/dist/tools/list-applications.js.map +0 -1
  290. package/dist/tools/list-diagrams.js.map +0 -1
  291. package/dist/tools/list-documents.js.map +0 -1
  292. package/dist/tools/list-endpoints.js.map +0 -1
  293. package/dist/tools/list-recon-scans.d.ts +0 -36
  294. package/dist/tools/list-recon-scans.js +0 -74
  295. package/dist/tools/list-recon-scans.js.map +0 -1
  296. package/dist/tools/list-scan-artifacts.d.ts +0 -41
  297. package/dist/tools/list-scan-artifacts.js +0 -63
  298. package/dist/tools/list-scan-artifacts.js.map +0 -1
  299. package/dist/tools/list-scans.d.ts +0 -44
  300. package/dist/tools/list-scans.js +0 -91
  301. package/dist/tools/list-scans.js.map +0 -1
  302. package/dist/tools/list-test-library.d.ts +0 -44
  303. package/dist/tools/list-test-library.js +0 -83
  304. package/dist/tools/list-test-library.js.map +0 -1
  305. package/dist/tools/list-test-scenarios.d.ts +0 -31
  306. package/dist/tools/list-test-scenarios.js +0 -66
  307. package/dist/tools/list-test-scenarios.js.map +0 -1
  308. package/dist/tools/local-scan.d.ts +0 -40
  309. package/dist/tools/local-scan.js +0 -261
  310. package/dist/tools/local-scan.js.map +0 -1
  311. package/dist/tools/manage-diagram.js.map +0 -1
  312. package/dist/tools/open-in-ide.js.map +0 -1
  313. package/dist/tools/run-test-scenario.d.ts +0 -37
  314. package/dist/tools/run-test-scenario.js +0 -70
  315. package/dist/tools/run-test-scenario.js.map +0 -1
  316. package/dist/tools/scan-pr.d.ts +0 -27
  317. package/dist/tools/scan-pr.js +0 -51
  318. package/dist/tools/scan-pr.js.map +0 -1
  319. package/dist/tools/security-review.js.map +0 -1
  320. package/dist/tools/setup-red-team-target.d.ts +0 -79
  321. package/dist/tools/setup-red-team-target.js +0 -430
  322. package/dist/tools/setup-red-team-target.js.map +0 -1
  323. package/dist/tools/triage-finding.d.ts +0 -47
  324. package/dist/tools/triage-finding.js +0 -116
  325. package/dist/tools/triage-finding.js.map +0 -1
  326. package/dist/tools/update-document.js.map +0 -1
  327. package/dist/tools/update-endpoint.js.map +0 -1
  328. package/dist/tools/update-mermaid-source.js.map +0 -1
  329. package/dist/tools/verify-trust-mark.js.map +0 -1
  330. package/dist/types.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,8 +1,2 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * ZIVIS MCP Security Server — Entry Point
4
- *
5
- * CLI tool and MCP server for AI-assisted security finding remediation.
6
- * Connects AI coding assistants to the ZIVIS security platform.
7
- */
8
2
  export {};
package/dist/index.js CHANGED
@@ -1,10 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * ZIVIS MCP Security Server — Entry Point
4
- *
5
- * CLI tool and MCP server for AI-assisted security finding remediation.
6
- * Connects AI coding assistants to the ZIVIS security platform.
7
- */
8
2
  import { parseArgs, runCli } from "./cli.js";
9
3
  import { DEFAULT_CONFIG } from "./types.js";
10
4
  const { command, options } = parseArgs(process.argv);
@@ -12,4 +6,3 @@ runCli(command, options, DEFAULT_CONFIG).catch((err) => {
12
6
  console.error("Fatal error:", err instanceof Error ? err.message : err);
13
7
  process.exit(1);
14
8
  });
15
- //# sourceMappingURL=index.js.map
@@ -0,0 +1,10 @@
1
+ export interface LocatedArtifact {
2
+ path: string;
3
+ mtimeMs: number;
4
+ }
5
+ export declare function userCacheRoot(): string;
6
+ export declare function deriveRepoId(cwd: string): Promise<string>;
7
+ export declare function locateLatestArtifact(cwd: string): Promise<LocatedArtifact | undefined>;
8
+ export declare const DEFAULT_INSPECT_CACHE_TTL_MS: number;
9
+ export declare function inspectCacheTtlMs(): number;
10
+ export declare function isFresh(mtimeMs: number, now?: number): boolean;
@@ -0,0 +1,75 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as fssync from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import * as crypto from "node:crypto";
6
+ import { exec } from "node:child_process";
7
+ import { promisify } from "node:util";
8
+ const execAsync = promisify(exec);
9
+ export function userCacheRoot() {
10
+ const home = os.homedir();
11
+ if (process.platform === "darwin") {
12
+ return path.join(home, "Library", "Caches", "zivis");
13
+ }
14
+ if (process.platform === "win32") {
15
+ const localAppData = process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local");
16
+ return path.join(localAppData, "zivis", "Cache");
17
+ }
18
+ const xdg = process.env.XDG_CACHE_HOME;
19
+ return path.join(xdg ?? path.join(home, ".cache"), "zivis");
20
+ }
21
+ export async function deriveRepoId(cwd) {
22
+ const remote = await tryGit(cwd, "remote get-url origin");
23
+ if (remote) {
24
+ return "remote-" + sha256Short(remote);
25
+ }
26
+ return "path-" + sha256Short(cwd);
27
+ }
28
+ async function tryGit(cwd, args) {
29
+ try {
30
+ const { stdout } = await execAsync(`git ${args}`, { cwd });
31
+ const value = stdout.trim();
32
+ return value || undefined;
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ }
38
+ function sha256Short(value) {
39
+ return crypto.createHash("sha256").update(value).digest("hex").slice(0, 16);
40
+ }
41
+ export async function locateLatestArtifact(cwd) {
42
+ const repoId = await deriveRepoId(cwd);
43
+ const runsDir = path.join(userCacheRoot(), "repos", repoId, "inspect", "runs");
44
+ if (!fssync.existsSync(runsDir))
45
+ return undefined;
46
+ const candidates = [];
47
+ for (const entry of await fs.readdir(runsDir)) {
48
+ if (!entry.endsWith(".json"))
49
+ continue;
50
+ const full = path.join(runsDir, entry);
51
+ try {
52
+ const stat = await fs.stat(full);
53
+ candidates.push({ path: full, mtimeMs: stat.mtimeMs });
54
+ }
55
+ catch {
56
+ }
57
+ }
58
+ if (candidates.length === 0)
59
+ return undefined;
60
+ candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
61
+ return candidates[0];
62
+ }
63
+ export const DEFAULT_INSPECT_CACHE_TTL_MS = 15 * 60 * 1000;
64
+ export function inspectCacheTtlMs() {
65
+ const raw = process.env.ZIVIS_INSPECT_CACHE_TTL_MS;
66
+ if (!raw)
67
+ return DEFAULT_INSPECT_CACHE_TTL_MS;
68
+ const parsed = Number.parseInt(raw, 10);
69
+ if (!Number.isFinite(parsed) || parsed <= 0)
70
+ return DEFAULT_INSPECT_CACHE_TTL_MS;
71
+ return parsed;
72
+ }
73
+ export function isFresh(mtimeMs, now = Date.now()) {
74
+ return now - mtimeMs <= inspectCacheTtlMs();
75
+ }
@@ -0,0 +1,27 @@
1
+ export interface NextStep {
2
+ id: string;
3
+ label: string;
4
+ tool: string;
5
+ args_hint?: Record<string, unknown>;
6
+ why: string;
7
+ requires_tier?: "free" | "pro" | "enterprise";
8
+ }
9
+ export interface ZivisToolPayload<T> {
10
+ result: T;
11
+ next_steps?: NextStep[];
12
+ summary?: string;
13
+ }
14
+ export declare function withNextSteps<T>(result: T, nextSteps: NextStep[], summary?: string): {
15
+ content: Array<{
16
+ type: "text";
17
+ text: string;
18
+ }>;
19
+ isError?: boolean;
20
+ };
21
+ export declare function withNextStepsError(message: string, nextSteps: NextStep[], summary?: string): {
22
+ content: Array<{
23
+ type: "text";
24
+ text: string;
25
+ }>;
26
+ isError: true;
27
+ };
@@ -0,0 +1,21 @@
1
+ export function withNextSteps(result, nextSteps, summary) {
2
+ const payload = {
3
+ result,
4
+ next_steps: nextSteps,
5
+ ...(summary ? { summary } : {}),
6
+ };
7
+ return {
8
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
9
+ };
10
+ }
11
+ export function withNextStepsError(message, nextSteps, summary) {
12
+ const payload = {
13
+ result: { error: message },
14
+ next_steps: nextSteps,
15
+ ...(summary ? { summary } : {}),
16
+ };
17
+ return {
18
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
19
+ isError: true,
20
+ };
21
+ }
@@ -0,0 +1,8 @@
1
+ export type AstLanguage = "typescript" | "javascript" | "python" | "go";
2
+ export interface AstMatch {
3
+ file: string;
4
+ start_line: number;
5
+ end_line: number;
6
+ matched_text: string;
7
+ }
8
+ export declare function evaluateAstStrategy(expression: unknown, language: AstLanguage, files: string[], rootDir: string): Promise<AstMatch[]>;
@@ -0,0 +1,95 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import * as yaml from "js-yaml";
4
+ import * as napi from "@ast-grep/napi";
5
+ let registered = false;
6
+ async function ensureLanguagesRegistered() {
7
+ if (registered)
8
+ return;
9
+ const py = (await import("@ast-grep/lang-python")).default;
10
+ const go = (await import("@ast-grep/lang-go")).default;
11
+ napi.registerDynamicLanguage({ python: py, go: go });
12
+ registered = true;
13
+ }
14
+ export async function evaluateAstStrategy(expression, language, files, rootDir) {
15
+ await ensureLanguagesRegistered();
16
+ const rule = normalizeExpressionToRule(expression);
17
+ if (!rule)
18
+ return [];
19
+ const matches = [];
20
+ const langKey = languageKey(language);
21
+ for (const file of files) {
22
+ let raw;
23
+ try {
24
+ raw = await fs.readFile(file, "utf8");
25
+ }
26
+ catch {
27
+ continue;
28
+ }
29
+ if (!raw)
30
+ continue;
31
+ let root;
32
+ try {
33
+ root = napi.parse(langKey, raw);
34
+ }
35
+ catch {
36
+ continue;
37
+ }
38
+ let foundNodes;
39
+ try {
40
+ foundNodes = root.root().findAll(rule);
41
+ }
42
+ catch {
43
+ continue;
44
+ }
45
+ for (const node of foundNodes) {
46
+ const range = node.range();
47
+ matches.push({
48
+ file: relPosix(rootDir, file),
49
+ start_line: (range.start.line ?? 0) + 1,
50
+ end_line: (range.end.line ?? 0) + 1,
51
+ matched_text: truncate(node.text(), 240),
52
+ });
53
+ }
54
+ }
55
+ return matches;
56
+ }
57
+ function normalizeExpressionToRule(expression) {
58
+ if (typeof expression === "string") {
59
+ try {
60
+ return ensureRuleWrapper(yaml.load(expression));
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ }
66
+ if (expression && typeof expression === "object") {
67
+ return ensureRuleWrapper(expression);
68
+ }
69
+ return undefined;
70
+ }
71
+ function ensureRuleWrapper(parsed) {
72
+ if (!parsed || typeof parsed !== "object")
73
+ return parsed;
74
+ const obj = parsed;
75
+ if ("rule" in obj)
76
+ return obj;
77
+ return { rule: obj };
78
+ }
79
+ function languageKey(lang) {
80
+ switch (lang) {
81
+ case "typescript": return "ts";
82
+ case "javascript": return "js";
83
+ case "python": return "python";
84
+ case "go": return "go";
85
+ }
86
+ }
87
+ function relPosix(rootDir, abs) {
88
+ const rel = path.relative(rootDir, abs);
89
+ return rel.split(path.sep).join("/");
90
+ }
91
+ function truncate(s, max) {
92
+ if (s.length <= max)
93
+ return s;
94
+ return s.slice(0, max) + "…";
95
+ }
@@ -0,0 +1,55 @@
1
+ export type Lane = "trusted" | "inferred";
2
+ export interface MatchedEvidence {
3
+ file: string;
4
+ start_line: number;
5
+ end_line?: number;
6
+ matched_text?: string;
7
+ strategy_code: string;
8
+ }
9
+ export interface FiredStrategy {
10
+ code: string;
11
+ language?: string;
12
+ trusted: boolean;
13
+ confidence_weight: number;
14
+ match_count: number;
15
+ }
16
+ export interface InferenceCandidate {
17
+ prompt_ref: string;
18
+ expected_output_schema?: unknown;
19
+ minimum_context_required?: {
20
+ lines?: number;
21
+ symbols?: string[];
22
+ };
23
+ reason: string;
24
+ }
25
+ export interface Finding {
26
+ pattern_id: string;
27
+ pattern_version: string;
28
+ lane: Lane;
29
+ confidence: number;
30
+ fired_strategies: FiredStrategy[];
31
+ evidence: MatchedEvidence[];
32
+ inference_candidate?: InferenceCandidate;
33
+ safe_summary?: string;
34
+ threats?: unknown[];
35
+ repair_contract?: unknown;
36
+ }
37
+ export interface MatcherSummary {
38
+ trusted_count: number;
39
+ inferred_count: number;
40
+ total: number;
41
+ }
42
+ export interface MatcherResult {
43
+ pack: {
44
+ id: string;
45
+ version: string;
46
+ };
47
+ artifact_path: string;
48
+ cwd: string;
49
+ capsules_relevant: number;
50
+ capsules_evaluated: number;
51
+ ast_files_scanned: number;
52
+ duration_ms: number;
53
+ summary: MatcherSummary;
54
+ findings: Finding[];
55
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { MatcherResult } from "./finding.js";
2
+ export type { Finding, FiredStrategy, MatchedEvidence, MatcherResult, Lane } from "./finding.js";
3
+ export interface RunMatcherOpts {
4
+ artifactPath: string;
5
+ cwd: string;
6
+ packId?: string;
7
+ }
8
+ export declare function runMatcher(opts: RunMatcherOpts): Promise<MatcherResult>;
@@ -0,0 +1,202 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as fssync from "node:fs";
3
+ import { loadActivePack, findRelevantCapsules, getControl, } from "../pattern-pack/index.js";
4
+ import { walkLanguageFiles } from "./walker.js";
5
+ import { evaluateAstStrategy } from "./ast-eval.js";
6
+ const SUPPORTED_AST_LANGS = new Set([
7
+ "typescript",
8
+ "javascript",
9
+ "python",
10
+ "go",
11
+ ]);
12
+ export async function runMatcher(opts) {
13
+ const startedAt = Date.now();
14
+ const handle = await loadActivePack(opts.packId);
15
+ const artifact = await readArtifact(opts.artifactPath);
16
+ const relevant = await findRelevantCapsules(handle, artifact);
17
+ const langsNeeded = collectAstLanguagesNeeded(relevant);
18
+ const walked = langsNeeded.length > 0
19
+ ? await walkLanguageFiles(opts.cwd, langsNeeded)
20
+ : { filesByLanguage: new Map(), filesScanned: 0, filesSkipped: 0 };
21
+ const controlPresence = await evaluateAllControls(handle, opts.cwd, walked.filesByLanguage);
22
+ const findings = [];
23
+ for (const cap of relevant) {
24
+ const finding = await evaluateCapsule(cap, opts.cwd, walked.filesByLanguage, controlPresence);
25
+ if (finding)
26
+ findings.push(finding);
27
+ }
28
+ const summary = {
29
+ trusted_count: findings.filter((f) => f.lane === "trusted").length,
30
+ inferred_count: findings.filter((f) => f.lane === "inferred").length,
31
+ total: findings.length,
32
+ };
33
+ return {
34
+ pack: { id: handle.manifest.pack_id, version: handle.manifest.version },
35
+ artifact_path: opts.artifactPath,
36
+ cwd: opts.cwd,
37
+ capsules_relevant: relevant.length,
38
+ capsules_evaluated: relevant.length,
39
+ ast_files_scanned: walked.filesScanned,
40
+ duration_ms: Date.now() - startedAt,
41
+ summary,
42
+ findings,
43
+ };
44
+ }
45
+ async function evaluateCapsule(cap, cwd, filesByLanguage, controlPresence) {
46
+ const strategies = (cap.strategies ?? []);
47
+ const fired = [];
48
+ const evidence = [];
49
+ let inferenceCandidate;
50
+ for (const strategy of strategies) {
51
+ const code = strategy.code;
52
+ const trusted = strategy.trusted !== false && code !== "INFER" && code !== "SEM" && code !== "REGEX";
53
+ if (code === "AST") {
54
+ const lang = (strategy.language ?? "").toLowerCase();
55
+ if (!SUPPORTED_AST_LANGS.has(lang)) {
56
+ fired.push({ code, language: lang, trusted, confidence_weight: strategy.confidence_weight, match_count: 0 });
57
+ continue;
58
+ }
59
+ const files = filesByLanguage.get(lang) ?? [];
60
+ if (files.length === 0) {
61
+ fired.push({ code, language: lang, trusted, confidence_weight: strategy.confidence_weight, match_count: 0 });
62
+ continue;
63
+ }
64
+ const matches = await evaluateAstStrategy(strategy.expression, lang, files, cwd);
65
+ fired.push({
66
+ code,
67
+ language: lang,
68
+ trusted,
69
+ confidence_weight: strategy.confidence_weight,
70
+ match_count: matches.length,
71
+ });
72
+ for (const m of matches) {
73
+ evidence.push({
74
+ file: m.file,
75
+ start_line: m.start_line,
76
+ end_line: m.end_line,
77
+ matched_text: m.matched_text,
78
+ strategy_code: code,
79
+ });
80
+ }
81
+ }
82
+ else if (code === "META") {
83
+ const result = evaluateMetaStrategy(strategy.expression, controlPresence);
84
+ fired.push({
85
+ code,
86
+ trusted,
87
+ confidence_weight: strategy.confidence_weight,
88
+ match_count: result.fired ? 1 : 0,
89
+ });
90
+ if (result.fired) {
91
+ evidence.push({
92
+ file: "(synthetic)",
93
+ start_line: 0,
94
+ matched_text: `META: none_of_controls satisfied; absent: [${result.absent.join(", ")}]`,
95
+ strategy_code: code,
96
+ });
97
+ }
98
+ }
99
+ else if (code === "INFER") {
100
+ if (cap.model_task_prompt_ref) {
101
+ inferenceCandidate = {
102
+ prompt_ref: cap.model_task_prompt_ref,
103
+ expected_output_schema: cap.expected_output_schema,
104
+ minimum_context_required: cap.minimum_context_required,
105
+ reason: "Capsule has an INFER strategy. Use zivis_threat_get_inference_prompt to retrieve the prompt bundle, gather the indicated code spans, and run the inference in your model.",
106
+ };
107
+ }
108
+ fired.push({ code, trusted: false, confidence_weight: strategy.confidence_weight, match_count: 1 });
109
+ }
110
+ else {
111
+ fired.push({ code, trusted, confidence_weight: strategy.confidence_weight, match_count: 0 });
112
+ }
113
+ }
114
+ const anyFired = fired.some((f) => f.match_count > 0);
115
+ if (!anyFired)
116
+ return undefined;
117
+ const trustedFired = fired.filter((f) => f.trusted && f.match_count > 0).length;
118
+ const requiredCount = cap.required_evidence_count ?? 1;
119
+ const lane = trustedFired >= requiredCount ? "trusted" : "inferred";
120
+ const confidence = Math.min(1, fired.reduce((acc, f) => (f.match_count > 0 ? acc + f.confidence_weight : acc), 0));
121
+ return {
122
+ pattern_id: cap.id,
123
+ pattern_version: cap.version,
124
+ lane,
125
+ confidence,
126
+ fired_strategies: fired,
127
+ evidence,
128
+ inference_candidate: inferenceCandidate,
129
+ safe_summary: cap.safe_summary,
130
+ threats: cap.threats,
131
+ repair_contract: cap.repair_contract,
132
+ };
133
+ }
134
+ async function readArtifact(p) {
135
+ if (!fssync.existsSync(p)) {
136
+ throw new Error(`Artifact not found: ${p}`);
137
+ }
138
+ const raw = await fs.readFile(p, "utf8");
139
+ return JSON.parse(raw);
140
+ }
141
+ function collectAstLanguagesNeeded(capsules) {
142
+ const set = new Set();
143
+ for (const cap of capsules) {
144
+ for (const strategy of cap.strategies) {
145
+ if (strategy.code !== "AST")
146
+ continue;
147
+ const lang = (strategy.language ?? "").toLowerCase();
148
+ if (SUPPORTED_AST_LANGS.has(lang))
149
+ set.add(lang);
150
+ }
151
+ }
152
+ set.add("typescript");
153
+ set.add("python");
154
+ return [...set];
155
+ }
156
+ function evaluateMetaStrategy(expression, presence) {
157
+ const expr = expression;
158
+ if (!expr || typeof expr !== "object")
159
+ return { fired: false, absent: [] };
160
+ if (expr.none_of_controls && expr.none_of_controls.length > 0) {
161
+ const checkable = expr.none_of_controls.filter((id) => presence.get(id)?.checkable);
162
+ if (checkable.length === 0)
163
+ return { fired: false, absent: [] };
164
+ const absent = checkable.filter((id) => !presence.get(id).present);
165
+ if (absent.length === checkable.length) {
166
+ return { fired: true, absent };
167
+ }
168
+ return { fired: false, absent };
169
+ }
170
+ return { fired: false, absent: [] };
171
+ }
172
+ async function evaluateAllControls(handle, cwd, filesByLanguage) {
173
+ const out = new Map();
174
+ const controlEntries = handle.manifest.controls ?? [];
175
+ for (const entry of controlEntries) {
176
+ let control;
177
+ try {
178
+ control = await getControl(handle, entry.id);
179
+ }
180
+ catch {
181
+ continue;
182
+ }
183
+ let present = false;
184
+ let checkable = false;
185
+ for (const det of control.detection ?? []) {
186
+ const lang = det.language;
187
+ if (!SUPPORTED_AST_LANGS.has(lang))
188
+ continue;
189
+ const files = filesByLanguage.get(lang) ?? [];
190
+ if (files.length === 0)
191
+ continue;
192
+ checkable = true;
193
+ const matches = await evaluateAstStrategy(det.rule, lang, files, cwd);
194
+ if (matches.length > 0) {
195
+ present = true;
196
+ break;
197
+ }
198
+ }
199
+ out.set(control.id, { present, checkable });
200
+ }
201
+ return out;
202
+ }
@@ -0,0 +1,26 @@
1
+ import { type Capsule } from "../pattern-pack/index.js";
2
+ import type { Finding } from "./finding.js";
3
+ export interface BundledInferenceCandidate {
4
+ candidate_id: string;
5
+ capsule_id: string;
6
+ capsule_version: string;
7
+ pattern_title?: string;
8
+ prompt: string;
9
+ expected_output_schema: unknown;
10
+ evidence_focus: Array<{
11
+ file: string;
12
+ start_line: number;
13
+ end_line?: number;
14
+ note?: string;
15
+ }>;
16
+ minimum_context_required?: {
17
+ lines?: number;
18
+ symbols?: string[];
19
+ };
20
+ instructions_for_host: string;
21
+ }
22
+ export interface InferenceBundle {
23
+ inference_candidates: BundledInferenceCandidate[];
24
+ host_required_action: string;
25
+ }
26
+ export declare function buildInferenceBundle(findings: Finding[], capsuleByPatternId?: Map<string, Capsule>): Promise<InferenceBundle>;
@@ -0,0 +1,81 @@
1
+ import { loadActivePack, getInferencePrompt, } from "../pattern-pack/index.js";
2
+ export async function buildInferenceBundle(findings, capsuleByPatternId) {
3
+ const candidates = [];
4
+ let handle;
5
+ for (let i = 0; i < findings.length; i++) {
6
+ const f = findings[i];
7
+ if (!f.inference_candidate)
8
+ continue;
9
+ if (!handle) {
10
+ try {
11
+ handle = await loadActivePack();
12
+ }
13
+ catch {
14
+ candidates.push(toFallbackCandidate(f, i));
15
+ continue;
16
+ }
17
+ }
18
+ let promptText;
19
+ try {
20
+ promptText = await getInferencePrompt(handle, f.inference_candidate.prompt_ref);
21
+ }
22
+ catch {
23
+ candidates.push(toFallbackCandidate(f, i));
24
+ continue;
25
+ }
26
+ const cap = capsuleByPatternId?.get(f.pattern_id);
27
+ candidates.push({
28
+ candidate_id: `ic-${i + 1}`,
29
+ capsule_id: f.pattern_id,
30
+ capsule_version: f.pattern_version,
31
+ pattern_title: cap?.title,
32
+ prompt: promptText,
33
+ expected_output_schema: f.inference_candidate.expected_output_schema ?? null,
34
+ evidence_focus: f.evidence
35
+ .filter((e) => e.file !== "(synthetic)")
36
+ .map((e) => ({
37
+ file: e.file,
38
+ start_line: e.start_line,
39
+ end_line: e.end_line,
40
+ note: e.matched_text ? e.matched_text.slice(0, 200) : undefined,
41
+ })),
42
+ minimum_context_required: f.inference_candidate.minimum_context_required,
43
+ instructions_for_host: "Read the source code at each evidence_focus[*].file:start_line — pull at least minimum_context_required.lines around each span. " +
44
+ "Attach those snippets to the prompt above. Run the prompt against your model. " +
45
+ "Return JSON matching expected_output_schema. The output enters the inferred lane.",
46
+ });
47
+ }
48
+ const action = buildHostRequiredAction(candidates);
49
+ return { inference_candidates: candidates, host_required_action: action };
50
+ }
51
+ function toFallbackCandidate(f, i) {
52
+ return {
53
+ candidate_id: `ic-${i + 1}`,
54
+ capsule_id: f.pattern_id,
55
+ capsule_version: f.pattern_version,
56
+ prompt: "",
57
+ expected_output_schema: f.inference_candidate?.expected_output_schema ?? null,
58
+ evidence_focus: f.evidence
59
+ .filter((e) => e.file !== "(synthetic)")
60
+ .map((e) => ({
61
+ file: e.file,
62
+ start_line: e.start_line,
63
+ end_line: e.end_line,
64
+ })),
65
+ minimum_context_required: f.inference_candidate?.minimum_context_required,
66
+ instructions_for_host: "Inline prompt unavailable. Call zivis_threat_get_inference_prompt with capsule_id=" +
67
+ f.pattern_id +
68
+ " to retrieve it.",
69
+ };
70
+ }
71
+ function buildHostRequiredAction(candidates) {
72
+ if (candidates.length === 0) {
73
+ return "No inference candidates emitted by this run. Findings are deterministic-only.";
74
+ }
75
+ return (`MANDATORY HOST ACTION: For each of the ${candidates.length} inference_candidate${candidates.length === 1 ? "" : "s"} below, ` +
76
+ `you MUST: (1) read the source code at evidence_focus[*].file:start_line (open each file, grab at least minimum_context_required.lines of surrounding context), ` +
77
+ `(2) run the candidate's prompt against your model with that source attached, ` +
78
+ `(3) produce JSON output matching expected_output_schema. ` +
79
+ `Do this BEFORE summarizing findings to the user — the inferred-lane verdict from your inference is what the user actually wants. ` +
80
+ `Each candidate is a self-contained inference task; you do not need to call any other ZIVIS tool to execute it.`);
81
+ }
@@ -0,0 +1,7 @@
1
+ export type WalkLanguage = "typescript" | "javascript" | "python" | "go";
2
+ export interface WalkResult {
3
+ filesByLanguage: Map<WalkLanguage, string[]>;
4
+ filesScanned: number;
5
+ filesSkipped: number;
6
+ }
7
+ export declare function walkLanguageFiles(rootDir: string, languages: WalkLanguage[]): Promise<WalkResult>;