@intentius/chant-lexicon-terraform 0.57.0 → 0.58.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.
Files changed (381) hide show
  1. package/dist/composites/terraform-adopt-op.d.ts +126 -0
  2. package/dist/composites/terraform-adopt-op.d.ts.map +1 -0
  3. package/dist/composites/terraform-apply-op.d.ts +63 -16
  4. package/dist/composites/terraform-apply-op.d.ts.map +1 -1
  5. package/dist/composites/terraform-watch-op.d.ts +80 -36
  6. package/dist/composites/terraform-watch-op.d.ts.map +1 -1
  7. package/dist/config.d.ts +49 -2
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/describe-resources.d.ts +256 -16
  10. package/dist/describe-resources.d.ts.map +1 -1
  11. package/dist/hcl/descend.d.ts +98 -0
  12. package/dist/hcl/descend.d.ts.map +1 -0
  13. package/dist/hcl/marker.d.ts +130 -0
  14. package/dist/hcl/marker.d.ts.map +1 -0
  15. package/dist/hcl/parse.d.ts +142 -9
  16. package/dist/hcl/parse.d.ts.map +1 -1
  17. package/dist/hcl/references.d.ts +76 -0
  18. package/dist/hcl/references.d.ts.map +1 -0
  19. package/dist/hcl/roots.d.ts +22 -3
  20. package/dist/hcl/roots.d.ts.map +1 -1
  21. package/dist/hcl/suppressions.d.ts +54 -0
  22. package/dist/hcl/suppressions.d.ts.map +1 -0
  23. package/dist/hcl/value.d.ts +77 -0
  24. package/dist/hcl/value.d.ts.map +1 -0
  25. package/dist/index.d.ts +5 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/integrity.json +32 -5
  28. package/dist/lint/audit-catalog.d.ts +3 -2
  29. package/dist/lint/audit-catalog.d.ts.map +1 -1
  30. package/dist/lint/audit-lineage.d.ts +68 -0
  31. package/dist/lint/audit-lineage.d.ts.map +1 -1
  32. package/dist/lint/post-synth/blocks.d.ts +53 -0
  33. package/dist/lint/post-synth/blocks.d.ts.map +1 -0
  34. package/dist/lint/post-synth/fixtures/load.d.ts +37 -0
  35. package/dist/lint/post-synth/fixtures/load.d.ts.map +1 -0
  36. package/dist/lint/post-synth/index.d.ts.map +1 -1
  37. package/dist/lint/post-synth/module-source.d.ts +38 -0
  38. package/dist/lint/post-synth/module-source.d.ts.map +1 -0
  39. package/dist/lint/post-synth/scope.d.ts +65 -0
  40. package/dist/lint/post-synth/scope.d.ts.map +1 -0
  41. package/dist/lint/post-synth/tf001.d.ts +18 -0
  42. package/dist/lint/post-synth/tf001.d.ts.map +1 -1
  43. package/dist/lint/post-synth/tf002.d.ts +32 -0
  44. package/dist/lint/post-synth/tf002.d.ts.map +1 -0
  45. package/dist/lint/post-synth/tf003.d.ts +22 -0
  46. package/dist/lint/post-synth/tf003.d.ts.map +1 -0
  47. package/dist/lint/post-synth/tf004.d.ts +22 -0
  48. package/dist/lint/post-synth/tf004.d.ts.map +1 -0
  49. package/dist/lint/post-synth/tf005.d.ts +28 -0
  50. package/dist/lint/post-synth/tf005.d.ts.map +1 -0
  51. package/dist/lint/post-synth/tf006.d.ts +21 -0
  52. package/dist/lint/post-synth/tf006.d.ts.map +1 -0
  53. package/dist/lint/post-synth/tf007.d.ts +21 -0
  54. package/dist/lint/post-synth/tf007.d.ts.map +1 -0
  55. package/dist/lint/post-synth/tf008.d.ts +22 -0
  56. package/dist/lint/post-synth/tf008.d.ts.map +1 -0
  57. package/dist/lint/post-synth/tf009.d.ts +24 -0
  58. package/dist/lint/post-synth/tf009.d.ts.map +1 -0
  59. package/dist/lint/post-synth/tf010.d.ts +19 -0
  60. package/dist/lint/post-synth/tf010.d.ts.map +1 -0
  61. package/dist/lint/post-synth/tf011.d.ts +18 -0
  62. package/dist/lint/post-synth/tf011.d.ts.map +1 -0
  63. package/dist/lint/post-synth/tf012.d.ts +17 -0
  64. package/dist/lint/post-synth/tf012.d.ts.map +1 -0
  65. package/dist/lint/post-synth/tf013.d.ts +21 -0
  66. package/dist/lint/post-synth/tf013.d.ts.map +1 -0
  67. package/dist/lint/post-synth/tf014.d.ts +25 -0
  68. package/dist/lint/post-synth/tf014.d.ts.map +1 -0
  69. package/dist/lint/post-synth/tf015.d.ts +21 -0
  70. package/dist/lint/post-synth/tf015.d.ts.map +1 -0
  71. package/dist/lint/post-synth/tf016.d.ts +30 -0
  72. package/dist/lint/post-synth/tf016.d.ts.map +1 -0
  73. package/dist/lint/post-synth/tf017.d.ts +19 -0
  74. package/dist/lint/post-synth/tf017.d.ts.map +1 -0
  75. package/dist/lint/post-synth/tf018.d.ts +20 -0
  76. package/dist/lint/post-synth/tf018.d.ts.map +1 -0
  77. package/dist/lint/post-synth/tf019.d.ts +25 -0
  78. package/dist/lint/post-synth/tf019.d.ts.map +1 -0
  79. package/dist/lint/post-synth/tf020.d.ts +38 -0
  80. package/dist/lint/post-synth/tf020.d.ts.map +1 -0
  81. package/dist/lint/post-synth/tf021.d.ts +41 -0
  82. package/dist/lint/post-synth/tf021.d.ts.map +1 -0
  83. package/dist/lint/post-synth/tf022.d.ts +24 -0
  84. package/dist/lint/post-synth/tf022.d.ts.map +1 -0
  85. package/dist/lint/post-synth/tf024.d.ts +24 -0
  86. package/dist/lint/post-synth/tf024.d.ts.map +1 -0
  87. package/dist/lint/post-synth/tf025.d.ts +29 -0
  88. package/dist/lint/post-synth/tf025.d.ts.map +1 -0
  89. package/dist/lint/post-synth/tf026.d.ts +21 -0
  90. package/dist/lint/post-synth/tf026.d.ts.map +1 -0
  91. package/dist/lint/rules/fixtures/load.d.ts +13 -0
  92. package/dist/lint/rules/fixtures/load.d.ts.map +1 -0
  93. package/dist/lint/rules/plan-before-apply.d.ts +11 -0
  94. package/dist/lint/rules/plan-before-apply.d.ts.map +1 -1
  95. package/dist/lint/secret-shape.d.ts +68 -0
  96. package/dist/lint/secret-shape.d.ts.map +1 -0
  97. package/dist/live-ownership.d.ts +55 -0
  98. package/dist/live-ownership.d.ts.map +1 -0
  99. package/dist/lsp/option-keys.d.ts.map +1 -1
  100. package/dist/manifest.json +1 -1
  101. package/dist/okf/index.md +24 -0
  102. package/dist/okf/rules/TF002.md +11 -0
  103. package/dist/okf/rules/TF003.md +11 -0
  104. package/dist/okf/rules/TF004.md +11 -0
  105. package/dist/okf/rules/TF005.md +11 -0
  106. package/dist/okf/rules/TF006.md +11 -0
  107. package/dist/okf/rules/TF007.md +11 -0
  108. package/dist/okf/rules/TF008.md +11 -0
  109. package/dist/okf/rules/TF009.md +11 -0
  110. package/dist/okf/rules/TF010.md +11 -0
  111. package/dist/okf/rules/TF011.md +11 -0
  112. package/dist/okf/rules/TF012.md +11 -0
  113. package/dist/okf/rules/TF013.md +11 -0
  114. package/dist/okf/rules/TF014.md +11 -0
  115. package/dist/okf/rules/TF015.md +11 -0
  116. package/dist/okf/rules/TF016.md +11 -0
  117. package/dist/okf/rules/TF017.md +11 -0
  118. package/dist/okf/rules/TF018.md +11 -0
  119. package/dist/okf/rules/TF019.md +11 -0
  120. package/dist/okf/rules/TF020.md +11 -0
  121. package/dist/okf/rules/TF021.md +11 -0
  122. package/dist/okf/rules/TF022.md +11 -0
  123. package/dist/okf/rules/TF024.md +11 -0
  124. package/dist/okf/rules/TF025.md +11 -0
  125. package/dist/okf/rules/TF026.md +11 -0
  126. package/dist/op/activities/index.d.ts +13 -6
  127. package/dist/op/activities/index.d.ts.map +1 -1
  128. package/dist/op/activities/live-detect.d.ts +51 -0
  129. package/dist/op/activities/live-detect.d.ts.map +1 -0
  130. package/dist/op/activities/terraform.d.ts +445 -17
  131. package/dist/op/activities/terraform.d.ts.map +1 -1
  132. package/dist/op/activity-contracts.d.ts +148 -0
  133. package/dist/op/activity-contracts.d.ts.map +1 -0
  134. package/dist/op/adoption.d.ts +118 -0
  135. package/dist/op/adoption.d.ts.map +1 -0
  136. package/dist/op/builders.d.ts +46 -6
  137. package/dist/op/builders.d.ts.map +1 -1
  138. package/dist/op/resolve-root-mode.d.ts +45 -0
  139. package/dist/op/resolve-root-mode.d.ts.map +1 -0
  140. package/dist/plugin.d.ts.map +1 -1
  141. package/dist/rules/blocks.ts +109 -0
  142. package/dist/rules/module-source.ts +121 -0
  143. package/dist/rules/plan-before-apply.ts +11 -0
  144. package/dist/rules/scope.ts +107 -0
  145. package/dist/rules/tf001.ts +32 -8
  146. package/dist/rules/tf002.ts +151 -0
  147. package/dist/rules/tf003.ts +71 -0
  148. package/dist/rules/tf004.ts +63 -0
  149. package/dist/rules/tf005.ts +76 -0
  150. package/dist/rules/tf006.ts +53 -0
  151. package/dist/rules/tf007.ts +78 -0
  152. package/dist/rules/tf008.ts +75 -0
  153. package/dist/rules/tf009.ts +59 -0
  154. package/dist/rules/tf010.ts +51 -0
  155. package/dist/rules/tf011.ts +49 -0
  156. package/dist/rules/tf012.ts +47 -0
  157. package/dist/rules/tf013.ts +63 -0
  158. package/dist/rules/tf014.ts +72 -0
  159. package/dist/rules/tf015.ts +63 -0
  160. package/dist/rules/tf016.ts +75 -0
  161. package/dist/rules/tf017.ts +50 -0
  162. package/dist/rules/tf018.ts +72 -0
  163. package/dist/rules/tf019.ts +72 -0
  164. package/dist/rules/tf020.ts +123 -0
  165. package/dist/rules/tf021.ts +126 -0
  166. package/dist/rules/tf022.ts +61 -0
  167. package/dist/rules/tf024.ts +70 -0
  168. package/dist/rules/tf025.ts +101 -0
  169. package/dist/rules/tf026.ts +80 -0
  170. package/dist/skills/chant-terraform.md +1 -1
  171. package/package.json +7 -2
  172. package/src/__fixtures__/live/main.tf +28 -0
  173. package/src/__fixtures__/live-adopt/estate.chdf.hcl +6 -0
  174. package/src/__fixtures__/live-adopt/main.tf +21 -0
  175. package/src/__fixtures__/live-estate/README.md +58 -0
  176. package/src/__fixtures__/live-estate/compute.tf +10 -0
  177. package/src/__fixtures__/live-estate/estate.chdf.hcl +1 -0
  178. package/src/__fixtures__/live-estate/logs.tf +8 -0
  179. package/src/__fixtures__/live-estate/network.tf +24 -0
  180. package/src/__fixtures__/live-estate/rule.tf +11 -0
  181. package/src/__fixtures__/live-estate/unowned.tf +21 -0
  182. package/src/__fixtures__/live-estate/versions.tf +31 -0
  183. package/src/__fixtures__/live-ls.json +98 -0
  184. package/src/__fixtures__/live-plan.json +285 -0
  185. package/src/__fixtures__/live-sidecar/estate.chdf.hcl +3 -0
  186. package/src/__fixtures__/live-sidecar/main.tf +24 -0
  187. package/src/__fixtures__/module-tree/README.md +16 -0
  188. package/src/__fixtures__/module-tree/cycle/main.tf +3 -0
  189. package/src/__fixtures__/module-tree/cycle/modules/a/main.tf +9 -0
  190. package/src/__fixtures__/module-tree/cycle/modules/b/main.tf +9 -0
  191. package/src/__fixtures__/module-tree/missing/main.tf +9 -0
  192. package/src/__fixtures__/module-tree/outside/root/main.tf +9 -0
  193. package/src/__fixtures__/module-tree/root/main.tf +28 -0
  194. package/src/__fixtures__/module-tree/root/modules/cdn/main.tf +15 -0
  195. package/src/__fixtures__/module-tree/root/modules/cdn/modules/bucket/main.tf +11 -0
  196. package/src/__fixtures__/module-tree/shared/main.tf +5 -0
  197. package/src/__fixtures__/references/main.tf +56 -0
  198. package/src/codegen/lint-rules-page.test.ts +28 -0
  199. package/src/composites/terraform-adopt-op.acceptance.test.ts +166 -0
  200. package/src/composites/terraform-adopt-op.test.ts +170 -0
  201. package/src/composites/terraform-adopt-op.ts +197 -0
  202. package/src/composites/terraform-apply-op.acceptance.test.ts +183 -5
  203. package/src/composites/terraform-apply-op.test.ts +167 -15
  204. package/src/composites/terraform-apply-op.ts +105 -28
  205. package/src/composites/terraform-watch-op.test.ts +85 -26
  206. package/src/composites/terraform-watch-op.ts +130 -73
  207. package/src/config.ts +32 -3
  208. package/src/describe-resources.live.test.ts +598 -0
  209. package/src/describe-resources.test.ts +53 -0
  210. package/src/describe-resources.ts +811 -28
  211. package/src/hcl/descend.test.ts +162 -0
  212. package/src/hcl/descend.ts +273 -0
  213. package/src/hcl/marker.test.ts +147 -0
  214. package/src/hcl/marker.ts +235 -0
  215. package/src/hcl/parse.test.ts +69 -0
  216. package/src/hcl/parse.ts +249 -27
  217. package/src/hcl/references.test.ts +116 -0
  218. package/src/hcl/references.ts +172 -0
  219. package/src/hcl/roots.ts +59 -5
  220. package/src/hcl/suppressions.test.ts +147 -0
  221. package/src/hcl/suppressions.ts +204 -0
  222. package/src/hcl/value.test.ts +73 -0
  223. package/src/hcl/value.ts +106 -0
  224. package/src/index.ts +31 -1
  225. package/src/lint/audit-catalog.ts +264 -3
  226. package/src/lint/audit-lineage.ts +319 -1
  227. package/src/lint/audit.test.ts +40 -1
  228. package/src/lint/post-synth/blocks.ts +109 -0
  229. package/src/lint/post-synth/fixtures/TF001/negative.tf +28 -0
  230. package/src/lint/post-synth/fixtures/TF001/positive.tf +24 -0
  231. package/src/lint/post-synth/fixtures/TF002/negative.tf +17 -0
  232. package/src/lint/post-synth/fixtures/TF002/positive-legacy.tf +10 -0
  233. package/src/lint/post-synth/fixtures/TF002/positive-no-version.tf +12 -0
  234. package/src/lint/post-synth/fixtures/TF002/positive.tf +7 -0
  235. package/src/lint/post-synth/fixtures/TF003/negative.tf +10 -0
  236. package/src/lint/post-synth/fixtures/TF003/positive.tf +8 -0
  237. package/src/lint/post-synth/fixtures/TF004/negative-git.tf +3 -0
  238. package/src/lint/post-synth/fixtures/TF004/negative-local.tf +3 -0
  239. package/src/lint/post-synth/fixtures/TF004/negative.tf +4 -0
  240. package/src/lint/post-synth/fixtures/TF004/positive.tf +3 -0
  241. package/src/lint/post-synth/fixtures/TF005/negative-local.tf +3 -0
  242. package/src/lint/post-synth/fixtures/TF005/negative-registry.tf +3 -0
  243. package/src/lint/post-synth/fixtures/TF005/negative-sha.tf +3 -0
  244. package/src/lint/post-synth/fixtures/TF005/negative.tf +3 -0
  245. package/src/lint/post-synth/fixtures/TF005/positive-branch.tf +3 -0
  246. package/src/lint/post-synth/fixtures/TF005/positive-non-semver.tf +3 -0
  247. package/src/lint/post-synth/fixtures/TF005/positive.tf +3 -0
  248. package/src/lint/post-synth/fixtures/TF006/negative.tf +5 -0
  249. package/src/lint/post-synth/fixtures/TF006/positive-empty-default.tf +11 -0
  250. package/src/lint/post-synth/fixtures/TF006/positive.tf +6 -0
  251. package/src/lint/post-synth/fixtures/TF007/negative.tf +10 -0
  252. package/src/lint/post-synth/fixtures/TF007/positive.tf +9 -0
  253. package/src/lint/post-synth/fixtures/TF008/negative-variable.tf +10 -0
  254. package/src/lint/post-synth/fixtures/TF008/negative.tf +8 -0
  255. package/src/lint/post-synth/fixtures/TF008/positive-other-provider.tf +10 -0
  256. package/src/lint/post-synth/fixtures/TF008/positive.tf +5 -0
  257. package/src/lint/post-synth/fixtures/TF009/negative.tf +10 -0
  258. package/src/lint/post-synth/fixtures/TF009/positive.tf +4 -0
  259. package/src/lint/post-synth/fixtures/TF010/negative.tf +5 -0
  260. package/src/lint/post-synth/fixtures/TF010/positive.tf +4 -0
  261. package/src/lint/post-synth/fixtures/TF011/negative.tf +5 -0
  262. package/src/lint/post-synth/fixtures/TF011/positive-blank.tf +5 -0
  263. package/src/lint/post-synth/fixtures/TF011/positive.tf +4 -0
  264. package/src/lint/post-synth/fixtures/TF012/negative.tf +4 -0
  265. package/src/lint/post-synth/fixtures/TF012/positive.tf +3 -0
  266. package/src/lint/post-synth/fixtures/TF013/negative.tf +8 -0
  267. package/src/lint/post-synth/fixtures/TF013/positive-data.tf +8 -0
  268. package/src/lint/post-synth/fixtures/TF013/positive.tf +8 -0
  269. package/src/lint/post-synth/fixtures/TF014/negative/main.tf +26 -0
  270. package/src/lint/post-synth/fixtures/TF014/negative/modules/cdn/main.tf +19 -0
  271. package/src/lint/post-synth/fixtures/TF014/positive/main.tf +16 -0
  272. package/src/lint/post-synth/fixtures/TF014/positive/modules/cdn/main.tf +15 -0
  273. package/src/lint/post-synth/fixtures/TF015/negative/main.tf +13 -0
  274. package/src/lint/post-synth/fixtures/TF015/negative/modules/cdn/main.tf +16 -0
  275. package/src/lint/post-synth/fixtures/TF015/positive/main.tf +13 -0
  276. package/src/lint/post-synth/fixtures/TF015/positive/modules/cdn/main.tf +14 -0
  277. package/src/lint/post-synth/fixtures/TF016/negative-template.tf +7 -0
  278. package/src/lint/post-synth/fixtures/TF016/negative.tf +16 -0
  279. package/src/lint/post-synth/fixtures/TF016/positive-shared-file.tf +12 -0
  280. package/src/lint/post-synth/fixtures/TF016/positive.tf +13 -0
  281. package/src/lint/post-synth/fixtures/TF017/negative.tf +4 -0
  282. package/src/lint/post-synth/fixtures/TF017/positive.tf +5 -0
  283. package/src/lint/post-synth/fixtures/TF018/negative.tf +9 -0
  284. package/src/lint/post-synth/fixtures/TF018/positive-data.tf +9 -0
  285. package/src/lint/post-synth/fixtures/TF018/positive.tf +4 -0
  286. package/src/lint/post-synth/fixtures/TF019/negative.tf +14 -0
  287. package/src/lint/post-synth/fixtures/TF019/positive-output.tf +5 -0
  288. package/src/lint/post-synth/fixtures/TF019/positive.tf +16 -0
  289. package/src/lint/post-synth/fixtures/TF020/negative.tf +43 -0
  290. package/src/lint/post-synth/fixtures/TF020/positive.tf +32 -0
  291. package/src/lint/post-synth/fixtures/TF020/scoped/main.tf +21 -0
  292. package/src/lint/post-synth/fixtures/TF020/scoped/modules/cdn/main.tf +13 -0
  293. package/src/lint/post-synth/fixtures/TF021/negative.tf +31 -0
  294. package/src/lint/post-synth/fixtures/TF021/positive-length.tf +8 -0
  295. package/src/lint/post-synth/fixtures/TF021/positive.tf +8 -0
  296. package/src/lint/post-synth/fixtures/TF022/negative-locator.tf +7 -0
  297. package/src/lint/post-synth/fixtures/TF022/negative.tf +10 -0
  298. package/src/lint/post-synth/fixtures/TF022/positive-nested.tf +10 -0
  299. package/src/lint/post-synth/fixtures/TF022/positive.tf +6 -0
  300. package/src/lint/post-synth/fixtures/TF023/negative/main.tf +15 -0
  301. package/src/lint/post-synth/fixtures/TF023/positive/main.tf +9 -0
  302. package/src/lint/post-synth/fixtures/TF023/positive/state.json +24 -0
  303. package/src/lint/post-synth/fixtures/TF024/live-clean/main.tf +9 -0
  304. package/src/lint/post-synth/fixtures/TF024/live-with-backend/main.tf +14 -0
  305. package/src/lint/post-synth/fixtures/TF024/live-with-cloud/main.tf +16 -0
  306. package/src/lint/post-synth/fixtures/TF025/live-clean/main.tf +13 -0
  307. package/src/lint/post-synth/fixtures/TF025/live-with-workspace-ref/main.tf +13 -0
  308. package/src/lint/post-synth/fixtures/TF026/live-default/main.tf +9 -0
  309. package/src/lint/post-synth/fixtures/TF026/live-explicit-delete/main.tf +13 -0
  310. package/src/lint/post-synth/fixtures/TF026/live-keep/main.tf +13 -0
  311. package/src/lint/post-synth/fixtures/load.ts +108 -0
  312. package/src/lint/post-synth/index.ts +48 -0
  313. package/src/lint/post-synth/module-rules.test.ts +153 -0
  314. package/src/lint/post-synth/module-source.test.ts +75 -0
  315. package/src/lint/post-synth/module-source.ts +121 -0
  316. package/src/lint/post-synth/post-synth.test.ts +14 -15
  317. package/src/lint/post-synth/scope.ts +107 -0
  318. package/src/lint/post-synth/single-block.test.ts +263 -0
  319. package/src/lint/post-synth/suppression.test.ts +110 -0
  320. package/src/lint/post-synth/tf001.ts +32 -8
  321. package/src/lint/post-synth/tf002.test.ts +93 -0
  322. package/src/lint/post-synth/tf002.ts +151 -0
  323. package/src/lint/post-synth/tf003.test.ts +75 -0
  324. package/src/lint/post-synth/tf003.ts +71 -0
  325. package/src/lint/post-synth/tf004.test.ts +47 -0
  326. package/src/lint/post-synth/tf004.ts +63 -0
  327. package/src/lint/post-synth/tf005.test.ts +57 -0
  328. package/src/lint/post-synth/tf005.ts +76 -0
  329. package/src/lint/post-synth/tf006.ts +53 -0
  330. package/src/lint/post-synth/tf007.ts +78 -0
  331. package/src/lint/post-synth/tf008.ts +75 -0
  332. package/src/lint/post-synth/tf009.ts +59 -0
  333. package/src/lint/post-synth/tf010.ts +51 -0
  334. package/src/lint/post-synth/tf011.ts +49 -0
  335. package/src/lint/post-synth/tf012.ts +47 -0
  336. package/src/lint/post-synth/tf013.ts +63 -0
  337. package/src/lint/post-synth/tf014.ts +72 -0
  338. package/src/lint/post-synth/tf015.ts +63 -0
  339. package/src/lint/post-synth/tf016.ts +75 -0
  340. package/src/lint/post-synth/tf017.ts +50 -0
  341. package/src/lint/post-synth/tf018.ts +72 -0
  342. package/src/lint/post-synth/tf019.ts +72 -0
  343. package/src/lint/post-synth/tf020.ts +123 -0
  344. package/src/lint/post-synth/tf021.ts +126 -0
  345. package/src/lint/post-synth/tf022.ts +61 -0
  346. package/src/lint/post-synth/tf024.test.ts +42 -0
  347. package/src/lint/post-synth/tf024.ts +70 -0
  348. package/src/lint/post-synth/tf025.test.ts +46 -0
  349. package/src/lint/post-synth/tf025.ts +101 -0
  350. package/src/lint/post-synth/tf026.test.ts +56 -0
  351. package/src/lint/post-synth/tf026.ts +80 -0
  352. package/src/lint/presets.test.ts +72 -0
  353. package/src/lint/rules/fixtures/TF101/negative-op.ts +2 -0
  354. package/src/lint/rules/fixtures/TF101/positive-op.ts +2 -0
  355. package/src/lint/rules/fixtures/load.ts +53 -0
  356. package/src/lint/rules/plan-before-apply.test.ts +112 -7
  357. package/src/lint/rules/plan-before-apply.ts +11 -0
  358. package/src/lint/secret-shape.test.ts +150 -0
  359. package/src/lint/secret-shape.ts +159 -0
  360. package/src/live-ownership.ts +60 -0
  361. package/src/lsp/completions.test.ts +3 -2
  362. package/src/lsp/option-keys.ts +10 -5
  363. package/src/op/activities/choudoufu.acceptance.test.ts +143 -0
  364. package/src/op/activities/choudoufu.test.ts +693 -0
  365. package/src/op/activities/index.ts +40 -4
  366. package/src/op/activities/live-detect.test.ts +143 -0
  367. package/src/op/activities/live-detect.ts +162 -0
  368. package/src/op/activities/registry.test.ts +11 -3
  369. package/src/op/activities/terraform.test.ts +7 -3
  370. package/src/op/activities/terraform.ts +823 -69
  371. package/src/op/activity-contracts.test.ts +147 -0
  372. package/src/op/activity-contracts.ts +178 -0
  373. package/src/op/adoption.test.ts +170 -0
  374. package/src/op/adoption.ts +241 -0
  375. package/src/op/builders.test.ts +60 -5
  376. package/src/op/builders.ts +93 -5
  377. package/src/op/resolve-root-mode.test.ts +85 -0
  378. package/src/op/resolve-root-mode.ts +72 -0
  379. package/src/plugin.test.ts +68 -0
  380. package/src/plugin.ts +75 -9
  381. package/src/skills/chant-terraform.md +1 -1
