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.
- package/LICENSE +661 -0
- package/README.md +244 -0
- package/dist/agents/claude.d.ts +113 -0
- package/dist/agents/claudePretoolGate.d.ts +137 -0
- package/dist/agents/dispatchMetrics.d.ts +77 -0
- package/dist/agents/gateServer.d.ts +7 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/nativeFsDenies.d.ts +46 -0
- package/dist/agents/opencode.d.ts +284 -0
- package/dist/agents/opencodePlugin.d.ts +96 -0
- package/dist/agents/opencodeShared.d.ts +40 -0
- package/dist/agents/postRun.d.ts +126 -0
- package/dist/agents/reviewer.d.ts +41 -0
- package/dist/agents/sessionLabeler.d.ts +97 -0
- package/dist/agents/shared.d.ts +246 -0
- package/dist/agents/subagentModels.d.ts +19 -0
- package/dist/agents/tokenQuota.d.ts +118 -0
- package/dist/agents/writeGateSource.d.ts +22 -0
- package/dist/agents/writePolicy.d.ts +79 -0
- package/dist/brand.d.ts +67 -0
- package/dist/cli.mjs +247846 -0
- package/dist/external.d.ts +227 -0
- package/dist/i18n/scaffolding.d.ts +59 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +247061 -0
- package/dist/internal/index.d.ts +18 -0
- package/dist/internal.js +2398 -0
- package/dist/lifecycle.d.ts +2 -0
- package/dist/main.d.ts +8 -0
- package/dist/mcp/arkConfig.d.ts +1 -0
- package/dist/mcp/assess.d.ts +157 -0
- package/dist/mcp/capabilityContext.d.ts +71 -0
- package/dist/mcp/changeSummary.d.ts +52 -0
- package/dist/mcp/checkSuite.d.ts +27 -0
- package/dist/mcp/checkout.d.ts +92 -0
- package/dist/mcp/comment.d.ts +127 -0
- package/dist/mcp/commitInfo.d.ts +11 -0
- package/dist/mcp/crosswalk.d.ts +178 -0
- package/dist/mcp/crosswalkDigest.d.ts +1 -0
- package/dist/mcp/cyberEssentials.d.ts +24 -0
- package/dist/mcp/dashboard.d.ts +125 -0
- package/dist/mcp/dependencies.d.ts +12 -0
- package/dist/mcp/frameworks.d.ts +74 -0
- package/dist/mcp/geminiSanitizer.d.ts +28 -0
- package/dist/mcp/git.d.ts +60 -0
- package/dist/mcp/guardrails.d.ts +222 -0
- package/dist/mcp/issue.d.ts +20 -0
- package/dist/mcp/issueComments.d.ts +11 -0
- package/dist/mcp/issueEvents.d.ts +11 -0
- package/dist/mcp/issueInfo.d.ts +11 -0
- package/dist/mcp/labels.d.ts +14 -0
- package/dist/mcp/localContext.d.ts +26 -0
- package/dist/mcp/moduleExtraction.d.ts +79 -0
- package/dist/mcp/moduleTests.d.ts +106 -0
- package/dist/mcp/modules.d.ts +198 -0
- package/dist/mcp/output.d.ts +16 -0
- package/dist/mcp/pathSafety.d.ts +14 -0
- package/dist/mcp/policy.d.ts +50 -0
- package/dist/mcp/pr.d.ts +64 -0
- package/dist/mcp/prInfo.d.ts +11 -0
- package/dist/mcp/providerSchema.d.ts +52 -0
- package/dist/mcp/review.d.ts +212 -0
- package/dist/mcp/reviewComments.d.ts +245 -0
- package/dist/mcp/roots.d.ts +60 -0
- package/dist/mcp/scope.d.ts +26 -0
- package/dist/mcp/selectMode.d.ts +20 -0
- package/dist/mcp/server.d.ts +61 -0
- package/dist/mcp/shared.d.ts +62 -0
- package/dist/mcp/shell.d.ts +58 -0
- package/dist/mcp/staleFix.d.ts +138 -0
- package/dist/mcp/terraform/azurePrices.d.ts +8 -0
- package/dist/mcp/terraform/baseline.d.ts +57 -0
- package/dist/mcp/terraform/concernResult.d.ts +38 -0
- package/dist/mcp/terraform/cost.d.ts +55 -0
- package/dist/mcp/terraform/cspm.d.ts +80 -0
- package/dist/mcp/terraform/currency.d.ts +110 -0
- package/dist/mcp/terraform/decisions.d.ts +178 -0
- package/dist/mcp/terraform/eidas.d.ts +100 -0
- package/dist/mcp/terraform/evidence.d.ts +343 -0
- package/dist/mcp/terraform/findings.d.ts +76 -0
- package/dist/mcp/terraform/fixMemory.d.ts +81 -0
- package/dist/mcp/terraform/governance.d.ts +56 -0
- package/dist/mcp/terraform/hcl.d.ts +115 -0
- package/dist/mcp/terraform/iacLanguages.d.ts +120 -0
- package/dist/mcp/terraform/idleFloor.d.ts +78 -0
- package/dist/mcp/terraform/keyless.d.ts +68 -0
- package/dist/mcp/terraform/moduleDocs.d.ts +56 -0
- package/dist/mcp/terraform/nativeRules.d.ts +38 -0
- package/dist/mcp/terraform/nativeScan.d.ts +11 -0
- package/dist/mcp/terraform/noiseProfile.d.ts +100 -0
- package/dist/mcp/terraform/normalization.d.ts +52 -0
- package/dist/mcp/terraform/oscal.d.ts +103 -0
- package/dist/mcp/terraform/packs/azurerm-3-4.d.ts +2 -0
- package/dist/mcp/terraform/packs/cloudflare-4-5.d.ts +2 -0
- package/dist/mcp/terraform/paths.d.ts +28 -0
- package/dist/mcp/terraform/plan.d.ts +157 -0
- package/dist/mcp/terraform/planDrift.d.ts +199 -0
- package/dist/mcp/terraform/policyAuthor.d.ts +191 -0
- package/dist/mcp/terraform/prowlerOcsf.d.ts +136 -0
- package/dist/mcp/terraform/refactor.d.ts +183 -0
- package/dist/mcp/terraform/registry.d.ts +108 -0
- package/dist/mcp/terraform/risk.d.ts +41 -0
- package/dist/mcp/terraform/scanSession.d.ts +116 -0
- package/dist/mcp/terraform/scannerCache.d.ts +15 -0
- package/dist/mcp/terraform/scannerEgress.d.ts +72 -0
- package/dist/mcp/terraform/scannerJson.d.ts +13 -0
- package/dist/mcp/terraform/scanners.d.ts +205 -0
- package/dist/mcp/terraform/signing.d.ts +61 -0
- package/dist/mcp/terraform/stateLocking.d.ts +18 -0
- package/dist/mcp/terraform/subprocess.d.ts +43 -0
- package/dist/mcp/terraform/suppressions.d.ts +90 -0
- package/dist/mcp/terraform/taxonomy.d.ts +39 -0
- package/dist/mcp/terraform/tfquery.d.ts +47 -0
- package/dist/mcp/terraform/toolchainIntegrity.d.ts +82 -0
- package/dist/mcp/terraform/tools/authorPolicy.d.ts +59 -0
- package/dist/mcp/terraform/tools/detectPlanDrift.d.ts +20 -0
- package/dist/mcp/terraform/tools/emitCost.d.ts +11 -0
- package/dist/mcp/terraform/tools/emitSarif.d.ts +14 -0
- package/dist/mcp/terraform/tools/fixMemory.d.ts +19 -0
- package/dist/mcp/terraform/tools/infracostDiff.d.ts +22 -0
- package/dist/mcp/terraform/tools/ingestExternalFindings.d.ts +21 -0
- package/dist/mcp/terraform/tools/moduleLookup.d.ts +14 -0
- package/dist/mcp/terraform/tools/moduleSearch.d.ts +23 -0
- package/dist/mcp/terraform/tools/plan.d.ts +59 -0
- package/dist/mcp/terraform/tools/providerUpgrade.d.ts +55 -0
- package/dist/mcp/terraform/tools/readFindings.d.ts +17 -0
- package/dist/mcp/terraform/tools/scan.d.ts +114 -0
- package/dist/mcp/terraform/tools/validate.d.ts +31 -0
- package/dist/mcp/terraform/tools/verifyRemediation.d.ts +31 -0
- package/dist/mcp/terraform/tools/versionCurrency.d.ts +5 -0
- package/dist/mcp/terraform/tools.d.ts +16 -0
- package/dist/mcp/terraform/transformPacks.d.ts +267 -0
- package/dist/mcp/terraform/types.d.ts +226 -0
- package/dist/mcp/terraform/verification.d.ts +81 -0
- package/dist/mcp/terraform/vex.d.ts +115 -0
- package/dist/mcp/terraform/writeOnly.d.ts +67 -0
- package/dist/mcp/terraform.d.ts +51 -0
- package/dist/mcp/terratest.d.ts +85 -0
- package/dist/mcp/untrustedContent.d.ts +76 -0
- package/dist/mcp/upload.d.ts +8 -0
- package/dist/models.d.ts +181 -0
- package/dist/modes/address-reviews.d.ts +2 -0
- package/dist/modes/assess.d.ts +2 -0
- package/dist/modes/build.d.ts +2 -0
- package/dist/modes/compliance-audit.d.ts +2 -0
- package/dist/modes/cost-optimization.d.ts +2 -0
- package/dist/modes/drift-detect.d.ts +2 -0
- package/dist/modes/fix.d.ts +2 -0
- package/dist/modes/incremental-review.d.ts +2 -0
- package/dist/modes/index.d.ts +24 -0
- package/dist/modes/modernize-deprecated.d.ts +2 -0
- package/dist/modes/plan.d.ts +2 -0
- package/dist/modes/policy-gate.d.ts +2 -0
- package/dist/modes/prFormats.d.ts +3 -0
- package/dist/modes/refactor.d.ts +2 -0
- package/dist/modes/refresh-remediation.d.ts +2 -0
- package/dist/modes/remediate-and-refactor.d.ts +2 -0
- package/dist/modes/remediate.d.ts +2 -0
- package/dist/modes/resolve-conflicts.d.ts +2 -0
- package/dist/modes/review.d.ts +2 -0
- package/dist/modes/summarize-pr.d.ts +2 -0
- package/dist/modes/task.d.ts +2 -0
- package/dist/modes/terraform-code-review.d.ts +2 -0
- package/dist/modes/types.d.ts +9 -0
- package/dist/modes/update-dependencies.d.ts +2 -0
- package/dist/prep/index.d.ts +7 -0
- package/dist/prep/installNodeDependencies.d.ts +2 -0
- package/dist/prep/installPythonDependencies.d.ts +2 -0
- package/dist/prep/types.d.ts +31 -0
- package/dist/reviewQuality.d.ts +107 -0
- package/dist/skills/terraform-best-practices/SKILL.md +379 -0
- package/dist/toolState.d.ts +123 -0
- package/dist/utils/activity.d.ts +40 -0
- package/dist/utils/agent.d.ts +47 -0
- package/dist/utils/agentHangReport.d.ts +38 -0
- package/dist/utils/annotations.d.ts +17 -0
- package/dist/utils/apiFetch.d.ts +11 -0
- package/dist/utils/apiKeys.d.ts +48 -0
- package/dist/utils/apiUrl.d.ts +28 -0
- package/dist/utils/assets.d.ts +8 -0
- package/dist/utils/baseRefConfig.d.ts +121 -0
- package/dist/utils/billingErrors.d.ts +85 -0
- package/dist/utils/body.d.ts +34 -0
- package/dist/utils/buildInfraweaverFooter.d.ts +29 -0
- package/dist/utils/byokFallback.d.ts +85 -0
- package/dist/utils/changeImpact.d.ts +101 -0
- package/dist/utils/claudeSubscription.d.ts +30 -0
- package/dist/utils/cli.d.ts +10 -0
- package/dist/utils/cloudClient.d.ts +33 -0
- package/dist/utils/cloudFetchCore.d.ts +42 -0
- package/dist/utils/cloudReport.d.ts +114 -0
- package/dist/utils/codexHome.d.ts +29 -0
- package/dist/utils/codexOAuth.d.ts +60 -0
- package/dist/utils/diffCoverage.d.ts +63 -0
- package/dist/utils/env.d.ts +46 -0
- package/dist/utils/errorReport.d.ts +17 -0
- package/dist/utils/exitHandler.d.ts +8 -0
- package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
- package/dist/utils/gitAuth.d.ts +84 -0
- package/dist/utils/gitAuthServer.d.ts +24 -0
- package/dist/utils/github.d.ts +104 -0
- package/dist/utils/globals.d.ts +3 -0
- package/dist/utils/infraweaverConfig.d.ts +56 -0
- package/dist/utils/install.d.ts +37 -0
- package/dist/utils/instructions.d.ts +48 -0
- package/dist/utils/keylessOidc.d.ts +28 -0
- package/dist/utils/leapingComment.d.ts +11 -0
- package/dist/utils/learnings.d.ts +62 -0
- package/dist/utils/learningsTruncate.d.ts +25 -0
- package/dist/utils/lifecycle.d.ts +57 -0
- package/dist/utils/log.d.ts +111 -0
- package/dist/utils/modelResolver.d.ts +63 -0
- package/dist/utils/moduleFetch.d.ts +39 -0
- package/dist/utils/normalizeEnv.d.ts +30 -0
- package/dist/utils/openCodeModels.d.ts +11 -0
- package/dist/utils/openaiCompatible.d.ts +26 -0
- package/dist/utils/opentofuMcp.d.ts +50 -0
- package/dist/utils/overrides.d.ts +40 -0
- package/dist/utils/packageManager.d.ts +49 -0
- package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
- package/dist/utils/payload.d.ts +249 -0
- package/dist/utils/prSummary.d.ts +61 -0
- package/dist/utils/presets.d.ts +36 -0
- package/dist/utils/progressComment.d.ts +146 -0
- package/dist/utils/providerErrors.d.ts +31 -0
- package/dist/utils/proxyModel.d.ts +76 -0
- package/dist/utils/rangeDiff.d.ts +51 -0
- package/dist/utils/redact.d.ts +33 -0
- package/dist/utils/registryAuth.d.ts +52 -0
- package/dist/utils/remediationCommand.d.ts +58 -0
- package/dist/utils/retry.d.ts +38 -0
- package/dist/utils/reviewCleanup.d.ts +14 -0
- package/dist/utils/run.d.ts +9 -0
- package/dist/utils/runContext.d.ts +112 -0
- package/dist/utils/runContextData.d.ts +42 -0
- package/dist/utils/runErrorRenderer.d.ts +64 -0
- package/dist/utils/runLifecycle.d.ts +89 -0
- package/dist/utils/runStartupLog.d.ts +15 -0
- package/dist/utils/secrets.d.ts +34 -0
- package/dist/utils/setup.d.ts +90 -0
- package/dist/utils/shell.d.ts +44 -0
- package/dist/utils/skills.d.ts +10 -0
- package/dist/utils/subprocess.d.ts +81 -0
- package/dist/utils/terraformMcp.d.ts +46 -0
- package/dist/utils/time.d.ts +15 -0
- package/dist/utils/timer.d.ts +23 -0
- package/dist/utils/todoTracking.d.ts +16 -0
- package/dist/utils/token.d.ts +52 -0
- package/dist/utils/toolLicensing.d.ts +56 -0
- package/dist/utils/toolSelection.d.ts +73 -0
- package/dist/utils/toon.d.ts +16 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/versioning.d.ts +7 -0
- package/dist/utils/vertex.d.ts +16 -0
- package/dist/utils/workflow.d.ts +13 -0
- package/package.json +132 -0
- package/src/agents/claude.ts +1588 -0
- package/src/agents/claudePretoolGate.ts +286 -0
- package/src/agents/dispatchMetrics.ts +162 -0
- package/src/agents/gateServer.ts +178 -0
- package/src/agents/index.ts +10 -0
- package/src/agents/nativeFsDenies.ts +164 -0
- package/src/agents/opencode.ts +1600 -0
- package/src/agents/opencodePlugin.ts +304 -0
- package/src/agents/opencodeShared.ts +134 -0
- package/src/agents/postRun.ts +615 -0
- package/src/agents/reviewer.ts +134 -0
- package/src/agents/sessionLabeler.ts +185 -0
- package/src/agents/shared.ts +377 -0
- package/src/agents/subagentModels.ts +40 -0
- package/src/agents/tokenQuota.ts +203 -0
- package/src/agents/writeGateSource.ts +148 -0
- package/src/agents/writePolicy.ts +132 -0
- package/src/brand.ts +84 -0
- package/src/cli.ts +117 -0
- package/src/commands/gha.ts +188 -0
- package/src/commands/mcp.ts +126 -0
- package/src/commands/verifyEvidence.ts +100 -0
- package/src/entry.ts +7 -0
- package/src/entryPost.ts +109 -0
- package/src/external.ts +308 -0
- package/src/i18n/scaffolding.ts +191 -0
- package/src/index.ts +7 -0
- package/src/internal/index.ts +74 -0
- package/src/lifecycle.ts +2 -0
- package/src/main.ts +815 -0
- package/src/mcp/__fixtures__/infraweaver-scratch-pr-49-review-3485940013.json +110 -0
- package/src/mcp/__fixtures__/infraweaver-scratch-pr-64-review-3531000326.json +14 -0
- package/src/mcp/__fixtures__/infraweaver-test-repo-pr-1.diff.json +67 -0
- package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
- package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
- package/src/mcp/arkConfig.ts +7 -0
- package/src/mcp/assess.ts +723 -0
- package/src/mcp/capabilityContext.ts +80 -0
- package/src/mcp/changeSummary.ts +145 -0
- package/src/mcp/checkSuite.ts +261 -0
- package/src/mcp/checkout.ts +1015 -0
- package/src/mcp/comment.ts +683 -0
- package/src/mcp/commitInfo.ts +57 -0
- package/src/mcp/crosswalk.ts +1253 -0
- package/src/mcp/crosswalkDigest.ts +5 -0
- package/src/mcp/cyberEssentials.ts +60 -0
- package/src/mcp/dashboard.ts +232 -0
- package/src/mcp/dependencies.ts +190 -0
- package/src/mcp/frameworks.ts +236 -0
- package/src/mcp/geminiSanitizer.ts +212 -0
- package/src/mcp/git.ts +1116 -0
- package/src/mcp/guardrails.ts +771 -0
- package/src/mcp/issue.ts +74 -0
- package/src/mcp/issueComments.ts +48 -0
- package/src/mcp/issueEvents.ts +100 -0
- package/src/mcp/issueInfo.ts +72 -0
- package/src/mcp/labels.ts +35 -0
- package/src/mcp/localContext.ts +65 -0
- package/src/mcp/localServer.ts +217 -0
- package/src/mcp/moduleExtraction.ts +368 -0
- package/src/mcp/moduleTests.ts +421 -0
- package/src/mcp/modules.ts +752 -0
- package/src/mcp/output.ts +71 -0
- package/src/mcp/pathSafety.ts +28 -0
- package/src/mcp/policy.ts +226 -0
- package/src/mcp/pr.ts +238 -0
- package/src/mcp/prInfo.ts +91 -0
- package/src/mcp/providerSchema.ts +175 -0
- package/src/mcp/review.ts +1081 -0
- package/src/mcp/reviewComments.ts +1137 -0
- package/src/mcp/roots.ts +217 -0
- package/src/mcp/scope.ts +82 -0
- package/src/mcp/selectMode.ts +207 -0
- package/src/mcp/server.ts +498 -0
- package/src/mcp/shared.ts +120 -0
- package/src/mcp/shell.ts +631 -0
- package/src/mcp/staleFix.ts +557 -0
- package/src/mcp/terraform/__snapshots__/moduleDocs.test.ts.snap +40 -0
- package/src/mcp/terraform/azurePrices.ts +38 -0
- package/src/mcp/terraform/baseline.ts +172 -0
- package/src/mcp/terraform/concernResult.ts +111 -0
- package/src/mcp/terraform/cost.ts +175 -0
- package/src/mcp/terraform/cspm.ts +326 -0
- package/src/mcp/terraform/currency.ts +354 -0
- package/src/mcp/terraform/decisions.ts +590 -0
- package/src/mcp/terraform/eidas.ts +134 -0
- package/src/mcp/terraform/evidence.ts +771 -0
- package/src/mcp/terraform/findings.ts +383 -0
- package/src/mcp/terraform/fixMemory.ts +253 -0
- package/src/mcp/terraform/governance.ts +231 -0
- package/src/mcp/terraform/hcl.ts +273 -0
- package/src/mcp/terraform/iacLanguages.ts +431 -0
- package/src/mcp/terraform/idleFloor.ts +304 -0
- package/src/mcp/terraform/keyless.ts +123 -0
- package/src/mcp/terraform/moduleDocs.ts +303 -0
- package/src/mcp/terraform/nativeRules.ts +152 -0
- package/src/mcp/terraform/nativeScan.ts +67 -0
- package/src/mcp/terraform/noiseProfile.ts +183 -0
- package/src/mcp/terraform/normalization.ts +265 -0
- package/src/mcp/terraform/oscal.ts +283 -0
- package/src/mcp/terraform/packs/azurerm-3-4.ts +382 -0
- package/src/mcp/terraform/packs/cloudflare-4-5.ts +114 -0
- package/src/mcp/terraform/paths.ts +59 -0
- package/src/mcp/terraform/plan.ts +377 -0
- package/src/mcp/terraform/planDrift.ts +520 -0
- package/src/mcp/terraform/policyAuthor.ts +886 -0
- package/src/mcp/terraform/prowlerOcsf.ts +380 -0
- package/src/mcp/terraform/refactor.ts +879 -0
- package/src/mcp/terraform/registry.ts +317 -0
- package/src/mcp/terraform/risk.ts +99 -0
- package/src/mcp/terraform/scanSession.ts +242 -0
- package/src/mcp/terraform/scannerCache.ts +86 -0
- package/src/mcp/terraform/scannerEgress.ts +141 -0
- package/src/mcp/terraform/scannerJson.ts +22 -0
- package/src/mcp/terraform/scanners.ts +1134 -0
- package/src/mcp/terraform/signing.ts +151 -0
- package/src/mcp/terraform/stateLocking.ts +106 -0
- package/src/mcp/terraform/subprocess.ts +102 -0
- package/src/mcp/terraform/suppressions.ts +551 -0
- package/src/mcp/terraform/taxonomy.ts +0 -0
- package/src/mcp/terraform/tfquery.ts +159 -0
- package/src/mcp/terraform/toolchainIntegrity.ts +151 -0
- package/src/mcp/terraform/tools/authorPolicy.ts +185 -0
- package/src/mcp/terraform/tools/detectPlanDrift.ts +279 -0
- package/src/mcp/terraform/tools/emitCost.ts +130 -0
- package/src/mcp/terraform/tools/emitSarif.ts +108 -0
- package/src/mcp/terraform/tools/fixMemory.ts +82 -0
- package/src/mcp/terraform/tools/infracostDiff.ts +110 -0
- package/src/mcp/terraform/tools/ingestExternalFindings.ts +259 -0
- package/src/mcp/terraform/tools/moduleLookup.ts +86 -0
- package/src/mcp/terraform/tools/moduleSearch.ts +46 -0
- package/src/mcp/terraform/tools/plan.ts +384 -0
- package/src/mcp/terraform/tools/providerUpgrade.ts +217 -0
- package/src/mcp/terraform/tools/readFindings.ts +138 -0
- package/src/mcp/terraform/tools/scan.ts +303 -0
- package/src/mcp/terraform/tools/validate.ts +160 -0
- package/src/mcp/terraform/tools/verifyRemediation.ts +190 -0
- package/src/mcp/terraform/tools/versionCurrency.ts +64 -0
- package/src/mcp/terraform/tools.ts +62 -0
- package/src/mcp/terraform/transformPacks.ts +594 -0
- package/src/mcp/terraform/types.ts +382 -0
- package/src/mcp/terraform/verification.ts +150 -0
- package/src/mcp/terraform/vex.ts +367 -0
- package/src/mcp/terraform/writeOnly.ts +252 -0
- package/src/mcp/terraform.ts +52 -0
- package/src/mcp/terratest.ts +215 -0
- package/src/mcp/untrustedContent.ts +126 -0
- package/src/mcp/upload.ts +123 -0
- package/src/models.ts +753 -0
- package/src/modes/address-reviews.ts +35 -0
- package/src/modes/assess.ts +27 -0
- package/src/modes/build.ts +86 -0
- package/src/modes/compliance-audit.ts +25 -0
- package/src/modes/cost-optimization.ts +36 -0
- package/src/modes/drift-detect.ts +31 -0
- package/src/modes/fix.ts +29 -0
- package/src/modes/incremental-review.ts +103 -0
- package/src/modes/index.ts +94 -0
- package/src/modes/modernize-deprecated.ts +36 -0
- package/src/modes/plan.ts +21 -0
- package/src/modes/policy-gate.ts +27 -0
- package/src/modes/prFormats.ts +325 -0
- package/src/modes/refactor.ts +74 -0
- package/src/modes/refresh-remediation.ts +40 -0
- package/src/modes/remediate-and-refactor.ts +42 -0
- package/src/modes/remediate.ts +78 -0
- package/src/modes/resolve-conflicts.ts +32 -0
- package/src/modes/review.ts +135 -0
- package/src/modes/summarize-pr.ts +42 -0
- package/src/modes/task.ts +26 -0
- package/src/modes/terraform-code-review.ts +68 -0
- package/src/modes/types.ts +17 -0
- package/src/modes/update-dependencies.ts +44 -0
- package/src/prep/index.ts +96 -0
- package/src/prep/installNodeDependencies.ts +251 -0
- package/src/prep/installPythonDependencies.ts +235 -0
- package/src/prep/types.ts +38 -0
- package/src/reviewQuality.ts +237 -0
- package/src/runCli.ts +335 -0
- package/src/skills/terraform-best-practices/SKILL.md +379 -0
- package/src/toolState.ts +241 -0
- package/src/utils/activity.ts +210 -0
- package/src/utils/agent.ts +245 -0
- package/src/utils/agentHangReport.ts +180 -0
- package/src/utils/annotations.ts +56 -0
- package/src/utils/apiFetch.ts +19 -0
- package/src/utils/apiKeys.ts +305 -0
- package/src/utils/apiUrl.ts +42 -0
- package/src/utils/assets.ts +123 -0
- package/src/utils/baseRefConfig.ts +254 -0
- package/src/utils/billingErrors.ts +210 -0
- package/src/utils/body.ts +168 -0
- package/src/utils/buildInfraweaverFooter.ts +104 -0
- package/src/utils/byokFallback.ts +137 -0
- package/src/utils/changeImpact.ts +330 -0
- package/src/utils/claudeSubscription.ts +93 -0
- package/src/utils/cli.ts +36 -0
- package/src/utils/cloudClient.ts +57 -0
- package/src/utils/cloudFetchCore.ts +139 -0
- package/src/utils/cloudReport.ts +316 -0
- package/src/utils/codexHome.ts +204 -0
- package/src/utils/codexOAuth.ts +154 -0
- package/src/utils/codexRefreshDetect.ts +36 -0
- package/src/utils/diffCoverage.ts +404 -0
- package/src/utils/env.ts +84 -0
- package/src/utils/errorReport.ts +94 -0
- package/src/utils/exitHandler.ts +35 -0
- package/src/utils/fixDoubleEscapedString.ts +9 -0
- package/src/utils/ghaCore.ts +13 -0
- package/src/utils/gitAuth.ts +268 -0
- package/src/utils/gitAuthServer.ts +186 -0
- package/src/utils/github.ts +676 -0
- package/src/utils/globals.ts +9 -0
- package/src/utils/humanEditCapture.ts +198 -0
- package/src/utils/infraweaverConfig.ts +202 -0
- package/src/utils/install.ts +279 -0
- package/src/utils/instructions.ts +640 -0
- package/src/utils/keylessOidc.ts +47 -0
- package/src/utils/leapingComment.ts +20 -0
- package/src/utils/learnings.ts +145 -0
- package/src/utils/learningsTruncate.ts +42 -0
- package/src/utils/lifecycle.ts +198 -0
- package/src/utils/log.ts +452 -0
- package/src/utils/modelResolver.ts +105 -0
- package/src/utils/moduleFetch.ts +138 -0
- package/src/utils/normalizeEnv.ts +106 -0
- package/src/utils/openCodeModels.ts +86 -0
- package/src/utils/openaiCompatible.ts +52 -0
- package/src/utils/opentofuMcp.ts +61 -0
- package/src/utils/overrides.ts +100 -0
- package/src/utils/packageManager.ts +257 -0
- package/src/utils/patchWorkflowRunFields.ts +173 -0
- package/src/utils/payload.ts +1206 -0
- package/src/utils/prSummary.ts +148 -0
- package/src/utils/presets.ts +105 -0
- package/src/utils/progressComment.ts +266 -0
- package/src/utils/providerErrors.ts +189 -0
- package/src/utils/proxyModel.ts +239 -0
- package/src/utils/rangeDiff.ts +182 -0
- package/src/utils/redact.ts +86 -0
- package/src/utils/registryAuth.ts +115 -0
- package/src/utils/remediationCommand.ts +144 -0
- package/src/utils/retry.ts +180 -0
- package/src/utils/reviewCleanup.ts +116 -0
- package/src/utils/run.ts +100 -0
- package/src/utils/runContext.ts +276 -0
- package/src/utils/runContextData.ts +121 -0
- package/src/utils/runErrorRenderer.ts +282 -0
- package/src/utils/runFixture.ts +91 -0
- package/src/utils/runLifecycle.ts +360 -0
- package/src/utils/runStartupLog.ts +67 -0
- package/src/utils/secrets.ts +208 -0
- package/src/utils/setup.ts +368 -0
- package/src/utils/shell.ts +132 -0
- package/src/utils/skills.ts +67 -0
- package/src/utils/subprocess.ts +474 -0
- package/src/utils/terraformMcp.ts +99 -0
- package/src/utils/time.ts +59 -0
- package/src/utils/timer.ts +72 -0
- package/src/utils/todoTracking.ts +168 -0
- package/src/utils/token.ts +294 -0
- package/src/utils/toolLicensing.ts +152 -0
- package/src/utils/toolSelection.ts +239 -0
- package/src/utils/toon.ts +76 -0
- package/src/utils/version.ts +10 -0
- package/src/utils/versioning.ts +44 -0
- package/src/utils/vertex.ts +94 -0
- 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
|
+
}
|