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
package/src/utils/cli.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
|
|
8
|
+
// re-export logging utilities for backward compatibility
|
|
9
|
+
export {
|
|
10
|
+
formatIndentedField,
|
|
11
|
+
formatJsonValue,
|
|
12
|
+
formatUsageSummary,
|
|
13
|
+
log,
|
|
14
|
+
writeSummary,
|
|
15
|
+
} from "#app/utils/log";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Finds a CLI executable path by checking if it's installed globally
|
|
19
|
+
* @param name The name of the CLI executable to find
|
|
20
|
+
* @returns The path to the CLI executable, or null if not found
|
|
21
|
+
*/
|
|
22
|
+
export function findCliPath(name: string): string | null {
|
|
23
|
+
// `which` is POSIX-only. The action always runs on Linux, but this repo is
|
|
24
|
+
// developed on Windows, where `which` does not exist and the lookup fails
|
|
25
|
+
// silently as "not installed" — use `where` there. `where` can print several
|
|
26
|
+
// matches, one per line, so take the first.
|
|
27
|
+
const isWindows = process.platform === "win32";
|
|
28
|
+
const result = spawnSync(isWindows ? "where" : "which", [name], { encoding: "utf-8" });
|
|
29
|
+
if (result.status === 0 && result.stdout) {
|
|
30
|
+
const cliPath = result.stdout.split(/\r?\n/)[0]?.trim();
|
|
31
|
+
if (cliPath && existsSync(cliPath)) {
|
|
32
|
+
return cliPath;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type ApiFetchOptions, apiFetch } from "#app/utils/apiFetch";
|
|
2
|
+
import { DEFAULT_CLOUD_TIMEOUT_MS } from "#app/utils/cloudFetchCore";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Thin typed seam over `apiFetch` for the Infraweaver Cloud routes.
|
|
6
|
+
*
|
|
7
|
+
* Consumers previously hand-built each request: the `Authorization: Bearer`
|
|
8
|
+
* header (with `Authorization`/`authorization` casing drift), JSON serialization
|
|
9
|
+
* + content-type, and the timeout were re-inlined at every call site. This owns
|
|
10
|
+
* those three pieces once and returns the raw `Response`, so each caller keeps
|
|
11
|
+
* its own status/JSON/retry handling.
|
|
12
|
+
*
|
|
13
|
+
* The stdlib-only post hook (`entryPost.ts`) intentionally does NOT use this —
|
|
14
|
+
* it calls `cloudFetchCore` directly to stay free of node_modules imports.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** The one home for the bearer header — the org JWT (`apiToken`), a GitHub App
|
|
18
|
+
* installation token, or an OIDC id-token, depending on the route. */
|
|
19
|
+
export function bearer(credential: string): { Authorization: string } {
|
|
20
|
+
return { Authorization: `Bearer ${credential}` };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type CloudRequest = {
|
|
24
|
+
path: string;
|
|
25
|
+
method?: string | undefined;
|
|
26
|
+
/** bearer token for the `Authorization` header; omit for an unauthenticated call. */
|
|
27
|
+
credential?: string | undefined;
|
|
28
|
+
/** extra headers beyond `Authorization` (e.g. `X-GitHub-OIDC-Token`). */
|
|
29
|
+
headers?: Record<string, string> | undefined;
|
|
30
|
+
/** a JSON body — serialized here, with `content-type: application/json` set. */
|
|
31
|
+
json?: unknown;
|
|
32
|
+
/** a pre-serialized body (used when the body is not JSON). */
|
|
33
|
+
body?: string | undefined;
|
|
34
|
+
/** request timeout in ms; defaults to the shared cloud ceiling. */
|
|
35
|
+
timeoutMs?: number | undefined;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Issue an authenticated Cloud API request; returns the raw `Response`. */
|
|
39
|
+
export async function cloudRequest(req: CloudRequest): Promise<Response> {
|
|
40
|
+
const headers: Record<string, string> = { ...req.headers };
|
|
41
|
+
if (req.credential) Object.assign(headers, bearer(req.credential));
|
|
42
|
+
|
|
43
|
+
let body = req.body;
|
|
44
|
+
if (req.json !== undefined) {
|
|
45
|
+
body = JSON.stringify(req.json);
|
|
46
|
+
headers["content-type"] = "application/json";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const options: ApiFetchOptions = {
|
|
50
|
+
path: req.path,
|
|
51
|
+
method: req.method,
|
|
52
|
+
headers,
|
|
53
|
+
body,
|
|
54
|
+
signal: AbortSignal.timeout(req.timeoutMs ?? DEFAULT_CLOUD_TIMEOUT_MS),
|
|
55
|
+
};
|
|
56
|
+
return apiFetch(options);
|
|
57
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdlib-only Infraweaver API fetch core (no node_modules) — shared by
|
|
3
|
+
* `apiFetch` (the main runtime wrapper) and `entryPost.ts` (the GHA `post:`
|
|
4
|
+
* hook, which runs directly from the action checkout without node_modules;
|
|
5
|
+
* see entryPost.stdlibOnly.test.ts). Owns everything the two callers
|
|
6
|
+
* previously kept in lockstep by hand: the default API host, the
|
|
7
|
+
* bearer-credential host allowlist, the Vercel bypass secret, and the
|
|
8
|
+
* default request timeout.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { DEFAULT_API_URL, PRIMARY_DOMAIN } from "#app/brand";
|
|
12
|
+
|
|
13
|
+
export { DEFAULT_API_URL };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Ceiling for Cloud API calls that don't bring their own AbortSignal — a
|
|
17
|
+
* stalled backend must never hang the action (or its post hook) indefinitely.
|
|
18
|
+
* Callers with tighter or looser needs pass an explicit `signal`.
|
|
19
|
+
*/
|
|
20
|
+
export const DEFAULT_CLOUD_TIMEOUT_MS = 30_000;
|
|
21
|
+
|
|
22
|
+
function isLocalUrl(url: URL): boolean {
|
|
23
|
+
return url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Operator-pinned extra hosts (comma-separated, exact hostnames) for a
|
|
28
|
+
* self-hosted / alternate Cloud deployment — e.g. a Railway or custom-domain
|
|
29
|
+
* backend that isn't under `*.infraweaver.dev`. This preserves the security
|
|
30
|
+
* property: the operator must *explicitly name the exact host* in
|
|
31
|
+
* `API_ALLOWED_HOSTS` before any bearer credential is sent there; it only widens
|
|
32
|
+
* the allowlist for hosts the operator already controls and configured.
|
|
33
|
+
*/
|
|
34
|
+
function configuredAllowedHosts(): string[] {
|
|
35
|
+
return (process.env.API_ALLOWED_HOSTS ?? "")
|
|
36
|
+
.split(",")
|
|
37
|
+
.map((h) => h.trim().toLowerCase())
|
|
38
|
+
.filter(Boolean);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The Infraweaver JWT (apiToken) and codex write-back secret travel as
|
|
42
|
+
// `Authorization: Bearer` to this host. Pin it to a known allowlist so a
|
|
43
|
+
// misconfigured/hostile `API_URL` can't redirect those bearer credentials to
|
|
44
|
+
// an attacker-controlled host (https alone is not enough — it must be the right
|
|
45
|
+
// host). localhost stays exempt for local dev; self-hosted deployments add their
|
|
46
|
+
// exact host via `API_ALLOWED_HOSTS`.
|
|
47
|
+
function isAllowedApiHost(url: URL): boolean {
|
|
48
|
+
if (isLocalUrl(url)) return true;
|
|
49
|
+
const host = url.hostname.toLowerCase();
|
|
50
|
+
if (host === PRIMARY_DOMAIN || host.endsWith(`.${PRIMARY_DOMAIN}`))
|
|
51
|
+
return true;
|
|
52
|
+
return configuredAllowedHosts().includes(host);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* resolve the Infraweaver API base URL.
|
|
57
|
+
*
|
|
58
|
+
* in the action: API_URL is not explicitly set, so this falls back to
|
|
59
|
+
* DEFAULT_API_URL. in local dev: API_URL=http://localhost:3000 (from .env).
|
|
60
|
+
*
|
|
61
|
+
* enforces https:// for non-local URLs to prevent cleartext credential
|
|
62
|
+
* transmission.
|
|
63
|
+
*/
|
|
64
|
+
export function resolveApiUrl(): string {
|
|
65
|
+
const raw = process.env.API_URL || DEFAULT_API_URL;
|
|
66
|
+
const parsed = new URL(raw);
|
|
67
|
+
|
|
68
|
+
if (parsed.protocol !== "https:" && !isLocalUrl(parsed)) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`API_URL must use https:// (got ${parsed.protocol}). only localhost is exempt.`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!isAllowedApiHost(parsed)) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`API_URL host '${parsed.hostname}' is not allowed. ` +
|
|
77
|
+
`Bearer credentials are only sent to ${PRIMARY_DOMAIN} (or a *.${PRIMARY_DOMAIN} host), localhost, ` +
|
|
78
|
+
`or a host you explicitly pin in API_ALLOWED_HOSTS.`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return raw;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type CloudFetchOptions = {
|
|
86
|
+
path: string;
|
|
87
|
+
method?: string | undefined;
|
|
88
|
+
headers?: Record<string, string> | undefined;
|
|
89
|
+
body?: string | undefined;
|
|
90
|
+
signal?: AbortSignal | undefined;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* fetch against the Infraweaver API with Vercel deployment protection bypass.
|
|
95
|
+
*
|
|
96
|
+
* adds the bypass secret as BOTH a query parameter and a header for maximum
|
|
97
|
+
* reliability. the server-side forwarding code uses query params, and the
|
|
98
|
+
* Vercel docs say both work, so we do both as belt-and-suspenders.
|
|
99
|
+
*/
|
|
100
|
+
export async function cloudFetch(
|
|
101
|
+
options: CloudFetchOptions,
|
|
102
|
+
): Promise<Response> {
|
|
103
|
+
const url = new URL(options.path, resolveApiUrl());
|
|
104
|
+
|
|
105
|
+
const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
106
|
+
if (bypassSecret) {
|
|
107
|
+
url.searchParams.set("x-vercel-protection-bypass", bypassSecret);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const headers: Record<string, string> = {
|
|
111
|
+
...options.headers,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// also add as header for belt-and-suspenders
|
|
115
|
+
if (bypassSecret) {
|
|
116
|
+
headers["x-vercel-protection-bypass"] = bypassSecret;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// never send Content-Type on body-less requests. empirically, Vercel's
|
|
120
|
+
// Next.js lambda adapter (Next 16.1.x) throws `SyntaxError: Unexpected
|
|
121
|
+
// end of data` before delegating to the route handler — returning a 500 —
|
|
122
|
+
// when Content-Type is set but no body is present. exact mechanism is
|
|
123
|
+
// unverified (minified runtime frame), but Content-Type on a body-less
|
|
124
|
+
// request has no defined semantics per RFC 9110 §8.3 anyway. see #692.
|
|
125
|
+
if (!options.body) {
|
|
126
|
+
for (const key of Object.keys(headers)) {
|
|
127
|
+
if (key.toLowerCase() === "content-type") delete headers[key];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const init: RequestInit = {
|
|
132
|
+
method: options.method ?? "GET",
|
|
133
|
+
headers,
|
|
134
|
+
signal: options.signal ?? AbortSignal.timeout(DEFAULT_CLOUD_TIMEOUT_MS),
|
|
135
|
+
};
|
|
136
|
+
if (options.body) init.body = options.body;
|
|
137
|
+
|
|
138
|
+
return fetch(url.toString(), init);
|
|
139
|
+
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import * as core from "@actions/core";
|
|
2
|
+
import { PRODUCT_NAME } from "#app/brand";
|
|
3
|
+
import { CROSSWALK_VERSION, packControlsForConcern } from "#app/mcp/crosswalk";
|
|
4
|
+
import { cyberEssentialsScore } from "#app/mcp/cyberEssentials";
|
|
5
|
+
import { ruleDocUrl } from "#app/mcp/terraform/decisions";
|
|
6
|
+
import { dedupeCaptures } from "#app/mcp/terraform/fixMemory";
|
|
7
|
+
import { riskScore } from "#app/mcp/terraform/risk";
|
|
8
|
+
import {
|
|
9
|
+
scanSessionOf,
|
|
10
|
+
upgradeStatementOf,
|
|
11
|
+
} from "#app/mcp/terraform/scanSession";
|
|
12
|
+
import { captureProvenTransforms } from "#app/mcp/terraform/transformPacks";
|
|
13
|
+
import { type Concern, concernKeyOf } from "#app/mcp/terraform/types";
|
|
14
|
+
|
|
15
|
+
// The CE score is computed in the shared `cyberEssentials` module so the Assess
|
|
16
|
+
// report and this Cloud report report the identical number; re-exported here to
|
|
17
|
+
// keep this module's existing public surface (and the report test) intact.
|
|
18
|
+
export { cyberEssentialsScore } from "#app/mcp/cyberEssentials";
|
|
19
|
+
|
|
20
|
+
import type { ToolState } from "#app/toolState";
|
|
21
|
+
import { cloudOidcAudience, isBackendConfigured } from "#app/utils/apiUrl";
|
|
22
|
+
import { log } from "#app/utils/cli";
|
|
23
|
+
import { cloudRequest } from "#app/utils/cloudClient";
|
|
24
|
+
|
|
25
|
+
// The OIDC audience the tokenless path requests; resolved via `cloudOidcAudience()` so it
|
|
26
|
+
// matches the Cloud's `expectedOidcAudience()` and stays operator-overridable from a
|
|
27
|
+
// single place. Re-exported to preserve this module's public surface.
|
|
28
|
+
export { cloudOidcAudience };
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the credential to authenticate the Cloud report with, in order of
|
|
32
|
+
* preference:
|
|
33
|
+
* 1. An explicit `tmnd_` org token (the `api_token` input).
|
|
34
|
+
* 2. A GitHub Actions OIDC token — the tokenless GitHub App path. Requires
|
|
35
|
+
* `permissions: id-token: write`; the App installation is the consent gate
|
|
36
|
+
* Cloud checks. Returns undefined when neither is available (pure OSS run).
|
|
37
|
+
*/
|
|
38
|
+
export async function resolveCloudCredential(
|
|
39
|
+
apiToken: string | undefined,
|
|
40
|
+
): Promise<string | undefined> {
|
|
41
|
+
if (apiToken) return apiToken;
|
|
42
|
+
try {
|
|
43
|
+
const oidc = await core.getIDToken(cloudOidcAudience());
|
|
44
|
+
return oidc || undefined;
|
|
45
|
+
} catch {
|
|
46
|
+
// No `id-token: write` permission, or not running in GitHub Actions — the
|
|
47
|
+
// run stays pure OSS and reports nothing.
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Ingest seam — POST a finished run's findings/posture to Infraweaver Cloud
|
|
54
|
+
* so the dashboard reflects this repo. This is the explicit ORG-TOKEN path: the
|
|
55
|
+
* caller passes the `tmnd_` token (the `api_token` input); the tokenless GitHub
|
|
56
|
+
* App path reports differently and standalone OSS runs don't report at all.
|
|
57
|
+
*
|
|
58
|
+
* The wire shape matches infraweaver-ui `reportSchema`
|
|
59
|
+
* (src/features/api/schemas.ts) — kept in sync by hand across the action ⇄ cloud
|
|
60
|
+
* JSON boundary (the two codebases can't share types).
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
export type CloudPosture = "clean" | "advisory" | "action-required";
|
|
64
|
+
|
|
65
|
+
// The Cloud `run_mode` enum. The engine's mode NAME is title-cased ("Remediate"),
|
|
66
|
+
// so it must be lowered to the enum value or the server's run insert rejects it.
|
|
67
|
+
// NOTE: "generate" was removed with infra-generation (2026-06-22) — the engine can no
|
|
68
|
+
// longer select that mode, so it's dropped here too. "review" stays: the generic
|
|
69
|
+
// PR-review surface is still reachable (IncrementalReview / select_mode). "refactor"
|
|
70
|
+
// is the behaviour-preserving modularise verb (its proof rides in run.refactor below).
|
|
71
|
+
// The 2026-06-27 CI verbs (PolicyGate/UpdateDependencies/ModernizeDeprecated/
|
|
72
|
+
// CostOptimization) and the read-only posture verbs DriftDetect/ComplianceAudit
|
|
73
|
+
// lower 1:1 onto matching Cloud enum values — apply the Cloud run_mode enum +
|
|
74
|
+
// reportSchema additions BEFORE deploying this, or the run insert rejects.
|
|
75
|
+
// (TerraformCodeReview is intentionally absent: like IncrementalReview it reports
|
|
76
|
+
// as undefined → the server default, since it is a PR-review surface not a verb.)
|
|
77
|
+
const RUN_MODES = new Set([
|
|
78
|
+
"remediate",
|
|
79
|
+
"assess",
|
|
80
|
+
"review",
|
|
81
|
+
"refactor",
|
|
82
|
+
"remediate-refactor",
|
|
83
|
+
"policygate",
|
|
84
|
+
"updatedependencies",
|
|
85
|
+
"modernizedeprecated",
|
|
86
|
+
"costoptimization",
|
|
87
|
+
"driftdetect",
|
|
88
|
+
"complianceaudit",
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
// engine mode names that don't lower-case 1:1 onto the Cloud enum. The combined
|
|
92
|
+
// verb "RemediateAndRefactor" reports as "remediate-refactor" (its refactor proof
|
|
93
|
+
// still rides in run.refactor below, driven by toolState — independent of mode).
|
|
94
|
+
const RUN_MODE_ALIASES: Readonly<Record<string, string>> = {
|
|
95
|
+
remediateandrefactor: "remediate-refactor",
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** Posture from the open concern set — any critical/high ⇒ action-required. */
|
|
99
|
+
export function derivePosture(concerns: Concern[]): CloudPosture {
|
|
100
|
+
const open = concerns.filter((c) => !c.suppression);
|
|
101
|
+
if (open.length === 0) return "clean";
|
|
102
|
+
return open.some((c) => c.severity === "critical" || c.severity === "high")
|
|
103
|
+
? "action-required"
|
|
104
|
+
: "advisory";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Map the engine mode name to the Cloud run_mode enum; undefined for an
|
|
108
|
+
* unknown/custom mode so the server applies its own default. */
|
|
109
|
+
function normalizeMode(mode: string | undefined): string | undefined {
|
|
110
|
+
if (!mode) return undefined;
|
|
111
|
+
const m = mode.toLowerCase();
|
|
112
|
+
const aliased = RUN_MODE_ALIASES[m] ?? m;
|
|
113
|
+
return RUN_MODES.has(aliased) ? aliased : undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** the Cloud-bound refactor (modularise) verdict, mirrors infraweaver-ui
|
|
117
|
+
* reportSchema.run.refactor.equivalence_verdict. */
|
|
118
|
+
export type RefactorVerdict =
|
|
119
|
+
| "equivalence-proven"
|
|
120
|
+
| "equivalence-failed"
|
|
121
|
+
| "proposed-unproven";
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The refactor (modularise) proof for the Cloud report, or undefined on a
|
|
125
|
+
* non-refactor run (so the wire omits it). Built from the recorded keys-free
|
|
126
|
+
* EQUIVALENCE proof when one ran (b.1/b.2/b.3), else the b.4 `proposed — unproven`
|
|
127
|
+
* marker — an equivalence proof always wins, so a change is never both. Asserts
|
|
128
|
+
* only what the engine proved: a failed/absent proof is reported as such, never
|
|
129
|
+
* upgraded. Pure over `toolState`. Mirrors infraweaver-ui reportSchema.run.refactor.
|
|
130
|
+
*/
|
|
131
|
+
export function buildRefactorReport(toolState: ToolState):
|
|
132
|
+
| {
|
|
133
|
+
equivalence_verdict: RefactorVerdict;
|
|
134
|
+
proposed_unproven: boolean;
|
|
135
|
+
moved_block_count: number;
|
|
136
|
+
uncovered_moves: number;
|
|
137
|
+
}
|
|
138
|
+
| undefined {
|
|
139
|
+
const session = scanSessionOf(toolState);
|
|
140
|
+
const eq = session.refactorEquivalence;
|
|
141
|
+
const proposedUnproven = session.refactorProposedUnproven === true;
|
|
142
|
+
if (!eq && !proposedUnproven) return undefined;
|
|
143
|
+
const verdict: RefactorVerdict = eq
|
|
144
|
+
? eq.equivalent
|
|
145
|
+
? "equivalence-proven"
|
|
146
|
+
: "equivalence-failed"
|
|
147
|
+
: "proposed-unproven";
|
|
148
|
+
return {
|
|
149
|
+
equivalence_verdict: verdict,
|
|
150
|
+
proposed_unproven: verdict === "proposed-unproven",
|
|
151
|
+
moved_block_count: eq?.moves_detected ?? 0,
|
|
152
|
+
uncovered_moves: eq?.uncovered_moves.length ?? 0,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** A `remediation_hint` that is just a URL (checkov's `guideline`, tflint's rule
|
|
157
|
+
* link) is the rule's docs page, not guidance — and it already surfaces as `doc_url`
|
|
158
|
+
* (ruleDocUrl reads the URL-valued hint). Emitting it as the hint too makes the
|
|
159
|
+
* dashboard render a bare URL where actionable text belongs, so drop it here. A real
|
|
160
|
+
* text hint (trivy's `Resolution`, the fmt hint) is kept. */
|
|
161
|
+
function textualHint(hint: string | null | undefined): string | undefined {
|
|
162
|
+
const trimmed = hint?.trim();
|
|
163
|
+
if (!trimmed || /^https?:\/\//i.test(trimmed)) return undefined;
|
|
164
|
+
return trimmed;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Build the `/report` request body from the finished run's tool state. Exported
|
|
168
|
+
* for tests; pure (reads only `toolState` + GitHub env). */
|
|
169
|
+
export function buildReportBody(toolState: ToolState) {
|
|
170
|
+
const concerns = scanSessionOf(toolState).lastScanConcerns ?? [];
|
|
171
|
+
const findings = concerns.slice(0, 2000).map((c) => ({
|
|
172
|
+
concern_id: c.id,
|
|
173
|
+
concern_key: concernKeyOf(c),
|
|
174
|
+
source: c.source,
|
|
175
|
+
rule_id: c.rule_id,
|
|
176
|
+
severity: c.severity,
|
|
177
|
+
category: c.category,
|
|
178
|
+
evidence: c.evidence,
|
|
179
|
+
file: c.location.file,
|
|
180
|
+
line: c.location.line ?? undefined,
|
|
181
|
+
remediation_hint: textualHint(c.remediation_hint),
|
|
182
|
+
// The offending source line(s) the scanner flagged + the rule's canonical
|
|
183
|
+
// docs page — so the finding detail shows the exact code and a working
|
|
184
|
+
// "Open rule docs" link instead of placeholders.
|
|
185
|
+
code_snippet: c.code_snippet ?? undefined,
|
|
186
|
+
doc_url: ruleDocUrl(c) ?? undefined,
|
|
187
|
+
// The maintained-pack control ids this concern evidences (CE / ISO 27001 /
|
|
188
|
+
// NCSC), the engine⇄Cloud join key the dashboard's per-control verdicts and
|
|
189
|
+
// required-control gate key on (empty array = no mapping). See
|
|
190
|
+
// crosswalk.packControlsForConcern — hand-synced with infraweaver-ui pack.ts.
|
|
191
|
+
compliance: packControlsForConcern(c),
|
|
192
|
+
// 2b-viii: the composite risk score (CVSS anchor + exposure + fix-with-proof
|
|
193
|
+
// boost) so the Cloud dashboard can surface the "top N that matter".
|
|
194
|
+
risk_score: riskScore(c),
|
|
195
|
+
...(c.suppression
|
|
196
|
+
? {
|
|
197
|
+
suppressed: true as const,
|
|
198
|
+
suppression_reason: c.suppression.reason,
|
|
199
|
+
suppression_source: c.suppression.source,
|
|
200
|
+
suppression_expires: c.suppression.expires ?? undefined,
|
|
201
|
+
}
|
|
202
|
+
: {}),
|
|
203
|
+
}));
|
|
204
|
+
|
|
205
|
+
const runNumber = Number(process.env.GITHUB_RUN_NUMBER);
|
|
206
|
+
// The refactor (modularise) proof, present only on a Refactor run — keeps the
|
|
207
|
+
// wire clean (and the server's run.refactor optional) on every other mode.
|
|
208
|
+
const refactor = buildRefactorReport(toolState);
|
|
209
|
+
// §5.12 the proven-fix patterns captured this run (a finding-type that went
|
|
210
|
+
// ✗→✓). Only present when fix_memory is on (capture is gated in verify), and
|
|
211
|
+
// deduped to one per finding-type. Cloud upserts these into the org library.
|
|
212
|
+
const provenFixes = dedupeCaptures(
|
|
213
|
+
scanSessionOf(toolState).provenFixCaptures ?? [],
|
|
214
|
+
).map((p) => ({
|
|
215
|
+
finding_type: p.finding_type,
|
|
216
|
+
source: p.source ?? undefined,
|
|
217
|
+
canonical_class: p.canonical_class ?? undefined,
|
|
218
|
+
category: p.category,
|
|
219
|
+
title: p.title,
|
|
220
|
+
description: p.description ?? undefined,
|
|
221
|
+
remediation_hint: p.remediation_hint ?? undefined,
|
|
222
|
+
before_example: p.before_example ?? undefined,
|
|
223
|
+
}));
|
|
224
|
+
// TC-2.2 the provider-upgrade transforms this run's PLAN proved out. Computed
|
|
225
|
+
// from the same statement the signed evidence carries, so the org library and
|
|
226
|
+
// the signed artefact can never disagree about what was proven. Empty unless a
|
|
227
|
+
// pack applied AND the plan came back clean — a transform that needed a human
|
|
228
|
+
// is deliberately excluded, since a human intervening is not evidence that the
|
|
229
|
+
// transform is safe unattended, which is the only claim the counter makes.
|
|
230
|
+
const session = scanSessionOf(toolState);
|
|
231
|
+
const provenTransforms = captureProvenTransforms(
|
|
232
|
+
upgradeStatementOf(session),
|
|
233
|
+
session.transformMatches ?? [],
|
|
234
|
+
);
|
|
235
|
+
return {
|
|
236
|
+
commit_sha: process.env.GITHUB_SHA || undefined,
|
|
237
|
+
posture: derivePosture(concerns),
|
|
238
|
+
// Cyber Essentials posture (0–100) — what the dashboard's "CE SCORE" shows.
|
|
239
|
+
ce_score: cyberEssentialsScore(concerns),
|
|
240
|
+
prs_open: toolState.remediationPrsOpened,
|
|
241
|
+
findings,
|
|
242
|
+
...(provenFixes.length ? { proven_fixes: provenFixes } : {}),
|
|
243
|
+
...(provenTransforms.length ? { proven_transforms: provenTransforms } : {}),
|
|
244
|
+
run: {
|
|
245
|
+
run_number: Number.isInteger(runNumber) ? runNumber : undefined,
|
|
246
|
+
// The CI run's native id — the same value patchWorkflowRunFields PATCHes
|
|
247
|
+
// /workflow-run/{id} with, so Cloud can attach the late usage/cost telemetry
|
|
248
|
+
// to the run row this report creates.
|
|
249
|
+
external_run_id: process.env.GITHUB_RUN_ID || undefined,
|
|
250
|
+
mode: normalizeMode(toolState.selectedMode),
|
|
251
|
+
trigger: process.env.GITHUB_EVENT_NAME || undefined,
|
|
252
|
+
status: "success" as const,
|
|
253
|
+
// The engine crosswalk revision each finding's `compliance[]` was computed
|
|
254
|
+
// against — stamped so a historical run's verdicts stay reproducible after
|
|
255
|
+
// the rule-pack moves (Cloud stamps its own pack version at ingest).
|
|
256
|
+
engine_crosswalk_version: CROSSWALK_VERSION,
|
|
257
|
+
...(refactor ? { refactor } : {}),
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Best-effort report of this run to Infraweaver Cloud. No-ops (silently) when:
|
|
264
|
+
* - `API_URL` unset — standalone BYOK; don't POST into the marketing host.
|
|
265
|
+
* - no scan ran (`lastScanConcerns` undefined) — nothing to report.
|
|
266
|
+
* - no credential — neither an `api_token` nor a mintable GitHub Actions OIDC
|
|
267
|
+
* token (no `id-token: write`); the run stays pure OSS.
|
|
268
|
+
* A network/Cloud failure is logged at debug and swallowed — reporting must
|
|
269
|
+
* never flip an already-successful run outcome.
|
|
270
|
+
*/
|
|
271
|
+
export async function reportToCloud(input: {
|
|
272
|
+
toolState: ToolState;
|
|
273
|
+
repo: { owner: string; name: string };
|
|
274
|
+
apiToken: string | undefined;
|
|
275
|
+
}): Promise<void> {
|
|
276
|
+
if (!isBackendConfigured()) return;
|
|
277
|
+
if (!scanSessionOf(input.toolState).lastScanConcerns) {
|
|
278
|
+
log.debug("cloud report skipped: no scan concerns recorded this run");
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Prefer the explicit org token; otherwise fall back to a tokenless OIDC token.
|
|
283
|
+
const credential = await resolveCloudCredential(input.apiToken);
|
|
284
|
+
if (!credential) {
|
|
285
|
+
log.debug(
|
|
286
|
+
"cloud report skipped: no credential (api_token absent + OIDC unavailable)",
|
|
287
|
+
);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
// Inside the try: a throw here (e.g. malformed concern) must surface as a
|
|
293
|
+
// visible warning, not unwind into finalizeSuccessRun's catch and vanish.
|
|
294
|
+
const body = buildReportBody(input.toolState);
|
|
295
|
+
const response = await cloudRequest({
|
|
296
|
+
path: `/api/repo/${input.repo.owner}/${input.repo.name}/report`,
|
|
297
|
+
method: "POST",
|
|
298
|
+
credential,
|
|
299
|
+
json: body,
|
|
300
|
+
});
|
|
301
|
+
if (!response.ok) {
|
|
302
|
+
// Promoted debug → warning with the response body: a dropped report is the
|
|
303
|
+
// dashboard silently going stale, which is worth a CI line to diagnose.
|
|
304
|
+
const detail = await response.text().catch(() => "(no body)");
|
|
305
|
+
log.warning(`cloud report rejected (${response.status}): ${detail}`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
log.info(
|
|
309
|
+
`» reported ${body.findings.length} finding(s) to ${PRODUCT_NAME} Cloud`,
|
|
310
|
+
);
|
|
311
|
+
} catch (error) {
|
|
312
|
+
log.warning(
|
|
313
|
+
`cloud report failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|