@@ -0,0 +1,80 @@
1
+ /**
2
+ * TF026: a live root declares `delete: "never"` but its `policy` block still
3
+ * deletes an orphaned marked resource.
4
+ *
5
+ * chant's cross-lexicon delete-mode vocabulary (`terraform.roots.<name>.delete`,
6
+ * `../../config.ts`'s `TerraformDeleteMode`) maps onto choudoufu's `policy`
7
+ * block: `undeclared_tagged` governs what happens to a resource this estate
8
+ * marked that the configuration no longer declares, and defaults to
9
+ * `"delete"` when the `policy` block omits it, or the root declares no
10
+ * `policy` block at all. `delete: "never"` promises that `TerraformApplyOp`
11
+ * never proposes deleting a resource it owns, so a root making that promise
12
+ * has to have actually turned the quadrant's default off — `"keep"`,
13
+ * `"untag"` or `"report"` all satisfy it; anything else (the unset default,
14
+ * or an explicit `"delete"`) does not.
15
+ *
16
+ * One diagnostic per root, fired from the root's `Terraform::Live` entity —
17
+ * the same entity TF024 and TF025 fire from.
18
+ */
19
+
20
+ import type {
21
+ PostSynthCheck,
22
+ PostSynthContext,
23
+ PostSynthDiagnostic,
24
+ } from "@intentius/chant/lint/post-synth";
25
+ import { isResourceDeclarable } from "@intentius/chant/declarable";
26
+ import { LIVE_TYPE, type BlockBody } from "../../hcl/parse";
27
+
28
+ /** Verbs that satisfy `delete: "never"` for the `undeclared_tagged` quadrant. */
29
+ const SATISFIES_NEVER = new Set(["keep", "untag", "report"]);
30
+
31
+ /** The `policy { }` block nested in a `live { }` block's body, hcl2json's own "one block, wrapped in an array" shape. */
32
+ function policyBlockOf(liveBody: BlockBody): BlockBody | undefined {
33
+ const policy = liveBody["policy"];
34
+ return Array.isArray(policy) && policy.length > 0 && typeof policy[0] === "object" && policy[0] !== null
35
+ ? (policy[0] as BlockBody)
36
+ : undefined;
37
+ }
38
+
39
+ export const tf026: PostSynthCheck = {
40
+ id: "TF026",
41
+ description: "Live root declares delete: \"never\" but its policy leaves undeclared_tagged at \"delete\"",
42
+
43
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
44
+ const diagnostics: PostSynthDiagnostic[] = [];
45
+ const flagged = new Set<string>();
46
+
47
+ for (const [name, entity] of ctx.entities) {
48
+ if (entity.entityType !== LIVE_TYPE) continue;
49
+ if (!isResourceDeclarable(entity)) continue;
50
+ const props = entity.props as { root?: unknown; body?: unknown; mode?: unknown; delete?: unknown };
51
+ if (props.mode !== "live") continue;
52
+ if (props.delete !== "never") continue;
53
+ const root = typeof props.root === "string" ? props.root : "";
54
+ if (flagged.has(root)) continue;
55
+
56
+ const body = (typeof props.body === "object" && props.body !== null ? props.body : {}) as BlockBody;
57
+ const policy = policyBlockOf(body);
58
+ const undeclaredTagged = policy && typeof policy["undeclared_tagged"] === "string" ? (policy["undeclared_tagged"] as string) : undefined;
59
+ if (undeclaredTagged !== undefined && SATISFIES_NEVER.has(undeclaredTagged)) continue;
60
+
61
+ flagged.add(root);
62
+ const found =
63
+ undeclaredTagged === undefined
64
+ ? "leaves undeclared_tagged unset, which defaults to \"delete\""
65
+ : `sets undeclared_tagged = "${undeclaredTagged}"`;
66
+ diagnostics.push({
67
+ checkId: "TF026",
68
+ severity: "error",
69
+ message:
70
+ `Root module "${root}" declares delete: "never" (terraform.roots.${root}.delete), but its ` +
71
+ `policy block ${found}. Add undeclared_tagged = "keep" (or "untag" or "report") to the live ` +
72
+ "block's policy block, or change this root's delete mode.",
73
+ entity: name,
74
+ lexicon: "terraform",
75
+ });
76
+ }
77
+
78
+ return diagnostics;
79
+ },
80
+ };
@@ -65,7 +65,7 @@ export const { op } = TerraformApplyOp({
65
65
  });
