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,268 @@
1
+ /**
2
+ * git authentication via GIT_ASKPASS.
3
+ *
4
+ * a localhost HTTP server serves tokens via UUID codes whose lifetime is
5
+ * bounded by the parent $git() invocation: register() makes the code active,
6
+ * the script (and any sibling subprocess — e.g. git-lfs pre-push) can fetch
7
+ * the token any number of times, and $git()'s finally calls revoke() to
8
+ * close the window. each $git() call writes a unique askpass script with
9
+ * the server port+code baked into the file body — no secrets in subprocess
10
+ * env. a replay of a revoked code trips a 409 and revokes the underlying
11
+ * github installation token.
12
+ *
13
+ * see wiki/askpass.md for full security documentation.
14
+ */
15
+
16
+ import { execSync } from "node:child_process";
17
+ import { createHash } from "node:crypto";
18
+ import { readFileSync, realpathSync, unlinkSync } from "node:fs";
19
+ import { log } from "#app/utils/cli";
20
+ import type { GitAuthServer } from "#app/utils/gitAuthServer";
21
+ import { filterEnv } from "#app/utils/secrets";
22
+ import { $ } from "#app/utils/shell";
23
+ import { spawn } from "#app/utils/subprocess";
24
+
25
+ type SafeGitSubcommand = "fetch" | "push";
26
+
27
+ type GitAuthOptions = {
28
+ token: string;
29
+ cwd?: string;
30
+ // when true (the default), this invocation runs with `core.hooksPath=/dev/null`
31
+ // so a repo-/agent-planted git hook (e.g. a `pre-push` written into
32
+ // `.git/hooks` or via an agent-set `core.hooksPath`) cannot fire while
33
+ // GIT_ASKPASS is live and read the installation token back out of the askpass
34
+ // script. Callers pass `false` only when the operator has granted full trust
35
+ // (shell: enabled), where honoring repo hooks (e.g. git-lfs pre-push upload)
36
+ // is intended and the agent could read the token through its shell anyway.
37
+ disableHooks?: boolean;
38
+ };
39
+
40
+ type GitResult = {
41
+ stdout: string;
42
+ stderr: string;
43
+ };
44
+
45
+ // --- git binary resolution and tamper detection ---
46
+
47
+ type GitBinaryInfo = {
48
+ path: string;
49
+ sha256: string;
50
+ };
51
+
52
+ let gitBinary: GitBinaryInfo | undefined;
53
+
54
+ function hashFile(path: string): string {
55
+ return createHash("sha256").update(readFileSync(path)).digest("hex");
56
+ }
57
+
58
+ /**
59
+ * resolve and fingerprint the git binary. must be called once at startup
60
+ * (in main()) before any agent code runs, so the path and hash reflect
61
+ * the untampered binary.
62
+ *
63
+ * resolves symlinks via realpath so the hash is of the actual binary.
64
+ * a malicious agent with sudo could replace the binary later, which is
65
+ * caught by verifyGitBinary() before each authenticated call.
66
+ */
67
+ export function resolveGit(): void {
68
+ // POSIX `which` / Windows `where` — the action runs on Linux, but this repo is
69
+ // developed on Windows, where `which git` throws and takes the whole run with
70
+ // it. `where` may print several matches; the first is the one that would run.
71
+ const lookup = process.platform === "win32" ? "where git" : "which git";
72
+ const whichPath = execSync(lookup, { encoding: "utf-8" }).split(/\r?\n/)[0]?.trim();
73
+ if (!whichPath) throw new Error("git not found on PATH");
74
+ const resolvedPath = realpathSync(whichPath);
75
+ const sha256 = hashFile(resolvedPath);
76
+ gitBinary = { path: resolvedPath, sha256 };
77
+ log.debug(`» git binary: ${resolvedPath} (sha256: ${sha256.slice(0, 12)}...)`);
78
+ }
79
+
80
+ function verifyGitBinary(): string {
81
+ if (!gitBinary) {
82
+ throw new Error("git binary not initialized — call resolveGit() at startup");
83
+ }
84
+ const currentHash = hashFile(gitBinary.path);
85
+ if (currentHash !== gitBinary.sha256) {
86
+ throw new Error(
87
+ `git binary tampered: expected sha256 ${gitBinary.sha256}, got ${currentHash}. ` +
88
+ `path: ${gitBinary.path}`,
89
+ );
90
+ }
91
+ return gitBinary.path;
92
+ }
93
+
94
+ // --- auth server ---
95
+
96
+ let authServer: GitAuthServer | undefined;
97
+
98
+ export function setGitAuthServer(server: GitAuthServer): void {
99
+ authServer = server;
100
+ }
101
+
102
+ /**
103
+ * execute authenticated git command via ASKPASS.
104
+ *
105
+ * subcommand is restricted to "fetch" | "push" — operations that talk to
106
+ * a remote and need credentials. working-tree operations (checkout, merge)
107
+ * use $() from shell.ts which has no token.
108
+ *
109
+ * per call: registers a code with the auth server (valid for the lifetime
110
+ * of this invocation), writes a unique askpass script with port+code baked
111
+ * in, spawns git with GIT_ASKPASS pointing to the script. on completion,
112
+ * revokes the code and deletes the script in finally. multiple sibling
113
+ * askpass calls within one invocation (e.g. git itself + git-lfs pre-push)
114
+ * all see a valid code; replay attempts after finally trip a 409 and the
115
+ * server revokes the underlying github token as a tamper signal.
116
+ *
117
+ * @example
118
+ * await $git("fetch", ["origin", "main"], { token });
119
+ * await $git("push", ["-u", "origin", "feature"], { token });
120
+ */
121
+ export async function $git(
122
+ subcommand: SafeGitSubcommand,
123
+ args: string[],
124
+ options: GitAuthOptions,
125
+ ): Promise<GitResult> {
126
+ const gitPath = verifyGitBinary();
127
+
128
+ if (!authServer) {
129
+ throw new Error("git auth server not initialized — call setGitAuthServer() at startup");
130
+ }
131
+
132
+ const cwd = options.cwd ?? process.cwd();
133
+
134
+ const code = authServer.register(options.token);
135
+ const scriptPath = authServer.writeAskpassScript(code);
136
+
137
+ // -c flags override local .git/config — defense-in-depth against
138
+ // agent-set config that could spawn subprocesses before ASKPASS runs.
139
+ // a command-line `-c` wins over any value the agent may have written into
140
+ // .git/config (e.g. via the MCP `git config` tool in restricted mode), which
141
+ // is why hook neutralization belongs here and not only at setup.
142
+ const fullArgs = [
143
+ "-c",
144
+ "core.fsmonitor=false",
145
+ "-c",
146
+ "credential.helper=",
147
+ "-c",
148
+ "protocol.file.allow=never",
149
+ "-c",
150
+ "core.sshCommand=ssh",
151
+ // neutralize git hooks for this authenticated call unless the caller opted
152
+ // out (shell: enabled). a planted `pre-push`/`pre-receive` would otherwise
153
+ // run in the action process with GIT_ASKPASS set and could exfiltrate the
154
+ // token by invoking the askpass script itself.
155
+ ...(options.disableHooks === false ? [] : ["-c", "core.hooksPath=/dev/null"]),
156
+ subcommand,
157
+ ...args,
158
+ ];
159
+
160
+ log.debug(`git ${fullArgs.join(" ")}`);
161
+
162
+ try {
163
+ const result = await spawn({
164
+ cmd: gitPath,
165
+ args: fullArgs,
166
+ cwd,
167
+ env: {
168
+ ...filterEnv(),
169
+ GIT_ASKPASS: scriptPath,
170
+ GIT_TERMINAL_PROMPT: "0",
171
+ // blocks env-based git config injection from outer processes.
172
+ // GIT_CONFIG_COUNT=0 blocks the newer KEY_n/VALUE_n mechanism.
173
+ // GIT_CONFIG_PARAMETERS="" clears the legacy quoted-list mechanism.
174
+ // both are needed — they are independent systems.
175
+ GIT_CONFIG_COUNT: "0",
176
+ GIT_CONFIG_PARAMETERS: "",
177
+ },
178
+ activityTimeout: 0,
179
+ });
180
+
181
+ if (result.stderr.includes("askpass-compromised")) {
182
+ log.info("askpass code was replayed after revoke — token has been revoked");
183
+ throw new Error("git auth failed — askpass code was replayed after revoke, token revoked");
184
+ }
185
+
186
+ if (result.exitCode !== 0) {
187
+ const stderr = result.stderr.trim();
188
+ const stdout = result.stdout.trim();
189
+ // stderr is the primary channel for git diagnostics, but in rare cases
190
+ // (e.g. some HTTPS smart-protocol failures) the only useful detail is
191
+ // on stdout — without it the agent / operator sees an empty error.
192
+ // include exit code so we can distinguish e.g. signal-killed (1 with
193
+ // empty output) from a genuine git-level rejection.
194
+ const detail =
195
+ stderr && stdout
196
+ ? `${stderr}\n--- stdout ---\n${stdout}`
197
+ : stderr || stdout || "(no output)";
198
+ const message = `git ${subcommand} failed (exit ${result.exitCode}): ${detail}`;
199
+ log.info(message);
200
+ throw new Error(message);
201
+ }
202
+
203
+ return {
204
+ stdout: result.stdout.trim(),
205
+ stderr: result.stderr.trim(),
206
+ };
207
+ } finally {
208
+ authServer.revoke(code);
209
+ try {
210
+ unlinkSync(scriptPath);
211
+ } catch {
212
+ // script may already be gone (e.g. tmpdir cleanup raced us)
213
+ }
214
+ }
215
+ }
216
+
217
+ /**
218
+ * shallow-clone unreachable: when an existing local depth is too shallow for
219
+ * git to traverse to the requested ref's ancestry, the remote walk fails with
220
+ * one of these wordings (git emits the full OID via oid_to_hex, so the bound
221
+ * is 40 for SHA-1 or 64 for SHA-256). detecting both lets a single deepen
222
+ * retry recover before the error reaches the agent — see issue #564 for the
223
+ * original `git_fetch` precedent and #656 for the `checkout_pr` follow-up.
224
+ */
225
+ export const SHALLOW_UNREACHABLE_PATTERNS: RegExp[] = [
226
+ /Could not read [a-f0-9]{40,64}/,
227
+ /remote did not send all necessary objects/,
228
+ ];
229
+
230
+ /**
231
+ * large enough to clear the merge base on most real-world PRs without
232
+ * downloading the full history; matches the fallback used by
233
+ * `checkoutPrBranch` when the GitHub compare API is unavailable.
234
+ */
235
+ export const DEEPEN_RETRY_DEPTH = 1000;
236
+
237
+ /**
238
+ * authenticated `git fetch` that recovers from shallow-unreachable errors
239
+ * by retrying once with `--deepen=1000`. callers pass the same args they
240
+ * would to `$git("fetch", ...)`; on shallow-unreachable failures in a
241
+ * shallow repo, the second attempt prepends `--deepen=N` and strips any
242
+ * caller-supplied `--depth=` (the two flags are mutually exclusive, and
243
+ * the caller's depth is what got us into this mess).
244
+ *
245
+ * non-shallow-unreachable errors and non-shallow repos rethrow unchanged,
246
+ * so this is safe to wrap any fetch without changing fast-path behavior.
247
+ */
248
+ export async function $gitFetchWithDeepen(
249
+ args: string[],
250
+ options: GitAuthOptions,
251
+ label?: string,
252
+ ): Promise<GitResult> {
253
+ try {
254
+ return await $git("fetch", args, options);
255
+ } catch (err) {
256
+ const msg = err instanceof Error ? err.message : String(err);
257
+ const isShallowUnreachable = SHALLOW_UNREACHABLE_PATTERNS.some((p) => p.test(msg));
258
+ if (!isShallowUnreachable) throw err;
259
+ const isShallow =
260
+ $("git", ["rev-parse", "--is-shallow-repository"], { log: false }).trim() === "true";
261
+ if (!isShallow) throw err;
262
+ log.info(
263
+ `» ${label ?? "git fetch"} hit shallow-unreachable error, retrying with --deepen=${DEEPEN_RETRY_DEPTH}`,
264
+ );
265
+ const retryArgs = args.filter((a) => !a.startsWith("--depth="));
266
+ return await $git("fetch", [`--deepen=${DEEPEN_RETRY_DEPTH}`, ...retryArgs], options);
267
+ }
268
+ }
@@ -0,0 +1,186 @@
1
+ /**
2
+ * ASKPASS-based git authentication server.
3
+ *
4
+ * serves tokens via a localhost HTTP server with per-$git()-call UUID codes.
5
+ * each $git() call gets a unique askpass script with the port+code baked in.
6
+ * the token never appears in subprocess env — only the script file path.
7
+ *
8
+ * lifetime: the code is valid for as long as the $git() invocation is
9
+ * running. multiple askpass calls within one invocation (e.g. git's own
10
+ * fetch/push + a git-lfs pre-push hook that also authenticates) all
11
+ * succeed. $git() calls revoke(code) in finally; subsequent requests for
12
+ * a revoked code trigger immediate token revocation via the GitHub API
13
+ * as a tamper-evidence precaution (an agent replaying the code after the
14
+ * legitimate window has closed is the realistic attack we still catch).
15
+ */
16
+
17
+ import { randomUUID } from "node:crypto";
18
+ import { writeFileSync } from "node:fs";
19
+ import { createServer } from "node:http";
20
+ import { join } from "node:path";
21
+ import { PRODUCT_SLUG } from "#app/brand";
22
+ import { log } from "#app/utils/cli";
23
+
24
+ type CodeState = "active" | "revoked";
25
+
26
+ type CodeEntry = {
27
+ token: string;
28
+ state: CodeState;
29
+ // only present once the entry is revoked — bounds the replay-trap window.
30
+ // active entries have no timer because $git() can take arbitrarily long
31
+ // (large LFS pushes, slow networks, `activityTimeout: 0` on the spawn);
32
+ // any wall-clock TTL here would re-introduce the original LFS bug at
33
+ // a different boundary. revoke() is the only way out for an active code.
34
+ timeout?: NodeJS.Timeout;
35
+ };
36
+
37
+ const REVOKED_TRAP_MS = 60_000;
38
+
39
+ export type GitAuthServer = {
40
+ port: number;
41
+ register: (token: string) => string;
42
+ revoke: (code: string) => void;
43
+ writeAskpassScript: (code: string) => string;
44
+ close: () => Promise<void>;
45
+ [Symbol.asyncDispose]: () => Promise<void>;
46
+ };
47
+
48
+ function revokeGitHubToken(token: string): void {
49
+ // honor GITHUB_API_URL so the tamper-trap revocation also works on GitHub
50
+ // Enterprise Server (where the API host is not api.github.com); falls back to
51
+ // public GitHub otherwise. Mirrors src/utils/token.ts.
52
+ const apiBase = process.env.GITHUB_API_URL || "https://api.github.com";
53
+ fetch(`${apiBase}/installation/token`, {
54
+ method: "DELETE",
55
+ headers: {
56
+ Authorization: `Bearer ${token}`,
57
+ Accept: "application/vnd.github+json",
58
+ "User-Agent": PRODUCT_SLUG,
59
+ },
60
+ // best-effort revocation, but still bound it: a hung socket must not keep
61
+ // the process alive past teardown.
62
+ signal: AbortSignal.timeout(10_000),
63
+ }).then(
64
+ (r) => log.info(`token revocation response: ${r.status}`),
65
+ () => log.warning("token revocation request failed"),
66
+ );
67
+ }
68
+
69
+ export async function startGitAuthServer(tmpdir: string): Promise<GitAuthServer> {
70
+ const codes = new Map<string, CodeEntry>();
71
+
72
+ const server = createServer((req, res) => {
73
+ if (req.method !== "GET") {
74
+ res.writeHead(405).end();
75
+ return;
76
+ }
77
+
78
+ const code = req.url?.slice(1);
79
+ if (!code) {
80
+ res.writeHead(400).end();
81
+ return;
82
+ }
83
+
84
+ const entry = codes.get(code);
85
+ if (!entry) {
86
+ res.writeHead(404).end();
87
+ return;
88
+ }
89
+
90
+ if (entry.state === "active") {
91
+ // legitimate caller (git, git-lfs, or any subprocess of the running
92
+ // $git() call). hand back the token without consuming the code —
93
+ // revoke() in $git's finally is what closes the window.
94
+ res.writeHead(200, { "Content-Type": "text/plain" });
95
+ res.end(entry.token);
96
+ return;
97
+ }
98
+
99
+ // request for a revoked code — the $git() window has closed, so this
100
+ // is an agent replaying the code. revoke the token as a precaution.
101
+ log.info("askpass code used after revoke — revoking token");
102
+ revokeGitHubToken(entry.token);
103
+ if (entry.timeout) clearTimeout(entry.timeout);
104
+ codes.delete(code);
105
+ res.writeHead(409, { "Content-Type": "text/plain" });
106
+ res.end("compromised");
107
+ });
108
+
109
+ await new Promise<void>((resolve, reject) => {
110
+ server.on("error", reject);
111
+ server.listen(0, "127.0.0.1", () => resolve());
112
+ });
113
+
114
+ const rawAddr = server.address();
115
+ if (!rawAddr || typeof rawAddr === "string") {
116
+ throw new Error("git auth server failed to bind");
117
+ }
118
+ const port = rawAddr.port;
119
+
120
+ log.debug(`git auth server listening on 127.0.0.1:${port}`);
121
+
122
+ function register(token: string): string {
123
+ const code = randomUUID();
124
+ codes.set(code, { token, state: "active" });
125
+ return code;
126
+ }
127
+
128
+ function revoke(code: string): void {
129
+ const entry = codes.get(code);
130
+ if (!entry) return;
131
+ entry.state = "revoked";
132
+ // keep the entry around briefly so a replay attempt trips the trap
133
+ // (token revocation) instead of returning an opaque 404.
134
+ entry.timeout = setTimeout(() => codes.delete(code), REVOKED_TRAP_MS);
135
+ entry.timeout.unref();
136
+ }
137
+
138
+ function writeAskpassScript(code: string): string {
139
+ const scriptId = randomUUID();
140
+ const scriptName = `askpass-${scriptId}.js`;
141
+ const scriptPath = join(tmpdir, scriptName);
142
+
143
+ // standalone node script — no project dependencies.
144
+ // git invokes this once per credential prompt — separate process spawn
145
+ // per prompt: one for "Username for ...", one for "Password for ...".
146
+ // sibling subprocesses (git-lfs pre-push, custom auth-bound hooks)
147
+ // invoke it independently for their own auth, also one spawn per prompt.
148
+ // all succeed as long as the parent $git() is still running, which is
149
+ // why neither the script nor the code is single-use. cleanup happens
150
+ // in $git()'s finally.
151
+ // 409 = code was already revoked by $git()'s finally (replay attempt).
152
+ const content = [
153
+ `#!/usr/bin/env node`,
154
+ `var a=process.argv[2]||"";`,
155
+ `if(/^Username/i.test(a)){process.stdout.write("x-access-token\\n")}`,
156
+ `else{var h=require("http");`,
157
+ `h.get("http://127.0.0.1:${port}/${code}",function(r){`,
158
+ `if(r.statusCode===409){process.stderr.write("askpass-compromised\\n");process.exit(1)}`,
159
+ `if(r.statusCode!==200){process.exit(1)}`,
160
+ `var d="";r.on("data",function(c){d+=c});`,
161
+ `r.on("end",function(){process.stdout.write(d+"\\n")})`,
162
+ `}).on("error",function(){process.exit(1)})}`,
163
+ ].join("\n");
164
+
165
+ writeFileSync(scriptPath, content, { mode: 0o700 });
166
+ return scriptPath;
167
+ }
168
+
169
+ async function close(): Promise<void> {
170
+ for (const entry of codes.values()) {
171
+ if (entry.timeout) clearTimeout(entry.timeout);
172
+ }
173
+ codes.clear();
174
+ await new Promise<void>((resolve) => server.close(() => resolve()));
175
+ log.debug("git auth server closed");
176
+ }
177
+
178
+ return {
179
+ port,
180
+ register,
181
+ revoke,
182
+ writeAskpassScript,
183
+ close,
184
+ [Symbol.asyncDispose]: close,
185
+ };
186
+ }