infraweaver 0.1.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 (524) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +244 -0
  3. package/dist/agents/claude.d.ts +113 -0
  4. package/dist/agents/claudePretoolGate.d.ts +137 -0
  5. package/dist/agents/dispatchMetrics.d.ts +77 -0
  6. package/dist/agents/gateServer.d.ts +7 -0
  7. package/dist/agents/index.d.ts +6 -0
  8. package/dist/agents/nativeFsDenies.d.ts +46 -0
  9. package/dist/agents/opencode.d.ts +284 -0
  10. package/dist/agents/opencodePlugin.d.ts +96 -0
  11. package/dist/agents/opencodeShared.d.ts +40 -0
  12. package/dist/agents/postRun.d.ts +126 -0
  13. package/dist/agents/reviewer.d.ts +41 -0
  14. package/dist/agents/sessionLabeler.d.ts +97 -0
  15. package/dist/agents/shared.d.ts +246 -0
  16. package/dist/agents/subagentModels.d.ts +19 -0
  17. package/dist/agents/tokenQuota.d.ts +118 -0
  18. package/dist/agents/writeGateSource.d.ts +22 -0
  19. package/dist/agents/writePolicy.d.ts +79 -0
  20. package/dist/brand.d.ts +67 -0
  21. package/dist/cli.mjs +247846 -0
  22. package/dist/external.d.ts +227 -0
  23. package/dist/i18n/scaffolding.d.ts +59 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.js +247061 -0
  26. package/dist/internal/index.d.ts +18 -0
  27. package/dist/internal.js +2398 -0
  28. package/dist/lifecycle.d.ts +2 -0
  29. package/dist/main.d.ts +8 -0
  30. package/dist/mcp/arkConfig.d.ts +1 -0
  31. package/dist/mcp/assess.d.ts +157 -0
  32. package/dist/mcp/capabilityContext.d.ts +71 -0
  33. package/dist/mcp/changeSummary.d.ts +52 -0
  34. package/dist/mcp/checkSuite.d.ts +27 -0
  35. package/dist/mcp/checkout.d.ts +92 -0
  36. package/dist/mcp/comment.d.ts +127 -0
  37. package/dist/mcp/commitInfo.d.ts +11 -0
  38. package/dist/mcp/crosswalk.d.ts +178 -0
  39. package/dist/mcp/crosswalkDigest.d.ts +1 -0
  40. package/dist/mcp/cyberEssentials.d.ts +24 -0
  41. package/dist/mcp/dashboard.d.ts +125 -0
  42. package/dist/mcp/dependencies.d.ts +12 -0
  43. package/dist/mcp/frameworks.d.ts +74 -0
  44. package/dist/mcp/geminiSanitizer.d.ts +28 -0
  45. package/dist/mcp/git.d.ts +60 -0
  46. package/dist/mcp/guardrails.d.ts +222 -0
  47. package/dist/mcp/issue.d.ts +20 -0
  48. package/dist/mcp/issueComments.d.ts +11 -0
  49. package/dist/mcp/issueEvents.d.ts +11 -0
  50. package/dist/mcp/issueInfo.d.ts +11 -0
  51. package/dist/mcp/labels.d.ts +14 -0
  52. package/dist/mcp/localContext.d.ts +26 -0
  53. package/dist/mcp/moduleExtraction.d.ts +79 -0
  54. package/dist/mcp/moduleTests.d.ts +106 -0
  55. package/dist/mcp/modules.d.ts +198 -0
  56. package/dist/mcp/output.d.ts +16 -0
  57. package/dist/mcp/pathSafety.d.ts +14 -0
  58. package/dist/mcp/policy.d.ts +50 -0
  59. package/dist/mcp/pr.d.ts +64 -0
  60. package/dist/mcp/prInfo.d.ts +11 -0
  61. package/dist/mcp/providerSchema.d.ts +52 -0
  62. package/dist/mcp/review.d.ts +212 -0
  63. package/dist/mcp/reviewComments.d.ts +245 -0
  64. package/dist/mcp/roots.d.ts +60 -0
  65. package/dist/mcp/scope.d.ts +26 -0
  66. package/dist/mcp/selectMode.d.ts +20 -0
  67. package/dist/mcp/server.d.ts +61 -0
  68. package/dist/mcp/shared.d.ts +62 -0
  69. package/dist/mcp/shell.d.ts +58 -0
  70. package/dist/mcp/staleFix.d.ts +138 -0
  71. package/dist/mcp/terraform/azurePrices.d.ts +8 -0
  72. package/dist/mcp/terraform/baseline.d.ts +57 -0
  73. package/dist/mcp/terraform/concernResult.d.ts +38 -0
  74. package/dist/mcp/terraform/cost.d.ts +55 -0
  75. package/dist/mcp/terraform/cspm.d.ts +80 -0
  76. package/dist/mcp/terraform/currency.d.ts +110 -0
  77. package/dist/mcp/terraform/decisions.d.ts +178 -0
  78. package/dist/mcp/terraform/eidas.d.ts +100 -0
  79. package/dist/mcp/terraform/evidence.d.ts +343 -0
  80. package/dist/mcp/terraform/findings.d.ts +76 -0
  81. package/dist/mcp/terraform/fixMemory.d.ts +81 -0
  82. package/dist/mcp/terraform/governance.d.ts +56 -0
  83. package/dist/mcp/terraform/hcl.d.ts +115 -0
  84. package/dist/mcp/terraform/iacLanguages.d.ts +120 -0
  85. package/dist/mcp/terraform/idleFloor.d.ts +78 -0
  86. package/dist/mcp/terraform/keyless.d.ts +68 -0
  87. package/dist/mcp/terraform/moduleDocs.d.ts +56 -0
  88. package/dist/mcp/terraform/nativeRules.d.ts +38 -0
  89. package/dist/mcp/terraform/nativeScan.d.ts +11 -0
  90. package/dist/mcp/terraform/noiseProfile.d.ts +100 -0
  91. package/dist/mcp/terraform/normalization.d.ts +52 -0
  92. package/dist/mcp/terraform/oscal.d.ts +103 -0
  93. package/dist/mcp/terraform/packs/azurerm-3-4.d.ts +2 -0
  94. package/dist/mcp/terraform/packs/cloudflare-4-5.d.ts +2 -0
  95. package/dist/mcp/terraform/paths.d.ts +28 -0
  96. package/dist/mcp/terraform/plan.d.ts +157 -0
  97. package/dist/mcp/terraform/planDrift.d.ts +199 -0
  98. package/dist/mcp/terraform/policyAuthor.d.ts +191 -0
  99. package/dist/mcp/terraform/prowlerOcsf.d.ts +136 -0
  100. package/dist/mcp/terraform/refactor.d.ts +183 -0
  101. package/dist/mcp/terraform/registry.d.ts +108 -0
  102. package/dist/mcp/terraform/risk.d.ts +41 -0
  103. package/dist/mcp/terraform/scanSession.d.ts +116 -0
  104. package/dist/mcp/terraform/scannerCache.d.ts +15 -0
  105. package/dist/mcp/terraform/scannerEgress.d.ts +72 -0
  106. package/dist/mcp/terraform/scannerJson.d.ts +13 -0
  107. package/dist/mcp/terraform/scanners.d.ts +205 -0
  108. package/dist/mcp/terraform/signing.d.ts +61 -0
  109. package/dist/mcp/terraform/stateLocking.d.ts +18 -0
  110. package/dist/mcp/terraform/subprocess.d.ts +43 -0
  111. package/dist/mcp/terraform/suppressions.d.ts +90 -0
  112. package/dist/mcp/terraform/taxonomy.d.ts +39 -0
  113. package/dist/mcp/terraform/tfquery.d.ts +47 -0
  114. package/dist/mcp/terraform/toolchainIntegrity.d.ts +82 -0
  115. package/dist/mcp/terraform/tools/authorPolicy.d.ts +59 -0
  116. package/dist/mcp/terraform/tools/detectPlanDrift.d.ts +20 -0
  117. package/dist/mcp/terraform/tools/emitCost.d.ts +11 -0
  118. package/dist/mcp/terraform/tools/emitSarif.d.ts +14 -0
  119. package/dist/mcp/terraform/tools/fixMemory.d.ts +19 -0
  120. package/dist/mcp/terraform/tools/infracostDiff.d.ts +22 -0
  121. package/dist/mcp/terraform/tools/ingestExternalFindings.d.ts +21 -0
  122. package/dist/mcp/terraform/tools/moduleLookup.d.ts +14 -0
  123. package/dist/mcp/terraform/tools/moduleSearch.d.ts +23 -0
  124. package/dist/mcp/terraform/tools/plan.d.ts +59 -0
  125. package/dist/mcp/terraform/tools/providerUpgrade.d.ts +55 -0
  126. package/dist/mcp/terraform/tools/readFindings.d.ts +17 -0
  127. package/dist/mcp/terraform/tools/scan.d.ts +114 -0
  128. package/dist/mcp/terraform/tools/validate.d.ts +31 -0
  129. package/dist/mcp/terraform/tools/verifyRemediation.d.ts +31 -0
  130. package/dist/mcp/terraform/tools/versionCurrency.d.ts +5 -0
  131. package/dist/mcp/terraform/tools.d.ts +16 -0
  132. package/dist/mcp/terraform/transformPacks.d.ts +267 -0
  133. package/dist/mcp/terraform/types.d.ts +226 -0
  134. package/dist/mcp/terraform/verification.d.ts +81 -0
  135. package/dist/mcp/terraform/vex.d.ts +115 -0
  136. package/dist/mcp/terraform/writeOnly.d.ts +67 -0
  137. package/dist/mcp/terraform.d.ts +51 -0
  138. package/dist/mcp/terratest.d.ts +85 -0
  139. package/dist/mcp/untrustedContent.d.ts +76 -0
  140. package/dist/mcp/upload.d.ts +8 -0
  141. package/dist/models.d.ts +181 -0
  142. package/dist/modes/address-reviews.d.ts +2 -0
  143. package/dist/modes/assess.d.ts +2 -0
  144. package/dist/modes/build.d.ts +2 -0
  145. package/dist/modes/compliance-audit.d.ts +2 -0
  146. package/dist/modes/cost-optimization.d.ts +2 -0
  147. package/dist/modes/drift-detect.d.ts +2 -0
  148. package/dist/modes/fix.d.ts +2 -0
  149. package/dist/modes/incremental-review.d.ts +2 -0
  150. package/dist/modes/index.d.ts +24 -0
  151. package/dist/modes/modernize-deprecated.d.ts +2 -0
  152. package/dist/modes/plan.d.ts +2 -0
  153. package/dist/modes/policy-gate.d.ts +2 -0
  154. package/dist/modes/prFormats.d.ts +3 -0
  155. package/dist/modes/refactor.d.ts +2 -0
  156. package/dist/modes/refresh-remediation.d.ts +2 -0
  157. package/dist/modes/remediate-and-refactor.d.ts +2 -0
  158. package/dist/modes/remediate.d.ts +2 -0
  159. package/dist/modes/resolve-conflicts.d.ts +2 -0
  160. package/dist/modes/review.d.ts +2 -0
  161. package/dist/modes/summarize-pr.d.ts +2 -0
  162. package/dist/modes/task.d.ts +2 -0
  163. package/dist/modes/terraform-code-review.d.ts +2 -0
  164. package/dist/modes/types.d.ts +9 -0
  165. package/dist/modes/update-dependencies.d.ts +2 -0
  166. package/dist/prep/index.d.ts +7 -0
  167. package/dist/prep/installNodeDependencies.d.ts +2 -0
  168. package/dist/prep/installPythonDependencies.d.ts +2 -0
  169. package/dist/prep/types.d.ts +31 -0
  170. package/dist/reviewQuality.d.ts +107 -0
  171. package/dist/skills/terraform-best-practices/SKILL.md +379 -0
  172. package/dist/toolState.d.ts +123 -0
  173. package/dist/utils/activity.d.ts +40 -0
  174. package/dist/utils/agent.d.ts +47 -0
  175. package/dist/utils/agentHangReport.d.ts +38 -0
  176. package/dist/utils/annotations.d.ts +17 -0
  177. package/dist/utils/apiFetch.d.ts +11 -0
  178. package/dist/utils/apiKeys.d.ts +48 -0
  179. package/dist/utils/apiUrl.d.ts +28 -0
  180. package/dist/utils/assets.d.ts +8 -0
  181. package/dist/utils/baseRefConfig.d.ts +121 -0
  182. package/dist/utils/billingErrors.d.ts +85 -0
  183. package/dist/utils/body.d.ts +34 -0
  184. package/dist/utils/buildInfraweaverFooter.d.ts +29 -0
  185. package/dist/utils/byokFallback.d.ts +85 -0
  186. package/dist/utils/changeImpact.d.ts +101 -0
  187. package/dist/utils/claudeSubscription.d.ts +30 -0
  188. package/dist/utils/cli.d.ts +10 -0
  189. package/dist/utils/cloudClient.d.ts +33 -0
  190. package/dist/utils/cloudFetchCore.d.ts +42 -0
  191. package/dist/utils/cloudReport.d.ts +114 -0
  192. package/dist/utils/codexHome.d.ts +29 -0
  193. package/dist/utils/codexOAuth.d.ts +60 -0
  194. package/dist/utils/diffCoverage.d.ts +63 -0
  195. package/dist/utils/env.d.ts +46 -0
  196. package/dist/utils/errorReport.d.ts +17 -0
  197. package/dist/utils/exitHandler.d.ts +8 -0
  198. package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
  199. package/dist/utils/gitAuth.d.ts +84 -0
  200. package/dist/utils/gitAuthServer.d.ts +24 -0
  201. package/dist/utils/github.d.ts +104 -0
  202. package/dist/utils/globals.d.ts +3 -0
  203. package/dist/utils/infraweaverConfig.d.ts +56 -0
  204. package/dist/utils/install.d.ts +37 -0
  205. package/dist/utils/instructions.d.ts +48 -0
  206. package/dist/utils/keylessOidc.d.ts +28 -0
  207. package/dist/utils/leapingComment.d.ts +11 -0
  208. package/dist/utils/learnings.d.ts +62 -0
  209. package/dist/utils/learningsTruncate.d.ts +25 -0
  210. package/dist/utils/lifecycle.d.ts +57 -0
  211. package/dist/utils/log.d.ts +111 -0
  212. package/dist/utils/modelResolver.d.ts +63 -0
  213. package/dist/utils/moduleFetch.d.ts +39 -0
  214. package/dist/utils/normalizeEnv.d.ts +30 -0
  215. package/dist/utils/openCodeModels.d.ts +11 -0
  216. package/dist/utils/openaiCompatible.d.ts +26 -0
  217. package/dist/utils/opentofuMcp.d.ts +50 -0
  218. package/dist/utils/overrides.d.ts +40 -0
  219. package/dist/utils/packageManager.d.ts +49 -0
  220. package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
  221. package/dist/utils/payload.d.ts +249 -0
  222. package/dist/utils/prSummary.d.ts +61 -0
  223. package/dist/utils/presets.d.ts +36 -0
  224. package/dist/utils/progressComment.d.ts +146 -0
  225. package/dist/utils/providerErrors.d.ts +31 -0
  226. package/dist/utils/proxyModel.d.ts +76 -0
  227. package/dist/utils/rangeDiff.d.ts +51 -0
  228. package/dist/utils/redact.d.ts +33 -0
  229. package/dist/utils/registryAuth.d.ts +52 -0
  230. package/dist/utils/remediationCommand.d.ts +58 -0
  231. package/dist/utils/retry.d.ts +38 -0
  232. package/dist/utils/reviewCleanup.d.ts +14 -0
  233. package/dist/utils/run.d.ts +9 -0
  234. package/dist/utils/runContext.d.ts +112 -0
  235. package/dist/utils/runContextData.d.ts +42 -0
  236. package/dist/utils/runErrorRenderer.d.ts +64 -0
  237. package/dist/utils/runLifecycle.d.ts +89 -0
  238. package/dist/utils/runStartupLog.d.ts +15 -0
  239. package/dist/utils/secrets.d.ts +34 -0
  240. package/dist/utils/setup.d.ts +90 -0
  241. package/dist/utils/shell.d.ts +44 -0
  242. package/dist/utils/skills.d.ts +10 -0
  243. package/dist/utils/subprocess.d.ts +81 -0
  244. package/dist/utils/terraformMcp.d.ts +46 -0
  245. package/dist/utils/time.d.ts +15 -0
  246. package/dist/utils/timer.d.ts +23 -0
  247. package/dist/utils/todoTracking.d.ts +16 -0
  248. package/dist/utils/token.d.ts +52 -0
  249. package/dist/utils/toolLicensing.d.ts +56 -0
  250. package/dist/utils/toolSelection.d.ts +73 -0
  251. package/dist/utils/toon.d.ts +16 -0
  252. package/dist/utils/version.d.ts +2 -0
  253. package/dist/utils/versioning.d.ts +7 -0
  254. package/dist/utils/vertex.d.ts +16 -0
  255. package/dist/utils/workflow.d.ts +13 -0
  256. package/package.json +132 -0
  257. package/src/agents/claude.ts +1588 -0
  258. package/src/agents/claudePretoolGate.ts +286 -0
  259. package/src/agents/dispatchMetrics.ts +162 -0
  260. package/src/agents/gateServer.ts +178 -0
  261. package/src/agents/index.ts +10 -0
  262. package/src/agents/nativeFsDenies.ts +164 -0
  263. package/src/agents/opencode.ts +1600 -0
  264. package/src/agents/opencodePlugin.ts +304 -0
  265. package/src/agents/opencodeShared.ts +134 -0
  266. package/src/agents/postRun.ts +615 -0
  267. package/src/agents/reviewer.ts +134 -0
  268. package/src/agents/sessionLabeler.ts +185 -0
  269. package/src/agents/shared.ts +377 -0
  270. package/src/agents/subagentModels.ts +40 -0
  271. package/src/agents/tokenQuota.ts +203 -0
  272. package/src/agents/writeGateSource.ts +148 -0
  273. package/src/agents/writePolicy.ts +132 -0
  274. package/src/brand.ts +84 -0
  275. package/src/cli.ts +117 -0
  276. package/src/commands/gha.ts +188 -0
  277. package/src/commands/mcp.ts +126 -0
  278. package/src/commands/verifyEvidence.ts +100 -0
  279. package/src/entry.ts +7 -0
  280. package/src/entryPost.ts +109 -0
  281. package/src/external.ts +308 -0
  282. package/src/i18n/scaffolding.ts +191 -0
  283. package/src/index.ts +7 -0
  284. package/src/internal/index.ts +74 -0
  285. package/src/lifecycle.ts +2 -0
  286. package/src/main.ts +815 -0
  287. package/src/mcp/__fixtures__/infraweaver-scratch-pr-49-review-3485940013.json +110 -0
  288. package/src/mcp/__fixtures__/infraweaver-scratch-pr-64-review-3531000326.json +14 -0
  289. package/src/mcp/__fixtures__/infraweaver-test-repo-pr-1.diff.json +67 -0
  290. package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
  291. package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
  292. package/src/mcp/arkConfig.ts +7 -0
  293. package/src/mcp/assess.ts +723 -0
  294. package/src/mcp/capabilityContext.ts +80 -0
  295. package/src/mcp/changeSummary.ts +145 -0
  296. package/src/mcp/checkSuite.ts +261 -0
  297. package/src/mcp/checkout.ts +1015 -0
  298. package/src/mcp/comment.ts +683 -0
  299. package/src/mcp/commitInfo.ts +57 -0
  300. package/src/mcp/crosswalk.ts +1253 -0
  301. package/src/mcp/crosswalkDigest.ts +5 -0
  302. package/src/mcp/cyberEssentials.ts +60 -0
  303. package/src/mcp/dashboard.ts +232 -0
  304. package/src/mcp/dependencies.ts +190 -0
  305. package/src/mcp/frameworks.ts +236 -0
  306. package/src/mcp/geminiSanitizer.ts +212 -0
  307. package/src/mcp/git.ts +1116 -0
  308. package/src/mcp/guardrails.ts +771 -0
  309. package/src/mcp/issue.ts +74 -0
  310. package/src/mcp/issueComments.ts +48 -0
  311. package/src/mcp/issueEvents.ts +100 -0
  312. package/src/mcp/issueInfo.ts +72 -0
  313. package/src/mcp/labels.ts +35 -0
  314. package/src/mcp/localContext.ts +65 -0
  315. package/src/mcp/localServer.ts +217 -0
  316. package/src/mcp/moduleExtraction.ts +368 -0
  317. package/src/mcp/moduleTests.ts +421 -0
  318. package/src/mcp/modules.ts +752 -0
  319. package/src/mcp/output.ts +71 -0
  320. package/src/mcp/pathSafety.ts +28 -0
  321. package/src/mcp/policy.ts +226 -0
  322. package/src/mcp/pr.ts +238 -0
  323. package/src/mcp/prInfo.ts +91 -0
  324. package/src/mcp/providerSchema.ts +175 -0
  325. package/src/mcp/review.ts +1081 -0
  326. package/src/mcp/reviewComments.ts +1137 -0
  327. package/src/mcp/roots.ts +217 -0
  328. package/src/mcp/scope.ts +82 -0
  329. package/src/mcp/selectMode.ts +207 -0
  330. package/src/mcp/server.ts +498 -0
  331. package/src/mcp/shared.ts +120 -0
  332. package/src/mcp/shell.ts +631 -0
  333. package/src/mcp/staleFix.ts +557 -0
  334. package/src/mcp/terraform/__snapshots__/moduleDocs.test.ts.snap +40 -0
  335. package/src/mcp/terraform/azurePrices.ts +38 -0
  336. package/src/mcp/terraform/baseline.ts +172 -0
  337. package/src/mcp/terraform/concernResult.ts +111 -0
  338. package/src/mcp/terraform/cost.ts +175 -0
  339. package/src/mcp/terraform/cspm.ts +326 -0
  340. package/src/mcp/terraform/currency.ts +354 -0
  341. package/src/mcp/terraform/decisions.ts +590 -0
  342. package/src/mcp/terraform/eidas.ts +134 -0
  343. package/src/mcp/terraform/evidence.ts +771 -0
  344. package/src/mcp/terraform/findings.ts +383 -0
  345. package/src/mcp/terraform/fixMemory.ts +253 -0
  346. package/src/mcp/terraform/governance.ts +231 -0
  347. package/src/mcp/terraform/hcl.ts +273 -0
  348. package/src/mcp/terraform/iacLanguages.ts +431 -0
  349. package/src/mcp/terraform/idleFloor.ts +304 -0
  350. package/src/mcp/terraform/keyless.ts +123 -0
  351. package/src/mcp/terraform/moduleDocs.ts +303 -0
  352. package/src/mcp/terraform/nativeRules.ts +152 -0
  353. package/src/mcp/terraform/nativeScan.ts +67 -0
  354. package/src/mcp/terraform/noiseProfile.ts +183 -0
  355. package/src/mcp/terraform/normalization.ts +265 -0
  356. package/src/mcp/terraform/oscal.ts +283 -0
  357. package/src/mcp/terraform/packs/azurerm-3-4.ts +382 -0
  358. package/src/mcp/terraform/packs/cloudflare-4-5.ts +114 -0
  359. package/src/mcp/terraform/paths.ts +59 -0
  360. package/src/mcp/terraform/plan.ts +377 -0
  361. package/src/mcp/terraform/planDrift.ts +520 -0
  362. package/src/mcp/terraform/policyAuthor.ts +886 -0
  363. package/src/mcp/terraform/prowlerOcsf.ts +380 -0
  364. package/src/mcp/terraform/refactor.ts +879 -0
  365. package/src/mcp/terraform/registry.ts +317 -0
  366. package/src/mcp/terraform/risk.ts +99 -0
  367. package/src/mcp/terraform/scanSession.ts +242 -0
  368. package/src/mcp/terraform/scannerCache.ts +86 -0
  369. package/src/mcp/terraform/scannerEgress.ts +141 -0
  370. package/src/mcp/terraform/scannerJson.ts +22 -0
  371. package/src/mcp/terraform/scanners.ts +1134 -0
  372. package/src/mcp/terraform/signing.ts +151 -0
  373. package/src/mcp/terraform/stateLocking.ts +106 -0
  374. package/src/mcp/terraform/subprocess.ts +102 -0
  375. package/src/mcp/terraform/suppressions.ts +551 -0
  376. package/src/mcp/terraform/taxonomy.ts +0 -0
  377. package/src/mcp/terraform/tfquery.ts +159 -0
  378. package/src/mcp/terraform/toolchainIntegrity.ts +151 -0
  379. package/src/mcp/terraform/tools/authorPolicy.ts +185 -0
  380. package/src/mcp/terraform/tools/detectPlanDrift.ts +279 -0
  381. package/src/mcp/terraform/tools/emitCost.ts +130 -0
  382. package/src/mcp/terraform/tools/emitSarif.ts +108 -0
  383. package/src/mcp/terraform/tools/fixMemory.ts +82 -0
  384. package/src/mcp/terraform/tools/infracostDiff.ts +110 -0
  385. package/src/mcp/terraform/tools/ingestExternalFindings.ts +259 -0
  386. package/src/mcp/terraform/tools/moduleLookup.ts +86 -0
  387. package/src/mcp/terraform/tools/moduleSearch.ts +46 -0
  388. package/src/mcp/terraform/tools/plan.ts +384 -0
  389. package/src/mcp/terraform/tools/providerUpgrade.ts +217 -0
  390. package/src/mcp/terraform/tools/readFindings.ts +138 -0
  391. package/src/mcp/terraform/tools/scan.ts +303 -0
  392. package/src/mcp/terraform/tools/validate.ts +160 -0
  393. package/src/mcp/terraform/tools/verifyRemediation.ts +190 -0
  394. package/src/mcp/terraform/tools/versionCurrency.ts +64 -0
  395. package/src/mcp/terraform/tools.ts +62 -0
  396. package/src/mcp/terraform/transformPacks.ts +594 -0
  397. package/src/mcp/terraform/types.ts +382 -0
  398. package/src/mcp/terraform/verification.ts +150 -0
  399. package/src/mcp/terraform/vex.ts +367 -0
  400. package/src/mcp/terraform/writeOnly.ts +252 -0
  401. package/src/mcp/terraform.ts +52 -0
  402. package/src/mcp/terratest.ts +215 -0
  403. package/src/mcp/untrustedContent.ts +126 -0
  404. package/src/mcp/upload.ts +123 -0
  405. package/src/models.ts +753 -0
  406. package/src/modes/address-reviews.ts +35 -0
  407. package/src/modes/assess.ts +27 -0
  408. package/src/modes/build.ts +86 -0
  409. package/src/modes/compliance-audit.ts +25 -0
  410. package/src/modes/cost-optimization.ts +36 -0
  411. package/src/modes/drift-detect.ts +31 -0
  412. package/src/modes/fix.ts +29 -0
  413. package/src/modes/incremental-review.ts +103 -0
  414. package/src/modes/index.ts +94 -0
  415. package/src/modes/modernize-deprecated.ts +36 -0
  416. package/src/modes/plan.ts +21 -0
  417. package/src/modes/policy-gate.ts +27 -0
  418. package/src/modes/prFormats.ts +325 -0
  419. package/src/modes/refactor.ts +74 -0
  420. package/src/modes/refresh-remediation.ts +40 -0
  421. package/src/modes/remediate-and-refactor.ts +42 -0
  422. package/src/modes/remediate.ts +78 -0
  423. package/src/modes/resolve-conflicts.ts +32 -0
  424. package/src/modes/review.ts +135 -0
  425. package/src/modes/summarize-pr.ts +42 -0
  426. package/src/modes/task.ts +26 -0
  427. package/src/modes/terraform-code-review.ts +68 -0
  428. package/src/modes/types.ts +17 -0
  429. package/src/modes/update-dependencies.ts +44 -0
  430. package/src/prep/index.ts +96 -0
  431. package/src/prep/installNodeDependencies.ts +251 -0
  432. package/src/prep/installPythonDependencies.ts +235 -0
  433. package/src/prep/types.ts +38 -0
  434. package/src/reviewQuality.ts +237 -0
  435. package/src/runCli.ts +335 -0
  436. package/src/skills/terraform-best-practices/SKILL.md +379 -0
  437. package/src/toolState.ts +241 -0
  438. package/src/utils/activity.ts +210 -0
  439. package/src/utils/agent.ts +245 -0
  440. package/src/utils/agentHangReport.ts +180 -0
  441. package/src/utils/annotations.ts +56 -0
  442. package/src/utils/apiFetch.ts +19 -0
  443. package/src/utils/apiKeys.ts +305 -0
  444. package/src/utils/apiUrl.ts +42 -0
  445. package/src/utils/assets.ts +123 -0
  446. package/src/utils/baseRefConfig.ts +254 -0
  447. package/src/utils/billingErrors.ts +210 -0
  448. package/src/utils/body.ts +168 -0
  449. package/src/utils/buildInfraweaverFooter.ts +104 -0
  450. package/src/utils/byokFallback.ts +137 -0
  451. package/src/utils/changeImpact.ts +330 -0
  452. package/src/utils/claudeSubscription.ts +93 -0
  453. package/src/utils/cli.ts +36 -0
  454. package/src/utils/cloudClient.ts +57 -0
  455. package/src/utils/cloudFetchCore.ts +139 -0
  456. package/src/utils/cloudReport.ts +316 -0
  457. package/src/utils/codexHome.ts +204 -0
  458. package/src/utils/codexOAuth.ts +154 -0
  459. package/src/utils/codexRefreshDetect.ts +36 -0
  460. package/src/utils/diffCoverage.ts +404 -0
  461. package/src/utils/env.ts +84 -0
  462. package/src/utils/errorReport.ts +94 -0
  463. package/src/utils/exitHandler.ts +35 -0
  464. package/src/utils/fixDoubleEscapedString.ts +9 -0
  465. package/src/utils/ghaCore.ts +13 -0
  466. package/src/utils/gitAuth.ts +268 -0
  467. package/src/utils/gitAuthServer.ts +186 -0
  468. package/src/utils/github.ts +676 -0
  469. package/src/utils/globals.ts +9 -0
  470. package/src/utils/humanEditCapture.ts +198 -0
  471. package/src/utils/infraweaverConfig.ts +202 -0
  472. package/src/utils/install.ts +279 -0
  473. package/src/utils/instructions.ts +640 -0
  474. package/src/utils/keylessOidc.ts +47 -0
  475. package/src/utils/leapingComment.ts +20 -0
  476. package/src/utils/learnings.ts +145 -0
  477. package/src/utils/learningsTruncate.ts +42 -0
  478. package/src/utils/lifecycle.ts +198 -0
  479. package/src/utils/log.ts +452 -0
  480. package/src/utils/modelResolver.ts +105 -0
  481. package/src/utils/moduleFetch.ts +138 -0
  482. package/src/utils/normalizeEnv.ts +106 -0
  483. package/src/utils/openCodeModels.ts +86 -0
  484. package/src/utils/openaiCompatible.ts +52 -0
  485. package/src/utils/opentofuMcp.ts +61 -0
  486. package/src/utils/overrides.ts +100 -0
  487. package/src/utils/packageManager.ts +257 -0
  488. package/src/utils/patchWorkflowRunFields.ts +173 -0
  489. package/src/utils/payload.ts +1206 -0
  490. package/src/utils/prSummary.ts +148 -0
  491. package/src/utils/presets.ts +105 -0
  492. package/src/utils/progressComment.ts +266 -0
  493. package/src/utils/providerErrors.ts +189 -0
  494. package/src/utils/proxyModel.ts +239 -0
  495. package/src/utils/rangeDiff.ts +182 -0
  496. package/src/utils/redact.ts +86 -0
  497. package/src/utils/registryAuth.ts +115 -0
  498. package/src/utils/remediationCommand.ts +144 -0
  499. package/src/utils/retry.ts +180 -0
  500. package/src/utils/reviewCleanup.ts +116 -0
  501. package/src/utils/run.ts +100 -0
  502. package/src/utils/runContext.ts +276 -0
  503. package/src/utils/runContextData.ts +121 -0
  504. package/src/utils/runErrorRenderer.ts +282 -0
  505. package/src/utils/runFixture.ts +91 -0
  506. package/src/utils/runLifecycle.ts +360 -0
  507. package/src/utils/runStartupLog.ts +67 -0
  508. package/src/utils/secrets.ts +208 -0
  509. package/src/utils/setup.ts +368 -0
  510. package/src/utils/shell.ts +132 -0
  511. package/src/utils/skills.ts +67 -0
  512. package/src/utils/subprocess.ts +474 -0
  513. package/src/utils/terraformMcp.ts +99 -0
  514. package/src/utils/time.ts +59 -0
  515. package/src/utils/timer.ts +72 -0
  516. package/src/utils/todoTracking.ts +168 -0
  517. package/src/utils/token.ts +294 -0
  518. package/src/utils/toolLicensing.ts +152 -0
  519. package/src/utils/toolSelection.ts +239 -0
  520. package/src/utils/toon.ts +76 -0
  521. package/src/utils/version.ts +10 -0
  522. package/src/utils/versioning.ts +44 -0
  523. package/src/utils/vertex.ts +94 -0
  524. package/src/utils/workflow.ts +25 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * CLI utilities
