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,304 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AZURE_HOURLY_PRICES,
|
|
3
|
+
AZURE_PRICE_CURRENCY,
|
|
4
|
+
AZURE_PRICE_FETCHED_AT,
|
|
5
|
+
AZURE_PRICE_REGION,
|
|
6
|
+
} from "#app/mcp/terraform/azurePrices";
|
|
7
|
+
import type { TfResourceEntry } from "#app/mcp/terraform/cspm";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Idle-floor detection (§5.19) — the resources that cost money at ZERO traffic.
|
|
11
|
+
*
|
|
12
|
+
* WHY THIS AND NOT A TOTAL. The hard part of plan-based cost estimation is not
|
|
13
|
+
* the pricing API, it is that usage-dependent lines (GB, requests, egress) are
|
|
14
|
+
* simply NOT derivable from Terraform. Any tool publishing a precise monthly
|
|
15
|
+
* total from a plan is guessing at the usage half. The idle floor is the portion
|
|
16
|
+
* that is deterministic — true regardless of traffic — so it is both the most
|
|
17
|
+
* defensible number we can publish and the most actionable one: an App Service
|
|
18
|
+
* Premium plan or an Azure Firewall bills the same whether or not anyone calls it.
|
|
19
|
+
*
|
|
20
|
+
* CREDENTIAL-FREE AND OFFLINE. Prices come from the bundled snapshot
|
|
21
|
+
* (`azurePrices.ts`, public Azure list prices captured at build time), so a scan
|
|
22
|
+
* makes no network call and needs no cloud credentials or pricing API key.
|
|
23
|
+
*
|
|
24
|
+
* FLOOR SEMANTICS — WE UNDER-CLAIM ON PURPOSE, AND NEVER GUESS A TIER. A
|
|
25
|
+
* resource is priced ONLY when its tier is identifiable from source AND is one
|
|
26
|
+
* this catalog carries. There is deliberately NO cheapest-tier fallback: every
|
|
27
|
+
* one of these resource types has a cheap or free tier (App Service `F1`/`B1`,
|
|
28
|
+
* Bastion `Developer`, a Basic VPN gateway, Basic Redis), so falling back would
|
|
29
|
+
* invent a charge for a resource that may cost nothing — the single failure mode
|
|
30
|
+
* that discredits the whole number. An unidentifiable tier is reported as an
|
|
31
|
+
* explicit coverage gap instead. A floor that is too low is honest; one that is
|
|
32
|
+
* too high is a number the customer can disprove.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/** Billable hours per month — the 365×24/12 convention list prices assume. */
|
|
36
|
+
export const HOURS_PER_MONTH = 730;
|
|
37
|
+
|
|
38
|
+
/** What an idle-floor rule knows about one chargeable resource type. */
|
|
39
|
+
interface IdleFloorRule {
|
|
40
|
+
/** Bare rule token (namespaced to `reviewer:` by `buildConcern`). */
|
|
41
|
+
id: string;
|
|
42
|
+
/** The Terraform resource type this rule applies to. */
|
|
43
|
+
resourceType: string;
|
|
44
|
+
/** Why it bills at zero traffic — quoted verbatim into cost.md. */
|
|
45
|
+
why: string;
|
|
46
|
+
/** SKU literal (lower-cased, as it appears in the resource block) → meter key.
|
|
47
|
+
* A resource whose tier is not one of these is NOT priced. */
|
|
48
|
+
meters: Record<string, string>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The catalog. Every entry is a resource whose charge is a fixed hourly rate for
|
|
53
|
+
* merely existing, at the tiers listed. Usage-metered services (Functions
|
|
54
|
+
* consumption, storage, bandwidth) are deliberately absent — they have no floor
|
|
55
|
+
* to state. Cheap/free tiers are absent too: their floor is not worth claiming
|
|
56
|
+
* and pricing them wrongly would be worse than saying nothing.
|
|
57
|
+
*
|
|
58
|
+
* SKU matching runs against the resource block's string literals, which
|
|
59
|
+
* `indexTfResources` already collects lower-cased, so no new HCL parser is
|
|
60
|
+
* needed and the match is exact-token, never substring.
|
|
61
|
+
*/
|
|
62
|
+
const RULES: IdleFloorRule[] = [
|
|
63
|
+
{
|
|
64
|
+
id: "azure-app-service-premium-idle-floor",
|
|
65
|
+
resourceType: "azurerm_service_plan",
|
|
66
|
+
why: "A Premium v3 App Service plan bills for reserved compute for as long as it exists — requests do not change the bill.",
|
|
67
|
+
meters: {
|
|
68
|
+
p0v3: "app-service-p0v3",
|
|
69
|
+
p1v3: "app-service-p1v3",
|
|
70
|
+
p2v3: "app-service-p2v3",
|
|
71
|
+
p3v3: "app-service-p3v3",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "azure-firewall-idle-floor",
|
|
76
|
+
resourceType: "azurerm_firewall",
|
|
77
|
+
why: "Azure Firewall bills a fixed deployment charge per hour; data-processing fees are on top of it, never instead of it.",
|
|
78
|
+
meters: {
|
|
79
|
+
basic: "firewall-basic",
|
|
80
|
+
standard: "firewall-standard",
|
|
81
|
+
premium: "firewall-premium",
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "azure-bastion-idle-floor",
|
|
86
|
+
resourceType: "azurerm_bastion_host",
|
|
87
|
+
why: "A Bastion host bills per hour for the deployed gateway whether or not anyone connects through it.",
|
|
88
|
+
// NB the `Developer` SKU is free and deliberately absent — it must never be
|
|
89
|
+
// priced at the Basic rate.
|
|
90
|
+
meters: {
|
|
91
|
+
basic: "bastion-basic",
|
|
92
|
+
standard: "bastion-standard",
|
|
93
|
+
premium: "bastion-premium",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: "azure-vpn-gateway-idle-floor",
|
|
98
|
+
resourceType: "azurerm_virtual_network_gateway",
|
|
99
|
+
why: "A VPN gateway bills per hour for the provisioned gateway SKU with no tunnels connected.",
|
|
100
|
+
// `Basic` and the ExpressRoute SKUs are absent: different meters, and pricing
|
|
101
|
+
// them from a VpnGw rate would overstate by several times.
|
|
102
|
+
meters: {
|
|
103
|
+
vpngw1: "vpn-gateway-vpngw1",
|
|
104
|
+
vpngw2: "vpn-gateway-vpngw2",
|
|
105
|
+
vpngw3: "vpn-gateway-vpngw3",
|
|
106
|
+
vpngw4: "vpn-gateway-vpngw4",
|
|
107
|
+
vpngw5: "vpn-gateway-vpngw5",
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "azure-redis-idle-floor",
|
|
112
|
+
resourceType: "azurerm_redis_cache",
|
|
113
|
+
why: "A provisioned Redis cache bills per hour for reserved capacity independent of operations served.",
|
|
114
|
+
// `capacity` is numeric and so unreadable from string literals; each tier maps
|
|
115
|
+
// to its SMALLEST cache, a true lower bound for that tier. The Basic tier is
|
|
116
|
+
// absent — it is priced on a different meter than Standard C0.
|
|
117
|
+
meters: { premium: "redis-p1", standard: "redis-c0" },
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
/** One resource billing at zero traffic. */
|
|
122
|
+
export interface IdleFloorItem {
|
|
123
|
+
/** `type.name` of the Terraform resource. */
|
|
124
|
+
address: string;
|
|
125
|
+
resourceType: string;
|
|
126
|
+
file: string;
|
|
127
|
+
line: number;
|
|
128
|
+
/** The rule that fired. */
|
|
129
|
+
rule_id: string;
|
|
130
|
+
why: string;
|
|
131
|
+
/** Meter key resolved from the bundled snapshot. */
|
|
132
|
+
meter: string;
|
|
133
|
+
monthly_cost: number;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** A catalogued resource type whose tier could not be identified, so it was not
|
|
137
|
+
* priced. Reported so the floor states exactly what it left out. */
|
|
138
|
+
export interface UnpricedResource {
|
|
139
|
+
address: string;
|
|
140
|
+
resourceType: string;
|
|
141
|
+
file: string;
|
|
142
|
+
line: number;
|
|
143
|
+
reason: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface IdleFloorReport {
|
|
147
|
+
currency: string;
|
|
148
|
+
region: string;
|
|
149
|
+
/** ISO date the bundled price snapshot was captured. */
|
|
150
|
+
priced_at: string;
|
|
151
|
+
items: IdleFloorItem[];
|
|
152
|
+
/** Sum of every item's monthly cost, rounded to cents. */
|
|
153
|
+
monthly_floor: number;
|
|
154
|
+
/** Catalogued resources left unpriced because their tier wasn't identifiable —
|
|
155
|
+
* the floor is a lower bound by exactly these. */
|
|
156
|
+
unpriced: UnpricedResource[];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Round to cents so the number is stable and printable. */
|
|
160
|
+
function cents(n: number): number {
|
|
161
|
+
return Math.round(n * 100) / 100;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Detect every resource that bills at zero traffic, priced from the bundled
|
|
166
|
+
* snapshot. Pure and deterministic — no fs, no network, no credentials. Items
|
|
167
|
+
* come back in source order (file, then line) so `cost.md` is diff-stable.
|
|
168
|
+
*/
|
|
169
|
+
export function detectIdleFloor(
|
|
170
|
+
resources: ReadonlyArray<TfResourceEntry>,
|
|
171
|
+
): IdleFloorReport {
|
|
172
|
+
const byType = new Map(RULES.map((r) => [r.resourceType, r]));
|
|
173
|
+
const items: IdleFloorItem[] = [];
|
|
174
|
+
const unpriced: UnpricedResource[] = [];
|
|
175
|
+
for (const entry of resources) {
|
|
176
|
+
const rule = byType.get(entry.type);
|
|
177
|
+
if (!rule) continue;
|
|
178
|
+
const literals = new Set(entry.identifiers);
|
|
179
|
+
// Exact-token match against the block's string literals — the same discipline
|
|
180
|
+
// the CSPM ARN matcher uses; a substring match would let an unrelated literal
|
|
181
|
+
// pick the wrong (and possibly pricier) SKU. When several tier words appear in
|
|
182
|
+
// one block (a tier literal plus a tag value, say) take the CHEAPEST match, so
|
|
183
|
+
// the result can only under-claim and never depends on declaration order.
|
|
184
|
+
const priced = Object.entries(rule.meters)
|
|
185
|
+
.filter(([sku]) => literals.has(sku))
|
|
186
|
+
.map(([, meter]) => ({ meter, hourly: AZURE_HOURLY_PRICES[meter] }))
|
|
187
|
+
.filter(
|
|
188
|
+
(m): m is { meter: string; hourly: number } =>
|
|
189
|
+
typeof m.hourly === "number",
|
|
190
|
+
)
|
|
191
|
+
.sort((a, b) => a.hourly - b.hourly)[0];
|
|
192
|
+
if (!priced) {
|
|
193
|
+
unpriced.push({
|
|
194
|
+
address: entry.address,
|
|
195
|
+
resourceType: entry.type,
|
|
196
|
+
file: entry.file,
|
|
197
|
+
line: entry.line,
|
|
198
|
+
reason:
|
|
199
|
+
"tier not identifiable from source, or not one this catalog prices — left unpriced " +
|
|
200
|
+
"because this resource type has cheap or free tiers and a guess could only overstate",
|
|
201
|
+
});
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
items.push({
|
|
205
|
+
address: entry.address,
|
|
206
|
+
resourceType: entry.type,
|
|
207
|
+
file: entry.file,
|
|
208
|
+
line: entry.line,
|
|
209
|
+
rule_id: rule.id,
|
|
210
|
+
why: rule.why,
|
|
211
|
+
meter: priced.meter,
|
|
212
|
+
monthly_cost: cents(priced.hourly * HOURS_PER_MONTH),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
items.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
216
|
+
unpriced.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
217
|
+
return {
|
|
218
|
+
currency: AZURE_PRICE_CURRENCY,
|
|
219
|
+
region: AZURE_PRICE_REGION,
|
|
220
|
+
priced_at: AZURE_PRICE_FETCHED_AT,
|
|
221
|
+
items,
|
|
222
|
+
monthly_floor: cents(items.reduce((sum, i) => sum + i.monthly_cost, 0)),
|
|
223
|
+
unpriced,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** What the idle-floor number does and does not assert — carried verbatim into
|
|
228
|
+
* `cost.md` and the signed evidence bundle so the claim can never drift. */
|
|
229
|
+
export const IDLE_FLOOR_ASSERTS =
|
|
230
|
+
"These resources bill at a fixed rate for as long as they exist, at public list prices " +
|
|
231
|
+
`for ${AZURE_PRICE_REGION} captured ${AZURE_PRICE_FETCHED_AT}.`;
|
|
232
|
+
export const IDLE_FLOOR_DOES_NOT_ASSERT =
|
|
233
|
+
"This is NOT a total cost estimate and NOT your bill. It excludes all usage-dependent " +
|
|
234
|
+
"charges (data processed, requests, egress, storage), any discounts, reservations or " +
|
|
235
|
+
"enterprise agreement pricing, every resource type outside the idle-floor catalog, and " +
|
|
236
|
+
"any listed resource whose tier could not be identified. Actual spend is higher than " +
|
|
237
|
+
"this floor, never lower.";
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Render the `cost.md` artifact. Pure and deterministic — the same report always
|
|
241
|
+
* produces the same bytes, so re-running on an unchanged plan yields no diff.
|
|
242
|
+
*/
|
|
243
|
+
export function renderCostMarkdown(
|
|
244
|
+
report: IdleFloorReport,
|
|
245
|
+
toolVersion: string,
|
|
246
|
+
): string {
|
|
247
|
+
const money = (n: number) => `${report.currency} ${n.toFixed(2)}`;
|
|
248
|
+
const lines: string[] = [
|
|
249
|
+
"# Cost analysis — idle floor",
|
|
250
|
+
"",
|
|
251
|
+
`**${money(report.monthly_floor)} / month** accrues from ${report.items.length} resource(s) ` +
|
|
252
|
+
"even at zero traffic.",
|
|
253
|
+
"",
|
|
254
|
+
IDLE_FLOOR_ASSERTS,
|
|
255
|
+
"",
|
|
256
|
+
];
|
|
257
|
+
if (report.items.length === 0) {
|
|
258
|
+
lines.push(
|
|
259
|
+
"No resources from the idle-floor catalog were priced in this configuration.",
|
|
260
|
+
"",
|
|
261
|
+
);
|
|
262
|
+
} else {
|
|
263
|
+
lines.push(
|
|
264
|
+
"| Resource | Type | Location | Monthly |",
|
|
265
|
+
"| --- | --- | --- | --- |",
|
|
266
|
+
...report.items.map(
|
|
267
|
+
(i) =>
|
|
268
|
+
`| \`${i.address}\` | ${i.resourceType} | ${i.file}:${i.line} | ${money(i.monthly_cost)} |`,
|
|
269
|
+
),
|
|
270
|
+
"",
|
|
271
|
+
"## Why these bill at zero traffic",
|
|
272
|
+
"",
|
|
273
|
+
);
|
|
274
|
+
// One bullet per distinct rule, not per resource, so the section stays short.
|
|
275
|
+
const seen = new Set<string>();
|
|
276
|
+
for (const i of report.items) {
|
|
277
|
+
if (seen.has(i.rule_id)) continue;
|
|
278
|
+
seen.add(i.rule_id);
|
|
279
|
+
lines.push(`- **${i.resourceType}** — ${i.why}`);
|
|
280
|
+
}
|
|
281
|
+
lines.push("");
|
|
282
|
+
}
|
|
283
|
+
if (report.unpriced.length > 0) {
|
|
284
|
+
lines.push(
|
|
285
|
+
"## Not priced — the floor is a lower bound by these",
|
|
286
|
+
"",
|
|
287
|
+
...report.unpriced.map(
|
|
288
|
+
(u) => `- \`${u.address}\` (${u.file}:${u.line}) — ${u.reason}`,
|
|
289
|
+
),
|
|
290
|
+
"",
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
lines.push(
|
|
294
|
+
"## What this number does not include",
|
|
295
|
+
"",
|
|
296
|
+
IDLE_FLOOR_DOES_NOT_ASSERT,
|
|
297
|
+
"",
|
|
298
|
+
"---",
|
|
299
|
+
"",
|
|
300
|
+
`generated-by: infraweaver ${toolVersion} · prices: Azure list, ${report.region}, ${report.priced_at}`,
|
|
301
|
+
"",
|
|
302
|
+
);
|
|
303
|
+
return lines.join("\n");
|
|
304
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KEYLESS (Sigstore) signing — the SECOND evidence tier, alongside the Ed25519
|
|
3
|
+
* detached signature in [[signing]].
|
|
4
|
+
*
|
|
5
|
+
* Where the Ed25519 tier proves "signed by whoever holds INFRAWEAVER_SIGNING_KEY"
|
|
6
|
+
* (and needs that key distributed to verifiers), the keyless tier signs with the
|
|
7
|
+
* workflow's ephemeral GitHub Actions OIDC identity: Fulcio issues a short-lived
|
|
8
|
+
* X.509 cert bound to "this repo, this workflow, this run", the signature +
|
|
9
|
+
* cert + an inclusion proof go into a Sigstore **bundle**, and the signing event
|
|
10
|
+
* is recorded in the public **Rekor** transparency log. There is no key to
|
|
11
|
+
* distribute — a verifier checks the CERTIFICATE IDENTITY (the workflow ref +
|
|
12
|
+
* the GitHub OIDC issuer), not a pinned fingerprint. That converts the
|
|
13
|
+
* fingerprint-pinning problem into a certificate-identity check.
|
|
14
|
+
*
|
|
15
|
+
* The signed payload is an in-toto v1 attestation whose `subject` is the evidence
|
|
16
|
+
* artifact (by sha256 digest) and whose `predicate` is a compact summary — the
|
|
17
|
+
* same shape that slots into a CycloneDX/VEX attestation pipeline.
|
|
18
|
+
*
|
|
19
|
+
* OPT-IN + best-effort: enabled by `INFRAWEAVER_KEYLESS_SIGNING=true` and only when
|
|
20
|
+
* an ambient OIDC identity was captured (CI with `id-token: write`). It performs
|
|
21
|
+
* live network calls to Fulcio + Rekor, so a failure is logged and the emit still
|
|
22
|
+
* succeeds with the deterministic bundle + optional Ed25519 `.sig` — a transient
|
|
23
|
+
* Rekor outage must not block emitting evidence.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
import { bundleToJSON, type SerializedBundle } from "@sigstore/bundle";
|
|
28
|
+
import { DSSEBundleBuilder, FulcioSigner, RekorWitness } from "@sigstore/sign";
|
|
29
|
+
import {
|
|
30
|
+
fetchSigstoreOidcToken,
|
|
31
|
+
keylessOidcAvailable,
|
|
32
|
+
} from "#app/utils/keylessOidc";
|
|
33
|
+
|
|
34
|
+
export const KEYLESS_SIGNING_ENV = "INFRAWEAVER_KEYLESS_SIGNING";
|
|
35
|
+
|
|
36
|
+
/** The in-toto predicateType for a Infraweaver evidence attestation. */
|
|
37
|
+
export const INFRAWEAVER_ATTESTATION_PREDICATE_TYPE =
|
|
38
|
+
"https://infraweaver.dev/attestations/evidence/v1" as const;
|
|
39
|
+
|
|
40
|
+
/** DSSE payloadType for an in-toto statement (the Sigstore/in-toto convention). */
|
|
41
|
+
const IN_TOTO_PAYLOAD_TYPE = "application/vnd.in-toto+json";
|
|
42
|
+
|
|
43
|
+
/** in-toto Statement v1 — what actually gets DSSE-signed. */
|
|
44
|
+
export interface InTotoStatement {
|
|
45
|
+
_type: "https://in-toto.io/Statement/v1";
|
|
46
|
+
subject: Array<{ name: string; digest: { sha256: string } }>;
|
|
47
|
+
predicateType: string;
|
|
48
|
+
predicate: Record<string, unknown>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Opt-in check — keyless signing performs live Fulcio/Rekor calls, so it never
|
|
52
|
+
* runs unless explicitly enabled. Distinct from {@link keylessSigningPossible}. */
|
|
53
|
+
export function keylessSigningEnabled(
|
|
54
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
55
|
+
): boolean {
|
|
56
|
+
const v = env[KEYLESS_SIGNING_ENV]?.trim().toLowerCase();
|
|
57
|
+
return v === "true" || v === "1" || v === "yes";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** True when keyless signing is both enabled AND an ambient OIDC identity was
|
|
61
|
+
* captured (running in CI with id-token:write). The emit tools gate on this. */
|
|
62
|
+
export function keylessSigningPossible(
|
|
63
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
64
|
+
): boolean {
|
|
65
|
+
return keylessSigningEnabled(env) && keylessOidcAvailable();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Build the in-toto v1 Statement that attests `artifactBytes` by sha256 digest.
|
|
70
|
+
* Pure — the signable payload, independent of any network. The predicate carries
|
|
71
|
+
* a compact, non-authoritative summary (the artifact itself is the authority; the
|
|
72
|
+
* attestation binds it to the workflow identity).
|
|
73
|
+
*/
|
|
74
|
+
export function buildInTotoStatement(args: {
|
|
75
|
+
subjectName: string;
|
|
76
|
+
artifactBytes: string | Buffer;
|
|
77
|
+
predicate: Record<string, unknown>;
|
|
78
|
+
predicateType?: string;
|
|
79
|
+
}): InTotoStatement {
|
|
80
|
+
const data =
|
|
81
|
+
typeof args.artifactBytes === "string"
|
|
82
|
+
? Buffer.from(args.artifactBytes, "utf8")
|
|
83
|
+
: args.artifactBytes;
|
|
84
|
+
const sha256 = createHash("sha256").update(data).digest("hex");
|
|
85
|
+
return {
|
|
86
|
+
_type: "https://in-toto.io/Statement/v1",
|
|
87
|
+
subject: [{ name: args.subjectName, digest: { sha256 } }],
|
|
88
|
+
predicateType: args.predicateType ?? INFRAWEAVER_ATTESTATION_PREDICATE_TYPE,
|
|
89
|
+
predicate: args.predicate,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The sibling filename the Sigstore bundle is written to, next to `artifactPath`. */
|
|
94
|
+
export function keylessBundlePath(artifactPath: string): string {
|
|
95
|
+
return `${artifactPath}.sigstore.json`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Keyless-sign an in-toto statement: mint a `sigstore`-audience OIDC token, get a
|
|
100
|
+
* short-lived Fulcio signing cert for it, DSSE-sign the statement, and record the
|
|
101
|
+
* entry in Rekor. Returns the serialized Sigstore bundle (write it as
|
|
102
|
+
* `<artifact>.sigstore.json`). NETWORK — Fulcio + Rekor. Throws on any failure;
|
|
103
|
+
* callers treat keyless as best-effort and log rather than abort the emit.
|
|
104
|
+
*/
|
|
105
|
+
export async function keylessSignStatement(
|
|
106
|
+
statement: InTotoStatement,
|
|
107
|
+
): Promise<SerializedBundle> {
|
|
108
|
+
const signer = new FulcioSigner({
|
|
109
|
+
identityProvider: { getToken: () => fetchSigstoreOidcToken() },
|
|
110
|
+
});
|
|
111
|
+
// Rekor v1 dsse entry — the transparency-log record. certificateChain:false
|
|
112
|
+
// keeps just the leaf cert in the bundle (the trust root supplies the chain).
|
|
113
|
+
const builder = new DSSEBundleBuilder({
|
|
114
|
+
signer,
|
|
115
|
+
witnesses: [new RekorWitness({ entryType: "dsse" })],
|
|
116
|
+
certificateChain: false,
|
|
117
|
+
});
|
|
118
|
+
const bundle = await builder.create({
|
|
119
|
+
data: Buffer.from(JSON.stringify(statement), "utf8"),
|
|
120
|
+
type: IN_TOTO_PAYLOAD_TYPE,
|
|
121
|
+
});
|
|
122
|
+
return bundleToJSON(bundle);
|
|
123
|
+
}
|