@intentius/chant-lexicon-terraform 0.124.52 → 0.124.55

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.
Files changed (641) hide show
  1. package/README.md +14 -10
  2. package/dist/__fixtures__/pr-loop/estate.component.d.ts +7 -0
  3. package/dist/__fixtures__/pr-loop/estate.component.d.ts.map +1 -0
  4. package/dist/__fixtures__/pr-loop/estate.component.js +7 -0
  5. package/dist/__fixtures__/report/generate.d.ts +26 -0
  6. package/dist/__fixtures__/report/generate.d.ts.map +1 -0
  7. package/dist/__fixtures__/report/generate.js +58 -0
  8. package/dist/applied-state.d.ts +27 -0
  9. package/dist/applied-state.d.ts.map +1 -0
  10. package/dist/applied-state.js +44 -0
  11. package/dist/backend-config.d.ts +53 -0
  12. package/dist/backend-config.d.ts.map +1 -0
  13. package/dist/backend-config.js +136 -0
  14. package/dist/behaviour/kinds.d.ts.map +1 -1
  15. package/dist/behaviour/kinds.js +4 -0
  16. package/dist/behaviour/predict.d.ts.map +1 -1
  17. package/dist/behaviour/predict.js +6 -2
  18. package/dist/behaviour/reference-catalog.d.ts +16 -5
  19. package/dist/behaviour/reference-catalog.d.ts.map +1 -1
  20. package/dist/behaviour/reference-catalog.js +16 -5
  21. package/dist/behaviour/request.d.ts.map +1 -1
  22. package/dist/behaviour/request.js +3 -2
  23. package/dist/changed-roots.d.ts +6 -4
  24. package/dist/changed-roots.d.ts.map +1 -1
  25. package/dist/changed-roots.js +14 -18
  26. package/dist/ci-setup.d.ts +11 -0
  27. package/dist/ci-setup.d.ts.map +1 -0
  28. package/dist/ci-setup.js +41 -0
  29. package/dist/commands.d.ts.map +1 -1
  30. package/dist/commands.js +4 -3
  31. package/dist/components/capability-plugin.d.ts +105 -9
  32. package/dist/components/capability-plugin.d.ts.map +1 -1
  33. package/dist/components/capability-plugin.js +357 -36
  34. package/dist/components/compose-group.d.ts +145 -0
  35. package/dist/components/compose-group.d.ts.map +1 -0
  36. package/dist/components/compose-group.js +407 -0
  37. package/dist/components/placeholder-preview.d.ts +78 -0
  38. package/dist/components/placeholder-preview.d.ts.map +1 -0
  39. package/dist/components/placeholder-preview.js +254 -0
  40. package/dist/components/release-inputs.d.ts +29 -0
  41. package/dist/components/release-inputs.d.ts.map +1 -0
  42. package/dist/components/release-inputs.js +57 -0
  43. package/dist/components/trace-facts.d.ts +16 -0
  44. package/dist/components/trace-facts.d.ts.map +1 -0
  45. package/dist/components/trace-facts.js +19 -0
  46. package/dist/compose/apply-events.d.ts +46 -0
  47. package/dist/compose/apply-events.d.ts.map +1 -0
  48. package/dist/compose/apply-events.js +77 -0
  49. package/dist/compose/estate.d.ts +194 -0
  50. package/dist/compose/estate.d.ts.map +1 -0
  51. package/dist/compose/estate.js +363 -0
  52. package/dist/compose/hcl.d.ts +99 -0
  53. package/dist/compose/hcl.d.ts.map +1 -0
  54. package/dist/compose/hcl.js +302 -0
  55. package/dist/compose/module-address.d.ts +24 -0
  56. package/dist/compose/module-address.d.ts.map +1 -0
  57. package/dist/compose/module-address.js +43 -0
  58. package/dist/compose/root.d.ts +127 -0
  59. package/dist/compose/root.d.ts.map +1 -0
  60. package/dist/compose/root.js +586 -0
  61. package/dist/compose/run.d.ts +183 -0
  62. package/dist/compose/run.d.ts.map +1 -0
  63. package/dist/compose/run.js +447 -0
  64. package/dist/compose/slice.d.ts +102 -0
  65. package/dist/compose/slice.d.ts.map +1 -0
  66. package/dist/compose/slice.js +249 -0
  67. package/dist/compose/state-address.d.ts +28 -0
  68. package/dist/compose/state-address.d.ts.map +1 -0
  69. package/dist/compose/state-address.js +154 -0
  70. package/dist/compose/state-merge.d.ts +52 -0
  71. package/dist/compose/state-merge.d.ts.map +1 -0
  72. package/dist/compose/state-merge.js +135 -0
  73. package/dist/compose.d.ts +179 -0
  74. package/dist/compose.d.ts.map +1 -0
  75. package/dist/compose.js +482 -0
  76. package/dist/composites/terraform-apply-op.d.ts.map +1 -1
  77. package/dist/composites/terraform-apply-op.js +7 -3
  78. package/dist/cone.d.ts +53 -0
  79. package/dist/cone.d.ts.map +1 -0
  80. package/dist/cone.js +119 -0
  81. package/dist/config.d.ts +59 -13
  82. package/dist/config.d.ts.map +1 -1
  83. package/dist/config.js +43 -9
  84. package/dist/cost-hold.d.ts +27 -0
  85. package/dist/cost-hold.d.ts.map +1 -0
  86. package/dist/cost-hold.js +21 -0
  87. package/dist/describe-resources.d.ts +74 -12
  88. package/dist/describe-resources.d.ts.map +1 -1
  89. package/dist/describe-resources.js +374 -66
  90. package/dist/drift-read.d.ts +33 -0
  91. package/dist/drift-read.d.ts.map +1 -0
  92. package/dist/drift-read.js +243 -0
  93. package/dist/drift-record.d.ts +147 -0
  94. package/dist/drift-record.d.ts.map +1 -0
  95. package/dist/drift-record.js +383 -0
  96. package/dist/drift-rows.d.ts +61 -0
  97. package/dist/drift-rows.d.ts.map +1 -0
  98. package/dist/drift-rows.js +108 -0
  99. package/dist/exit-codes.d.ts +55 -0
  100. package/dist/exit-codes.d.ts.map +1 -0
  101. package/dist/exit-codes.js +48 -0
  102. package/dist/hcl/edges.d.ts.map +1 -1
  103. package/dist/hcl/edges.js +24 -1
  104. package/dist/hcl/files.d.ts +61 -0
  105. package/dist/hcl/files.d.ts.map +1 -0
  106. package/dist/hcl/files.js +221 -0
  107. package/dist/hcl/instances.d.ts +82 -0
  108. package/dist/hcl/instances.d.ts.map +1 -0
  109. package/dist/hcl/instances.js +390 -0
  110. package/dist/hcl/parse.d.ts +81 -9
  111. package/dist/hcl/parse.d.ts.map +1 -1
  112. package/dist/hcl/parse.js +114 -16
  113. package/dist/hcl/roots.d.ts.map +1 -1
  114. package/dist/hcl/roots.js +5 -0
  115. package/dist/hcl/suppressions.d.ts.map +1 -1
  116. package/dist/hcl/suppressions.js +8 -2
  117. package/dist/index.d.ts +13 -2
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +24 -2
  120. package/dist/integrity.json +8 -5
  121. package/dist/lint/audit-catalog.d.ts.map +1 -1
  122. package/dist/lint/audit-catalog.js +27 -3
  123. package/dist/lint/audit-lineage.d.ts +14 -2
  124. package/dist/lint/audit-lineage.d.ts.map +1 -1
  125. package/dist/lint/post-synth/index.d.ts.map +1 -1
  126. package/dist/lint/post-synth/index.js +4 -0
  127. package/dist/lint/post-synth/record-store.d.ts +54 -0
  128. package/dist/lint/post-synth/record-store.d.ts.map +1 -0
  129. package/dist/lint/post-synth/record-store.js +104 -0
  130. package/dist/lint/post-synth/tf001.d.ts +2 -2
  131. package/dist/lint/post-synth/tf001.js +2 -2
  132. package/dist/lint/post-synth/tf024.d.ts +35 -11
  133. package/dist/lint/post-synth/tf024.d.ts.map +1 -1
  134. package/dist/lint/post-synth/tf024.js +92 -20
  135. package/dist/lint/post-synth/tf046.d.ts +64 -0
  136. package/dist/lint/post-synth/tf046.d.ts.map +1 -0
  137. package/dist/lint/post-synth/tf046.js +175 -0
  138. package/dist/lint/post-synth/tf047.d.ts +36 -0
  139. package/dist/lint/post-synth/tf047.d.ts.map +1 -0
  140. package/dist/lint/post-synth/tf047.js +94 -0
  141. package/dist/live-plan-reasons.d.ts +21 -0
  142. package/dist/live-plan-reasons.d.ts.map +1 -0
  143. package/dist/live-plan-reasons.js +47 -0
  144. package/dist/lock-rows.d.ts +36 -0
  145. package/dist/lock-rows.d.ts.map +1 -0
  146. package/dist/lock-rows.js +60 -0
  147. package/dist/lock-timeout.d.ts +22 -0
  148. package/dist/lock-timeout.d.ts.map +1 -0
  149. package/dist/lock-timeout.js +32 -0
  150. package/dist/lsp/option-keys.d.ts.map +1 -1
  151. package/dist/lsp/option-keys.js +2 -0
  152. package/dist/manifest.json +1 -1
  153. package/dist/module-catalog/index.d.ts +69 -0
  154. package/dist/module-catalog/index.d.ts.map +1 -0
  155. package/dist/module-catalog/index.js +110 -0
  156. package/dist/module-catalog/refresh-cli.d.ts +4 -0
  157. package/dist/module-catalog/refresh-cli.d.ts.map +1 -0
  158. package/dist/module-catalog/refresh-cli.js +64 -0
  159. package/dist/module-catalog/static-tier.d.ts +6 -0
  160. package/dist/module-catalog/static-tier.d.ts.map +1 -0
  161. package/dist/module-catalog/static-tier.js +1650 -0
  162. package/dist/module-catalog/types.d.ts +65 -0
  163. package/dist/module-catalog/types.d.ts.map +1 -0
  164. package/dist/module-catalog/types.js +33 -0
  165. package/dist/okf/index.md +3 -1
  166. package/dist/okf/rules/TF024.md +2 -2
  167. package/dist/okf/rules/TF046.md +11 -0
  168. package/dist/okf/rules/TF047.md +11 -0
  169. package/dist/op/activities/index.d.ts +6 -2
  170. package/dist/op/activities/index.d.ts.map +1 -1
  171. package/dist/op/activities/index.js +5 -1
  172. package/dist/op/activities/live-detect.d.ts +4 -3
  173. package/dist/op/activities/live-detect.d.ts.map +1 -1
  174. package/dist/op/activities/live-detect.js +57 -32
  175. package/dist/op/activities/pin-rollout.d.ts +2 -0
  176. package/dist/op/activities/pin-rollout.d.ts.map +1 -1
  177. package/dist/op/activities/pin-rollout.js +1 -0
  178. package/dist/op/activities/terraform.d.ts +182 -5
  179. package/dist/op/activities/terraform.d.ts.map +1 -1
  180. package/dist/op/activities/terraform.js +224 -24
  181. package/dist/op/activity-contracts.d.ts +27 -0
  182. package/dist/op/activity-contracts.d.ts.map +1 -1
  183. package/dist/op/activity-contracts.js +19 -1
  184. package/dist/op/builders.d.ts +7 -1
  185. package/dist/op/builders.d.ts.map +1 -1
  186. package/dist/op/builders.js +9 -0
  187. package/dist/pin/consumers.d.ts +35 -0
  188. package/dist/pin/consumers.d.ts.map +1 -0
  189. package/dist/pin/consumers.js +70 -0
  190. package/dist/pin/edit.d.ts.map +1 -1
  191. package/dist/pin/edit.js +35 -0
  192. package/dist/pin/rollout.d.ts +2 -0
  193. package/dist/pin/rollout.d.ts.map +1 -1
  194. package/dist/pin/rollout.js +14 -11
  195. package/dist/plan-shape.d.ts +30 -0
  196. package/dist/plan-shape.d.ts.map +1 -0
  197. package/dist/plan-shape.js +125 -0
  198. package/dist/plugin.d.ts.map +1 -1
  199. package/dist/plugin.js +37 -18
  200. package/dist/registry/address.d.ts +63 -0
  201. package/dist/registry/address.d.ts.map +1 -0
  202. package/dist/registry/address.js +65 -0
  203. package/dist/registry/catalog-read.d.ts +14 -0
  204. package/dist/registry/catalog-read.d.ts.map +1 -0
  205. package/dist/registry/catalog-read.js +58 -0
  206. package/dist/registry/deprecated.d.ts +37 -0
  207. package/dist/registry/deprecated.d.ts.map +1 -0
  208. package/dist/registry/deprecated.js +43 -0
  209. package/dist/registry/docs.d.ts +96 -0
  210. package/dist/registry/docs.d.ts.map +1 -0
  211. package/dist/registry/docs.js +210 -0
  212. package/dist/registry/edge/edge.d.ts +46 -0
  213. package/dist/registry/edge/edge.d.ts.map +1 -0
  214. package/dist/registry/edge/edge.js +194 -0
  215. package/dist/registry/edge/index.d.ts +11 -0
  216. package/dist/registry/edge/index.d.ts.map +1 -0
  217. package/dist/registry/edge/index.js +10 -0
  218. package/dist/registry/edge/lambda-edge.d.ts +76 -0
  219. package/dist/registry/edge/lambda-edge.d.ts.map +1 -0
  220. package/dist/registry/edge/lambda-edge.js +95 -0
  221. package/dist/registry/edge/sigv4-web.d.ts +33 -0
  222. package/dist/registry/edge/sigv4-web.d.ts.map +1 -0
  223. package/dist/registry/edge/sigv4-web.js +56 -0
  224. package/dist/registry/edge/token-source.d.ts +73 -0
  225. package/dist/registry/edge/token-source.d.ts.map +1 -0
  226. package/dist/registry/edge/token-source.js +115 -0
  227. package/dist/registry/edge/worker.d.ts +45 -0
  228. package/dist/registry/edge/worker.d.ts.map +1 -0
  229. package/dist/registry/edge/worker.js +26 -0
  230. package/dist/registry/handler.d.ts +25 -0
  231. package/dist/registry/handler.d.ts.map +1 -0
  232. package/dist/registry/handler.js +75 -0
  233. package/dist/registry/headers-file.d.ts +21 -0
  234. package/dist/registry/headers-file.d.ts.map +1 -0
  235. package/dist/registry/headers-file.js +57 -0
  236. package/dist/registry/index.d.ts +31 -0
  237. package/dist/registry/index.d.ts.map +1 -0
  238. package/dist/registry/index.js +30 -0
  239. package/dist/registry/mirror-paths.d.ts +9 -0
  240. package/dist/registry/mirror-paths.d.ts.map +1 -0
  241. package/dist/registry/mirror-paths.js +8 -0
  242. package/dist/registry/mirror.d.ts +130 -0
  243. package/dist/registry/mirror.d.ts.map +1 -0
  244. package/dist/registry/mirror.js +319 -0
  245. package/dist/registry/proxies.d.ts +73 -0
  246. package/dist/registry/proxies.d.ts.map +1 -0
  247. package/dist/registry/proxies.js +111 -0
  248. package/dist/registry/reader.d.ts +57 -0
  249. package/dist/registry/reader.d.ts.map +1 -0
  250. package/dist/registry/reader.js +198 -0
  251. package/dist/registry/semver.d.ts +16 -0
  252. package/dist/registry/semver.d.ts.map +1 -0
  253. package/dist/registry/semver.js +24 -0
  254. package/dist/registry/serve.d.ts +24 -0
  255. package/dist/registry/serve.d.ts.map +1 -0
  256. package/dist/registry/serve.js +64 -0
  257. package/dist/registry/source-forms.d.ts +79 -0
  258. package/dist/registry/source-forms.d.ts.map +1 -0
  259. package/dist/registry/source-forms.js +202 -0
  260. package/dist/registry/targets/artifactory.d.ts +28 -0
  261. package/dist/registry/targets/artifactory.d.ts.map +1 -0
  262. package/dist/registry/targets/artifactory.js +206 -0
  263. package/dist/registry/targets/fake-artifactory.d.ts +30 -0
  264. package/dist/registry/targets/fake-artifactory.d.ts.map +1 -0
  265. package/dist/registry/targets/fake-artifactory.js +142 -0
  266. package/dist/registry/targets/fake-gitlab.d.ts +39 -0
  267. package/dist/registry/targets/fake-gitlab.d.ts.map +1 -0
  268. package/dist/registry/targets/fake-gitlab.js +136 -0
  269. package/dist/registry/targets/fake-hcp.d.ts +50 -0
  270. package/dist/registry/targets/fake-hcp.d.ts.map +1 -0
  271. package/dist/registry/targets/fake-hcp.js +202 -0
  272. package/dist/registry/targets/fake-http.d.ts +31 -0
  273. package/dist/registry/targets/fake-http.d.ts.map +1 -0
  274. package/dist/registry/targets/fake-http.js +87 -0
  275. package/dist/registry/targets/fake-nexus.d.ts +27 -0
  276. package/dist/registry/targets/fake-nexus.d.ts.map +1 -0
  277. package/dist/registry/targets/fake-nexus.js +137 -0
  278. package/dist/registry/targets/gitlab.d.ts +53 -0
  279. package/dist/registry/targets/gitlab.d.ts.map +1 -0
  280. package/dist/registry/targets/gitlab.js +187 -0
  281. package/dist/registry/targets/hcp.d.ts +29 -0
  282. package/dist/registry/targets/hcp.d.ts.map +1 -0
  283. package/dist/registry/targets/hcp.js +310 -0
  284. package/dist/registry/targets/hosted.d.ts +62 -0
  285. package/dist/registry/targets/hosted.d.ts.map +1 -0
  286. package/dist/registry/targets/hosted.js +74 -0
  287. package/dist/registry/targets/index.d.ts +18 -0
  288. package/dist/registry/targets/index.d.ts.map +1 -0
  289. package/dist/registry/targets/index.js +17 -0
  290. package/dist/registry/targets/module-target.d.ts +68 -0
  291. package/dist/registry/targets/module-target.d.ts.map +1 -0
  292. package/dist/registry/targets/module-target.js +63 -0
  293. package/dist/registry/targets/nexus.d.ts +43 -0
  294. package/dist/registry/targets/nexus.d.ts.map +1 -0
  295. package/dist/registry/targets/nexus.js +250 -0
  296. package/dist/registry/targets/zip.d.ts +55 -0
  297. package/dist/registry/targets/zip.d.ts.map +1 -0
  298. package/dist/registry/targets/zip.js +278 -0
  299. package/dist/registry/writer.d.ts +101 -0
  300. package/dist/registry/writer.d.ts.map +1 -0
  301. package/dist/registry/writer.js +109 -0
  302. package/dist/report.d.ts +15 -6
  303. package/dist/report.d.ts.map +1 -1
  304. package/dist/report.js +28 -55
  305. package/dist/rules/record-store.ts +122 -0
  306. package/dist/rules/tf001.ts +2 -2
  307. package/dist/rules/tf024.ts +105 -22
  308. package/dist/rules/tf046.ts +204 -0
  309. package/dist/rules/tf047.ts +114 -0
  310. package/dist/skills/chant-terraform.md +1 -1
  311. package/dist/state/azure-blob.d.ts +9 -0
  312. package/dist/state/azure-blob.d.ts.map +1 -0
  313. package/dist/state/azure-blob.js +8 -0
  314. package/dist/state/backend.d.ts +158 -0
  315. package/dist/state/backend.d.ts.map +1 -0
  316. package/dist/state/backend.js +406 -0
  317. package/dist/state/exec.d.ts +39 -0
  318. package/dist/state/exec.d.ts.map +1 -0
  319. package/dist/state/exec.js +80 -0
  320. package/dist/state/gcs.d.ts +8 -0
  321. package/dist/state/gcs.d.ts.map +1 -0
  322. package/dist/state/gcs.js +7 -0
  323. package/dist/state/index.d.ts +15 -0
  324. package/dist/state/index.d.ts.map +1 -0
  325. package/dist/state/index.js +14 -0
  326. package/dist/state/locks.d.ts +105 -0
  327. package/dist/state/locks.d.ts.map +1 -0
  328. package/dist/state/locks.js +130 -0
  329. package/dist/state/object-store.d.ts +8 -0
  330. package/dist/state/object-store.d.ts.map +1 -0
  331. package/dist/state/object-store.js +7 -0
  332. package/dist/state/root-states.d.ts +131 -0
  333. package/dist/state/root-states.d.ts.map +1 -0
  334. package/dist/state/root-states.js +241 -0
  335. package/dist/state/s3.d.ts +21 -0
  336. package/dist/state/s3.d.ts.map +1 -0
  337. package/dist/state/s3.js +19 -0
  338. package/dist/state/store.d.ts +51 -0
  339. package/dist/state/store.d.ts.map +1 -0
  340. package/dist/state/store.js +185 -0
  341. package/dist/state-ops.d.ts +255 -0
  342. package/dist/state-ops.d.ts.map +1 -0
  343. package/dist/state-ops.js +305 -0
  344. package/dist/state-reads.d.ts +57 -0
  345. package/dist/state-reads.d.ts.map +1 -0
  346. package/dist/state-reads.js +104 -0
  347. package/dist/terragrunt/affected.d.ts.map +1 -1
  348. package/dist/terragrunt/affected.js +2 -1
  349. package/dist/used-sources.d.ts +54 -0
  350. package/dist/used-sources.d.ts.map +1 -0
  351. package/dist/used-sources.js +157 -0
  352. package/package.json +24 -4
  353. package/src/__fixtures__/ACCEPTANCE.md +69 -7
  354. package/src/__fixtures__/compose/apply-failed-in-app.jsonl +12 -0
  355. package/src/__fixtures__/compose/state-app.json +66 -0
  356. package/src/__fixtures__/compose/state-edge.json +40 -0
  357. package/src/__fixtures__/compose/state-net.json +58 -0
  358. package/src/__fixtures__/compose/three-app.plan.json +184 -0
  359. package/src/__fixtures__/compose/three-composed.plan.json +509 -0
  360. package/src/__fixtures__/compose/three-edge.plan.json +144 -0
  361. package/src/__fixtures__/compose/three-net.plan.json +174 -0
  362. package/src/__fixtures__/compose/unknown-composed.plan.json +228 -0
  363. package/src/__fixtures__/compose/working-after-apply.json +145 -0
  364. package/src/__fixtures__/config-blocks/app/main.tf +61 -0
  365. package/src/__fixtures__/config-blocks/app/modules/network/main.tf +4 -0
  366. package/src/__fixtures__/config-blocks/app-json/main.tf.json +39 -0
  367. package/src/__fixtures__/config-files/shadow/main.tf +3 -0
  368. package/src/__fixtures__/config-files/shadow/main.tofu +3 -0
  369. package/src/__fixtures__/config-files/shadow/other.tf +3 -0
  370. package/src/__fixtures__/config-files/tf/main.tf +11 -0
  371. package/src/__fixtures__/config-files/tf-json/main.tf.json +18 -0
  372. package/src/__fixtures__/config-files/tofu/main.tofu +11 -0
  373. package/src/__fixtures__/config-files/tofu-json/main.tofu.json +18 -0
  374. package/src/__fixtures__/config-files/tofu-only/main.tofu +3 -0
  375. package/src/__fixtures__/drift-record/README.md +16 -0
  376. package/src/__fixtures__/drift-record/live-plan-sections.json +27 -0
  377. package/src/__fixtures__/drift-rows/live-root-plan.json +70 -0
  378. package/src/__fixtures__/drift-rows/refresh-plan.json +61 -0
  379. package/src/__fixtures__/instance-forms/app/main.tf +110 -0
  380. package/src/__fixtures__/instance-forms/app/modules/svc/main.tf +3 -0
  381. package/src/__fixtures__/instance-vars/app/main.tf +52 -0
  382. package/src/__fixtures__/instance-vars/app/modules/app/main.tf +12 -0
  383. package/src/__fixtures__/instance-vars/app/modules/edge/main.tf +3 -0
  384. package/src/__fixtures__/instance-vars/app/terraform.tfvars +1 -0
  385. package/src/__fixtures__/live-module-keyed/live-graph.json +259 -0
  386. package/src/__fixtures__/live-module-keyed/live-plan.json +87 -0
  387. package/src/__fixtures__/live-module-keyed/root/estate.chdf.hcl +1 -0
  388. package/src/__fixtures__/live-module-keyed/root/main.tf +21 -0
  389. package/src/__fixtures__/live-module-keyed/root/modules/app/main.tf +17 -0
  390. package/src/__fixtures__/live-module-keyed/root/modules/edge/main.tf +7 -0
  391. package/src/__fixtures__/live-module-keyed/root/versions.tf +30 -0
  392. package/src/__fixtures__/live-module-keyed/show-state.json +146 -0
  393. package/src/__fixtures__/pr-loop/README.md +50 -0
  394. package/src/__fixtures__/pr-loop/chant.config.json +13 -0
  395. package/src/__fixtures__/pr-loop/estate.component.ts +10 -0
  396. package/src/__fixtures__/pr-loop/roots/a/main.tf +11 -0
  397. package/src/__fixtures__/pr-loop/roots/app/main.tf +19 -0
  398. package/src/__fixtures__/pr-loop/roots/b/main.tf +7 -0
  399. package/src/__fixtures__/pr-loop/roots/dns/main.tf +3 -0
  400. package/src/__fixtures__/pr-loop/roots/net/main.tf +7 -0
  401. package/src/__fixtures__/report/applied.show.json +51 -0
  402. package/src/__fixtures__/report/generate.ts +63 -0
  403. package/src/__fixtures__/report/plan.show.json +200 -0
  404. package/src/__fixtures__/report/tf-apply/change-set.json +170 -0
  405. package/src/__fixtures__/report/tf-apply/report.json +338 -0
  406. package/src/__fixtures__/report/tf-plan/change-set.json +170 -0
  407. package/src/__fixtures__/report/tf-plan/report.json +320 -0
  408. package/src/__fixtures__/three-cloud-azure.graph.json +290 -0
  409. package/src/__fixtures__/used-sources/root/extra.tofu +1 -0
  410. package/src/__fixtures__/used-sources/root/main.tf +31 -0
  411. package/src/__fixtures__/used-sources/root/modules/net/main.tf +14 -0
  412. package/src/__fixtures__/used-sources/root/modules/net/versions.tf.json +7 -0
  413. package/src/__fixtures__/used-sources/unit/terragrunt.hcl +3 -0
  414. package/src/applied-state.ts +52 -0
  415. package/src/backend-config.test.ts +105 -0
  416. package/src/backend-config.ts +133 -0
  417. package/src/behaviour/kinds.ts +4 -0
  418. package/src/behaviour/predict.ts +5 -2
  419. package/src/behaviour/reference-catalog.plugin.test.ts +65 -0
  420. package/src/behaviour/reference-catalog.ts +16 -5
  421. package/src/behaviour/request.ts +3 -2
  422. package/src/change-set-instances.test.ts +98 -0
  423. package/src/changed-roots.ts +14 -16
  424. package/src/ci-setup.ts +42 -0
  425. package/src/commands.ts +4 -3
  426. package/src/components/capability-plugin.test.ts +198 -19
  427. package/src/components/capability-plugin.ts +383 -35
  428. package/src/components/change-set-graph.e2e.test.ts +11 -5
  429. package/src/components/compose-group.test.ts +486 -0
  430. package/src/components/compose-group.ts +489 -0
  431. package/src/components/demo-composed-roots.e2e.test.ts +440 -0
  432. package/src/components/member-outputs.test.ts +76 -0
  433. package/src/components/placeholder-preview.test.ts +147 -0
  434. package/src/components/placeholder-preview.ts +257 -0
  435. package/src/components/pr-loop-compose.tofu.e2e.test.ts +363 -0
  436. package/src/components/pr-loop.tofu.test.ts +113 -57
  437. package/src/components/release-inputs.ts +69 -0
  438. package/src/components/trace-facts.test.ts +21 -0
  439. package/src/components/trace-facts.ts +27 -0
  440. package/src/compose/apply-events.test.ts +62 -0
  441. package/src/compose/apply-events.ts +100 -0
  442. package/src/compose/estate.choudoufu.e2e.test.ts +112 -0
  443. package/src/compose/estate.test.ts +421 -0
  444. package/src/compose/estate.ts +443 -0
  445. package/src/compose/hcl.ts +311 -0
  446. package/src/compose/module-address.ts +49 -0
  447. package/src/compose/root.test.ts +416 -0
  448. package/src/compose/root.ts +592 -0
  449. package/src/compose/run.test.ts +440 -0
  450. package/src/compose/run.tofu.test.ts +176 -0
  451. package/src/compose/run.ts +527 -0
  452. package/src/compose/slice.test.ts +184 -0
  453. package/src/compose/slice.ts +290 -0
  454. package/src/compose/state-address.ts +157 -0
  455. package/src/compose/state-merge.test.ts +131 -0
  456. package/src/compose/state-merge.ts +148 -0
  457. package/src/compose.test.ts +248 -0
  458. package/src/compose.ts +627 -0
  459. package/src/composites/terraform-apply-op.test.ts +9 -0
  460. package/src/composites/terraform-apply-op.ts +7 -3
  461. package/src/cone.ts +138 -0
  462. package/src/config-file-listers.test.ts +265 -0
  463. package/src/config.ts +44 -9
  464. package/src/cost-hold.ts +29 -0
  465. package/src/describe-resources.engine-facts.test.ts +411 -0
  466. package/src/describe-resources.live-module-keyed.test.ts +290 -0
  467. package/src/describe-resources.ts +416 -70
  468. package/src/drift-read.ts +284 -0
  469. package/src/drift-record.test.ts +223 -0
  470. package/src/drift-record.ts +455 -0
  471. package/src/drift-rows.test.ts +135 -0
  472. package/src/drift-rows.ts +137 -0
  473. package/src/exit-codes.test.ts +23 -0
  474. package/src/exit-codes.ts +59 -0
  475. package/src/hcl/config-blocks.test.ts +174 -0
  476. package/src/hcl/edges.ts +21 -1
  477. package/src/hcl/files.ts +234 -0
  478. package/src/hcl/instance-forms.test.ts +94 -0
  479. package/src/hcl/instances.test.ts +137 -0
  480. package/src/hcl/instances.ts +422 -0
  481. package/src/hcl/parse.test.ts +139 -1
  482. package/src/hcl/parse.ts +149 -16
  483. package/src/hcl/roots.ts +6 -0
  484. package/src/hcl/suppressions.ts +8 -2
  485. package/src/index.ts +79 -0
  486. package/src/lint/audit-catalog.ts +29 -3
  487. package/src/lint/audit-lineage.ts +14 -2
  488. package/src/lint/post-synth/fixtures/TF024/live-with-record-store/main.tf +18 -0
  489. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/estate.chdf.hcl +1 -0
  490. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/main.tf +10 -0
  491. package/src/lint/post-synth/fixtures/TF046/azurerm-no-resource-group/main.tf +15 -0
  492. package/src/lint/post-synth/fixtures/TF046/backend-config-only/main.tf +14 -0
  493. package/src/lint/post-synth/fixtures/TF046/derived-s3/backend.tf +7 -0
  494. package/src/lint/post-synth/fixtures/TF046/derived-s3/main.tf +9 -0
  495. package/src/lint/post-synth/fixtures/TF046/explicit-local/main.tf +16 -0
  496. package/src/lint/post-synth/fixtures/TF046/explicit-s3-beside-local-backend/main.tf +15 -0
  497. package/src/lint/post-synth/fixtures/TF046/implied-local/main.tf +9 -0
  498. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/estate.chdf.hcl +1 -0
  499. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/main.tf +5 -0
  500. package/src/lint/post-synth/fixtures/TF047/clear/main.tf +12 -0
  501. package/src/lint/post-synth/fixtures/TF047/refused/main.tf +12 -0
  502. package/src/lint/post-synth/fixtures/TF047/unknown-module/main.tf +12 -0
  503. package/src/lint/post-synth/fixtures/TF047/unknown-version/main.tf +12 -0
  504. package/src/lint/post-synth/index.ts +4 -0
  505. package/src/lint/post-synth/record-store.ts +122 -0
  506. package/src/lint/post-synth/tf001.ts +2 -2
  507. package/src/lint/post-synth/tf024.test.ts +26 -5
  508. package/src/lint/post-synth/tf024.ts +105 -22
  509. package/src/lint/post-synth/tf046.test.ts +137 -0
  510. package/src/lint/post-synth/tf046.ts +204 -0
  511. package/src/lint/post-synth/tf047.test.ts +56 -0
  512. package/src/lint/post-synth/tf047.ts +114 -0
  513. package/src/live-plan-reasons.ts +54 -0
  514. package/src/lock-rows.test.ts +70 -0
  515. package/src/lock-rows.ts +82 -0
  516. package/src/lock-timeout.ts +34 -0
  517. package/src/lsp/completions.test.ts +1 -1
  518. package/src/lsp/option-keys.ts +2 -0
  519. package/src/module-catalog/index.test.ts +93 -0
  520. package/src/module-catalog/index.ts +159 -0
  521. package/src/module-catalog/refresh-cli.ts +68 -0
  522. package/src/module-catalog/static-tier.ts +1659 -0
  523. package/src/module-catalog/types.ts +88 -0
  524. package/src/op/activities/choudoufu-plan-set-op.test.ts +111 -0
  525. package/src/op/activities/index.ts +9 -0
  526. package/src/op/activities/live-detect.ts +55 -26
  527. package/src/op/activities/pin-rollout.ts +3 -0
  528. package/src/op/activities/registry.test.ts +2 -1
  529. package/src/op/activities/terraform.test.ts +55 -0
  530. package/src/op/activities/terraform.ts +312 -27
  531. package/src/op/activity-contracts.test.ts +1 -0
  532. package/src/op/activity-contracts.ts +24 -1
  533. package/src/op/builders.ts +14 -0
  534. package/src/op-wave-step.test.ts +109 -0
  535. package/src/pin/__fixtures__/consumers/live/dev/main.tf +4 -0
  536. package/src/pin/__fixtures__/consumers/live/prod/main.tf +21 -0
  537. package/src/pin/__fixtures__/consumers/units/vpc/terragrunt.hcl +7 -0
  538. package/src/pin/bundle.test.ts +2 -0
  539. package/src/pin/consumers.test.ts +57 -0
  540. package/src/pin/consumers.ts +95 -0
  541. package/src/pin/edit.ts +30 -0
  542. package/src/pin/rollout.ts +16 -11
  543. package/src/plan-shape.test.ts +148 -0
  544. package/src/plan-shape.ts +128 -0
  545. package/src/plugin.ts +39 -19
  546. package/src/registry/__fixtures__/docs/documented/.terraform-docs.yml +3 -0
  547. package/src/registry/__fixtures__/docs/documented/README.md +1 -0
  548. package/src/registry/__fixtures__/docs/documented/main.tf +8 -0
  549. package/src/registry/__fixtures__/docs/json/main.tf.json +14 -0
  550. package/src/registry/__fixtures__/docs/vpc/README.md +3 -0
  551. package/src/registry/__fixtures__/docs/vpc/examples/complete/main.tf +5 -0
  552. package/src/registry/__fixtures__/docs/vpc/examples/simple/README.md +1 -0
  553. package/src/registry/__fixtures__/docs/vpc/examples/simple/main.tf +4 -0
  554. package/src/registry/__fixtures__/docs/vpc/main.tf +14 -0
  555. package/src/registry/__fixtures__/docs/vpc/outputs.tf +9 -0
  556. package/src/registry/__fixtures__/docs/vpc/variables.tf +16 -0
  557. package/src/registry/__fixtures__/proxied-root/main.tf +12 -0
  558. package/src/registry/address.ts +100 -0
  559. package/src/registry/catalog-read.ts +56 -0
  560. package/src/registry/deprecated.test.ts +139 -0
  561. package/src/registry/deprecated.ts +76 -0
  562. package/src/registry/docs.test.ts +140 -0
  563. package/src/registry/docs.ts +299 -0
  564. package/src/registry/edge/bundle.test.ts +50 -0
  565. package/src/registry/edge/edge.test.ts +176 -0
  566. package/src/registry/edge/edge.ts +211 -0
  567. package/src/registry/edge/index.ts +10 -0
  568. package/src/registry/edge/lambda-edge.ts +127 -0
  569. package/src/registry/edge/sigv4-web.ts +79 -0
  570. package/src/registry/edge/token-source.test.ts +258 -0
  571. package/src/registry/edge/token-source.ts +169 -0
  572. package/src/registry/edge/worker.ts +61 -0
  573. package/src/registry/handler.ts +89 -0
  574. package/src/registry/headers-file.ts +61 -0
  575. package/src/registry/index.ts +31 -0
  576. package/src/registry/mirror-paths.ts +10 -0
  577. package/src/registry/mirror.test.ts +198 -0
  578. package/src/registry/mirror.ts +395 -0
  579. package/src/registry/proxies.test.ts +153 -0
  580. package/src/registry/proxies.ts +132 -0
  581. package/src/registry/reader.ts +225 -0
  582. package/src/registry/registry.test.ts +262 -0
  583. package/src/registry/semver.ts +34 -0
  584. package/src/registry/serve.ts +82 -0
  585. package/src/registry/source-forms.test.ts +87 -0
  586. package/src/registry/source-forms.ts +216 -0
  587. package/src/registry/targets/artifactory.test.ts +248 -0
  588. package/src/registry/targets/artifactory.ts +257 -0
  589. package/src/registry/targets/fake-artifactory.ts +158 -0
  590. package/src/registry/targets/fake-gitlab.ts +161 -0
  591. package/src/registry/targets/fake-hcp.ts +233 -0
  592. package/src/registry/targets/fake-http.ts +97 -0
  593. package/src/registry/targets/fake-nexus.ts +152 -0
  594. package/src/registry/targets/gitlab.test.ts +208 -0
  595. package/src/registry/targets/gitlab.ts +223 -0
  596. package/src/registry/targets/hcp.test.ts +230 -0
  597. package/src/registry/targets/hcp.ts +360 -0
  598. package/src/registry/targets/hosted.ts +117 -0
  599. package/src/registry/targets/index.ts +17 -0
  600. package/src/registry/targets/module-target.ts +131 -0
  601. package/src/registry/targets/nexus.test.ts +220 -0
  602. package/src/registry/targets/nexus.ts +314 -0
  603. package/src/registry/targets/zip.test.ts +65 -0
  604. package/src/registry/targets/zip.ts +287 -0
  605. package/src/registry/writer.ts +155 -0
  606. package/src/report.test.ts +82 -1
  607. package/src/report.ts +31 -54
  608. package/src/signal-only-root.test.ts +72 -0
  609. package/src/skills/chant-terraform.md +1 -1
  610. package/src/state/azure-blob.ts +8 -0
  611. package/src/state/backend-verdict.test.ts +187 -0
  612. package/src/state/backend.test.ts +127 -0
  613. package/src/state/backend.ts +488 -0
  614. package/src/state/exec.ts +111 -0
  615. package/src/state/gcs.ts +7 -0
  616. package/src/state/index.ts +15 -0
  617. package/src/state/locks.test.ts +84 -0
  618. package/src/state/locks.ts +201 -0
  619. package/src/state/object-store.ts +7 -0
  620. package/src/state/root-states-floci.e2e.test.ts +66 -0
  621. package/src/state/root-states.test.ts +462 -0
  622. package/src/state/root-states.ts +309 -0
  623. package/src/state/s3.ts +21 -0
  624. package/src/state/store.ts +225 -0
  625. package/src/state-ops.test.ts +182 -0
  626. package/src/state-ops.ts +462 -0
  627. package/src/state-reads.ts +116 -0
  628. package/src/terragrunt/affected.ts +2 -1
  629. package/src/used-sources.test.ts +75 -0
  630. package/src/used-sources.ts +204 -0
  631. package/src/workspace-kinds.test.ts +4 -17
  632. package/workspace-kinds.json +1 -24
  633. package/dist/workspace-member.d.ts +0 -30
  634. package/dist/workspace-member.d.ts.map +0 -1
  635. package/dist/workspace-member.js +0 -91
  636. package/schemas/pulumi.schema.json +0 -34
  637. package/src/testdata/pulumi-member/Pulumi.yaml +0 -2
  638. package/src/testdata/pulumi-member/stack-export.json +0 -53
  639. package/src/testdata/pulumi-unexported/Pulumi.yaml +0 -2
  640. package/src/workspace-member.test.ts +0 -89
  641. package/src/workspace-member.ts +0 -126
