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,72 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { log } from "#app/utils/cli";
|
|
3
|
+
|
|
4
|
+
export class Timer {
|
|
5
|
+
private initialTimestamp: number;
|
|
6
|
+
private lastCheckpointTimestamp: number | null = null;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this.initialTimestamp = performance.now();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
checkpoint(name: string): void {
|
|
13
|
+
const now = performance.now();
|
|
14
|
+
const duration = this.lastCheckpointTimestamp
|
|
15
|
+
? now - this.lastCheckpointTimestamp
|
|
16
|
+
: now - this.initialTimestamp;
|
|
17
|
+
|
|
18
|
+
log.debug(`» ${name}: ${duration}ms`);
|
|
19
|
+
this.lastCheckpointTimestamp = now;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const THINKING_THRESHOLD = 3000; // ms
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Measures wall-clock gap between the last tool_result and the next tool_call,
|
|
27
|
+
* surfacing it as a "thought for Xs" log when over `THINKING_THRESHOLD`.
|
|
28
|
+
*
|
|
29
|
+
* Use one instance per logical session (orchestrator, each subagent) — sharing
|
|
30
|
+
* a single timer across sessions conflates cross-session interleaving as
|
|
31
|
+
* thinking time. The optional `formatLine` lets the caller prefix output with
|
|
32
|
+
* a session label so attribution is visible in the merged log stream.
|
|
33
|
+
*/
|
|
34
|
+
export class ThinkingTimer {
|
|
35
|
+
private readonly durationFormatter = new Intl.NumberFormat("en-US", {
|
|
36
|
+
style: "unit",
|
|
37
|
+
unit: "second",
|
|
38
|
+
unitDisplay: "long",
|
|
39
|
+
minimumFractionDigits: 0,
|
|
40
|
+
maximumFractionDigits: 1,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
private lastToolResultTimestamp: number | null = null;
|
|
44
|
+
private readonly formatLine: (line: string) => string;
|
|
45
|
+
|
|
46
|
+
// node's native TS strip-only mode does not support parameter properties,
|
|
47
|
+
// so the formatter is declared as a field and assigned in the body.
|
|
48
|
+
constructor(formatLine: (line: string) => string = (l) => l) {
|
|
49
|
+
this.formatLine = formatLine;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
markToolResult(): void {
|
|
53
|
+
this.lastToolResultTimestamp = performance.now();
|
|
54
|
+
log.debug(
|
|
55
|
+
this.formatLine(`» thinking timer: markToolResult at ${this.lastToolResultTimestamp}`),
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
markToolCall(): void {
|
|
60
|
+
const now = performance.now();
|
|
61
|
+
log.debug(
|
|
62
|
+
this.formatLine(
|
|
63
|
+
`» thinking timer: markToolCall at ${now}, lastToolResult=${this.lastToolResultTimestamp}`,
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
if (this.lastToolResultTimestamp === null) return;
|
|
67
|
+
const elapsed = now - this.lastToolResultTimestamp;
|
|
68
|
+
if (elapsed < THINKING_THRESHOLD) return;
|
|
69
|
+
const seconds = elapsed / 1000;
|
|
70
|
+
log.info(this.formatLine(`» thought for ${this.durationFormatter.format(seconds)}`));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { UPLOADS_URL } from "#app/brand";
|
|
2
|
+
import { log } from "#app/utils/log";
|
|
3
|
+
|
|
4
|
+
type TodoItem = {
|
|
5
|
+
id: string;
|
|
6
|
+
content: string;
|
|
7
|
+
status: "pending" | "in_progress" | "completed" | "cancelled";
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function isValidTodoStatus(value: string): value is TodoItem["status"] {
|
|
11
|
+
return (
|
|
12
|
+
value === "pending" || value === "in_progress" || value === "completed" || value === "cancelled"
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function parseTodowriteInput(input: unknown): { todos: unknown[]; merge: boolean } | undefined {
|
|
17
|
+
if (!input || typeof input !== "object" || !("todos" in input)) return undefined;
|
|
18
|
+
if (!Array.isArray(input.todos)) return undefined;
|
|
19
|
+
const merge = "merge" in input && input.merge === true;
|
|
20
|
+
return { todos: input.todos, merge };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function parseTodoItem(entry: unknown, index: number): TodoItem | undefined {
|
|
24
|
+
if (!entry || typeof entry !== "object") return undefined;
|
|
25
|
+
if (!("content" in entry) || typeof entry.content !== "string") return undefined;
|
|
26
|
+
const id = "id" in entry && typeof entry.id === "string" ? entry.id : String(index);
|
|
27
|
+
const status =
|
|
28
|
+
"status" in entry && typeof entry.status === "string" && isValidTodoStatus(entry.status)
|
|
29
|
+
? entry.status
|
|
30
|
+
: "pending";
|
|
31
|
+
return { id, content: entry.content, status };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function renderTodoMarkdown(todos: TodoItem[]): string {
|
|
35
|
+
return todos
|
|
36
|
+
.map((todo) => {
|
|
37
|
+
switch (todo.status) {
|
|
38
|
+
case "completed":
|
|
39
|
+
return `- [x] ${todo.content}`;
|
|
40
|
+
case "cancelled":
|
|
41
|
+
return `- ~~${todo.content}~~`;
|
|
42
|
+
case "in_progress":
|
|
43
|
+
return `- [ ] <img src="${UPLOADS_URL}/Progress%20Indicator.gif" width="11" style="visibility: visible; max-width: 100%;" /> ${todo.content}`;
|
|
44
|
+
case "pending":
|
|
45
|
+
return `- [ ] ${todo.content}`;
|
|
46
|
+
default:
|
|
47
|
+
todo.status satisfies never;
|
|
48
|
+
return `- [ ] ${todo.content}`;
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
.join("\n");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type TodoTracker = {
|
|
55
|
+
update: (input: unknown) => void;
|
|
56
|
+
flush: () => Promise<void>;
|
|
57
|
+
cancel: () => void;
|
|
58
|
+
/** resolves when any in-flight onUpdate call completes */
|
|
59
|
+
settled: () => Promise<void>;
|
|
60
|
+
/** mark in-progress items as completed (for final snapshot before review/progress post) */
|
|
61
|
+
completeInProgress: () => void;
|
|
62
|
+
renderCollapsible: (options?: { completeInProgress?: boolean }) => string;
|
|
63
|
+
readonly enabled: boolean;
|
|
64
|
+
/** true after the tracker has successfully called onUpdate at least once */
|
|
65
|
+
readonly hasPublished: boolean;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const DEBOUNCE_MS = 2000;
|
|
69
|
+
|
|
70
|
+
export function createTodoTracker(onUpdate: (body: string) => Promise<void>): TodoTracker {
|
|
71
|
+
const state = new Map<string, TodoItem>();
|
|
72
|
+
let enabled = true;
|
|
73
|
+
let hasPublished = false;
|
|
74
|
+
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
75
|
+
let inflightPromise: Promise<void> = Promise.resolve();
|
|
76
|
+
|
|
77
|
+
function scheduleUpdate() {
|
|
78
|
+
if (!enabled) return;
|
|
79
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
80
|
+
debounceTimer = setTimeout(() => {
|
|
81
|
+
debounceTimer = null;
|
|
82
|
+
if (!enabled || state.size === 0) return;
|
|
83
|
+
const markdown = renderTodoMarkdown(Array.from(state.values()));
|
|
84
|
+
inflightPromise = inflightPromise
|
|
85
|
+
.then(async () => {
|
|
86
|
+
if (!enabled) return;
|
|
87
|
+
await onUpdate(markdown);
|
|
88
|
+
hasPublished = true;
|
|
89
|
+
})
|
|
90
|
+
.catch((err) => {
|
|
91
|
+
log.debug(`todo progress update failed: ${err}`);
|
|
92
|
+
});
|
|
93
|
+
}, DEBOUNCE_MS);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
update(input: unknown) {
|
|
98
|
+
if (!enabled) return;
|
|
99
|
+
const parsed = parseTodowriteInput(input);
|
|
100
|
+
if (!parsed) return;
|
|
101
|
+
if (!parsed.merge) state.clear();
|
|
102
|
+
for (const [index, entry] of parsed.todos.entries()) {
|
|
103
|
+
const item = parseTodoItem(entry, index);
|
|
104
|
+
if (item) state.set(item.id, item);
|
|
105
|
+
}
|
|
106
|
+
log.debug(`» todowrite: ${state.size} items tracked`);
|
|
107
|
+
scheduleUpdate();
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
async flush() {
|
|
111
|
+
if (debounceTimer) {
|
|
112
|
+
clearTimeout(debounceTimer);
|
|
113
|
+
debounceTimer = null;
|
|
114
|
+
}
|
|
115
|
+
if (!enabled || state.size === 0) return;
|
|
116
|
+
const markdown = renderTodoMarkdown(Array.from(state.values()));
|
|
117
|
+
inflightPromise = inflightPromise
|
|
118
|
+
.then(async () => {
|
|
119
|
+
if (!enabled) return;
|
|
120
|
+
await onUpdate(markdown);
|
|
121
|
+
hasPublished = true;
|
|
122
|
+
})
|
|
123
|
+
.catch((err) => {
|
|
124
|
+
log.debug(`todo progress flush failed: ${err}`);
|
|
125
|
+
});
|
|
126
|
+
await inflightPromise;
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
cancel() {
|
|
130
|
+
enabled = false;
|
|
131
|
+
if (debounceTimer) {
|
|
132
|
+
clearTimeout(debounceTimer);
|
|
133
|
+
debounceTimer = null;
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
async settled() {
|
|
138
|
+
await inflightPromise;
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
completeInProgress() {
|
|
142
|
+
for (const item of state.values()) {
|
|
143
|
+
if (item.status === "in_progress") item.status = "completed";
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
renderCollapsible(options?: { completeInProgress?: boolean }): string {
|
|
148
|
+
if (state.size === 0) return "";
|
|
149
|
+
const shouldCompleteInProgress = options?.completeInProgress === true;
|
|
150
|
+
const todos = Array.from(state.values()).map((item) =>
|
|
151
|
+
shouldCompleteInProgress && item.status === "in_progress"
|
|
152
|
+
? { ...item, status: "completed" as const }
|
|
153
|
+
: item,
|
|
154
|
+
);
|
|
155
|
+
const completed = todos.filter((t) => t.status === "completed").length;
|
|
156
|
+
const markdown = renderTodoMarkdown(todos);
|
|
157
|
+
return `<details>\n<summary>Task list (${completed}/${todos.length} completed)</summary>\n\n${markdown}\n\n</details>`;
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
get enabled() {
|
|
161
|
+
return enabled;
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
get hasPublished() {
|
|
165
|
+
return hasPublished;
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import * as core from "@actions/core";
|
|
3
|
+
import type { PushPermission } from "#app/external";
|
|
4
|
+
import { log } from "#app/utils/cli";
|
|
5
|
+
import { onExitSignal } from "#app/utils/exitHandler";
|
|
6
|
+
import {
|
|
7
|
+
acquireNewToken,
|
|
8
|
+
type OidcCreds,
|
|
9
|
+
readOidcCreds,
|
|
10
|
+
} from "#app/utils/github";
|
|
11
|
+
import { isGitHubActions } from "#app/utils/globals";
|
|
12
|
+
import { stashKeylessOidcCreds } from "#app/utils/keylessOidc";
|
|
13
|
+
|
|
14
|
+
// re-export for `infraweaver gha token` subcommand
|
|
15
|
+
export {
|
|
16
|
+
acquireNewToken as acquireInstallationToken,
|
|
17
|
+
revokeGitHubInstallationToken as revokeInstallationToken,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// store MCP token in memory for getGitHubInstallationToken()
|
|
21
|
+
let mcpTokenValue: string | undefined;
|
|
22
|
+
|
|
23
|
+
// single-flight refresher for the MCP installation token, installed by
|
|
24
|
+
// resolveTokens when OIDC re-minting is possible. createOctokit calls it on a
|
|
25
|
+
// 401 to swap in a fresh token mid-run (pullfrog #891). undefined off-CI, on the
|
|
26
|
+
// external-GH_TOKEN path, or once tokens are disposed.
|
|
27
|
+
let refreshMcpTokenFn: ((stale: string) => Promise<string>) | undefined;
|
|
28
|
+
|
|
29
|
+
/** The live MCP-token refresher (see {@link refreshMcpTokenFn}), or undefined
|
|
30
|
+
* when re-minting isn't possible. Passed into `createOctokit` as `refreshAuth`. */
|
|
31
|
+
export function getMcpTokenRefresh():
|
|
32
|
+
| ((stale: string) => Promise<string>)
|
|
33
|
+
| undefined {
|
|
34
|
+
return refreshMcpTokenFn;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* get the job-scoped token from action input.
|
|
39
|
+
* this token has permissions defined by the workflow's permissions block.
|
|
40
|
+
*
|
|
41
|
+
* fallback order:
|
|
42
|
+
* 1. INPUT_TOKEN (from workflow `with: token:`)
|
|
43
|
+
* 2. GH_TOKEN (external token override)
|
|
44
|
+
* 3. GITHUB_TOKEN (pre-acquired in tests or from GHA env)
|
|
45
|
+
*/
|
|
46
|
+
export function getJobToken(): string {
|
|
47
|
+
const inputToken = core.getInput("token");
|
|
48
|
+
if (inputToken) {
|
|
49
|
+
return inputToken;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// fallback for test environment and local dev
|
|
53
|
+
const fallbackToken = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
|
|
54
|
+
if (fallbackToken) {
|
|
55
|
+
return fallbackToken;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new Error("token input is required");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type TokenRef = {
|
|
62
|
+
/** Read live via the getter below: after a mid-run re-mint (`refreshGitToken`
|
|
63
|
+
* recovers an auth-class push 401 with a fresh token, revoking the old one),
|
|
64
|
+
* this reflects the CURRENT git token. Push-class tools (push_branch,
|
|
65
|
+
* push_tags, delete_branch, git_fetch) that read it per call therefore never
|
|
66
|
+
* reuse a stale/revoked snapshot. Mirrors the `getMcpTokenRefresh` /
|
|
67
|
+
* `githubInstallationToken` live-getter pattern (pullfrog #891/#964). */
|
|
68
|
+
gitToken: string;
|
|
69
|
+
mcpToken: string;
|
|
70
|
+
/** single-flight re-mint of the git token, threaded into pushWithRetry so an
|
|
71
|
+
* auth-class push 401 can recover with a fresh token (pullfrog #972). undefined
|
|
72
|
+
* when re-minting isn't possible (off-CI or external GH_TOKEN). */
|
|
73
|
+
refreshGitToken?: (stale: string) => Promise<string>;
|
|
74
|
+
[Symbol.asyncDispose]: () => Promise<void>;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
type ResolveTokensParams = {
|
|
78
|
+
push: PushPermission;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* resolve tokens for the action run.
|
|
83
|
+
*
|
|
84
|
+
* creates two separate tokens:
|
|
85
|
+
* - gitToken: contents permission based on `push` setting (assumed exfiltratable)
|
|
86
|
+
* - push: enabled → contents:write (can push)
|
|
87
|
+
* - push: disabled → contents:read (read-only)
|
|
88
|
+
* - mcpToken: full installation token - used for GitHub API calls in MCP tools (not exfiltratable)
|
|
89
|
+
*
|
|
90
|
+
* security-conscious users can pass their own token via GH_TOKEN env var or inputs.token.
|
|
91
|
+
*/
|
|
92
|
+
export async function resolveTokens(
|
|
93
|
+
params: ResolveTokensParams,
|
|
94
|
+
): Promise<TokenRef> {
|
|
95
|
+
assert(!mcpTokenValue, "tokens are already resolved");
|
|
96
|
+
|
|
97
|
+
const externalToken = process.env.GH_TOKEN;
|
|
98
|
+
|
|
99
|
+
// external token takes precedence - use for both git and MCP
|
|
100
|
+
if (externalToken) {
|
|
101
|
+
mcpTokenValue = externalToken;
|
|
102
|
+
|
|
103
|
+
if (isGitHubActions) {
|
|
104
|
+
core.setSecret(externalToken);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
log.info("» using external GH_TOKEN for both git and MCP");
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
gitToken: externalToken,
|
|
111
|
+
mcpToken: externalToken,
|
|
112
|
+
async [Symbol.asyncDispose]() {
|
|
113
|
+
mcpTokenValue = undefined;
|
|
114
|
+
// GH_TOKEN isn't acquired here, so it's not revoked here either
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// create git token based on push permission (assumed exfiltratable)
|
|
120
|
+
// disabled = read-only, restricted/enabled = write (MCP tools enforce branch restrictions)
|
|
121
|
+
// workflows permission is write-only in the API, so only requested when pushing is allowed
|
|
122
|
+
const gitPermissions =
|
|
123
|
+
params.push === "disabled"
|
|
124
|
+
? { contents: "read" as const }
|
|
125
|
+
: { contents: "write" as const, workflows: "write" as const };
|
|
126
|
+
let currentGitToken = await acquireNewToken({ permissions: gitPermissions });
|
|
127
|
+
if (isGitHubActions) {
|
|
128
|
+
core.setSecret(currentGitToken);
|
|
129
|
+
}
|
|
130
|
+
log.info(
|
|
131
|
+
`» acquired git token (${Object.entries(gitPermissions)
|
|
132
|
+
.map((e) => e.join(":"))
|
|
133
|
+
.join(", ")})`,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// MCP token scoped to only what MCP tools actually need.
|
|
137
|
+
// not exfiltratable (only accessible via MCP tools), but scoped as defense-in-depth
|
|
138
|
+
// so even a compromised tool context can't touch secrets, admin, etc.
|
|
139
|
+
const mcpPermissions = {
|
|
140
|
+
contents: "write",
|
|
141
|
+
pull_requests: "write",
|
|
142
|
+
issues: "write",
|
|
143
|
+
checks: "read",
|
|
144
|
+
actions: "read",
|
|
145
|
+
} as const;
|
|
146
|
+
let currentMcpToken = await acquireNewToken({ permissions: mcpPermissions });
|
|
147
|
+
if (isGitHubActions) {
|
|
148
|
+
core.setSecret(currentMcpToken);
|
|
149
|
+
}
|
|
150
|
+
log.info(
|
|
151
|
+
`» acquired scoped MCP token (${Object.entries(mcpPermissions)
|
|
152
|
+
.map((e) => e.join(":"))
|
|
153
|
+
.join(", ")})`,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
mcpTokenValue = currentMcpToken;
|
|
157
|
+
|
|
158
|
+
// Stash the OIDC creds NOW — resolveTokens runs before main.ts scrubs the
|
|
159
|
+
// ACTIONS_ID_TOKEN_REQUEST_* env vars (in every shell mode), so without this the
|
|
160
|
+
// refreshers below couldn't re-mint mid-run. undefined off-CI (local GitHub-App
|
|
161
|
+
// path) → no refresher, which is fine: re-mint is a CI replication-lag cure.
|
|
162
|
+
const oidc: OidcCreds | undefined = readOidcCreds();
|
|
163
|
+
// Feed the same snapshot to keyless (Sigstore) evidence signing, which runs
|
|
164
|
+
// later in the agent loop after these env vars are scrubbed. No-op off-CI.
|
|
165
|
+
stashKeylessOidcCreds(oidc);
|
|
166
|
+
|
|
167
|
+
// Single-flight re-minters (pullfrog #891/#972). Each coalesces concurrent
|
|
168
|
+
// callers on the same stale token: a caller holding an already-superseded token
|
|
169
|
+
// gets the current one without minting, and only the first caller of a given
|
|
170
|
+
// stale token triggers acquireNewToken. The memo clears in `finally` so a
|
|
171
|
+
// transient mint failure doesn't permanently poison the run.
|
|
172
|
+
let gitRefreshPromise: Promise<string> | undefined;
|
|
173
|
+
const refreshGitToken = oidc
|
|
174
|
+
? (stale: string): Promise<string> => {
|
|
175
|
+
assert(mcpTokenValue, "tokens already disposed");
|
|
176
|
+
if (stale !== currentGitToken) return Promise.resolve(currentGitToken);
|
|
177
|
+
gitRefreshPromise ??= acquireNewToken({
|
|
178
|
+
permissions: gitPermissions,
|
|
179
|
+
oidc,
|
|
180
|
+
})
|
|
181
|
+
.then((fresh) => {
|
|
182
|
+
if (isGitHubActions) core.setSecret(fresh);
|
|
183
|
+
const superseded = currentGitToken;
|
|
184
|
+
currentGitToken = fresh;
|
|
185
|
+
void revokeGitHubInstallationToken(superseded);
|
|
186
|
+
log.warning(
|
|
187
|
+
"» GitHub rejected the git token; re-acquired a fresh installation token",
|
|
188
|
+
);
|
|
189
|
+
return fresh;
|
|
190
|
+
})
|
|
191
|
+
.finally(() => {
|
|
192
|
+
gitRefreshPromise = undefined;
|
|
193
|
+
});
|
|
194
|
+
return gitRefreshPromise;
|
|
195
|
+
}
|
|
196
|
+
: undefined;
|
|
197
|
+
|
|
198
|
+
let mcpRefreshPromise: Promise<string> | undefined;
|
|
199
|
+
refreshMcpTokenFn = oidc
|
|
200
|
+
? (stale: string): Promise<string> => {
|
|
201
|
+
assert(mcpTokenValue, "tokens already disposed");
|
|
202
|
+
if (stale !== currentMcpToken) return Promise.resolve(currentMcpToken);
|
|
203
|
+
mcpRefreshPromise ??= acquireNewToken({
|
|
204
|
+
permissions: mcpPermissions,
|
|
205
|
+
oidc,
|
|
206
|
+
})
|
|
207
|
+
.then((fresh) => {
|
|
208
|
+
if (isGitHubActions) core.setSecret(fresh);
|
|
209
|
+
const superseded = currentMcpToken;
|
|
210
|
+
currentMcpToken = fresh;
|
|
211
|
+
mcpTokenValue = fresh;
|
|
212
|
+
void revokeGitHubInstallationToken(superseded);
|
|
213
|
+
log.warning(
|
|
214
|
+
"» GitHub rejected the MCP token; re-acquired a fresh installation token",
|
|
215
|
+
);
|
|
216
|
+
return fresh;
|
|
217
|
+
})
|
|
218
|
+
.finally(() => {
|
|
219
|
+
mcpRefreshPromise = undefined;
|
|
220
|
+
});
|
|
221
|
+
return mcpRefreshPromise;
|
|
222
|
+
}
|
|
223
|
+
: undefined;
|
|
224
|
+
|
|
225
|
+
let disposingRef: PromiseWithResolvers<void> | undefined;
|
|
226
|
+
|
|
227
|
+
const dispose = async () => {
|
|
228
|
+
if (disposingRef) {
|
|
229
|
+
// this can happen if the signal arrives when disposing tokens
|
|
230
|
+
// we make sure to wait for the current dispose to complete
|
|
231
|
+
return disposingRef.promise;
|
|
232
|
+
}
|
|
233
|
+
disposingRef = Promise.withResolvers();
|
|
234
|
+
try {
|
|
235
|
+
mcpTokenValue = undefined;
|
|
236
|
+
refreshMcpTokenFn = undefined;
|
|
237
|
+
// revoke the freshest tokens (a re-mint already revoked any superseded one)
|
|
238
|
+
await Promise.all([
|
|
239
|
+
revokeGitHubInstallationToken(currentGitToken),
|
|
240
|
+
revokeGitHubInstallationToken(currentMcpToken),
|
|
241
|
+
]);
|
|
242
|
+
} finally {
|
|
243
|
+
removeSignalHandler();
|
|
244
|
+
disposingRef.resolve();
|
|
245
|
+
disposingRef = undefined;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const removeSignalHandler = onExitSignal(dispose);
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
// live getter (not a captured value): a mid-run re-mint advances
|
|
253
|
+
// `currentGitToken` and revokes the prior one, so any consumer that reads
|
|
254
|
+
// `tokenRef.gitToken` per call always sees the fresh token. see #964.
|
|
255
|
+
get gitToken() {
|
|
256
|
+
return currentGitToken;
|
|
257
|
+
},
|
|
258
|
+
mcpToken: currentMcpToken,
|
|
259
|
+
...(refreshGitToken ? { refreshGitToken } : {}),
|
|
260
|
+
[Symbol.asyncDispose]: dispose,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* get the MCP token from memory.
|
|
266
|
+
* this is the token used for GitHub API calls in MCP tools.
|
|
267
|
+
*/
|
|
268
|
+
export function getGitHubInstallationToken(): string {
|
|
269
|
+
assert(mcpTokenValue, "tokens not set. call resolveTokens first.");
|
|
270
|
+
return mcpTokenValue;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export async function revokeGitHubInstallationToken(
|
|
274
|
+
token: string,
|
|
275
|
+
): Promise<void> {
|
|
276
|
+
const apiUrl = process.env.GITHUB_API_URL || "https://api.github.com";
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
await fetch(`${apiUrl}/installation/token`, {
|
|
280
|
+
method: "DELETE",
|
|
281
|
+
headers: {
|
|
282
|
+
Accept: "application/vnd.github+json",
|
|
283
|
+
Authorization: `Bearer ${token}`,
|
|
284
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
285
|
+
},
|
|
286
|
+
signal: AbortSignal.timeout(10_000),
|
|
287
|
+
});
|
|
288
|
+
log.debug("» installation token revoked");
|
|
289
|
+
} catch (error) {
|
|
290
|
+
log.info(
|
|
291
|
+
`Failed to revoke installation token: ${error instanceof Error ? error.message : String(error)}`,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-licence classification (dependency posture; the "non-permissive-tool
|
|
3
|
+
* confirmation gate").
|
|
4
|
+
*
|
|
5
|
+
* Infraweaver ORCHESTRATES external tools — it never bundles or redistributes
|
|
6
|
+
* their binaries ("be an orchestrator, not a redistributor"). This module
|
|
7
|
+
* makes the licence of every selectable tool explicit so the engine can DEFAULT
|
|
8
|
+
* to the permissively-licensed tools and treat a non-permissive one (tflint's
|
|
9
|
+
* embedded BUSL Terraform fork, HashiCorp's terraform-mcp-server) as an
|
|
10
|
+
* *informed, named opt-in* rather than something whose output is consumed
|
|
11
|
+
* silently. Pure data + pure predicates — the gate that consumes it lives in
|
|
12
|
+
* [[toolSelection]].
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** every external tool the engine can be configured to run. */
|
|
16
|
+
export type ToolId =
|
|
17
|
+
| "terraform"
|
|
18
|
+
| "tflint"
|
|
19
|
+
| "trivy"
|
|
20
|
+
| "checkov"
|
|
21
|
+
| "infracost"
|
|
22
|
+
| "gitleaks"
|
|
23
|
+
| "conftest"
|
|
24
|
+
| "terratest"
|
|
25
|
+
| "terraform_mcp"
|
|
26
|
+
| "opentofu_mcp";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Coarse licence family the gate reasons about:
|
|
30
|
+
* - `permissive` — MIT / Apache-2.0 / BSD / ISC: default-enabled.
|
|
31
|
+
* - `copyleft` — MPL / (L)GPL / AGPL: gated (explicit opt-in).
|
|
32
|
+
* - `source-available` — BUSL / SSPL / Elastic: gated (explicit opt-in).
|
|
33
|
+
*/
|
|
34
|
+
export type LicenseClass = "permissive" | "copyleft" | "source-available";
|
|
35
|
+
|
|
36
|
+
export interface ToolLicense {
|
|
37
|
+
id: ToolId;
|
|
38
|
+
/** display name for logs / PR notes. */
|
|
39
|
+
name: string;
|
|
40
|
+
/** human-facing SPDX-ish identifier (shown, never parsed). */
|
|
41
|
+
license: string;
|
|
42
|
+
class: LicenseClass;
|
|
43
|
+
/**
|
|
44
|
+
* The core Terraform CLI is the SUBSTRATE the engine cannot run without and
|
|
45
|
+
* which the operator installs themselves — invoking it is never
|
|
46
|
+
* redistribution. It is licence-classified for honesty (Terraform moved to
|
|
47
|
+
* BUSL-1.1 at v1.6) but EXEMPT from the opt-in gate, so a Terraform fixer
|
|
48
|
+
* always has Terraform.
|
|
49
|
+
*/
|
|
50
|
+
required?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The single source of truth for what each tool is licensed under. Verified
|
|
55
|
+
* against the "third-party dependency posture" note (June 2026). Keep in sync
|
|
56
|
+
* when a tool's licence changes (e.g. a vendor relicensing event).
|
|
57
|
+
*/
|
|
58
|
+
export const TOOL_LICENSES: Readonly<Record<ToolId, ToolLicense>> = {
|
|
59
|
+
terraform: {
|
|
60
|
+
id: "terraform",
|
|
61
|
+
name: "Terraform CLI",
|
|
62
|
+
license: "BUSL-1.1",
|
|
63
|
+
class: "source-available",
|
|
64
|
+
required: true,
|
|
65
|
+
},
|
|
66
|
+
// tflint is MPL-2.0, but it embeds a BUSL Terraform fork — flagged as the
|
|
67
|
+
// canonical "never bundle/redistribute; invoke as an external process" case.
|
|
68
|
+
tflint: {
|
|
69
|
+
id: "tflint",
|
|
70
|
+
name: "TFLint",
|
|
71
|
+
license: "MPL-2.0",
|
|
72
|
+
class: "copyleft",
|
|
73
|
+
},
|
|
74
|
+
trivy: {
|
|
75
|
+
id: "trivy",
|
|
76
|
+
name: "Trivy",
|
|
77
|
+
license: "Apache-2.0",
|
|
78
|
+
class: "permissive",
|
|
79
|
+
},
|
|
80
|
+
checkov: {
|
|
81
|
+
id: "checkov",
|
|
82
|
+
name: "Checkov",
|
|
83
|
+
license: "Apache-2.0",
|
|
84
|
+
class: "permissive",
|
|
85
|
+
},
|
|
86
|
+
infracost: {
|
|
87
|
+
id: "infracost",
|
|
88
|
+
name: "Infracost CLI",
|
|
89
|
+
license: "Apache-2.0",
|
|
90
|
+
class: "permissive",
|
|
91
|
+
},
|
|
92
|
+
gitleaks: {
|
|
93
|
+
id: "gitleaks",
|
|
94
|
+
name: "gitleaks",
|
|
95
|
+
license: "MIT",
|
|
96
|
+
class: "permissive",
|
|
97
|
+
},
|
|
98
|
+
conftest: {
|
|
99
|
+
id: "conftest",
|
|
100
|
+
name: "Conftest (OPA)",
|
|
101
|
+
license: "Apache-2.0",
|
|
102
|
+
class: "permissive",
|
|
103
|
+
},
|
|
104
|
+
terratest: {
|
|
105
|
+
id: "terratest",
|
|
106
|
+
name: "Terratest",
|
|
107
|
+
license: "Apache-2.0",
|
|
108
|
+
class: "permissive",
|
|
109
|
+
},
|
|
110
|
+
// HashiCorp's terraform-mcp-server, run as a Docker image — a redistribution-
|
|
111
|
+
// sensitive HashiCorp surface, so it is gated like tflint.
|
|
112
|
+
terraform_mcp: {
|
|
113
|
+
id: "terraform_mcp",
|
|
114
|
+
name: "terraform-mcp-server",
|
|
115
|
+
license: "MPL-2.0",
|
|
116
|
+
class: "copyleft",
|
|
117
|
+
},
|
|
118
|
+
// The OpenTofu project's registry MCP server — the permissively-preferred
|
|
119
|
+
// sibling to terraform-mcp-server (OpenTofu is the MPL fork; Terraform is BUSL).
|
|
120
|
+
// MPL-2.0 → gated as an explicit opt-in, same class as terraform_mcp. Reached
|
|
121
|
+
// as OpenTofu's own hosted endpoint (public registry data, no credentials), so
|
|
122
|
+
// there's no binary to redistribute — but kept behind the opt-in gate for
|
|
123
|
+
// parity and because it's an external network surface the operator chooses.
|
|
124
|
+
opentofu_mcp: {
|
|
125
|
+
id: "opentofu_mcp",
|
|
126
|
+
name: "opentofu-mcp-server",
|
|
127
|
+
license: "MPL-2.0",
|
|
128
|
+
class: "copyleft",
|
|
129
|
+
},
|
|
130
|
+
} as const;
|
|
131
|
+
|
|
132
|
+
export const ALL_TOOL_IDS = Object.keys(TOOL_LICENSES) as ToolId[];
|
|
133
|
+
|
|
134
|
+
/** a permissively-licensed tool can be enabled by default; anything else needs
|
|
135
|
+
* an explicit, licence-named opt-in. */
|
|
136
|
+
export function isPermissive(c: LicenseClass): boolean {
|
|
137
|
+
return c === "permissive";
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* A tool whose output must NOT be consumed without an explicit, licence-named
|
|
142
|
+
* opt-in: non-permissive AND not the required substrate. This is the predicate
|
|
143
|
+
* the confirmation gate is built on.
|
|
144
|
+
*/
|
|
145
|
+
export function isLicenseGated(id: ToolId): boolean {
|
|
146
|
+
const t = TOOL_LICENSES[id];
|
|
147
|
+
return !t.required && !isPermissive(t.class);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** every tool currently behind the licence gate (for docs / reporting). */
|
|
151
|
+
export const LICENSE_GATED_TOOLS: ToolId[] =
|
|
152
|
+
ALL_TOOL_IDS.filter(isLicenseGated);
|