66
66
  ```
67
67
 
68
- `gate: "never"` is what makes the Op runnable under the local executor (`chant run`); any other mode emits a Gate phase, and a gate is durable-runtime work the local executor refuses. The Gate phase always shows the saved plan first and reports its `destroys` count as a `Destroys` search attribute, because `GateStep` carries no condition to branch on at build time — the approver sees what's at stake before approving, rather than the Op deciding for them.
68
+ `gate: "never"` drops the Gate phase, so `chant run` walks straight from Plan to Apply; any other mode emits a Gate phase, and a run that reaches an unapproved gate records a pending fact on the gate ledger, ends `gated` and exits 3 until someone runs `chant approve <op> <gate>`. The Gate phase always shows the saved plan first and reports its `destroys` count as a `Destroys` run outcome, because `GateStep` carries no condition to branch on at build time — the approver sees what's at stake before approving, rather than the Op deciding for them.
69
69
 
70
70
  Terraform has no automatic rollback, so `compensate: true` with no command throws at build time, naming the Op, rather than warning once an apply has already half-run:
71
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-terraform",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/",
@@ -22,6 +22,11 @@
22
22
  "types": "./dist/op/activities/index.d.ts",
23
23
  "default": "./src/op/activities/index.ts"
24
24
  },
25
+ "./op/activity-contracts": {
26
+ "development": "./src/op/activity-contracts.ts",
27
+ "types": "./dist/op/activity-contracts.d.ts",
28
+ "default": "./src/op/activity-contracts.ts"
29
+ },
25
30
  "./lint/post-synth": {
26
31
  "development": "./src/lint/post-synth/index.ts",
27
32
  "types": "./dist/lint/post-synth/index.d.ts",
@@ -51,7 +56,7 @@
51
56
  },
52
57
  "peerDependencies": {
53
58
  "zod": "^4.3.6",
54
- "@intentius/chant": "^0.57.0",
59
+ "@intentius/chant": "^0.58.0",
55
60
  "typescript": "^5.9.3"
56
61
  },
57
62
  "description": "terraform lexicon for chant, existing Terraform root modules as declarable entities",
@@ -0,0 +1,28 @@
1
+ terraform {
2
+ required_version = ">= 1.5.0"
3
+
4
+ live {
5
+ estate = "fixture-estate"
6
+ }
7
+
8
+ required_providers {
9
+ null = {
10
+ source = "hashicorp/null"
11
+ version = "~> 3.2"
12
+ }
13
+ }
14
+ }
15
+
16
+ provider "null" {}
17
+
18
+ resource "null_resource" "first" {
19
+ triggers = {
20
+ name = "first"
21
+ }
22
+ }
23
+
24
+ resource "null_resource" "second" {
25
+ triggers = {
26
+ name = "second"
27
+ }
28
+ }
@@ -0,0 +1,6 @@
1
+ # The body of this file is the live block's content, with no wrapper block
2
+ # (choudoufu's live/MARKERS.md and site/content/docs/use/setup.md). The sidecar
3
+ # form rather than the in-block one, because choudoufu's own migration guide
4
+ # calls it the leading form: stock tooling never reads this file, so adopting
5
+ # live markers adds one file and changes zero existing lines.
6
+ estate = "chant-adopt-fixture"
@@ -0,0 +1,21 @@
1
+ terraform {
2
+ required_version = ">= 1.5.0"
3
+
4
+ required_providers {
5
+ aws = {
6
+ source = "hashicorp/aws"
7
+ version = "~> 6.0"
8
+ }
9
+ }
10
+ }
11
+
12
+ provider "aws" {}
13
+
14
+ # A VPC the acceptance test creates out of band, with no ownership marker on
15
+ # it, before this root ever plans. choudoufu's content matcher offers a VPC on
16
+ # `cidr_block` (`matchTable` in choudoufu's internal/live/foreign/classify.go),
17
+ # so an unmarked live VPC at this exact cidr is what makes this root's plan
18
+ # report one adoptable match rather than proposing a second VPC beside it.
19
+ resource "aws_vpc" "adoptable" {
20
+ cidr_block = "10.77.0.0/16"
21
+ }
@@ -0,0 +1,58 @@
1
+ # The live-root fixture, and the two documents recorded from it
2
+
3
+ This directory is one choudoufu live root: `.tf` files derived from
4
+ choudoufu's own `live/e2e/estate-block/`, plus an `estate.chdf.hcl` sidecar
5
+ naming the estate `stateless-e2e-block`. Under `terraform.binary:
6
+ "choudoufu"` chant reads it as `mode: "live"` (#2103), which is what makes
7
+ `describeResources()` branch onto `live-plan` instead of `terraform show`.
8
+
9
+ `../live-plan.json` and `../live-ls.json` were recorded from this exact
10
+ configuration, running choudoufu built from source at
11
+ https://github.com/INTENTIUS/choudoufu (`go build ./cmd/choudoufu`,
12
+ OpenTofu 1.13.0-dev) against that repository's own pinned floci emulator
13
+ (`live/smoke/README.md`'s `just smoke` stack image, `live/floci-image`):
14
+
15
+ ```
16
+ choudoufu init
17
+ choudoufu apply -auto-approve # with storage.tf still present
18
+ aws logs create-log-group --log-group-name /stateless-e2e-block/adoptable
19
+ aws logs create-log-group --log-group-name /stateless-e2e-block/held-elsewhere
20
+ aws logs tag-log-group --log-group-name /stateless-e2e-block/held-elsewhere \
21
+ --tags tofu-estate=other-estate,tofu-address=aws_cloudwatch_log_group.elsewhere
22
+ rm storage.tf # the applied bucket becomes an owned orphan
23
+ choudoufu live-plan -detailed-exitcode -json -estate=stateless-e2e-block
24
+ choudoufu live-ls -estate=stateless-e2e-block -json -consistent .
25
+ ```
26
+
27
+ Every row `describe-resources.ts` maps is in those two documents because the
28
+ run produced it, not because a fixture author typed it:
29
+
30
+ | Case | Where it came from |
31
+ |---|---|
32
+ | bound by marker | `aws_vpc.main`, `aws_subnet.app`, `aws_security_group.main`, and the two `aws_eip.pool` count instances with their slots |
33
+ | bound by derivation | `aws_cloudwatch_log_group.app`, whose identity is the name in the block |
34
+ | omission, `ABSENT` | `aws_cloudwatch_log_group.never_applied` and `aws_security_group_rule.https`, declared and never applied |
35
+ | omission, `UNOWNED` | the two log groups the `unowned[]` section also carries |
36
+ | unowned, adoptable | `aws_cloudwatch_log_group.adoptable`, with the two tag values that would claim it |
37
+ | unowned, held elsewhere | `aws_cloudwatch_log_group.held_elsewhere`, carrying `other-estate` |
38
+ | owned orphan | `aws_s3_bucket.data` in the listing, `declared: false` after `storage.tf` was removed |
39
+ | listing gap | `aws_security_group_rule.https`, on the declaration-carried rung |
40
+
41
+ ## Two things the recording could not do as a chant live root would
42
+
43
+ **The sidecar was not present during the recording.** `live-plan -json` is
44
+ choudoufu's `-estate` form only, and that form refuses to run against a
45
+ configuration that names its own estate: `choudoufu live-plan -estate=X` on a
46
+ root with a `live` block or an `estate.chdf.hcl` sidecar answers "Estate named
47
+ by both the live block and -estate", while plain `choudoufu plan -json` under
48
+ one answers "Machine-readable output is not available under live resource
49
+ markers yet" (`internal/command/live_plan.go` and `live_mode.go`). So the
50
+ documents were recorded with the sidecar absent and `-estate` passed, and the
51
+ sidecar was added afterwards to make this directory the live root chant sees.
52
+ The documents themselves are byte-identical either way: the same estate, the
53
+ same resources, the same sections.
54
+
55
+ **The plan document's leading progress lines are not part of it.**
56
+ `live-plan -json` prints its refresh progress to stdout ahead of the document.
57
+ `../live-plan.json` is the document alone, from the first line that is a bare
58
+ `{`.
@@ -0,0 +1,10 @@
1
+ # Coverage: fungible count (aws_eip.pool, count = 2). Two rather than the
2
+ # main estate's three — enough to prove slot markers survive a plain apply
3
+ # without re-proving count-scale-down's exactness, which is step 9's job
4
+ # against the main estate.
5
+
6
+ resource "aws_eip" "pool" {
7
+ count = 2
8
+
9
+ domain = "vpc"
10
+ }
@@ -0,0 +1 @@
1
+ estate = "stateless-e2e-block"
@@ -0,0 +1,8 @@
1
+ # Coverage: client-named path (aws_cloudwatch_log_group — identity is the
2
+ # log group name in config). No conditional-idiom instance here (the main
3
+ # estate's aws_cloudwatch_log_group.optional already covers that row).
4
+
5
+ resource "aws_cloudwatch_log_group" "app" {
6
+ name = "/stateless-e2e-block/app"
7
+ retention_in_days = 1
8
+ }
@@ -0,0 +1,24 @@
1
+ # Coverage: marker path (aws_vpc, aws_subnet, aws_security_group) — the same
2
+ # admission row the main estate's network.tf covers. No for_each here (the
3
+ # main estate's aws_subnet.this carries that row already); one subnet is
4
+ # enough for this fixture's purpose, which is proving plain plan/apply, not
5
+ # re-proving admission coverage.
6
+ #
7
+ # No tags argument on any resource below, unlike the main estate: this is the
8
+ # point of estate-block (README.md) — every marker here is one stamping
9
+ # writes at apply time, never one hand-written in config.
10
+
11
+ resource "aws_vpc" "main" {
12
+ cidr_block = "10.99.0.0/16"
13
+ }
14
+
15
+ resource "aws_subnet" "app" {
16
+ vpc_id = aws_vpc.main.id
17
+ cidr_block = "10.99.1.0/24"
18
+ }
19
+
20
+ resource "aws_security_group" "main" {
21
+ name = "stateless-e2e-block-main"
22
+ description = "estate-block fixture security group"
23
+ vpc_id = aws_vpc.main.id
24
+ }
@@ -0,0 +1,11 @@
1
+ # aws_security_group_rule carries no tags argument at all, so no ownership
2
+ # marker was ever written for it: live-ls reports it as a gap on the
3
+ # declaration-carried rung rather than as an absence.
4
+ resource "aws_security_group_rule" "https" {
5
+ type = "ingress"
6
+ from_port = 443
7
+ to_port = 443
8
+ protocol = "tcp"
9
+ cidr_blocks = ["10.99.0.0/16"]
10
+ security_group_id = aws_security_group.main.id
11
+ }
@@ -0,0 +1,21 @@
1
+ # A live log group that exists in the account carrying no marker at all:
2
+ # live-plan reports it unowned at a declared identity with the exact tag
3
+ # write that would adopt it.
4
+ resource "aws_cloudwatch_log_group" "adoptable" {
5
+ name = "/stateless-e2e-block/adoptable"
6
+ retention_in_days = 1
7
+ }
8
+
9
+ # A live log group carrying another estate's marker: unowned, and not this
10
+ # run's to adopt.
11
+ resource "aws_cloudwatch_log_group" "held_elsewhere" {
12
+ name = "/stateless-e2e-block/held-elsewhere"
13
+ retention_in_days = 1
14
+ }
15
+
16
+ # Declared and never applied: nothing exists at this identity, so the plan
17
+ # omits it with reason ABSENT and proposes creating it.
18
+ resource "aws_cloudwatch_log_group" "never_applied" {
19
+ name = "/stateless-e2e-block/never-applied"
20
+ retention_in_days = 1
21
+ }
@@ -0,0 +1,31 @@
1
+ # Provider wiring for the live-root fixture. Derived from choudoufu's own
2
+ # live/e2e/estate-block/versions.tf; the estate name is declared in the
3
+ # estate.chdf.hcl sidecar beside this file rather than in a `live` block
4
+ # here, for the reason README.md gives.
5
+ #
6
+ # Same environment-variable wiring as choudoufu's own fixture
7
+ # (AWS_ENDPOINT_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION);
8
+ # the provider block carries only the flags with no env-var form.
9
+
10
+ terraform {
11
+ required_version = ">= 1.5.0"
12
+
13
+ required_providers {
14
+ aws = {
15
+ source = "hashicorp/aws"
16
+ version = "= 6.58.0"
17
+ }
18
+ }
19
+ }
20
+
21
+ provider "aws" {
22
+ skip_credentials_validation = true
23
+ skip_metadata_api_check = true
24
+
25
+ # skip_requesting_account_id deliberately absent — same rationale as the
26
+ # main estate's versions.tf (live/e2e/estate/versions.tf): letting the
27
+ # provider resolve the account keeps tag-filtered discovery honest about
28
+ # what real AWS would do.
29
+
30
+ s3_use_path_style = true
31
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "estate": "stateless-e2e-block",
3
+ "consistent": true,
4
+ "stabilized": true,
5
+ "attempts": 2,
6
+ "config_dir": ".",
7
+ "items": [
8
+ {
9
+ "id": "arn:aws:logs:us-east-1:000000000000:log-group:/stateless-e2e-block/app",
10
+ "type": "aws_cloudwatch_log_group",
11
+ "address": "aws_cloudwatch_log_group.app",
12
+ "declared": true,
13
+ "source": "tagging",
14
+ "tags": {
15
+ "tofu-address": "aws_cloudwatch_log_group.app",
16
+ "tofu-estate": "stateless-e2e-block"
17
+ }
18
+ },
19
+ {
20
+ "id": "arn:aws:ec2:us-east-1:000000000000:elastic-ip/eipalloc-956f58ee85678c4a2",
21
+ "type": "aws_eip",
22
+ "address": "aws_eip.pool[0]",
23
+ "slot": "0",
24
+ "declared": true,
25
+ "source": "tagging",
26
+ "tags": {
27
+ "tofu-address": "aws_eip.pool:0",
28
+ "tofu-estate": "stateless-e2e-block",
29
+ "tofu-slot": "0"
30
+ }
31
+ },
32
+ {
33
+ "id": "arn:aws:ec2:us-east-1:000000000000:elastic-ip/eipalloc-eb84912f9550b202b",
34
+ "type": "aws_eip",
35
+ "address": "aws_eip.pool[1]",
36
+ "slot": "1",
37
+ "declared": true,
38
+ "source": "tagging",
39
+ "tags": {
40
+ "tofu-address": "aws_eip.pool:1",
41
+ "tofu-estate": "stateless-e2e-block",
42
+ "tofu-slot": "1"
43
+ }
44
+ },
45
+ {
46
+ "id": "arn:aws:s3:::tofu-stateless-e2e-block-data",
47
+ "type": "aws_s3_bucket",
48
+ "address": "aws_s3_bucket.data",
49
+ "declared": false,
50
+ "source": "tagging",
51
+ "tags": {
52
+ "tofu-address": "aws_s3_bucket.data",
53
+ "tofu-estate": "stateless-e2e-block"
54
+ }
55
+ },
56
+ {
57
+ "id": "arn:aws:ec2:us-east-1:000000000000:security-group/sg-5fbb2850b62304cee",
58
+ "type": "aws_security_group",
59
+ "address": "aws_security_group.main",
60
+ "declared": true,
61
+ "source": "tagging",
62
+ "tags": {
63
+ "tofu-address": "aws_security_group.main",
64
+ "tofu-estate": "stateless-e2e-block"
65
+ }
66
+ },
67
+ {
68
+ "id": "arn:aws:ec2:us-east-1:000000000000:subnet/subnet-4d624e84",
69
+ "type": "aws_subnet",
70
+ "address": "aws_subnet.app",
71
+ "declared": true,
72
+ "source": "tagging",
73
+ "tags": {
74
+ "tofu-address": "aws_subnet.app",
75
+ "tofu-estate": "stateless-e2e-block"
76
+ }
77
+ },
78
+ {
79
+ "id": "arn:aws:ec2:us-east-1:000000000000:vpc/vpc-c1733cf7",
80
+ "type": "aws_vpc",
81
+ "address": "aws_vpc.main",
82
+ "declared": true,
83
+ "source": "tagging",
84
+ "tags": {
85
+ "tofu-address": "aws_vpc.main",
86
+ "tofu-estate": "stateless-e2e-block"
87
+ }
88
+ }
89
+ ],
90
+ "gaps": [
91
+ {
92
+ "address": "aws_security_group_rule.https",
93
+ "type": "aws_security_group_rule",
94
+ "rung": "declaration-carried",
95
+ "detail": "aws_security_group_rule has no settable tags argument, so no ownership marker was ever written for it - live/MARKERS.md's tier definitions (#417) name this the declaration-carried tier. Its identity comes entirely from configuration."
96
+ }
97
+ ]
98
+ }