@@ -22,7 +22,7 @@
22
22
  * system and refuses with exit 3 when its fresh plan differs (choudoufu
23
23
  * #878). Either refusal fails the step. choudoufu's refusal of a plan the
24
24
  * wave handed `run` throws {@link TerraformPlanMovedError}, so the command
25
- * that applied it exits 3 (#3997). terraform's and tofu's stale-plan error
25
+ * that applied it exits 4, the table's moved code (#3997, #4553). terraform's and tofu's stale-plan error
26
26
  * is not classified and exits 1.
27
27
  *
28
28
  * Run without a wave plan (`chant run --components`, or a fan-out with no
@@ -38,9 +38,27 @@
38
38
  * when both roots are in the change.
39
39
  *
40
40
  * A root whose `vars` read an output not known yet (`DeployContext.unresolvedInputs`)
41
- * is not planned: terraform takes no unknown variable. Its member gets a hole
42
- * naming the roots it waits on and no artifact, and the run that applies it
43
- * plans it once their outputs are known.
41
+ * cannot be planned as it stands: terraform takes no unknown variable. It is
42
+ * previewed instead (#4463, `./placeholder-preview.ts`): planned with a
43
+ * stand-in per variable that holds no value, typed from the root's
44
+ * `variable` block, with every attribute and output a stand-in drives marked
45
+ * unknown after apply. The member lists the variables under `placeholders`,
46
+ * and its artifact is the preview's shape, never a plan file. The apply plans
47
+ * the root again once the upstream applied, and core covers that round with
48
+ * the first approval when its shape is within the preview's; a `run` handed
49
+ * the shape itself holds the fresh plan to it. When no preview can be made
50
+ * (an undeclared variable, a `count` or `for_each` over a stand-in, a
51
+ * placeholder plan that fails) the member stays a hole naming the roots it
52
+ * waits on, and the hole's reason says why there is no preview.
53
+ *
54
+ * ## The plan's shape (#4436)
55
+ *
56
+ * `plan` also answers `shape`, `terraformPlanShape` over `show -json`: each
57
+ * resource the plan changes with its action, type, replacement, the
58
+ * attributes that differ and the ones unknown after apply. Core's
59
+ * `coveredRound` compares it with the shape of a later plan of the root. A
60
+ * previewed root's shape lists the upstreams it read as unknown inputs; a
61
+ * root that stays a hole has no plan, so no shape, and stays uncovered.
44
62
  *
45
63
  * ## choudoufu roots in a gated wave (#3459)
46
64
  *
@@ -63,11 +81,111 @@
63
81
  *
64
82
  * chant's waves stay the order. Each root is its own one-root set, so
65
83
  * choudoufu's wave over it is always wave 1.
84
+ *
85
+ * ## Composed runs (#4447)
86
+ *
87
+ * With `terraform.compose.enabled`, a group core forms of `terraform-apply`
88
+ * components that read each other (ws-107) plans as one plan and applies as
89
+ * one apply of a composed root, and a member's read of another member's new
90
+ * output is not a hole: the apply passes the value on. `groupReads`,
91
+ * `groupFallback`, `planGroup` and `runGroup` are in `./compose-group.ts`.
92
+ *
93
+ * ## A choudoufu member's outputs, for another member (#4455)
94
+ *
95
+ * The plugin also contributes {@link choudoufuOutputSource} to core's
96
+ * `member-outputs` verb (`CapabilityPlugin.engineOutputSources`), which is
97
+ * how a chant member's parameters read a choudoufu member of the same
98
+ * workspace: `choudoufu output -json` in the member's directory for the
99
+ * applied values, and `live-plan-set -json` over it for the planned ones,
100
+ * read the way `plan` reads a root's (`terraformPlannedOutputs`). The member
101
+ * is not a `terraform.roots` entry of the reading project; its directory
102
+ * comes from the workspace declaration.
103
+ *
104
+ * ## Op waves (#4545)
105
+ *
106
+ * The step is what an op wave's `step` names to plan and apply each root
107
+ * through chant (`chant run wave`), so terragucci's waves and plywood's run
108
+ * the engine in chant. Three inputs come from terragucci's wave callbacks:
109
+ *
110
+ * - `lockTimeout` (default `5m`, `false` for none): `plan` and `apply` wait
111
+ * that long for another run's state lock, unless `TF_CLI_ARGS` sets
112
+ * `-lock-timeout` already (`../lock-timeout.ts`).
113
+ * - `cone`: a revision. A live choudoufu root plans the cone of the change
114
+ * since it (`plan -cone`, `../cone.ts`), and the cone's targets join the
115
+ * plan digest, so an approval of one cone counts for no other. Such a root
116
+ * plans with `plan`, never as a one-root set.
117
+ * - `reads`: vars read from another root's outputs, Atmos's
118
+ * `!terraform.state` (`../state-reads.ts`). An upstream with no such output
119
+ * yet makes the member a hole naming it, so the root is never planned on a
120
+ * stand-in.
121
+ *
122
+ * Every plan also writes its `show -json` beside the plan file and names it
123
+ * as `artifact.planJson`, the document a wave's cost hold prices
124
+ * (`../cost-hold.ts`).
66
125
  */
126
+ import { rmSync, writeFileSync } from "node:fs";
127
+ import { dirname, join, resolve } from "node:path";
128
+ import { loadChantConfigUpward } from "@intentius/chant/config";
129
+ import { PlanShapeMovedError, planShapeDifferences, planShapeDigest, } from "@intentius/chant/components/covered-round";
67
130
  import { computePlanDigest } from "@intentius/chant/lifecycle/plan-digest";
68
131
  import { ownPackageVersion } from "@intentius/chant/components/capability-plugin";
69
- import { choudoufuPlanSet, choudoufuWaveApply, choudoufuWaveRoot, terraformApply, terraformInit, terraformOutputs, terraformPlan, } from "../op/activities/terraform.js";
70
- const rootArgs = (input) => ({ root: input.root, ...(input.cwd ? { cwd: input.cwd } : {}) });
132
+ import { choudoufuMemberOutputs, choudoufuMemberPlanSet, choudoufuPlanSet, choudoufuWaveApply, choudoufuWaveRoot, terraformApply, terraformInit, terraformOutputs, terraformPlan, } from "../op/activities/terraform.js";
133
+ import { terraformPlanMoved } from "../exit-codes.js";
134
+ import { terraformPlanShape } from "../plan-shape.js";
135
+ import { plannerForBinary, terraformChangeSetPart } from "../change-set.js";
136
+ import { terraformDefaultLockGrain, terraformLockGrainRefusal, terraformLockRows, terraformLockRowsFromPart } from "../lock-rows.js";
137
+ import { rootTexts } from "../compose/hcl.js";
138
+ import { declaredVariables } from "../compose/root.js";
139
+ import { terraformComposeGroup } from "./compose-group.js";
140
+ import { markPlaceholderDriven, placeholderVars, waitingHole } from "./placeholder-preview.js";
141
+ import { terraformReleaseInputs } from "./release-inputs.js";
142
+ import { terraformTraceFacts } from "./trace-facts.js";
143
+ import { DEFAULT_LOCK_TIMEOUT, isLockTimeout } from "../lock-timeout.js";
144
+ import { conePlanDigest } from "../cone.js";
145
+ import { fillStateReads, stateReadsProblems, waitingReadsReason } from "../state-reads.js";
146
+ import { terraformStateOpCapabilities } from "../state-ops.js";
147
+ /** The lock timeout a step's plan and apply pass (#4545). */
148
+ function lockTimeoutOf(input) {
149
+ if (input.lockTimeout === false)
150
+ return {};
151
+ const value = input.lockTimeout ?? DEFAULT_LOCK_TIMEOUT;
152
+ if (!isLockTimeout(value))
153
+ throw new Error(`terraform-apply: root "${input.root}": lockTimeout "${String(value)}" is not a duration such as "5m"`);
154
+ return { lockTimeout: value };
155
+ }
156
+ /**
157
+ * The step's input with its `reads` filled (#4545): each upstream's outputs
158
+ * read once, the values under the step's own `vars`. `waiting` when an
159
+ * upstream has no such output yet. Throws when a state cannot be read.
160
+ */
161
+ async function withReads(input) {
162
+ const reads = input.reads ?? [];
163
+ if (reads.length === 0)
164
+ return { input };
165
+ const problems = stateReadsProblems(reads);
166
+ if (problems.length > 0)
167
+ throw new Error(`terraform-apply: root "${input.root}": ${problems.join("; ")}`);
168
+ const filled = await fillStateReads(reads, async (root) => {
169
+ const at = { root, ...(input.cwd ? { cwd: input.cwd } : {}) };
170
+ await terraformInit(at);
171
+ return terraformOutputs(at);
172
+ });
173
+ if (filled.errors.length > 0)
174
+ throw new Error(`terraform-apply: root "${input.root}": ${filled.errors.join("; ")}`);
175
+ if (filled.waiting.length > 0)
176
+ return { waiting: waitingReadsReason(filled.waiting), upstreams: [...new Set(filled.waiting.map((w) => w.read.root))].sort() };
177
+ return { input: { ...input, vars: { ...filled.vars, ...(input.vars ?? {}) } } };
178
+ }
179
+ /** A root whose reads wait on an upstream (#4545): a hole naming it, and a digest over the root and those upstreams. */
180
+ function waitingOnReads(ctx, input, waiting) {
181
+ const planDigest = computePlanDigest("terraform-apply-reads-waiting", { env: ctx.env, root: input.root, upstreams: waiting.upstreams });
182
+ const changeSet = {
183
+ member: { member: input.root, lexicon: "terraform", planner: "chant", status: "planned", planDigest, holes: [{ address: input.root, type: "terraform_root", reason: waiting.waiting }] },
184
+ entries: [],
185
+ };
186
+ return { member: input.root, planDigest, changeSet };
187
+ }
188
+ const rootArgs = (input) => ({ root: input.root, ...(input.cwd ? { cwd: input.cwd } : {}), ...(input.dir ? { dir: input.dir } : {}) });
71
189
  function requireRoot(input) {
72
190
  if (typeof input.root !== "string" || input.root === "") {
73
191
  throw new Error('terraform-apply: "root" is required and names an entry in terraform.roots');
@@ -76,15 +194,35 @@ function requireRoot(input) {
76
194
  async function planRoot(input, targets) {
77
195
  requireRoot(input);
78
196
  await terraformInit(rootArgs(input));
197
+ // One `show -json` per plan (#4479): its document is the digest, the change
198
+ // set, the planned outputs and the shape. Nothing here reads the
199
+ // `-no-color` render, so the plan skips it.
79
200
  const planned = await terraformPlan({
80
201
  ...rootArgs(input),
81
202
  ...(input.vars ? { vars: input.vars } : {}),
82
203
  ...(targets && targets.length > 0 ? { targets } : {}),
204
+ ...lockTimeoutOf(input),
205
+ ...(input.cone && !(targets && targets.length > 0) ? { cone: input.cone } : {}),
206
+ text: false,
83
207
  });
208
+ // #4545: the cone's targets join the digest, so an approval of this cone counts for no other.
209
+ const planDigest = conePlanDigest(planned.planDigest, planned.cone);
210
+ const changeSet = planned.changeSet && planDigest !== planned.planDigest ? { ...planned.changeSet, member: { ...planned.changeSet.member, planDigest } } : planned.changeSet;
211
+ // #4545: the plan document beside the plan file, which a wave's cost hold prices.
212
+ const planJson = join(planned.dir, `${planned.planFile}.json`);
213
+ let wrote = true;
214
+ try {
215
+ writeFileSync(planJson, JSON.stringify(planned.json));
216
+ }
217
+ catch {
218
+ wrote = false;
219
+ }
84
220
  return {
85
221
  planFile: planned.planFile,
86
- planDigest: planned.planDigest,
87
- ...(planned.changeSet ? { changeSet: planned.changeSet } : {}),
222
+ planDigest,
223
+ ...(wrote ? { planJson } : {}),
224
+ ...(planned.cone ? { cone: planned.cone } : {}),
225
+ ...(changeSet ? { changeSet } : {}),
88
226
  json: planned.json,
89
227
  };
90
228
  }
@@ -127,12 +265,34 @@ export function terraformPlannedOutputs(json) {
127
265
  return { known, unknown };
128
266
  }
129
267
  /**
130
- * The member of a root whose `vars` read outputs not known yet (#3999): no
131
- * plan, a hole naming whose outputs it waits on, and a digest over the root,
132
- * the vars as resolved and those names.
268
+ * What a choudoufu member's set plan says about its outputs (#4455), for
269
+ * `member-outputs`: {@link terraformPlannedOutputs} of the embedded plan,
270
+ * chant's digest of that plan, and whether it has changes to apply.
271
+ */
272
+ export function choudoufuMemberPlannedOutputs(set) {
273
+ return { ...terraformPlannedOutputs(set.json), planDigest: set.planDigest, changes: set.changed };
274
+ }
275
+ const memberArgs = (ref) => ({ member: ref.member, dir: ref.dir, projectRoot: ref.workspaceRoot });
276
+ /**
277
+ * The choudoufu engine's member outputs (#4455): what core's
278
+ * `member-outputs` reads a workspace member of kind `choudoufu` through.
279
+ * Applied values from the member's root outputs (the record store, for a
280
+ * live estate); planned values from its one-root set plan.
281
+ */
282
+ export const choudoufuOutputSource = {
283
+ kinds: ["choudoufu"],
284
+ applied: (_ctx, ref) => choudoufuMemberOutputs(memberArgs(ref)),
285
+ planned: async (_ctx, ref) => choudoufuMemberPlannedOutputs(await choudoufuMemberPlanSet(memberArgs(ref))),
286
+ };
287
+ const resolvedVars = (input) => Object.fromEntries(Object.entries(input.vars ?? {}).map(([k, v]) => [k, v === undefined ? null : v]));
288
+ /**
289
+ * The member of a root whose `vars` read outputs not known yet and that
290
+ * could not be previewed (#3999, #4463): no plan, a hole naming whose outputs
291
+ * it waits on and, when a preview was tried, why it was not possible, and a
292
+ * digest over the root, the vars as resolved and those names.
133
293
  */
134
- function waitingRoot(ctx, input, unresolved) {
135
- const vars = Object.fromEntries(Object.entries(input.vars ?? {}).map(([k, v]) => [k, v === undefined ? null : v]));
294
+ function waitingRoot(ctx, input, unresolved, noPreview) {
295
+ const vars = resolvedVars(input);
136
296
  const planDigest = computePlanDigest("terraform-apply-unresolved", { env: ctx.env, root: input.root, vars, unresolved });
137
297
  const changeSet = {
138
298
  member: {
@@ -141,18 +301,107 @@ function waitingRoot(ctx, input, unresolved) {
141
301
  planner: "chant",
142
302
  status: "planned",
143
303
  planDigest,
144
- holes: [{ address: input.root, type: "terraform_root", reason: `inputs from ${unresolved.join(", ")}; planned again once they apply` }],
304
+ holes: [waitingHole(input.root, unresolved, noPreview)],
145
305
  },
146
306
  entries: [],
147
307
  };
148
308
  return { member: input.root, planDigest, changeSet, ...(ctx.targets?.length ? { targets: ctx.targets } : {}) };
149
309
  }
310
+ /** The plan file a preview writes, removed once it is read: a plan made with stand-ins must never apply. */
311
+ export const PREVIEW_PLAN_FILE = ".chant-preview.tfplan";
312
+ function isShapeArtifact(value) {
313
+ const v = value;
314
+ return v?.kind === "terraform-apply-shape" && typeof v.digest === "string" && typeof v.shape === "object" && v.shape !== null;
315
+ }
316
+ /** The root's directory, as `terraform.roots` names it from the nearest `chant.config.*`, and the configured binary. */
317
+ async function rootDir(input) {
318
+ const start = resolve(input.cwd ?? process.cwd());
319
+ const { config, configPath } = await loadChantConfigUpward(start);
320
+ const terraform = config.terraform;
321
+ const declared = terraform?.roots?.[input.root]?.dir;
322
+ if (declared === undefined)
323
+ return undefined;
324
+ const dir = input.dir ?? declared;
325
+ return { dir: resolve(configPath ? dirname(configPath) : start, dir), ...(terraform?.binary ? { binary: terraform.binary } : {}) };
326
+ }
327
+ const firstLines = (err) => {
328
+ const text = (err instanceof Error ? err.message : String(err)).trim();
329
+ const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
330
+ return lines.slice(0, 4).join(" ").slice(0, 600);
331
+ };
332
+ /**
333
+ * Preview a root whose `vars` read outputs not known yet (#4463): plan it
334
+ * with a typed stand-in per such variable, mark what the stand-ins drive
335
+ * unknown, and answer the change set, the planned outputs and the shape of
336
+ * that plan, with the shape as the artifact. The plan file is removed. When
337
+ * no preview can be made, the member stays a hole saying why.
338
+ */
339
+ async function previewRoot(ctx, input, unresolved, targets) {
340
+ const root = await rootDir(input);
341
+ if (root === undefined)
342
+ return waitingRoot(ctx, input, unresolved, `no root named "${input.root}" in terraform.roots to read its variables from`);
343
+ const { dir } = root;
344
+ // #4457: the same files the binary reads (`.tofu` only for tofu and choudoufu).
345
+ const stand = placeholderVars(input.vars, declaredVariables(rootTexts(dir, root.binary)));
346
+ if (typeof stand === "string")
347
+ return waitingRoot(ctx, input, unresolved, stand);
348
+ let planned;
349
+ try {
350
+ await terraformInit(rootArgs(input));
351
+ planned = await terraformPlan({
352
+ ...rootArgs(input),
353
+ vars: stand.vars,
354
+ planFile: PREVIEW_PLAN_FILE,
355
+ ...(targets ? { targets } : {}),
356
+ text: false,
357
+ });
358
+ }
359
+ catch (err) {
360
+ return waitingRoot(ctx, input, unresolved, `the plan with stand-in values failed: ${firstLines(err)}`);
361
+ }
362
+ finally {
363
+ rmSync(join(dir, PREVIEW_PLAN_FILE), { force: true });
364
+ }
365
+ const marked = markPlaceholderDriven(planned.json, stand.placeholders);
366
+ if ("refused" in marked)
367
+ return waitingRoot(ctx, input, unresolved, marked.refused);
368
+ const placeholders = stand.placeholders.map((name) => `var.${name}`);
369
+ const shape = terraformPlanShape(marked.plan, input.root, { unknownInputs: unresolved });
370
+ const artifact = { kind: "terraform-apply-shape", member: input.root, shape, digest: planShapeDigest(shape) };
371
+ const part = terraformChangeSetPart({
372
+ member: input.root,
373
+ plan: marked.plan,
374
+ ...(planned.changeSet?.member.planner ? { planner: planned.changeSet.member.planner } : {}),
375
+ ...(planned.changeSet?.member.scope ? { scope: planned.changeSet.member.scope } : {}),
376
+ });
377
+ // The stand-ins' values are not real, so the digest is over the preview's shape and entries, never the raw plan.
378
+ const planDigest = computePlanDigest("terraform-apply-preview", {
379
+ env: ctx.env,
380
+ root: input.root,
381
+ vars: resolvedVars(input),
382
+ unresolved,
383
+ placeholders,
384
+ shape: artifact.digest,
385
+ entries: part.entries,
386
+ });
387
+ const changeSet = { ...part, member: { ...part.member, planDigest, placeholders } };
388
+ return {
389
+ member: input.root,
390
+ planDigest,
391
+ artifact,
392
+ changeSet,
393
+ outputs: terraformPlannedOutputs(marked.plan),
394
+ shape,
395
+ ...(targets ? { targets } : {}),
396
+ };
397
+ }
150
398
  /**
151
- * choudoufu refused the plan `run` was handed by its wave (its exit 3):
152
- * the live system moved since the plan, or the plan names another estate.
153
- * Nothing was applied. `planMoved` is core's mark for a moved plan
154
- * (`isPlanMovedError`), so the command that applied it exits 3, as for the
155
- * other capabilities that refuse a moved plan (#3997).
399
+ * choudoufu refused the plan `run` was handed by its wave (its exit 3)
400
+ * because the live system moved since the plan. Nothing was applied.
401
+ * `planMoved` is core's mark for a moved plan (`isPlanMovedError`), so the
402
+ * command that applied it exits `CHANT_EXIT.moved`, 4, as for the other
403
+ * capabilities that refuse a moved plan (#3997, #4553). A plan made against
404
+ * another estate is a plain failure (`terraformExitOf` in ../exit-codes).
156
405
  */
157
406
  export class TerraformPlanMovedError extends Error {
158
407
  constructor(root, message) {
@@ -162,8 +411,6 @@ export class TerraformPlanMovedError extends Error {
162
411
  this.name = "TerraformPlanMovedError";
163
412
  }
164
413
  }
165
- /** `live-wave-apply`'s exit status for a set whose plan moved (`CHOUDOUFU_WAVE_EXIT.setMoved`). */
166
- const CHOUDOUFU_SET_MOVED_EXIT = 3;
167
414
  function isPlannedRoot(value) {
168
415
  const v = value;
169
416
  return typeof v?.planFile === "string" && typeof v.planDigest === "string";
@@ -186,13 +433,28 @@ async function runChoudoufuWave(ctx, input, planned) {
186
433
  ctx.carry?.(input.root, applied.carry);
187
434
  if (!applied.landed) {
188
435
  const message = `terraform-apply: root "${input.root}": ${applied.message}`;
189
- if (applied.exitCode === CHOUDOUFU_SET_MOVED_EXIT)
436
+ if (terraformPlanMoved({ command: "live-wave-apply", code: applied.exitCode }))
190
437
  throw new TerraformPlanMovedError(input.root, message);
191
438
  throw new Error(message);
192
439
  }
193
440
  const outputs = await terraformOutputs(rootArgs(input));
194
441
  return { root: input.root, planDigest: planned.planDigest, fromWavePlan: true, outputs };
195
442
  }
443
+ /** The input a `run` that plans for itself plans with (#4545): its reads filled, or an error naming the upstream to apply first. */
444
+ async function readsForRun(input) {
445
+ const read = await withReads(input);
446
+ if ("waiting" in read)
447
+ throw new Error(`terraform-apply: root "${input.root}": ${read.waiting}`);
448
+ return read.input;
449
+ }
450
+ /** The engine a root plans with (#4552): the configured binary's, else the plan's planner. */
451
+ async function plannerOf(input, plan) {
452
+ const binary = (await rootDir(input).catch(() => undefined))?.binary;
453
+ if (binary !== undefined)
454
+ return plannerForBinary(binary);
455
+ const planner = plan?.changeSet?.member.planner;
456
+ return planner === "terraform" || planner === "tofu" || planner === "choudoufu" ? planner : "terraform";
457
+ }
196
458
  export const terraformApplyCapability = {
197
459
  kind: "terraform-apply",
198
460
  // A root's apply has no undo short of applying the previous configuration,
@@ -200,29 +462,38 @@ export const terraformApplyCapability = {
200
462
  rollbackPolicy: "needs-opt-out",
201
463
  // #4300: `--target` passes through as `-target`, and the saved plan holds those addresses alone.
202
464
  targets: "accept",
203
- async plan(ctx, input) {
204
- requireRoot(input);
465
+ async plan(ctx, given) {
466
+ requireRoot(given);
467
+ // #4545: a root reading an upstream's output that is not there yet is a hole naming the upstream.
468
+ const read = await withReads(given);
469
+ if ("waiting" in read)
470
+ return waitingOnReads(ctx, given, read);
471
+ const { input } = read;
205
472
  const unresolved = [...(ctx.unresolvedInputs ?? [])].sort();
206
- if (unresolved.length > 0)
207
- return waitingRoot(ctx, input, unresolved);
208
473
  const targets = ctx.targets && ctx.targets.length > 0 ? ctx.targets : undefined;
209
- // A targeted root plans with `plan -target`, never as a choudoufu one-root set.
210
- const wave = targets ? { wave: false } : await choudoufuWaveRoot({ ...rootArgs(input), ...(input.vars ? { vars: input.vars } : {}) });
474
+ if (unresolved.length > 0)
475
+ return previewRoot(ctx, input, unresolved, targets);
476
+ // A targeted root plans with `plan -target`, and a cone plan with `plan -cone` (#4545), never as a choudoufu one-root set.
477
+ const wave = targets || input.cone ? { wave: false } : await choudoufuWaveRoot({ ...rootArgs(input), ...(input.vars ? { vars: input.vars } : {}) });
211
478
  if (wave.wave) {
212
479
  const set = await choudoufuPlanSet(rootArgs(input));
213
480
  const artifact = {
214
481
  planDigest: set.planDigest,
215
482
  choudoufu: { planSetFile: set.planSetFile, setDigest: set.setDigest },
483
+ lockRows: terraformLockRows(input.root, set.changeSet.member.scope, set.json),
216
484
  };
217
- return { member: input.root, planDigest: set.planDigest, artifact, changeSet: set.changeSet, outputs: terraformPlannedOutputs(set.json) };
485
+ return { member: input.root, planDigest: set.planDigest, artifact, changeSet: set.changeSet, outputs: terraformPlannedOutputs(set.json), shape: terraformPlanShape(set.json, input.root) };
218
486
  }
219
487
  const { changeSet, json, ...planned } = await planRoot(input, targets);
488
+ // #4552: a choudoufu root's rows, keyed from the plan document while it is at hand.
489
+ const lockRows = changeSet?.member.planner === "choudoufu" ? terraformLockRows(input.root, changeSet.member.scope, json) : undefined;
220
490
  return {
221
491
  member: input.root,
222
492
  planDigest: planned.planDigest,
223
- artifact: planned,
493
+ artifact: { ...planned, ...(lockRows ? { lockRows } : {}) },
224
494
  ...(changeSet ? { changeSet } : {}),
225
495
  outputs: terraformPlannedOutputs(json),
496
+ shape: terraformPlanShape(json, input.root),
226
497
  ...(targets ? { targets } : {}),
227
498
  };
228
499
  },
@@ -233,20 +504,64 @@ export const terraformApplyCapability = {
233
504
  await terraformInit(rootArgs(input));
234
505
  return terraformOutputs(rootArgs(input));
235
506
  },
507
+ // #4447 (ws-107): a group core forms of components that read each other plans and applies as one composed run
508
+ // when `terraform.compose.enabled` is set (./compose-group.ts). Delegates, so the methods are read when called.
509
+ groupReads: (ctx, members) => terraformComposeGroup.groupReads(ctx, members),
510
+ // #4542: a member pointed at a release's recorded copy plans alone, since a composition reads the declared roots.
511
+ groupFallback: async (ctx, members) => members.some((m) => typeof m.step.dir === "string")
512
+ ? { kind: "release-copy", reason: "a member deploys a release's recorded copy of its root, which a composition does not read" }
513
+ : terraformComposeGroup.groupFallback(ctx, members),
514
+ // #4542: the root's files, which a release cut records and a promote under it plans.
515
+ releaseInputs: (input, ctx) => terraformReleaseInputs(input, ctx),
516
+ // #4552: resource under choudoufu, the root under Terraform, tofu and Terragrunt, which refuse resource by name.
517
+ async defaultLockGrain(input, plan) {
518
+ return terraformDefaultLockGrain(await plannerOf(input, plan));
519
+ },
520
+ async lockGrainRefusal(input, grain, plan) {
521
+ if (grain !== "resource")
522
+ return undefined;
523
+ const binary = (await rootDir(input).catch(() => undefined))?.binary;
524
+ return terraformLockGrainRefusal(grain, await plannerOf(input, plan), binary);
525
+ },
526
+ lockRows(input, plan) {
527
+ const kept = plan.artifact?.lockRows;
528
+ if (Array.isArray(kept))
529
+ return kept;
530
+ return plan.changeSet ? terraformLockRowsFromPart(input.root, plan.changeSet) : [];
531
+ },
532
+ // #4555: the root and the binary, for the step's span and run record.
533
+ traceFacts: async (input, outcome) => terraformTraceFacts(input, outcome, (await rootDir(input).catch(() => undefined))?.binary),
534
+ planGroup: (ctx, members) => terraformComposeGroup.planGroup(ctx, members),
535
+ runGroup: (ctx, run, members) => terraformComposeGroup.runGroup(ctx, run, members),
236
536
  async run(ctx, input) {
237
537
  const fromWave = ctx.plans?.[input.root];
238
538
  if (isChoudoufuWavePlan(fromWave))
239
539
  return runChoudoufuWave(ctx, input, fromWave);
540
+ if (isShapeArtifact(fromWave)) {
541
+ // A root previewed with stand-ins (#4463): plan it now with the real
542
+ // values, and apply that plan only when it is within the preview's shape.
543
+ const fresh = await planRoot(await readsForRun(input), ctx.targets);
544
+ const differences = planShapeDifferences(fromWave.shape, terraformPlanShape(fresh.json, input.root));
545
+ if (differences.length > 0)
546
+ throw new PlanShapeMovedError(input.root, differences);
547
+ const applied = await terraformApply({ ...rootArgs(input), planFile: fresh.planFile, ...lockTimeoutOf(input) });
548
+ if (!applied.applied) {
549
+ throw new Error(`terraform-apply: root "${input.root}" refused the plan it was given (${applied.refused ?? "refused"}). ${applied.refusal ?? ""}`);
550
+ }
551
+ const outputs = await terraformOutputs(rootArgs(input));
552
+ return { root: input.root, planDigest: fresh.planDigest, fromWavePlan: false, outputs };
553
+ }
240
554
  const planned = isPlannedRoot(fromWave)
241
555
  ? fromWave
242
- : await planRoot(input, ctx.targets).then(({ planFile, planDigest }) => ({ planFile, planDigest }));
243
- const applied = await terraformApply({ ...rootArgs(input), planFile: planned.planFile });
556
+ : await planRoot(await readsForRun(input), ctx.targets).then(({ planFile, planDigest }) => ({ planFile, planDigest }));
557
+ const applied = await terraformApply({ ...rootArgs(input), planFile: planned.planFile, ...lockTimeoutOf(input) });
244
558
  if (!applied.applied) {
245
559
  const message = `terraform-apply: root "${input.root}" refused the plan it was given (${applied.refused ?? "refused"}). ` +
246
560
  (applied.refusal ?? "");
247
- // A plan the wave approved that choudoufu refuses moved since the
248
- // approval. One this run made itself is planned afresh by the next run.
249
- if (applied.refused !== undefined && isPlannedRoot(fromWave))
561
+ // A plan the wave approved that choudoufu refuses as no longer matching
562
+ // moved since the approval (#4553: one made against another estate is a
563
+ // failure). One this run made itself is planned afresh by the next run.
564
+ if (applied.refused === "approval-mismatch" && isPlannedRoot(fromWave))
250
565
  throw new TerraformPlanMovedError(input.root, message);
251
566
  throw new Error(message);
252
567
  }
@@ -256,6 +571,9 @@ export const terraformApplyCapability = {
256
571
  };
257
572
  export const TERRAFORM_VERB_FAMILIES = {
258
573
  apply: ["terraform-apply"],
574
+ // #4618: the binary runs outside waves, each a fixed operation; the two that change state on their own run under a gated request.
575
+ state: ["terraform-state-unlock", "terraform-state-push"],
576
+ copy: ["terraform-copy"],
259
577
  };
260
578
  export const terraformCapabilityPlugin = {
261
579
  name: "terraform",
@@ -263,9 +581,12 @@ export const terraformCapabilityPlugin = {
263
581
  return ownPackageVersion(import.meta.url);
264
582
  },
265
583
  capabilities() {
266
- return [terraformApplyCapability];
584
+ return [terraformApplyCapability, ...terraformStateOpCapabilities.map((c) => c)];
267
585
  },
268
586
  families() {
269
587
  return TERRAFORM_VERB_FAMILIES;
270
588
  },
589
+ engineOutputSources() {
590
+ return [choudoufuOutputSource];
591
+ },
271
592
  };