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,520 @@
|
|
|
1
|
+
import { type } from "arktype";
|
|
2
|
+
import { PRODUCT_NAME } from "#app/brand";
|
|
3
|
+
import { isStatefulResourceType } from "#app/mcp/terraform/governance";
|
|
4
|
+
import {
|
|
5
|
+
buildConcern,
|
|
6
|
+
type Concern,
|
|
7
|
+
type Severity,
|
|
8
|
+
} from "#app/mcp/terraform/types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Detect infrastructure DRIFT from a `terraform show -json` plan artifact WITHOUT the
|
|
12
|
+
* engine ever holding a cloud credential. The customer's CI already runs
|
|
13
|
+
* `terraform plan` (that is where the creds live) and writes the plan out as JSON;
|
|
14
|
+
* Infraweaver reads that artifact and reports which resources have drifted from code.
|
|
15
|
+
* This is the sovereign, zero-credential companion to running `terraform_plan`
|
|
16
|
+
* against live state ourselves.
|
|
17
|
+
*
|
|
18
|
+
* Scope: a plan produced on a run whose CODE is unchanged (a scheduled / drift
|
|
19
|
+
* workflow) shows changes only because the live state diverged — that is drift.
|
|
20
|
+
* Each `resource_changes[]` entry with a mutating action is a drift item. Drift is
|
|
21
|
+
* DETECTION ONLY here: reconciling it is an `apply` or a code change a human owns.
|
|
22
|
+
*
|
|
23
|
+
* NB the parser: this reads the `terraform show -json` DOCUMENT form
|
|
24
|
+
* (`resource_changes[].change.actions[]`), NOT the `terraform plan -json` log stream
|
|
25
|
+
* (`plan.ts`). They are different shapes; a CI plan artifact is the document form.
|
|
26
|
+
* Pure: no filesystem, no network (the tool supplies the JSON + the resource index).
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// --- plan document schema ----------------------------------------------------
|
|
30
|
+
|
|
31
|
+
const PlanResourceChange = type({
|
|
32
|
+
address: "string",
|
|
33
|
+
"type?": "string",
|
|
34
|
+
"name?": "string",
|
|
35
|
+
"mode?": "string",
|
|
36
|
+
change: type({
|
|
37
|
+
actions: "string[]",
|
|
38
|
+
// `before`/`after` are the attribute maps the provider-noise filter diffs.
|
|
39
|
+
// Optional and untyped by design: their shape is the resource's own schema,
|
|
40
|
+
// and an absent pair simply means the filter makes no claim (never filters).
|
|
41
|
+
"before?": "unknown",
|
|
42
|
+
"after?": "unknown",
|
|
43
|
+
}),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Terraform 1.15's plan document lists provider-action invocations (the runtime
|
|
47
|
+
// counterpart of the static `imperative-action-trigger` finding). Field names
|
|
48
|
+
// follow hashicorp/terraform-json's ActionInvocation. Everything but the address
|
|
49
|
+
// is optional — this parser reports what is present, never demands more.
|
|
50
|
+
const PlanActionInvocation = type({
|
|
51
|
+
address: "string",
|
|
52
|
+
"type?": "string",
|
|
53
|
+
"name?": "string",
|
|
54
|
+
"provider_name?": "string",
|
|
55
|
+
"lifecycle_action_trigger?": type({
|
|
56
|
+
"triggering_resource_address?": "string",
|
|
57
|
+
"action_trigger_event?": "string",
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export const PlanDocument = type({
|
|
62
|
+
/** Terraform stamps the document form with a schema version. Absent on very
|
|
63
|
+
* old artifacts, so it stays optional — we tolerate rather than demand. */
|
|
64
|
+
"format_version?": "string",
|
|
65
|
+
"resource_changes?": PlanResourceChange.array(),
|
|
66
|
+
/** provider actions this plan will invoke (TF 1.15+). Absent on older plans. */
|
|
67
|
+
"action_invocations?": PlanActionInvocation.array(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// --- drift classification ----------------------------------------------------
|
|
71
|
+
|
|
72
|
+
/** Actions that do not mutate live infrastructure (mirrors `plan.ts`, plus the
|
|
73
|
+
* document-form `no-op` spelling). A change made up only of these is not drift.
|
|
74
|
+
* `open`/`renew`/`close` are EPHEMERAL lifecycle ops (TF 1.10+): an ephemeral
|
|
75
|
+
* value being (re)opened is session plumbing, not a resource being changed —
|
|
76
|
+
* classifying one as CRUD would fabricate drift out of a secret handshake. */
|
|
77
|
+
const NON_MUTATING: ReadonlySet<string> = new Set([
|
|
78
|
+
"no-op",
|
|
79
|
+
"noop",
|
|
80
|
+
"read",
|
|
81
|
+
"open",
|
|
82
|
+
"renew",
|
|
83
|
+
"close",
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
export type DriftKind = "modified" | "deleted" | "recreated" | "replaced";
|
|
87
|
+
|
|
88
|
+
export interface DriftItem {
|
|
89
|
+
address: string;
|
|
90
|
+
type: string | null;
|
|
91
|
+
name: string | null;
|
|
92
|
+
/** the raw plan actions, e.g. ["update"] or ["delete","create"]. */
|
|
93
|
+
actions: string[];
|
|
94
|
+
kind: DriftKind;
|
|
95
|
+
/** top-level attributes whose value differs between `change.before` and
|
|
96
|
+
* `change.after` — the input the provider-noise filter judges. `null` when
|
|
97
|
+
* the plan carries no diffable before/after pair (the filter then makes no
|
|
98
|
+
* claim about this item and always keeps it). */
|
|
99
|
+
changed_fields: string[] | null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Classify a resource change's actions into a drift kind, or null when the change
|
|
103
|
+
* is non-mutating (no drift). */
|
|
104
|
+
function classify(actions: string[]): DriftKind | null {
|
|
105
|
+
const acts = actions.filter((a) => !NON_MUTATING.has(a));
|
|
106
|
+
// A `forget` drops the resource from state while the cloud object survives:
|
|
107
|
+
// no live change, so it is not drift. It IS a coverage gap — see
|
|
108
|
+
// `detectForgotten`, which reports it separately rather than silently.
|
|
109
|
+
if (acts.includes("forget")) return null;
|
|
110
|
+
if (acts.length === 0) return null;
|
|
111
|
+
const set = new Set(acts);
|
|
112
|
+
if (set.has("create") && set.has("delete")) return "replaced";
|
|
113
|
+
if (set.has("delete")) return "deleted";
|
|
114
|
+
if (set.has("create")) return "recreated"; // live is missing the resource
|
|
115
|
+
if (set.has("update")) return "modified";
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The plan-JSON document schema versions this parser understands. Terraform has
|
|
121
|
+
* only ever shipped 1.x for the `show -json` document form and adds keys within
|
|
122
|
+
* it additively, so any 1.x parses; a 2.x would be a redesign we have not read.
|
|
123
|
+
*
|
|
124
|
+
* Forward-compatibility is the DEFAULT here: an unknown 1.x minor (or an absent
|
|
125
|
+
* version on an old artifact) parses normally, because arktype ignores keys we
|
|
126
|
+
* do not declare. Only a MAJOR bump is called out — and even then as an honest
|
|
127
|
+
* coverage gap for the caller to surface, never a silent mis-parse.
|
|
128
|
+
*/
|
|
129
|
+
export const SUPPORTED_PLAN_FORMAT_MAJOR = 1;
|
|
130
|
+
|
|
131
|
+
/** True when a plan document's `format_version` is one this parser understands.
|
|
132
|
+
* An absent version is accepted (pre-versioning artifacts). Pure. */
|
|
133
|
+
export function isSupportedPlanFormat(
|
|
134
|
+
formatVersion: string | undefined,
|
|
135
|
+
): boolean {
|
|
136
|
+
if (!formatVersion) return true;
|
|
137
|
+
const major = Number.parseInt(formatVersion.split(".")[0] ?? "", 10);
|
|
138
|
+
return Number.isFinite(major) && major === SUPPORTED_PLAN_FORMAT_MAJOR;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The resource TYPE for a plan entry: the declared `type` when present, else
|
|
142
|
+
* parsed from the address (`module.a.aws_db_instance.b` → `aws_db_instance`).
|
|
143
|
+
* Null when neither yields one. Pure. */
|
|
144
|
+
function resourceTypeOf(rc: {
|
|
145
|
+
address: string;
|
|
146
|
+
type?: string | undefined;
|
|
147
|
+
}): string | null {
|
|
148
|
+
if (rc.type) return rc.type;
|
|
149
|
+
const segments = rc.address.split(".");
|
|
150
|
+
return segments.length >= 2 ? (segments[segments.length - 2] ?? null) : null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface ForgottenResource {
|
|
154
|
+
address: string;
|
|
155
|
+
type: string | null;
|
|
156
|
+
/** true when the type is data-bearing ([[governance]] `isStatefulResourceType`)
|
|
157
|
+
* — forgetting a database is the case that must route through needs-human:
|
|
158
|
+
* after it, the data-bearing object exists with NO destroy protection and no
|
|
159
|
+
* drift visibility, and nothing in code says so. */
|
|
160
|
+
stateful: boolean;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Resources the plan would FORGET — dropped from state while the real cloud
|
|
165
|
+
* object keeps existing (Terraform `removed` blocks, OpenTofu `destroy = false`).
|
|
166
|
+
*
|
|
167
|
+
* A forget is deliberately NOT drift and NOT a destroy: nothing in the cloud
|
|
168
|
+
* changes, so reporting it as either would be a false positive. But it is not a
|
|
169
|
+
* non-event either — after a forget the resource is unmanaged, and every later
|
|
170
|
+
* drift scan is silently blind to it. Surfaced separately so the run can state
|
|
171
|
+
* the coverage gap instead of quietly shrinking what 'no drift' covers. Pure.
|
|
172
|
+
*/
|
|
173
|
+
export function classifyForgotten(
|
|
174
|
+
doc: typeof PlanDocument.infer,
|
|
175
|
+
): ForgottenResource[] {
|
|
176
|
+
const forgotten: ForgottenResource[] = [];
|
|
177
|
+
for (const rc of doc.resource_changes ?? []) {
|
|
178
|
+
if (!rc.change.actions.includes("forget")) continue;
|
|
179
|
+
const resourceType = resourceTypeOf(rc);
|
|
180
|
+
forgotten.push({
|
|
181
|
+
address: rc.address,
|
|
182
|
+
type: resourceType,
|
|
183
|
+
stateful: resourceType !== null && isStatefulResourceType(resourceType),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return forgotten;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** The forgotten addresses only — the compact form of {@link classifyForgotten}. */
|
|
190
|
+
export function detectForgotten(doc: typeof PlanDocument.infer): string[] {
|
|
191
|
+
return classifyForgotten(doc).map((f) => f.address);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Structural equality on plan attribute values (JSON-shaped data only). */
|
|
195
|
+
function sameValue(a: unknown, b: unknown): boolean {
|
|
196
|
+
if (Object.is(a, b)) return true;
|
|
197
|
+
if (
|
|
198
|
+
typeof a !== "object" ||
|
|
199
|
+
typeof b !== "object" ||
|
|
200
|
+
a === null ||
|
|
201
|
+
b === null
|
|
202
|
+
)
|
|
203
|
+
return false;
|
|
204
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
205
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
206
|
+
return a.length === b.length && a.every((v, i) => sameValue(v, b[i]));
|
|
207
|
+
}
|
|
208
|
+
const ka = Object.keys(a).sort();
|
|
209
|
+
const kb = Object.keys(b).sort();
|
|
210
|
+
if (ka.length !== kb.length || ka.some((k, i) => k !== kb[i])) return false;
|
|
211
|
+
return ka.every((k) =>
|
|
212
|
+
sameValue(
|
|
213
|
+
(a as Record<string, unknown>)[k],
|
|
214
|
+
(b as Record<string, unknown>)[k],
|
|
215
|
+
),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Top-level attribute names whose value differs between `before` and `after`,
|
|
220
|
+
* or null when the pair isn't two plain objects (nothing diffable). Pure. */
|
|
221
|
+
function changedFields(before: unknown, after: unknown): string[] | null {
|
|
222
|
+
const isPlain = (v: unknown): v is Record<string, unknown> =>
|
|
223
|
+
typeof v === "object" && v !== null && !Array.isArray(v);
|
|
224
|
+
if (!isPlain(before) || !isPlain(after)) return null;
|
|
225
|
+
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
226
|
+
return [...keys].filter((k) => !sameValue(before[k], after[k])).sort();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Every drifted resource in a plan document. A clean plan yields `[]`. */
|
|
230
|
+
export function detectDrift(doc: typeof PlanDocument.infer): DriftItem[] {
|
|
231
|
+
const items: DriftItem[] = [];
|
|
232
|
+
for (const rc of doc.resource_changes ?? []) {
|
|
233
|
+
const kind = classify(rc.change.actions);
|
|
234
|
+
if (!kind) continue;
|
|
235
|
+
items.push({
|
|
236
|
+
address: rc.address,
|
|
237
|
+
type: resourceTypeOf(rc),
|
|
238
|
+
name: rc.name ?? null,
|
|
239
|
+
actions: rc.change.actions,
|
|
240
|
+
kind,
|
|
241
|
+
changed_fields: changedFields(rc.change.before, rc.change.after),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
return items;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// --- provider-noise filter ---------------------------------------------------
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Computed fields whose churn is PROVIDER bookkeeping, not an operator touching
|
|
251
|
+
* infrastructure — the documented, always-computed merge targets that generate
|
|
252
|
+
* perpetual "drift" whenever provider-level defaults shift:
|
|
253
|
+
*
|
|
254
|
+
* - aws `tags_all`: the computed merge of `default_tags` into every resource's
|
|
255
|
+
* tags (the canonical drift-noise field of the AWS provider).
|
|
256
|
+
* - google `effective_labels` / `terraform_labels`: computed label merges
|
|
257
|
+
* introduced by provider v5's default-labels model.
|
|
258
|
+
*
|
|
259
|
+
* The list is deliberately SHORT and only ever names fields a provider computes
|
|
260
|
+
* — a field an operator can hand-edit in the console never belongs here, because
|
|
261
|
+
* filtering it would be exactly the false no-drift the roadmap forbids.
|
|
262
|
+
*/
|
|
263
|
+
export const PROVIDER_NOISE_FIELDS: Readonly<
|
|
264
|
+
Record<string, readonly string[]>
|
|
265
|
+
> = {
|
|
266
|
+
aws: ["tags_all"],
|
|
267
|
+
google: ["effective_labels", "terraform_labels"],
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/** A drift item excluded by the noise filter — retained for auditability, so the
|
|
271
|
+
* run can show WHAT was filtered and by which fields rather than silently
|
|
272
|
+
* shrinking the drift set. */
|
|
273
|
+
export interface NoiseFilteredDrift {
|
|
274
|
+
address: string;
|
|
275
|
+
kind: DriftKind;
|
|
276
|
+
/** the noisy fields that were the entire diff. */
|
|
277
|
+
fields: string[];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Split drift into signal and provider noise. An item is noise ONLY when every
|
|
282
|
+
* condition holds: it is a pure in-place update (`modified`), the plan carried a
|
|
283
|
+
* diffable before/after pair, at least one field changed, and EVERY changed
|
|
284
|
+
* field is on the noise list (the per-provider defaults plus any operator-
|
|
285
|
+
* supplied extras). Anything else — a delete, a replace, an undiffable change,
|
|
286
|
+
* a mixed diff where one field is real — is kept. The bias is deliberate:
|
|
287
|
+
* "never a false no-drift" means the filter must prove noise, not assume it.
|
|
288
|
+
*/
|
|
289
|
+
export function filterProviderNoise(
|
|
290
|
+
items: ReadonlyArray<DriftItem>,
|
|
291
|
+
extraNoiseFields: readonly string[] = [],
|
|
292
|
+
): { kept: DriftItem[]; filtered: NoiseFilteredDrift[] } {
|
|
293
|
+
const kept: DriftItem[] = [];
|
|
294
|
+
const filtered: NoiseFilteredDrift[] = [];
|
|
295
|
+
for (const item of items) {
|
|
296
|
+
const provider = item.type?.split("_")[0] ?? "";
|
|
297
|
+
const noise = new Set([
|
|
298
|
+
...(PROVIDER_NOISE_FIELDS[provider] ?? []),
|
|
299
|
+
...extraNoiseFields,
|
|
300
|
+
]);
|
|
301
|
+
const noiseOnly =
|
|
302
|
+
item.kind === "modified" &&
|
|
303
|
+
item.changed_fields !== null &&
|
|
304
|
+
item.changed_fields.length > 0 &&
|
|
305
|
+
item.changed_fields.every((f) => noise.has(f));
|
|
306
|
+
if (noiseOnly && item.changed_fields) {
|
|
307
|
+
filtered.push({
|
|
308
|
+
address: item.address,
|
|
309
|
+
kind: item.kind,
|
|
310
|
+
fields: item.changed_fields,
|
|
311
|
+
});
|
|
312
|
+
} else {
|
|
313
|
+
kept.push(item);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return { kept, filtered };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// --- action invocations (the runtime counterpart of imperative-action-trigger) --
|
|
320
|
+
|
|
321
|
+
export interface ActionInvocationItem {
|
|
322
|
+
/** absolute action address, `action.<type>.<name>`. */
|
|
323
|
+
address: string;
|
|
324
|
+
action_type: string | null;
|
|
325
|
+
/** the resource whose lifecycle event fires this action, when the plan says. */
|
|
326
|
+
triggered_by: string | null;
|
|
327
|
+
/** the lifecycle event (`after_create`, …), when the plan says. */
|
|
328
|
+
event: string | null;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* The provider actions this plan will invoke (TF 1.15's `action_invocations`).
|
|
333
|
+
* This is the RUNTIME counterpart of the static `imperative-action-trigger`
|
|
334
|
+
* finding ([[governance]]): the static rule says "an apply here can do work
|
|
335
|
+
* outside the resource graph"; this array is the plan saying "THIS apply will".
|
|
336
|
+
* Pure summarization — correlation to code happens in the tool, where the
|
|
337
|
+
* repo's HCL is available.
|
|
338
|
+
*/
|
|
339
|
+
export function summarizeActionInvocations(
|
|
340
|
+
doc: typeof PlanDocument.infer,
|
|
341
|
+
): ActionInvocationItem[] {
|
|
342
|
+
return (doc.action_invocations ?? []).map((inv) => ({
|
|
343
|
+
address: inv.address,
|
|
344
|
+
action_type: inv.type ?? null,
|
|
345
|
+
triggered_by:
|
|
346
|
+
inv.lifecycle_action_trigger?.triggering_resource_address ?? null,
|
|
347
|
+
event: inv.lifecycle_action_trigger?.action_trigger_event ?? null,
|
|
348
|
+
}));
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// --- drift → signed evidence -------------------------------------------------
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* The drift statement the evidence bundle carries — the 2.1 differentiator:
|
|
355
|
+
* *signed, verifiable proof that live cloud matched the committed IaC at the
|
|
356
|
+
* time the plan artifact was produced*, with every bound on that claim stated
|
|
357
|
+
* in the artifact itself rather than left to the reader's optimism.
|
|
358
|
+
*/
|
|
359
|
+
export interface DriftEvidenceStatement {
|
|
360
|
+
/** the plan artifact the claim is derived from. */
|
|
361
|
+
source_file: string;
|
|
362
|
+
/** drifted resources AFTER noise filtering — the signal set. */
|
|
363
|
+
detected: number;
|
|
364
|
+
by_kind: Record<DriftKind, number>;
|
|
365
|
+
items: { address: string; kind: DriftKind }[];
|
|
366
|
+
/** drift excluded as provider bookkeeping — listed field-by-field so the
|
|
367
|
+
* filtering is auditable (the unfiltered diff stays in the plan artifact). */
|
|
368
|
+
noise_filtered: NoiseFilteredDrift[];
|
|
369
|
+
/** resources this plan drops from management — the standing blind spot every
|
|
370
|
+
* later drift claim inherits, so it must ride the signed statement. */
|
|
371
|
+
forgotten: ForgottenResource[];
|
|
372
|
+
/** drifted addresses with no matching resource block in code. */
|
|
373
|
+
unlocated: number;
|
|
374
|
+
/** honest bounds: unsupported format major, etc. Empty = fully readable. */
|
|
375
|
+
coverage_gaps: string[];
|
|
376
|
+
asserts: string;
|
|
377
|
+
does_not_assert: string;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Build the drift evidence statement (pure). The asserts line is graded by what
|
|
382
|
+
* the inputs actually prove: a clean, fully-readable plan asserts the live-
|
|
383
|
+
* matches-code claim; drift asserts the detection; a coverage gap asserts
|
|
384
|
+
* nothing confident. INCONCLUSIVE-over-silence, in the signed artifact itself.
|
|
385
|
+
*/
|
|
386
|
+
export function buildDriftStatement(args: {
|
|
387
|
+
sourceFile: string;
|
|
388
|
+
kept: ReadonlyArray<DriftItem>;
|
|
389
|
+
filtered: ReadonlyArray<NoiseFilteredDrift>;
|
|
390
|
+
forgotten: ReadonlyArray<ForgottenResource>;
|
|
391
|
+
unlocated: number;
|
|
392
|
+
coverageGaps?: readonly string[];
|
|
393
|
+
}): DriftEvidenceStatement {
|
|
394
|
+
const { sourceFile, kept, filtered, forgotten, unlocated } = args;
|
|
395
|
+
const coverage_gaps = [...(args.coverageGaps ?? [])];
|
|
396
|
+
const by_kind: Record<DriftKind, number> = {
|
|
397
|
+
modified: 0,
|
|
398
|
+
deleted: 0,
|
|
399
|
+
recreated: 0,
|
|
400
|
+
replaced: 0,
|
|
401
|
+
};
|
|
402
|
+
for (const item of kept) by_kind[item.kind]++;
|
|
403
|
+
|
|
404
|
+
let asserts: string;
|
|
405
|
+
if (coverage_gaps.length > 0) {
|
|
406
|
+
asserts =
|
|
407
|
+
"nothing confident — the plan artifact could not be fully read (see coverage_gaps); " +
|
|
408
|
+
"treat this statement as INCONCLUSIVE, never as 'no drift'.";
|
|
409
|
+
} else if (kept.length === 0) {
|
|
410
|
+
asserts =
|
|
411
|
+
"at the time the plan artifact was produced, every resource under Terraform management " +
|
|
412
|
+
"matched the committed configuration (no mutating change was planned).";
|
|
413
|
+
} else {
|
|
414
|
+
asserts =
|
|
415
|
+
`${kept.length} resource(s) had drifted from the committed configuration when the plan ` +
|
|
416
|
+
"artifact was produced (each listed with the reconciling action kind).";
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const forgottenNote = forgotten.length
|
|
420
|
+
? ` ${forgotten.length} resource(s) are being dropped from management (\`forgotten\`) and are not observable by any later drift scan.`
|
|
421
|
+
: "";
|
|
422
|
+
const filteredNote = filtered.length
|
|
423
|
+
? ` ${filtered.length} change(s) were excluded as provider-computed noise (listed field-by-field in \`noise_filtered\`; the unfiltered diff remains in the plan artifact).`
|
|
424
|
+
: "";
|
|
425
|
+
return {
|
|
426
|
+
source_file: sourceFile,
|
|
427
|
+
detected: kept.length,
|
|
428
|
+
by_kind,
|
|
429
|
+
items: kept.map((i) => ({ address: i.address, kind: i.kind })),
|
|
430
|
+
noise_filtered: [...filtered],
|
|
431
|
+
forgotten: [...forgotten],
|
|
432
|
+
unlocated,
|
|
433
|
+
coverage_gaps,
|
|
434
|
+
asserts,
|
|
435
|
+
does_not_assert:
|
|
436
|
+
"anything about resources outside Terraform management, or about changes made after " +
|
|
437
|
+
`the plan artifact was produced.${forgottenNote}${filteredNote}`,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// --- drift → concerns --------------------------------------------------------
|
|
442
|
+
|
|
443
|
+
const DRIFT_SEVERITY: Record<DriftKind, Severity> = {
|
|
444
|
+
// Losing/replacing a live resource to reconcile risks data loss — the loud cases.
|
|
445
|
+
deleted: "high",
|
|
446
|
+
replaced: "high",
|
|
447
|
+
recreated: "medium",
|
|
448
|
+
modified: "medium",
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const DRIFT_EVIDENCE: Record<DriftKind, string> = {
|
|
452
|
+
modified:
|
|
453
|
+
"configuration has drifted from code (a plan would update it to reconcile)",
|
|
454
|
+
deleted:
|
|
455
|
+
"the resource no longer exists in live infrastructure (a plan would recreate it)",
|
|
456
|
+
recreated:
|
|
457
|
+
"the resource is missing from live infrastructure and would be created",
|
|
458
|
+
replaced:
|
|
459
|
+
"live state has drifted such that a plan would destroy and recreate it",
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
/** Resolve a Terraform address to its source location, or null when the address
|
|
463
|
+
* isn't found in the repo's code (e.g. a resource removed from code but still in
|
|
464
|
+
* state). Supplied by the tool from a `.tf` resource index. */
|
|
465
|
+
export type LocationResolver = (
|
|
466
|
+
address: string,
|
|
467
|
+
) => { file: string; line: number } | null;
|
|
468
|
+
|
|
469
|
+
/** A drift item that couldn't be tied to a resource block in code (reported, not dropped). */
|
|
470
|
+
export interface UnlocatedDrift {
|
|
471
|
+
address: string;
|
|
472
|
+
kind: DriftKind;
|
|
473
|
+
reason: string;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export interface DriftConcerns {
|
|
477
|
+
concerns: Concern[];
|
|
478
|
+
unlocated: UnlocatedDrift[];
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Turn drift items into `reviewer`-source concerns at each resource's file:line.
|
|
483
|
+
* Drift is honestly `not-code-verifiable` by the ✗→✓ re-scan (proving it fixed needs
|
|
484
|
+
* live cloud access, which Infraweaver refuses) — the `reviewer` source carries exactly
|
|
485
|
+
* that meaning. Items whose address isn't in code are returned under `unlocated`.
|
|
486
|
+
*/
|
|
487
|
+
export function driftToConcerns(
|
|
488
|
+
items: ReadonlyArray<DriftItem>,
|
|
489
|
+
resolve: LocationResolver,
|
|
490
|
+
): DriftConcerns {
|
|
491
|
+
const concerns: Concern[] = [];
|
|
492
|
+
const unlocated: UnlocatedDrift[] = [];
|
|
493
|
+
for (const item of items) {
|
|
494
|
+
const loc = resolve(item.address);
|
|
495
|
+
if (!loc) {
|
|
496
|
+
unlocated.push({
|
|
497
|
+
address: item.address,
|
|
498
|
+
kind: item.kind,
|
|
499
|
+
reason: "no resource block in the repo matched this drifted address",
|
|
500
|
+
});
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
concerns.push(
|
|
504
|
+
buildConcern({
|
|
505
|
+
source: "reviewer",
|
|
506
|
+
// A stable, address-scoped rule token so the same drifted resource keeps its id.
|
|
507
|
+
rule: `drift-${item.kind}-${item.address}`,
|
|
508
|
+
file: loc.file,
|
|
509
|
+
line: loc.line,
|
|
510
|
+
severity: DRIFT_SEVERITY[item.kind],
|
|
511
|
+
category: "correctness",
|
|
512
|
+
evidence: `${item.address}: ${DRIFT_EVIDENCE[item.kind]}`,
|
|
513
|
+
remediation_hint:
|
|
514
|
+
"Reconcile the drift (an apply, or reverse the out-of-band change) or update the code to " +
|
|
515
|
+
`match intent — a human decision; ${PRODUCT_NAME} never applies.`,
|
|
516
|
+
}),
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
return { concerns, unlocated };
|
|
520
|
+
}
|