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,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `*.tfquery.hcl` — Terraform 1.14 query files, read as DISCOVERY INPUT ONLY.
|
|
3
|
+
*
|
|
4
|
+
* A query file holds `list` blocks that ask a provider "what already exists out
|
|
5
|
+
* there?", and `terraform query -generate-config-out` turns the answers into
|
|
6
|
+
* importable configuration. That makes it a genuinely useful inventory signal:
|
|
7
|
+
* it tells you which parts of an estate the team knows are unmanaged and intends
|
|
8
|
+
* to adopt, which is exactly the coverage question a compliance report should be
|
|
9
|
+
* able to speak to.
|
|
10
|
+
*
|
|
11
|
+
* THE HARD RULE, AND WHY IT IS ARCHITECTURAL RATHER THAN A CONVENTION.
|
|
12
|
+
* Query results must never reach remediation. A `list` block describes resources
|
|
13
|
+
* that are NOT under Terraform management, so "fixing" one would mean writing
|
|
14
|
+
* configuration for infrastructure nobody has adopted yet — the engine would be
|
|
15
|
+
* inventing managed resources out of a search result, and the ✗→✓ proof machinery
|
|
16
|
+
* has nothing to prove against because there is no prior finding to clear.
|
|
17
|
+
*
|
|
18
|
+
* Three independent things enforce that, so no single mistake is enough:
|
|
19
|
+
* 1. this module produces an INVENTORY type, not `Concern[]`. There is no code
|
|
20
|
+
* path from a query file to a finding, because the function that would do it
|
|
21
|
+
* does not exist;
|
|
22
|
+
* 2. `.tfquery.hcl` is not a `.tf`, so `isTerraformFile` is false and
|
|
23
|
+
* `buildConcernResult` — the single chokepoint every fixer-feeding surface
|
|
24
|
+
* routes through — would drop such a concern even if one were fabricated;
|
|
25
|
+
* 3. `.tfquery.hcl` matches neither of the `DEFAULT_ALLOWED_PATHS` globs
|
|
26
|
+
* (`*.tf`, `*.tfvars`), so the push guardrail refuses to write one.
|
|
27
|
+
*
|
|
28
|
+
* `tfquery.test.ts` asserts all three, so the rule survives a future refactor
|
|
29
|
+
* that forgets why it existed.
|
|
30
|
+
*
|
|
31
|
+
* Pure except `collectQueryInventory`, which reads the tree.
|
|
32
|
+
*/
|
|
33
|
+
import { readFileSync } from "node:fs";
|
|
34
|
+
import { join } from "node:path";
|
|
35
|
+
import { type } from "arktype";
|
|
36
|
+
import type { LocalToolContext } from "#app/mcp/localContext";
|
|
37
|
+
import { walkFilesBySuffix } from "#app/mcp/modules";
|
|
38
|
+
import { execute, tool, toolOk } from "#app/mcp/shared";
|
|
39
|
+
import { parseBlocks, stripTrailingComment, topLevelAssignments } from "#app/mcp/terraform/hcl";
|
|
40
|
+
import { log } from "#app/utils/cli";
|
|
41
|
+
|
|
42
|
+
/** The extension Terraform reserves for query configuration. */
|
|
43
|
+
export const TFQUERY_SUFFIX = ".tfquery.hcl";
|
|
44
|
+
|
|
45
|
+
/** True for a path Terraform would execute as a query configuration. */
|
|
46
|
+
export function isQueryFile(path: string): boolean {
|
|
47
|
+
return path.toLowerCase().endsWith(TFQUERY_SUFFIX);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** One `list "<type>" "<name>" { … }` block — a declared intent to discover
|
|
51
|
+
* unmanaged resources of that type. */
|
|
52
|
+
export interface QueryListBlock {
|
|
53
|
+
/** the resource type being searched for, e.g. `google_compute_instance`. */
|
|
54
|
+
resourceType: string;
|
|
55
|
+
/** the query's local name, unique within the directory. */
|
|
56
|
+
name: string;
|
|
57
|
+
/** the `provider` argument as written — which provider configuration is
|
|
58
|
+
* queried. Null when absent (Terraform requires it; we report, not validate). */
|
|
59
|
+
provider: string | null;
|
|
60
|
+
/** the `limit` as written, or null when defaulted (Terraform's default is 100). */
|
|
61
|
+
limit: string | null;
|
|
62
|
+
/** whether the block asks for full resource bodies (`include_resource`). */
|
|
63
|
+
includeResource: boolean;
|
|
64
|
+
/** 1-based line of the block header. */
|
|
65
|
+
line: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface QueryFileInventory {
|
|
69
|
+
file: string;
|
|
70
|
+
lists: QueryListBlock[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Parse one query file's `list` blocks. Pure. */
|
|
74
|
+
export function parseQueryFile(hcl: string): QueryListBlock[] {
|
|
75
|
+
return parseBlocks(hcl, ["list"]).map((block) => {
|
|
76
|
+
const args = topLevelAssignments(block.body);
|
|
77
|
+
const value = (key: string): string | null => {
|
|
78
|
+
const found = args.find((a) => a.name === key);
|
|
79
|
+
return found ? stripTrailingComment(found.value) : null;
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
resourceType: block.labels[0] ?? "",
|
|
83
|
+
name: block.labels[1] ?? "",
|
|
84
|
+
provider: value("provider"),
|
|
85
|
+
limit: value("limit"),
|
|
86
|
+
includeResource: value("include_resource") === "true",
|
|
87
|
+
line: block.line,
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface QueryInventory {
|
|
93
|
+
files: QueryFileInventory[];
|
|
94
|
+
/** total `list` blocks across the tree. */
|
|
95
|
+
total: number;
|
|
96
|
+
/** distinct resource types being searched for, sorted. */
|
|
97
|
+
resourceTypes: string[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Every query file under `cwd` and the `list` blocks it declares.
|
|
102
|
+
*
|
|
103
|
+
* Returns an inventory, never findings — see the module note. An unreadable file
|
|
104
|
+
* is skipped rather than reported: a query file we cannot read is a gap in the
|
|
105
|
+
* inventory, and inventing an entry for it would be worse than a shorter list.
|
|
106
|
+
*/
|
|
107
|
+
export function collectQueryInventory(cwd: string): QueryInventory {
|
|
108
|
+
const files: QueryFileInventory[] = [];
|
|
109
|
+
const types = new Set<string>();
|
|
110
|
+
let total = 0;
|
|
111
|
+
for (const rel of walkFilesBySuffix(cwd, TFQUERY_SUFFIX)) {
|
|
112
|
+
let text: string;
|
|
113
|
+
try {
|
|
114
|
+
text = readFileSync(join(cwd, rel), "utf8");
|
|
115
|
+
} catch {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const lists = parseQueryFile(text);
|
|
119
|
+
if (lists.length === 0) continue;
|
|
120
|
+
total += lists.length;
|
|
121
|
+
for (const l of lists) if (l.resourceType) types.add(l.resourceType);
|
|
122
|
+
files.push({ file: rel.replace(/\\/g, "/"), lists });
|
|
123
|
+
}
|
|
124
|
+
return { files, total, resourceTypes: [...types].sort() };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// --- the tool -----------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
export const TerraformQueryInventoryParams = type({});
|
|
130
|
+
|
|
131
|
+
export function TerraformQueryInventoryTool(ctx: LocalToolContext) {
|
|
132
|
+
return tool({
|
|
133
|
+
name: "terraform_query_inventory",
|
|
134
|
+
description:
|
|
135
|
+
"Inventory the repo's Terraform QUERY files (`*.tfquery.hcl`, Terraform 1.14 `list` blocks) — the " +
|
|
136
|
+
"declared intent to discover infrastructure that is NOT yet under Terraform management. Returns, per " +
|
|
137
|
+
"file, each `list` block's resource type, local name, `provider`, `limit` and `include_resource`, plus " +
|
|
138
|
+
"the distinct resource types across the tree. READ-ONLY DISCOVERY INPUT: use it to describe management " +
|
|
139
|
+
'coverage in an assessment ("the team is adopting N unmanaged resource types"). It NEVER produces ' +
|
|
140
|
+
"findings and its results must NEVER drive remediation — a `list` block describes resources nobody has " +
|
|
141
|
+
"adopted yet, so writing configuration from one would invent managed infrastructure. Query files are " +
|
|
142
|
+
"not `*.tf`, so the push guardrail refuses to write them and the fix loop drops them regardless.",
|
|
143
|
+
parameters: TerraformQueryInventoryParams,
|
|
144
|
+
execute: execute(async () => {
|
|
145
|
+
const cwd = ctx.payload.cwd ?? process.cwd();
|
|
146
|
+
const inventory = collectQueryInventory(cwd);
|
|
147
|
+
log.info(
|
|
148
|
+
`» terraform_query_inventory: ${inventory.total} list block(s) across ${inventory.files.length} query file(s)`,
|
|
149
|
+
);
|
|
150
|
+
return toolOk({
|
|
151
|
+
...inventory,
|
|
152
|
+
note:
|
|
153
|
+
inventory.total === 0
|
|
154
|
+
? "no *.tfquery.hcl files found — nothing declared as pending discovery"
|
|
155
|
+
: "read-only discovery input: report it as management-coverage context, never as findings and never as remediation input",
|
|
156
|
+
});
|
|
157
|
+
}),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { PRODUCT_NAME } from "#app/brand";
|
|
2
|
+
import { run } from "#app/mcp/terraform/subprocess";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Compromised-scanner gate (supply-chain phase 0.1).
|
|
6
|
+
*
|
|
7
|
+
* THE THREAT, CONCRETELY. In March 2026 the Trivy project was compromised
|
|
8
|
+
* (TeamPCP): a malicious **v0.69.4** was published across GHCR, ECR Public,
|
|
9
|
+
* Docker Hub, deb/rpm and `get.trivy.dev` on 19 Mar; 76 of 77 `trivy-action`
|
|
10
|
+
* tags and all 7 `setup-trivy` tags were repointed at infostealer commits;
|
|
11
|
+
* malicious 0.69.5 / 0.69.6 images followed on 22 Mar. The payload dumped
|
|
12
|
+
* runner memory and called home. Advisory: GHSA-69fq-xp46-6x23. Last clean
|
|
13
|
+
* release before the incident: 0.69.3.
|
|
14
|
+
*
|
|
15
|
+
* WHY THIS LIVES HERE. Infraweaver does not download the toolchain — it executes
|
|
16
|
+
* whatever `trivy`/`checkov`/`tflint` the customer's CI put on PATH, inside the
|
|
17
|
+
* customer's runner, alongside their credentials. So the registry-side controls
|
|
18
|
+
* that failed in this incident are not ours to fix; what we CAN do is refuse to
|
|
19
|
+
* execute a build we know is malicious. A scanner is the one subprocess whose
|
|
20
|
+
* output we trust, so running a known-backdoored one is the worst case for an
|
|
21
|
+
* attestation product: we would be both the execution vector and the notary.
|
|
22
|
+
*
|
|
23
|
+
* FAIL-CLOSED, NOT SKIP. Every other scanner problem here degrades to
|
|
24
|
+
* "skipped" (absent binary, unparseable output) because a missing tool must not
|
|
25
|
+
* block a run. A KNOWN-COMPROMISED tool is the opposite: continuing would mean
|
|
26
|
+
* knowingly executing malware, so this throws and the run stops.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/** A published release known to be malicious. */
|
|
30
|
+
interface CompromisedRelease {
|
|
31
|
+
/** Binary name as invoked (matches the `run()` command). */
|
|
32
|
+
tool: string;
|
|
33
|
+
/** Exact affected versions — never a range, so a fix release can't be caught. */
|
|
34
|
+
versions: readonly string[];
|
|
35
|
+
/** Advisory id to name in the failure message. */
|
|
36
|
+
advisory: string;
|
|
37
|
+
/** Shortest safe instruction for the operator. */
|
|
38
|
+
guidance: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The denylist. Deliberately EXACT versions: a range would sweep up the fixed
|
|
43
|
+
* release and turn a security control into an outage. Add an entry per advisory.
|
|
44
|
+
*/
|
|
45
|
+
export const COMPROMISED_RELEASES: readonly CompromisedRelease[] = [
|
|
46
|
+
{
|
|
47
|
+
tool: "trivy",
|
|
48
|
+
versions: ["0.69.4", "0.69.5", "0.69.6"],
|
|
49
|
+
advisory: "GHSA-69fq-xp46-6x23",
|
|
50
|
+
guidance:
|
|
51
|
+
"These builds contain an infostealer that dumps runner memory and exfiltrates it. " +
|
|
52
|
+
"Pin trivy to 0.69.3 (the last clean release before the incident) or a fixed release " +
|
|
53
|
+
"above 0.69.6, and re-pull from a trusted source — the compromised artifacts were " +
|
|
54
|
+
"published to every official channel including GHCR, Docker Hub, deb/rpm and the " +
|
|
55
|
+
"install script. Do NOT use aquasecurity/trivy-action or setup-trivy tags from the " +
|
|
56
|
+
"incident window: they were repointed at the malicious commits.",
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Extract a semantic version from a tool's `--version` output. Tools disagree
|
|
62
|
+
* wildly on format (`Version: 0.55.0`, `TFLint version 0.52.0`, a bare
|
|
63
|
+
* `3.2.0`), so take the first `x.y.z` that appears. Returns null when the output
|
|
64
|
+
* carries no recognisable version. Pure.
|
|
65
|
+
*/
|
|
66
|
+
export function parseToolVersion(output: string): string | null {
|
|
67
|
+
const m = /(\d+\.\d+\.\d+)/.exec(output);
|
|
68
|
+
return m?.[1] ?? null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The advisory matching a tool+version, or null when the pair is not known to be
|
|
73
|
+
* compromised. Pure — the whole decision is table-driven and testable without a
|
|
74
|
+
* subprocess.
|
|
75
|
+
*/
|
|
76
|
+
export function compromisedRelease(
|
|
77
|
+
tool: string,
|
|
78
|
+
version: string | null,
|
|
79
|
+
): CompromisedRelease | null {
|
|
80
|
+
if (!version) return null;
|
|
81
|
+
return (
|
|
82
|
+
COMPROMISED_RELEASES.find(
|
|
83
|
+
(r) => r.tool === tool && r.versions.includes(version),
|
|
84
|
+
) ?? null
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The operator-facing failure text for a compromised tool. Pure. */
|
|
89
|
+
export function compromisedToolMessage(
|
|
90
|
+
rel: CompromisedRelease,
|
|
91
|
+
version: string,
|
|
92
|
+
): string {
|
|
93
|
+
return (
|
|
94
|
+
`refusing to run ${rel.tool} ${version}: this release is known-compromised (${rel.advisory}). ` +
|
|
95
|
+
`${rel.guidance} ` +
|
|
96
|
+
`${PRODUCT_NAME} fails closed here rather than execute a scanner it knows is backdoored — ` +
|
|
97
|
+
"the scan did not run and no findings were produced."
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Cache: one `--version` probe per tool per process, not per scanned root. */
|
|
102
|
+
const probed = new Map<string, string | null>();
|
|
103
|
+
|
|
104
|
+
/** Reset the probe cache — tests only. */
|
|
105
|
+
export function resetToolVersionCache(): void {
|
|
106
|
+
probed.clear();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Every tool version probed this process, sorted by tool name — the scanner
|
|
111
|
+
* half of the evidence bundle's PROVENANCE block (A.3). These are the versions
|
|
112
|
+
* the integrity gate actually observed before executing each scanner, so the
|
|
113
|
+
* signed bundle records the toolchain that genuinely ran — nothing is probed
|
|
114
|
+
* retroactively and nothing is fabricated for a tool that never ran. `null`
|
|
115
|
+
* means the tool ran a probe but printed no recognisable version.
|
|
116
|
+
*/
|
|
117
|
+
export function probedToolVersions(): {
|
|
118
|
+
tool: string;
|
|
119
|
+
version: string | null;
|
|
120
|
+
}[] {
|
|
121
|
+
return [...probed.entries()]
|
|
122
|
+
.map(([tool, version]) => ({ tool, version }))
|
|
123
|
+
.sort((a, b) => a.tool.localeCompare(b.tool));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Detect a tool's version by running `<tool> --version`. Returns null when the
|
|
128
|
+
* binary is absent or prints nothing recognisable (both are non-events — the
|
|
129
|
+
* caller's normal "skipped" path handles an absent tool).
|
|
130
|
+
*/
|
|
131
|
+
export function detectToolVersion(tool: string, cwd: string): string | null {
|
|
132
|
+
const cached = probed.get(tool);
|
|
133
|
+
if (cached !== undefined) return cached;
|
|
134
|
+
const r = run(tool, ["--version"], cwd);
|
|
135
|
+
const version = r.missing
|
|
136
|
+
? null
|
|
137
|
+
: parseToolVersion(`${r.stdout}\n${r.stderr}`);
|
|
138
|
+
probed.set(tool, version);
|
|
139
|
+
return version;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Fail-closed gate: throws when `tool` on PATH is a known-compromised release.
|
|
144
|
+
* A no-op for an absent tool, an unknown version, or any tool with no advisory —
|
|
145
|
+
* this must never become a reason a clean run fails.
|
|
146
|
+
*/
|
|
147
|
+
export function assertToolchainIntegrity(tool: string, cwd: string): void {
|
|
148
|
+
const version = detectToolVersion(tool, cwd);
|
|
149
|
+
const rel = compromisedRelease(tool, version);
|
|
150
|
+
if (rel && version) throw new Error(compromisedToolMessage(rel, version));
|
|
151
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { type } from "arktype";
|
|
2
|
+
import { PRODUCT_NAME } from "#app/brand";
|
|
3
|
+
import { hubControlsForThemes, packControlsForThemes, THEME_TO_NIST } from "#app/mcp/crosswalk";
|
|
4
|
+
import { execute, tool, toolOk } from "#app/mcp/shared";
|
|
5
|
+
import {
|
|
6
|
+
AUTHORED_RULE_PREFIX,
|
|
7
|
+
authoredRuleId,
|
|
8
|
+
emitPlanFixture,
|
|
9
|
+
emitPolicyHcl,
|
|
10
|
+
emitPolicyTestHcl,
|
|
11
|
+
emitRego,
|
|
12
|
+
POLICY_OPERATORS,
|
|
13
|
+
type PolicyRuleSpec,
|
|
14
|
+
planFixtureFileName,
|
|
15
|
+
policyFileName,
|
|
16
|
+
policyHclFidelity,
|
|
17
|
+
policyTestFileName,
|
|
18
|
+
regoFileName,
|
|
19
|
+
selfTestSpec,
|
|
20
|
+
validateSpec,
|
|
21
|
+
} from "#app/mcp/terraform/policyAuthor";
|
|
22
|
+
import { skipResult } from "#app/mcp/terraform/types";
|
|
23
|
+
import { log } from "#app/utils/cli";
|
|
24
|
+
|
|
25
|
+
const THEMES = Object.keys(THEME_TO_NIST).sort();
|
|
26
|
+
|
|
27
|
+
export const PolicyAuthorParams = type({
|
|
28
|
+
id: type.string.describe(
|
|
29
|
+
`kebab-case rule id, unique within the pack — e.g. \`s3-bucket-encryption-aes256\`. Becomes the filename and the \`${AUTHORED_RULE_PREFIX}:<id>\` rule id in every emitted artifact.`,
|
|
30
|
+
),
|
|
31
|
+
title: type.string.describe("one-line human title for the rule."),
|
|
32
|
+
source_requirement: type.string.describe(
|
|
33
|
+
"the SENTENCE OF THE SOURCE STANDARD this rule was derived from, quoted as written. This is the audit trail from prose to policy — do not paraphrase it and do not invent one; if the standard does not say it, the rule should not exist.",
|
|
34
|
+
),
|
|
35
|
+
resource_type: type.string.describe(
|
|
36
|
+
"the Terraform resource type the rule applies to, e.g. `aws_s3_bucket`. One type per rule.",
|
|
37
|
+
),
|
|
38
|
+
attribute: type.string.describe(
|
|
39
|
+
"dotted path into the resource's PLANNED VALUES (what `terraform show -json` puts in `change.after`), e.g. `server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm`. A segment that resolves to a list is flattened and the rule must hold for every element.",
|
|
40
|
+
),
|
|
41
|
+
operator: type(`'${POLICY_OPERATORS.join("' | '")}'`).describe(
|
|
42
|
+
"the comparison. `equals`/`not_equals`/`matches`/`gte`/`lte` take a scalar `value`; `in`/`not_in` take a list `value`; `present`/`absent`/`is_true`/`is_false`/`non_empty` take none.",
|
|
43
|
+
),
|
|
44
|
+
"value?": type("string | number | boolean | (string | number)[]").describe(
|
|
45
|
+
"the operand, when the operator takes one. Omit it entirely otherwise.",
|
|
46
|
+
),
|
|
47
|
+
when_absent: type("'violation' | 'compliant'").describe(
|
|
48
|
+
"REQUIRED, and the field to think hardest about: what the rule concludes when the attribute is not set at all. `sse_algorithm` missing means unencrypted (violation); `acl` missing means the private default (compliant). Same shape, opposite answer — so state it, never guess it.",
|
|
49
|
+
),
|
|
50
|
+
severity: type("'critical' | 'high' | 'medium' | 'low' | 'info'").describe(
|
|
51
|
+
"severity of a violation. critical/high emit tfpolicy `enforcement_level = mandatory`; the rest emit `advisory`.",
|
|
52
|
+
),
|
|
53
|
+
theme: type.string.describe(
|
|
54
|
+
`the compliance theme the rule evidences — this is what earns the control citation, so it must be one of the reviewed crosswalk themes: ${THEMES.join(", ")}.`,
|
|
55
|
+
),
|
|
56
|
+
message: type.string.describe(
|
|
57
|
+
"the violation message an engineer reads in CI. Say what is wrong and what to set.",
|
|
58
|
+
),
|
|
59
|
+
"example_compliant?": type("string | number | boolean").describe(
|
|
60
|
+
"a value that SATISFIES the rule, used to build the compliant fixture. REQUIRED when operator is `matches` (a value cannot be derived from a regex); optional elsewhere, where it overrides the synthesised fixture value.",
|
|
61
|
+
),
|
|
62
|
+
"example_violating?": type("string | number | boolean").describe(
|
|
63
|
+
"a value that VIOLATES the rule. REQUIRED when operator is `matches`; optional elsewhere.",
|
|
64
|
+
),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* §5.2 — the authoring surface. Turns one requirement from a written standard
|
|
69
|
+
* into reviewed policy-as-code plus the fixtures that prove it is not vacuous.
|
|
70
|
+
*
|
|
71
|
+
* The tool is NON-MUTATING on purpose. It returns file CONTENT, never writes it:
|
|
72
|
+
* the whole premise of §5.2 is that the output is reviewed code a human commits,
|
|
73
|
+
* not a policy that appears in the repo because a model decided it should. That
|
|
74
|
+
* also keeps the push allow-list untouched.
|
|
75
|
+
*
|
|
76
|
+
* It takes no `LocalToolContext` for the same reason: nothing here reads the
|
|
77
|
+
* workspace, the run payload or the scan session. Spec in, artifacts out — which
|
|
78
|
+
* is what lets the whole path be unit-tested without a fixture repo.
|
|
79
|
+
*/
|
|
80
|
+
export function PolicyAuthorTool() {
|
|
81
|
+
return tool({
|
|
82
|
+
name: "policy_author",
|
|
83
|
+
description:
|
|
84
|
+
"Turn ONE requirement from a written standard (an internal policy, a control objective, a customer " +
|
|
85
|
+
"security schedule) into reviewed policy-as-code: an OPA/Rego file `policy_check` can enforce, a " +
|
|
86
|
+
"HashiCorp tfpolicy `.policy.hcl`, a `.policytest.hcl` of fixtures, a plan-JSON fixture, and the " +
|
|
87
|
+
"compliance controls the rule evidences. Call it ONCE PER RULE. " +
|
|
88
|
+
"You do not write Rego here — you fill in a closed rule spec, and the generator emits every artifact " +
|
|
89
|
+
"deterministically, which is what makes the result reviewable. Before emitting, it SELF-TESTS the " +
|
|
90
|
+
"rule against violating / compliant / attribute-absent fixtures and REFUSES a spec that fails or that " +
|
|
91
|
+
"denies nothing (a policy that never fires is the failure mode that matters — it reads as enforced " +
|
|
92
|
+
"and passes everything). " +
|
|
93
|
+
"Only express what a Terraform plan can actually decide: one resource type, one attribute, one " +
|
|
94
|
+
"comparison. A requirement about people, process, or runtime state is NOT authorable — say so and " +
|
|
95
|
+
"move on rather than encoding a rule that cannot be evaluated. " +
|
|
96
|
+
"It writes nothing: return the content to the human who reviews and commits it.",
|
|
97
|
+
parameters: PolicyAuthorParams,
|
|
98
|
+
execute: execute(async (params) => {
|
|
99
|
+
const spec = params as PolicyRuleSpec;
|
|
100
|
+
|
|
101
|
+
const errors = validateSpec(spec);
|
|
102
|
+
if (errors.length > 0) {
|
|
103
|
+
return skipResult("invalid_spec", `the rule spec is not valid: ${errors.join("; ")}`, {
|
|
104
|
+
key: "found",
|
|
105
|
+
reasonKey: "reason",
|
|
106
|
+
extra: { errors },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// The vacuity gate. A spec that does not deny its own violating fixture,
|
|
111
|
+
// or that denies nothing at all, is never emitted — handing a human a
|
|
112
|
+
// policy that contradicts its own description is worse than handing them
|
|
113
|
+
// nothing, because it will be reviewed as if it worked.
|
|
114
|
+
const selfTest = selfTestSpec(spec);
|
|
115
|
+
if (!selfTest.passed) {
|
|
116
|
+
const failed = selfTest.cases.filter((c) => !c.passed);
|
|
117
|
+
const detail = !selfTest.denies_something
|
|
118
|
+
? "the rule denies none of its own fixtures — as written it can never fire. Re-check `when_absent` and the operator."
|
|
119
|
+
: `the rule disagreed with its own fixtures: ${failed
|
|
120
|
+
.map(
|
|
121
|
+
(c) =>
|
|
122
|
+
`${c.kind} expected ${c.expected ? "violation" : "pass"}, got ${c.actual ? "violation" : "pass"} (${c.reason})`,
|
|
123
|
+
)
|
|
124
|
+
.join("; ")}`;
|
|
125
|
+
return skipResult("self_test_failed", detail, {
|
|
126
|
+
key: "found",
|
|
127
|
+
reasonKey: "reason",
|
|
128
|
+
extra: { self_test: selfTest },
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const controls = hubControlsForThemes([spec.theme]);
|
|
133
|
+
const fidelity = policyHclFidelity(spec);
|
|
134
|
+
log.info(
|
|
135
|
+
`» policy_author: ${authoredRuleId(spec.id)} self-test PASS (${selfTest.cases.length} fixtures), ${controls.length} control(s), .policy.hcl fidelity=${fidelity}`,
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
return toolOk({
|
|
139
|
+
rule_id: authoredRuleId(spec.id),
|
|
140
|
+
self_test: selfTest,
|
|
141
|
+
// what was verified, and — the part that matters — what was not.
|
|
142
|
+
asserts:
|
|
143
|
+
"the rule's SEMANTICS were evaluated in-process against a violating, a compliant and an " +
|
|
144
|
+
"attribute-absent fixture and behaved as each demands, and the emitted artifacts are a " +
|
|
145
|
+
"deterministic function of the spec",
|
|
146
|
+
does_not_assert:
|
|
147
|
+
"that the emitted Rego or .policy.hcl was EXECUTED — no OPA or tfpolicy binary is bundled. Run " +
|
|
148
|
+
"`policy_check` (conftest) against the plan fixture, and `tfpolicy validate` + `tfpolicy test` " +
|
|
149
|
+
"against the .policy.hcl and .policytest.hcl, before relying on either in a gate",
|
|
150
|
+
crosswalk: {
|
|
151
|
+
theme: spec.theme,
|
|
152
|
+
controls,
|
|
153
|
+
pack_control_ids: packControlsForThemes([spec.theme]),
|
|
154
|
+
},
|
|
155
|
+
artifacts: [
|
|
156
|
+
{
|
|
157
|
+
path: `policy/${regoFileName(spec)}`,
|
|
158
|
+
purpose: "OPA/Rego — the enforceable artifact; policy_check runs it via conftest",
|
|
159
|
+
content: emitRego(spec),
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
path: `policy/${planFixtureFileName(spec)}`,
|
|
163
|
+
purpose:
|
|
164
|
+
"plan-JSON fixture — run `conftest test -p policy <this file>` to execute the Rego above",
|
|
165
|
+
content: emitPlanFixture(spec),
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
path: policyFileName(spec),
|
|
169
|
+
purpose: `HashiCorp tfpolicy (authored, not enforced by ${PRODUCT_NAME}) — fidelity: ${fidelity}`,
|
|
170
|
+
content: emitPolicyHcl(spec),
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
path: policyTestFileName(spec),
|
|
174
|
+
purpose: "tfpolicy fixtures — `tfpolicy test --policies=. --tests=.`",
|
|
175
|
+
content: emitPolicyTestHcl(spec),
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
policy_hcl_fidelity: fidelity,
|
|
179
|
+
next_step:
|
|
180
|
+
"show the human the Rego and the source requirement it came from, state the self-test result, and let " +
|
|
181
|
+
"them commit it — this tool deliberately writes nothing",
|
|
182
|
+
});
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
}
|