3
+ */
4
+
5
+ import { spawnSync } from "node:child_process";
6
+ import { existsSync } from "node:fs";
7
+
8
+ // re-export logging utilities for backward compatibility
9
+ export {
10
+ formatIndentedField,
11
+ formatJsonValue,
12
+ formatUsageSummary,
13
+ log,
14
+ writeSummary,
15
+ } from "#app/utils/log";
16
+
17
+ /**
18
+ * Finds a CLI executable path by checking if it's installed globally
19
+ * @param name The name of the CLI executable to find
20
+ * @returns The path to the CLI executable, or null if not found
21
+ */
22
+ export function findCliPath(name: string): string | null {
23
+ // `which` is POSIX-only. The action always runs on Linux, but this repo is
24
+ // developed on Windows, where `which` does not exist and the lookup fails
25
+ // silently as "not installed" — use `where` there. `where` can print several
26
+ // matches, one per line, so take the first.
27
+ const isWindows = process.platform === "win32";
28
+ const result = spawnSync(isWindows ? "where" : "which", [name], { encoding: "utf-8" });
29
+ if (result.status === 0 && result.stdout) {
30
+ const cliPath = result.stdout.split(/\r?\n/)[0]?.trim();
31
+ if (cliPath && existsSync(cliPath)) {
32
+ return cliPath;
33
+ }
34
+ }
35
+ return null;
36
+ }
@@ -0,0 +1,57 @@
1
+ import { type ApiFetchOptions, apiFetch } from "#app/utils/apiFetch";
2
+ import { DEFAULT_CLOUD_TIMEOUT_MS } from "#app/utils/cloudFetchCore";
3
+
4
+ /**
5
+ * Thin typed seam over `apiFetch` for the Infraweaver Cloud routes.
6
+ *
7
+ * Consumers previously hand-built each request: the `Authorization: Bearer`
8
+ * header (with `Authorization`/`authorization` casing drift), JSON serialization
9
+ * + content-type, and the timeout were re-inlined at every call site. This owns
10
+ * those three pieces once and returns the raw `Response`, so each caller keeps
11
+ * its own status/JSON/retry handling.
12
+ *
13
+ * The stdlib-only post hook (`entryPost.ts`) intentionally does NOT use this —
14
+ * it calls `cloudFetchCore` directly to stay free of node_modules imports.
15
+ */
16
+
17
+ /** The one home for the bearer header — the org JWT (`apiToken`), a GitHub App
18
+ * installation token, or an OIDC id-token, depending on the route. */
19
+ export function bearer(credential: string): { Authorization: string } {
20
+ return { Authorization: `Bearer ${credential}` };
21
+ }
22
+
23
+ export type CloudRequest = {
24
+ path: string;
25
+ method?: string | undefined;
26
+ /** bearer token for the `Authorization` header; omit for an unauthenticated call. */
27
+ credential?: string | undefined;
28
+ /** extra headers beyond `Authorization` (e.g. `X-GitHub-OIDC-Token`). */
29
+ headers?: Record<string, string> | undefined;
30
+ /** a JSON body — serialized here, with `content-type: application/json` set. */
31
+ json?: unknown;
32
+ /** a pre-serialized body (used when the body is not JSON). */
33
+ body?: string | undefined;
34
+ /** request timeout in ms; defaults to the shared cloud ceiling. */
35
+ timeoutMs?: number | undefined;
36
+ };
37
+
38
+ /** Issue an authenticated Cloud API request; returns the raw `Response`. */
39
+ export async function cloudRequest(req: CloudRequest): Promise<Response> {
40
+ const headers: Record<string, string> = { ...req.headers };
41
+ if (req.credential) Object.assign(headers, bearer(req.credential));
42
+
43
+ let body = req.body;
44
+ if (req.json !== undefined) {
45
+ body = JSON.stringify(req.json);
46
+ headers["content-type"] = "application/json";
47
+ }
48
+
49
+ const options: ApiFetchOptions = {
50
+ path: req.path,
51
+ method: req.method,
52
+ headers,
53
+ body,
54
+ signal: AbortSignal.timeout(req.timeoutMs ?? DEFAULT_CLOUD_TIMEOUT_MS),
55
+ };
56
+ return apiFetch(options);
57
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * stdlib-only Infraweaver API fetch core (no node_modules) — shared by
3
+ * `apiFetch` (the main runtime wrapper) and `entryPost.ts` (the GHA `post:`
4
+ * hook, which runs directly from the action checkout without node_modules;
5
+ * see entryPost.stdlibOnly.test.ts). Owns everything the two callers
6
+ * previously kept in lockstep by hand: the default API host, the
7
+ * bearer-credential host allowlist, the Vercel bypass secret, and the
8
+ * default request timeout.
9
+ */
10
+
11
+ import { DEFAULT_API_URL, PRIMARY_DOMAIN } from "#app/brand";
12
+
13
+ export { DEFAULT_API_URL };
14
+
15
+ /**
16
+ * Ceiling for Cloud API calls that don't bring their own AbortSignal — a
17
+ * stalled backend must never hang the action (or its post hook) indefinitely.
18
+ * Callers with tighter or looser needs pass an explicit `signal`.
19
+ */
20
+ export const DEFAULT_CLOUD_TIMEOUT_MS = 30_000;
21
+
22
+ function isLocalUrl(url: URL): boolean {
23
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1";
24
+ }
25
+
26
+ /**
27
+ * Operator-pinned extra hosts (comma-separated, exact hostnames) for a
28
+ * self-hosted / alternate Cloud deployment — e.g. a Railway or custom-domain
29
+ * backend that isn't under `*.infraweaver.dev`. This preserves the security
30
+ * property: the operator must *explicitly name the exact host* in
31
+ * `API_ALLOWED_HOSTS` before any bearer credential is sent there; it only widens
32
+ * the allowlist for hosts the operator already controls and configured.
33
+ */
34
+ function configuredAllowedHosts(): string[] {
35
+ return (process.env.API_ALLOWED_HOSTS ?? "")
36
+ .split(",")
37
+ .map((h) => h.trim().toLowerCase())
38
+ .filter(Boolean);
39
+ }
40
+
41
+ // The Infraweaver JWT (apiToken) and codex write-back secret travel as
42
+ // `Authorization: Bearer` to this host. Pin it to a known allowlist so a
43
+ // misconfigured/hostile `API_URL` can't redirect those bearer credentials to
44
+ // an attacker-controlled host (https alone is not enough — it must be the right
45
+ // host). localhost stays exempt for local dev; self-hosted deployments add their
46
+ // exact host via `API_ALLOWED_HOSTS`.
47
+ function isAllowedApiHost(url: URL): boolean {
48
+ if (isLocalUrl(url)) return true;
49
+ const host = url.hostname.toLowerCase();
50
+ if (host === PRIMARY_DOMAIN || host.endsWith(`.${PRIMARY_DOMAIN}`))
51
+ return true;
52
+ return configuredAllowedHosts().includes(host);
53
+ }
54
+
55
+ /**
56
+ * resolve the Infraweaver API base URL.
57
+ *
58
+ * in the action: API_URL is not explicitly set, so this falls back to
59
+ * DEFAULT_API_URL. in local dev: API_URL=http://localhost:3000 (from .env).
60
+ *
61
+ * enforces https:// for non-local URLs to prevent cleartext credential
62
+ * transmission.
63
+ */
64
+ export function resolveApiUrl(): string {
65
+ const raw = process.env.API_URL || DEFAULT_API_URL;
66
+ const parsed = new URL(raw);
67
+
68
+ if (parsed.protocol !== "https:" && !isLocalUrl(parsed)) {
69
+ throw new Error(
70
+ `API_URL must use https:// (got ${parsed.protocol}). only localhost is exempt.`,
71
+ );
72
+ }
73
+
74
+ if (!isAllowedApiHost(parsed)) {
75
+ throw new Error(
76
+ `API_URL host '${parsed.hostname}' is not allowed. ` +
77
+ `Bearer credentials are only sent to ${PRIMARY_DOMAIN} (or a *.${PRIMARY_DOMAIN} host), localhost, ` +
78
+ `or a host you explicitly pin in API_ALLOWED_HOSTS.`,
79
+ );
80
+ }
81
+
82
+ return raw;
83
+ }
84
+
85
+ export type CloudFetchOptions = {
86
+ path: string;
87
+ method?: string | undefined;
88
+ headers?: Record<string, string> | undefined;
89
+ body?: string | undefined;
90
+ signal?: AbortSignal | undefined;
91
+ };
92
+
93
+ /**
94
+ * fetch against the Infraweaver API with Vercel deployment protection bypass.
95
+ *
96
+ * adds the bypass secret as BOTH a query parameter and a header for maximum
97
+ * reliability. the server-side forwarding code uses query params, and the
98
+ * Vercel docs say both work, so we do both as belt-and-suspenders.
99
+ */
100
+ export async function cloudFetch(
101
+ options: CloudFetchOptions,
102
+ ): Promise<Response> {
103
+ const url = new URL(options.path, resolveApiUrl());
104
+
105
+ const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
106
+ if (bypassSecret) {
107
+ url.searchParams.set("x-vercel-protection-bypass", bypassSecret);
108
+ }
109
+
110
+ const headers: Record<string, string> = {
111
+ ...options.headers,
112
+ };
113
+
114
+ // also add as header for belt-and-suspenders
115
+ if (bypassSecret) {
116
+ headers["x-vercel-protection-bypass"] = bypassSecret;
117
+ }
118
+
119
+ // never send Content-Type on body-less requests. empirically, Vercel's
120
+ // Next.js lambda adapter (Next 16.1.x) throws `SyntaxError: Unexpected
121
+ // end of data` before delegating to the route handler — returning a 500 —
122
+ // when Content-Type is set but no body is present. exact mechanism is
123
+ // unverified (minified runtime frame), but Content-Type on a body-less
124
+ // request has no defined semantics per RFC 9110 §8.3 anyway. see #692.
125
+ if (!options.body) {
126
+ for (const key of Object.keys(headers)) {
127
+ if (key.toLowerCase() === "content-type") delete headers[key];
128
+ }
129
+ }
130
+
131
+ const init: RequestInit = {
132
+ method: options.method ?? "GET",
133
+ headers,
134
+ signal: options.signal ?? AbortSignal.timeout(DEFAULT_CLOUD_TIMEOUT_MS),
135
+ };
136
+ if (options.body) init.body = options.body;
137
+
138
+ return fetch(url.toString(), init);
139
+ }
@@ -0,0 +1,316 @@
1
+ import * as core from "@actions/core";
2
+ import { PRODUCT_NAME } from "#app/brand";
3
+ import { CROSSWALK_VERSION, packControlsForConcern } from "#app/mcp/crosswalk";
4
+ import { cyberEssentialsScore } from "#app/mcp/cyberEssentials";
5
+ import { ruleDocUrl } from "#app/mcp/terraform/decisions";
6
+ import { dedupeCaptures } from "#app/mcp/terraform/fixMemory";
7
+ import { riskScore } from "#app/mcp/terraform/risk";
8
+ import {
9
+ scanSessionOf,
10
+ upgradeStatementOf,
11
+ } from "#app/mcp/terraform/scanSession";
12
+ import { captureProvenTransforms } from "#app/mcp/terraform/transformPacks";
13
+ import { type Concern, concernKeyOf } from "#app/mcp/terraform/types";
14
+
15
+ // The CE score is computed in the shared `cyberEssentials` module so the Assess
16
+ // report and this Cloud report report the identical number; re-exported here to
17
+ // keep this module's existing public surface (and the report test) intact.
18
+ export { cyberEssentialsScore } from "#app/mcp/cyberEssentials";
19
+
20
+ import type { ToolState } from "#app/toolState";
21
+ import { cloudOidcAudience, isBackendConfigured } from "#app/utils/apiUrl";
22
+ import { log } from "#app/utils/cli";
23
+ import { cloudRequest } from "#app/utils/cloudClient";
24
+
25
+ // The OIDC audience the tokenless path requests; resolved via `cloudOidcAudience()` so it
26
+ // matches the Cloud's `expectedOidcAudience()` and stays operator-overridable from a
27
+ // single place. Re-exported to preserve this module's public surface.
28
+ export { cloudOidcAudience };
29
+
30
+ /**
31
+ * Resolve the credential to authenticate the Cloud report with, in order of
32
+ * preference:
33
+ * 1. An explicit `tmnd_` org token (the `api_token` input).
34
+ * 2. A GitHub Actions OIDC token — the tokenless GitHub App path. Requires
35
+ * `permissions: id-token: write`; the App installation is the consent gate
36
+ * Cloud checks. Returns undefined when neither is available (pure OSS run).
37
+ */
38
+ export async function resolveCloudCredential(
39
+ apiToken: string | undefined,
40
+ ): Promise<string | undefined> {
41
+ if (apiToken) return apiToken;
42
+ try {
43
+ const oidc = await core.getIDToken(cloudOidcAudience());
44
+ return oidc || undefined;
45
+ } catch {
46
+ // No `id-token: write` permission, or not running in GitHub Actions — the
47
+ // run stays pure OSS and reports nothing.
48
+ return undefined;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Ingest seam — POST a finished run's findings/posture to Infraweaver Cloud
54
+ * so the dashboard reflects this repo. This is the explicit ORG-TOKEN path: the
55
+ * caller passes the `tmnd_` token (the `api_token` input); the tokenless GitHub
56
+ * App path reports differently and standalone OSS runs don't report at all.
57
+ *
58
+ * The wire shape matches infraweaver-ui `reportSchema`
59
+ * (src/features/api/schemas.ts) — kept in sync by hand across the action ⇄ cloud
60
+ * JSON boundary (the two codebases can't share types).
61
+ */
62
+
63
+ export type CloudPosture = "clean" | "advisory" | "action-required";
64
+
65
+ // The Cloud `run_mode` enum. The engine's mode NAME is title-cased ("Remediate"),
66
+ // so it must be lowered to the enum value or the server's run insert rejects it.
67
+ // NOTE: "generate" was removed with infra-generation (2026-06-22) — the engine can no
68
+ // longer select that mode, so it's dropped here too. "review" stays: the generic
69
+ // PR-review surface is still reachable (IncrementalReview / select_mode). "refactor"
70
+ // is the behaviour-preserving modularise verb (its proof rides in run.refactor below).
71
+ // The 2026-06-27 CI verbs (PolicyGate/UpdateDependencies/ModernizeDeprecated/
72
+ // CostOptimization) and the read-only posture verbs DriftDetect/ComplianceAudit
73
+ // lower 1:1 onto matching Cloud enum values — apply the Cloud run_mode enum +
74
+ // reportSchema additions BEFORE deploying this, or the run insert rejects.
75
+ // (TerraformCodeReview is intentionally absent: like IncrementalReview it reports
76
+ // as undefined → the server default, since it is a PR-review surface not a verb.)
77
+ const RUN_MODES = new Set([
78
+ "remediate",
79
+ "assess",
80
+ "review",
81
+ "refactor",
82
+ "remediate-refactor",
83
+ "policygate",
84
+ "updatedependencies",
85
+ "modernizedeprecated",
86
+ "costoptimization",
87
+ "driftdetect",
88
+ "complianceaudit",
89
+ ]);
90
+
91
+ // engine mode names that don't lower-case 1:1 onto the Cloud enum. The combined
92
+ // verb "RemediateAndRefactor" reports as "remediate-refactor" (its refactor proof
93
+ // still rides in run.refactor below, driven by toolState — independent of mode).
94
+ const RUN_MODE_ALIASES: Readonly<Record<string, string>> = {
95
+ remediateandrefactor: "remediate-refactor",
96
+ };
97
+
98
+ /** Posture from the open concern set — any critical/high ⇒ action-required. */
99
+ export function derivePosture(concerns: Concern[]): CloudPosture {
100
+ const open = concerns.filter((c) => !c.suppression);
101
+ if (open.length === 0) return "clean";
102
+ return open.some((c) => c.severity === "critical" || c.severity === "high")
103
+ ? "action-required"
104
+ : "advisory";
105
+ }
106
+
107
+ /** Map the engine mode name to the Cloud run_mode enum; undefined for an
108
+ * unknown/custom mode so the server applies its own default. */
109
+ function normalizeMode(mode: string | undefined): string | undefined {
110
+ if (!mode) return undefined;
111
+ const m = mode.toLowerCase();
112
+ const aliased = RUN_MODE_ALIASES[m] ?? m;
113
+ return RUN_MODES.has(aliased) ? aliased : undefined;
114
+ }
115
+
116
+ /** the Cloud-bound refactor (modularise) verdict, mirrors infraweaver-ui
117
+ * reportSchema.run.refactor.equivalence_verdict. */
118
+ export type RefactorVerdict =
119
+ | "equivalence-proven"
120
+ | "equivalence-failed"
121
+ | "proposed-unproven";
122
+
123
+ /**
124
+ * The refactor (modularise) proof for the Cloud report, or undefined on a
125
+ * non-refactor run (so the wire omits it). Built from the recorded keys-free
126
+ * EQUIVALENCE proof when one ran (b.1/b.2/b.3), else the b.4 `proposed — unproven`
127
+ * marker — an equivalence proof always wins, so a change is never both. Asserts
128
+ * only what the engine proved: a failed/absent proof is reported as such, never
129
+ * upgraded. Pure over `toolState`. Mirrors infraweaver-ui reportSchema.run.refactor.
130
+ */
131
+ export function buildRefactorReport(toolState: ToolState):
132
+ | {
133
+ equivalence_verdict: RefactorVerdict;
134
+ proposed_unproven: boolean;
135
+ moved_block_count: number;
136
+ uncovered_moves: number;
137
+ }
138
+ | undefined {
139
+ const session = scanSessionOf(toolState);
140
+ const eq = session.refactorEquivalence;
141
+ const proposedUnproven = session.refactorProposedUnproven === true;
142
+ if (!eq && !proposedUnproven) return undefined;
143
+ const verdict: RefactorVerdict = eq
144
+ ? eq.equivalent
145
+ ? "equivalence-proven"
146
+ : "equivalence-failed"
147
+ : "proposed-unproven";
148
+ return {
149
+ equivalence_verdict: verdict,
150
+ proposed_unproven: verdict === "proposed-unproven",
151
+ moved_block_count: eq?.moves_detected ?? 0,
152
+ uncovered_moves: eq?.uncovered_moves.length ?? 0,
153
+ };
154
+ }
155
+
156
+ /** A `remediation_hint` that is just a URL (checkov's `guideline`, tflint's rule
157
+ * link) is the rule's docs page, not guidance — and it already surfaces as `doc_url`
158
+ * (ruleDocUrl reads the URL-valued hint). Emitting it as the hint too makes the
159
+ * dashboard render a bare URL where actionable text belongs, so drop it here. A real
160
+ * text hint (trivy's `Resolution`, the fmt hint) is kept. */
161
+ function textualHint(hint: string | null | undefined): string | undefined {
162
+ const trimmed = hint?.trim();
163
+ if (!trimmed || /^https?:\/\//i.test(trimmed)) return undefined;
164
+ return trimmed;
165
+ }
166
+
167
+ /** Build the `/report` request body from the finished run's tool state. Exported
168
+ * for tests; pure (reads only `toolState` + GitHub env). */
169
+ export function buildReportBody(toolState: ToolState) {
170
+ const concerns = scanSessionOf(toolState).lastScanConcerns ?? [];
171
+ const findings = concerns.slice(0, 2000).map((c) => ({
172
+ concern_id: c.id,
173
+ concern_key: concernKeyOf(c),
174
+ source: c.source,
175
+ rule_id: c.rule_id,
176
+ severity: c.severity,
177
+ category: c.category,
178
+ evidence: c.evidence,
179
+ file: c.location.file,
180
+ line: c.location.line ?? undefined,
181
+ remediation_hint: textualHint(c.remediation_hint),
182
+ // The offending source line(s) the scanner flagged + the rule's canonical
183
+ // docs page — so the finding detail shows the exact code and a working
184
+ // "Open rule docs" link instead of placeholders.
185
+ code_snippet: c.code_snippet ?? undefined,
186
+ doc_url: ruleDocUrl(c) ?? undefined,
187
+ // The maintained-pack control ids this concern evidences (CE / ISO 27001 /
188
+ // NCSC), the engine⇄Cloud join key the dashboard's per-control verdicts and
189
+ // required-control gate key on (empty array = no mapping). See
190
+ // crosswalk.packControlsForConcern — hand-synced with infraweaver-ui pack.ts.
191
+ compliance: packControlsForConcern(c),
192
+ // 2b-viii: the composite risk score (CVSS anchor + exposure + fix-with-proof
193
+ // boost) so the Cloud dashboard can surface the "top N that matter".
194
+ risk_score: riskScore(c),
195
+ ...(c.suppression
196
+ ? {
197
+ suppressed: true as const,
198
+ suppression_reason: c.suppression.reason,
199
+ suppression_source: c.suppression.source,
200
+ suppression_expires: c.suppression.expires ?? undefined,
201
+ }
202
+ : {}),
203
+ }));
204
+
205
+ const runNumber = Number(process.env.GITHUB_RUN_NUMBER);
206
+ // The refactor (modularise) proof, present only on a Refactor run — keeps the
207
+ // wire clean (and the server's run.refactor optional) on every other mode.
208
+ const refactor = buildRefactorReport(toolState);
209
+ // §5.12 the proven-fix patterns captured this run (a finding-type that went
210
+ // ✗→✓). Only present when fix_memory is on (capture is gated in verify), and
211
+ // deduped to one per finding-type. Cloud upserts these into the org library.
212
+ const provenFixes = dedupeCaptures(
213
+ scanSessionOf(toolState).provenFixCaptures ?? [],
214
+ ).map((p) => ({
215
+ finding_type: p.finding_type,
216
+ source: p.source ?? undefined,
217
+ canonical_class: p.canonical_class ?? undefined,
218
+ category: p.category,
219
+ title: p.title,
220
+ description: p.description ?? undefined,
221
+ remediation_hint: p.remediation_hint ?? undefined,
222
+ before_example: p.before_example ?? undefined,
223
+ }));
224
+ // TC-2.2 the provider-upgrade transforms this run's PLAN proved out. Computed
225
+ // from the same statement the signed evidence carries, so the org library and
226
+ // the signed artefact can never disagree about what was proven. Empty unless a
227
+ // pack applied AND the plan came back clean — a transform that needed a human
228
+ // is deliberately excluded, since a human intervening is not evidence that the
229
+ // transform is safe unattended, which is the only claim the counter makes.
230
+ const session = scanSessionOf(toolState);
231
+ const provenTransforms = captureProvenTransforms(
232
+ upgradeStatementOf(session),
233
+ session.transformMatches ?? [],
234
+ );
235
+ return {
236
+ commit_sha: process.env.GITHUB_SHA || undefined,
237
+ posture: derivePosture(concerns),
238
+ // Cyber Essentials posture (0–100) — what the dashboard's "CE SCORE" shows.
239
+ ce_score: cyberEssentialsScore(concerns),
240
+ prs_open: toolState.remediationPrsOpened,
241
+ findings,
242
+ ...(provenFixes.length ? { proven_fixes: provenFixes } : {}),
243
+ ...(provenTransforms.length ? { proven_transforms: provenTransforms } : {}),
244
+ run: {
245
+ run_number: Number.isInteger(runNumber) ? runNumber : undefined,
246
+ // The CI run's native id — the same value patchWorkflowRunFields PATCHes
247
+ // /workflow-run/{id} with, so Cloud can attach the late usage/cost telemetry
248
+ // to the run row this report creates.
249
+ external_run_id: process.env.GITHUB_RUN_ID || undefined,
250
+ mode: normalizeMode(toolState.selectedMode),
251
+ trigger: process.env.GITHUB_EVENT_NAME || undefined,
252
+ status: "success" as const,
253
+ // The engine crosswalk revision each finding's `compliance[]` was computed
254
+ // against — stamped so a historical run's verdicts stay reproducible after
255
+ // the rule-pack moves (Cloud stamps its own pack version at ingest).
256
+ engine_crosswalk_version: CROSSWALK_VERSION,
257
+ ...(refactor ? { refactor } : {}),
258
+ },
259
+ };
260
+ }
261
+
262
+ /**
263
+ * Best-effort report of this run to Infraweaver Cloud. No-ops (silently) when:
264
+ * - `API_URL` unset — standalone BYOK; don't POST into the marketing host.
265
+ * - no scan ran (`lastScanConcerns` undefined) — nothing to report.
266
+ * - no credential — neither an `api_token` nor a mintable GitHub Actions OIDC
267
+ * token (no `id-token: write`); the run stays pure OSS.
268
+ * A network/Cloud failure is logged at debug and swallowed — reporting must
269
+ * never flip an already-successful run outcome.
270
+ */
271
+ export async function reportToCloud(input: {
272
+ toolState: ToolState;
273
+ repo: { owner: string; name: string };
274
+ apiToken: string | undefined;
275
+ }): Promise<void> {
276
+ if (!isBackendConfigured()) return;
277
+ if (!scanSessionOf(input.toolState).lastScanConcerns) {
278
+ log.debug("cloud report skipped: no scan concerns recorded this run");
279
+ return;
280
+ }
281
+
282
+ // Prefer the explicit org token; otherwise fall back to a tokenless OIDC token.
283
+ const credential = await resolveCloudCredential(input.apiToken);
284
+ if (!credential) {
285
+ log.debug(
286
+ "cloud report skipped: no credential (api_token absent + OIDC unavailable)",
287
+ );
288
+ return;
289
+ }
290
+
291
+ try {
292
+ // Inside the try: a throw here (e.g. malformed concern) must surface as a
293
+ // visible warning, not unwind into finalizeSuccessRun's catch and vanish.
294
+ const body = buildReportBody(input.toolState);
295
+ const response = await cloudRequest({
296
+ path: `/api/repo/${input.repo.owner}/${input.repo.name}/report`,
297
+ method: "POST",
298
+ credential,
299
+ json: body,
300
+ });
301
+ if (!response.ok) {
302
+ // Promoted debug → warning with the response body: a dropped report is the
303
+ // dashboard silently going stale, which is worth a CI line to diagnose.
304
+ const detail = await response.text().catch(() => "(no body)");
305
+ log.warning(`cloud report rejected (${response.status}): ${detail}`);
306
+ return;
307
+ }
308
+ log.info(
309
+ `» reported ${body.findings.length} finding(s) to ${PRODUCT_NAME} Cloud`,
310
+ );
311
+ } catch (error) {
312
+ log.warning(
313
+ `cloud report failed: ${error instanceof Error ? error.message : String(error)}`,
314
+ );
315
+ }
316
+ }