@intentius/chant-lexicon-terraform 0.57.0 → 0.59.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 (408) hide show
  1. package/README.md +9 -0
  2. package/dist/composites/terraform-adopt-op.d.ts +131 -0
  3. package/dist/composites/terraform-adopt-op.d.ts.map +1 -0
  4. package/dist/composites/terraform-apply-op.d.ts +70 -17
  5. package/dist/composites/terraform-apply-op.d.ts.map +1 -1
  6. package/dist/composites/terraform-watch-op.d.ts +104 -37
  7. package/dist/composites/terraform-watch-op.d.ts.map +1 -1
  8. package/dist/config.d.ts +49 -2
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/describe-resources.d.ts +256 -16
  11. package/dist/describe-resources.d.ts.map +1 -1
  12. package/dist/hcl/descend.d.ts +98 -0
  13. package/dist/hcl/descend.d.ts.map +1 -0
  14. package/dist/hcl/marker.d.ts +130 -0
  15. package/dist/hcl/marker.d.ts.map +1 -0
  16. package/dist/hcl/parse.d.ts +156 -9
  17. package/dist/hcl/parse.d.ts.map +1 -1
  18. package/dist/hcl/references.d.ts +76 -0
  19. package/dist/hcl/references.d.ts.map +1 -0
  20. package/dist/hcl/roots.d.ts +22 -3
  21. package/dist/hcl/roots.d.ts.map +1 -1
  22. package/dist/hcl/suppressions.d.ts +54 -0
  23. package/dist/hcl/suppressions.d.ts.map +1 -0
  24. package/dist/hcl/value.d.ts +77 -0
  25. package/dist/hcl/value.d.ts.map +1 -0
  26. package/dist/index.d.ts +5 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/integrity.json +34 -5
  29. package/dist/lint/audit-catalog.d.ts +3 -2
  30. package/dist/lint/audit-catalog.d.ts.map +1 -1
  31. package/dist/lint/audit-lineage.d.ts +95 -0
  32. package/dist/lint/audit-lineage.d.ts.map +1 -1
  33. package/dist/lint/post-synth/blocks.d.ts +53 -0
  34. package/dist/lint/post-synth/blocks.d.ts.map +1 -0
  35. package/dist/lint/post-synth/fixtures/load.d.ts +37 -0
  36. package/dist/lint/post-synth/fixtures/load.d.ts.map +1 -0
  37. package/dist/lint/post-synth/index.d.ts.map +1 -1
  38. package/dist/lint/post-synth/module-source.d.ts +38 -0
  39. package/dist/lint/post-synth/module-source.d.ts.map +1 -0
  40. package/dist/lint/post-synth/scope.d.ts +65 -0
  41. package/dist/lint/post-synth/scope.d.ts.map +1 -0
  42. package/dist/lint/post-synth/tf001.d.ts +58 -6
  43. package/dist/lint/post-synth/tf001.d.ts.map +1 -1
  44. package/dist/lint/post-synth/tf002.d.ts +32 -0
  45. package/dist/lint/post-synth/tf002.d.ts.map +1 -0
  46. package/dist/lint/post-synth/tf003.d.ts +22 -0
  47. package/dist/lint/post-synth/tf003.d.ts.map +1 -0
  48. package/dist/lint/post-synth/tf004.d.ts +22 -0
  49. package/dist/lint/post-synth/tf004.d.ts.map +1 -0
  50. package/dist/lint/post-synth/tf005.d.ts +28 -0
  51. package/dist/lint/post-synth/tf005.d.ts.map +1 -0
  52. package/dist/lint/post-synth/tf006.d.ts +21 -0
  53. package/dist/lint/post-synth/tf006.d.ts.map +1 -0
  54. package/dist/lint/post-synth/tf007.d.ts +21 -0
  55. package/dist/lint/post-synth/tf007.d.ts.map +1 -0
  56. package/dist/lint/post-synth/tf008.d.ts +22 -0
  57. package/dist/lint/post-synth/tf008.d.ts.map +1 -0
  58. package/dist/lint/post-synth/tf009.d.ts +24 -0
  59. package/dist/lint/post-synth/tf009.d.ts.map +1 -0
  60. package/dist/lint/post-synth/tf010.d.ts +19 -0
  61. package/dist/lint/post-synth/tf010.d.ts.map +1 -0
  62. package/dist/lint/post-synth/tf011.d.ts +18 -0
  63. package/dist/lint/post-synth/tf011.d.ts.map +1 -0
  64. package/dist/lint/post-synth/tf012.d.ts +17 -0
  65. package/dist/lint/post-synth/tf012.d.ts.map +1 -0
  66. package/dist/lint/post-synth/tf013.d.ts +21 -0
  67. package/dist/lint/post-synth/tf013.d.ts.map +1 -0
  68. package/dist/lint/post-synth/tf014.d.ts +25 -0
  69. package/dist/lint/post-synth/tf014.d.ts.map +1 -0
  70. package/dist/lint/post-synth/tf015.d.ts +30 -0
  71. package/dist/lint/post-synth/tf015.d.ts.map +1 -0
  72. package/dist/lint/post-synth/tf016.d.ts +30 -0
  73. package/dist/lint/post-synth/tf016.d.ts.map +1 -0
  74. package/dist/lint/post-synth/tf017.d.ts +19 -0
  75. package/dist/lint/post-synth/tf017.d.ts.map +1 -0
  76. package/dist/lint/post-synth/tf018.d.ts +20 -0
  77. package/dist/lint/post-synth/tf018.d.ts.map +1 -0
  78. package/dist/lint/post-synth/tf019.d.ts +25 -0
  79. package/dist/lint/post-synth/tf019.d.ts.map +1 -0
  80. package/dist/lint/post-synth/tf020.d.ts +38 -0
  81. package/dist/lint/post-synth/tf020.d.ts.map +1 -0
  82. package/dist/lint/post-synth/tf021.d.ts +41 -0
  83. package/dist/lint/post-synth/tf021.d.ts.map +1 -0
  84. package/dist/lint/post-synth/tf022.d.ts +24 -0
  85. package/dist/lint/post-synth/tf022.d.ts.map +1 -0
  86. package/dist/lint/post-synth/tf024.d.ts +24 -0
  87. package/dist/lint/post-synth/tf024.d.ts.map +1 -0
  88. package/dist/lint/post-synth/tf025.d.ts +29 -0
  89. package/dist/lint/post-synth/tf025.d.ts.map +1 -0
  90. package/dist/lint/post-synth/tf026.d.ts +28 -0
  91. package/dist/lint/post-synth/tf026.d.ts.map +1 -0
  92. package/dist/lint/post-synth/tf027.d.ts +30 -0
  93. package/dist/lint/post-synth/tf027.d.ts.map +1 -0
  94. package/dist/lint/post-synth/tf028.d.ts +33 -0
  95. package/dist/lint/post-synth/tf028.d.ts.map +1 -0
  96. package/dist/lint/rules/fixtures/load.d.ts +13 -0
  97. package/dist/lint/rules/fixtures/load.d.ts.map +1 -0
  98. package/dist/lint/rules/plan-before-apply.d.ts +11 -0
  99. package/dist/lint/rules/plan-before-apply.d.ts.map +1 -1
  100. package/dist/lint/secret-shape.d.ts +68 -0
  101. package/dist/lint/secret-shape.d.ts.map +1 -0
  102. package/dist/live-ownership.d.ts +55 -0
  103. package/dist/live-ownership.d.ts.map +1 -0
  104. package/dist/lsp/option-keys.d.ts.map +1 -1
  105. package/dist/manifest.json +1 -1
  106. package/dist/okf/index.md +26 -0
  107. package/dist/okf/rules/TF002.md +11 -0
  108. package/dist/okf/rules/TF003.md +11 -0
  109. package/dist/okf/rules/TF004.md +11 -0
  110. package/dist/okf/rules/TF005.md +11 -0
  111. package/dist/okf/rules/TF006.md +11 -0
  112. package/dist/okf/rules/TF007.md +11 -0
  113. package/dist/okf/rules/TF008.md +11 -0
  114. package/dist/okf/rules/TF009.md +11 -0
  115. package/dist/okf/rules/TF010.md +11 -0
  116. package/dist/okf/rules/TF011.md +11 -0
  117. package/dist/okf/rules/TF012.md +11 -0
  118. package/dist/okf/rules/TF013.md +11 -0
  119. package/dist/okf/rules/TF014.md +11 -0
  120. package/dist/okf/rules/TF015.md +11 -0
  121. package/dist/okf/rules/TF016.md +11 -0
  122. package/dist/okf/rules/TF017.md +11 -0
  123. package/dist/okf/rules/TF018.md +11 -0
  124. package/dist/okf/rules/TF019.md +11 -0
  125. package/dist/okf/rules/TF020.md +11 -0
  126. package/dist/okf/rules/TF021.md +11 -0
  127. package/dist/okf/rules/TF022.md +11 -0
  128. package/dist/okf/rules/TF024.md +11 -0
  129. package/dist/okf/rules/TF025.md +11 -0
  130. package/dist/okf/rules/TF026.md +11 -0
  131. package/dist/okf/rules/TF027.md +11 -0
  132. package/dist/okf/rules/TF028.md +11 -0
  133. package/dist/op/activities/index.d.ts +13 -6
  134. package/dist/op/activities/index.d.ts.map +1 -1
  135. package/dist/op/activities/live-detect.d.ts +51 -0
  136. package/dist/op/activities/live-detect.d.ts.map +1 -0
  137. package/dist/op/activities/terraform.d.ts +466 -17
  138. package/dist/op/activities/terraform.d.ts.map +1 -1
  139. package/dist/op/activity-contracts.d.ts +148 -0
  140. package/dist/op/activity-contracts.d.ts.map +1 -0
  141. package/dist/op/adoption.d.ts +118 -0
  142. package/dist/op/adoption.d.ts.map +1 -0
  143. package/dist/op/builders.d.ts +48 -6
  144. package/dist/op/builders.d.ts.map +1 -1
  145. package/dist/op/resolve-root-mode.d.ts +59 -0
  146. package/dist/op/resolve-root-mode.d.ts.map +1 -0
  147. package/dist/plugin.d.ts.map +1 -1
  148. package/dist/rules/blocks.ts +109 -0
  149. package/dist/rules/module-source.ts +121 -0
  150. package/dist/rules/plan-before-apply.ts +11 -0
  151. package/dist/rules/scope.ts +107 -0
  152. package/dist/rules/tf001.ts +98 -18
  153. package/dist/rules/tf002.ts +151 -0
  154. package/dist/rules/tf003.ts +71 -0
  155. package/dist/rules/tf004.ts +63 -0
  156. package/dist/rules/tf005.ts +76 -0
  157. package/dist/rules/tf006.ts +53 -0
  158. package/dist/rules/tf007.ts +78 -0
  159. package/dist/rules/tf008.ts +75 -0
  160. package/dist/rules/tf009.ts +59 -0
  161. package/dist/rules/tf010.ts +51 -0
  162. package/dist/rules/tf011.ts +49 -0
  163. package/dist/rules/tf012.ts +47 -0
  164. package/dist/rules/tf013.ts +63 -0
  165. package/dist/rules/tf014.ts +72 -0
  166. package/dist/rules/tf015.ts +72 -0
  167. package/dist/rules/tf016.ts +75 -0
  168. package/dist/rules/tf017.ts +50 -0
  169. package/dist/rules/tf018.ts +72 -0
  170. package/dist/rules/tf019.ts +72 -0
  171. package/dist/rules/tf020.ts +123 -0
  172. package/dist/rules/tf021.ts +126 -0
  173. package/dist/rules/tf022.ts +61 -0
  174. package/dist/rules/tf024.ts +70 -0
  175. package/dist/rules/tf025.ts +101 -0
  176. package/dist/rules/tf026.ts +84 -0
  177. package/dist/rules/tf027.ts +74 -0
  178. package/dist/rules/tf028.ts +96 -0
  179. package/dist/skills/chant-terraform.md +1 -1
  180. package/dist/validate.d.ts.map +1 -1
  181. package/package.json +7 -2
  182. package/src/__fixtures__/ACCEPTANCE.md +181 -0
  183. package/src/__fixtures__/live/main.tf +28 -0
  184. package/src/__fixtures__/live-adopt/estate.chdf.hcl +6 -0
  185. package/src/__fixtures__/live-adopt/main.tf +21 -0
  186. package/src/__fixtures__/live-estate/README.md +58 -0
  187. package/src/__fixtures__/live-estate/compute.tf +10 -0
  188. package/src/__fixtures__/live-estate/estate.chdf.hcl +1 -0
  189. package/src/__fixtures__/live-estate/logs.tf +8 -0
  190. package/src/__fixtures__/live-estate/network.tf +24 -0
  191. package/src/__fixtures__/live-estate/rule.tf +11 -0
  192. package/src/__fixtures__/live-estate/unowned.tf +21 -0
  193. package/src/__fixtures__/live-estate/versions.tf +31 -0
  194. package/src/__fixtures__/live-ls.json +98 -0
  195. package/src/__fixtures__/live-plan.json +285 -0
  196. package/src/__fixtures__/live-sidecar/estate.chdf.hcl +3 -0
  197. package/src/__fixtures__/live-sidecar/main.tf +24 -0
  198. package/src/__fixtures__/module-tree/README.md +16 -0
  199. package/src/__fixtures__/module-tree/cycle/main.tf +3 -0
  200. package/src/__fixtures__/module-tree/cycle/modules/a/main.tf +9 -0
  201. package/src/__fixtures__/module-tree/cycle/modules/b/main.tf +9 -0
  202. package/src/__fixtures__/module-tree/missing/main.tf +9 -0
  203. package/src/__fixtures__/module-tree/outside/root/main.tf +9 -0
  204. package/src/__fixtures__/module-tree/root/main.tf +28 -0
  205. package/src/__fixtures__/module-tree/root/modules/cdn/main.tf +15 -0
  206. package/src/__fixtures__/module-tree/root/modules/cdn/modules/bucket/main.tf +11 -0
  207. package/src/__fixtures__/module-tree/shared/main.tf +5 -0
  208. package/src/__fixtures__/references/main.tf +56 -0
  209. package/src/__fixtures__/remote-backend/main.tf +34 -0
  210. package/src/__fixtures__/with-backend/main.tf +7 -0
  211. package/src/codegen/lint-rules-page.test.ts +45 -0
  212. package/src/composites/terraform-adopt-op.acceptance.test.ts +193 -0
  213. package/src/composites/terraform-adopt-op.test.ts +175 -0
  214. package/src/composites/terraform-adopt-op.ts +202 -0
  215. package/src/composites/terraform-apply-op.acceptance.test.ts +188 -5
  216. package/src/composites/terraform-apply-op.test.ts +179 -19
  217. package/src/composites/terraform-apply-op.ts +123 -30
  218. package/src/composites/terraform-watch-op.test.ts +169 -29
  219. package/src/composites/terraform-watch-op.ts +183 -75
  220. package/src/config.ts +32 -3
  221. package/src/describe-resources.live.test.ts +598 -0
  222. package/src/describe-resources.test.ts +53 -0
  223. package/src/describe-resources.ts +811 -28
  224. package/src/hcl/descend.test.ts +162 -0
  225. package/src/hcl/descend.ts +273 -0
  226. package/src/hcl/marker.test.ts +147 -0
  227. package/src/hcl/marker.ts +235 -0
  228. package/src/hcl/parse.test.ts +69 -0
  229. package/src/hcl/parse.ts +269 -27
  230. package/src/hcl/references.test.ts +116 -0
  231. package/src/hcl/references.ts +172 -0
  232. package/src/hcl/roots.ts +59 -5
  233. package/src/hcl/suppressions.test.ts +147 -0
  234. package/src/hcl/suppressions.ts +204 -0
  235. package/src/hcl/value.test.ts +73 -0
  236. package/src/hcl/value.ts +106 -0
  237. package/src/index.ts +31 -1
  238. package/src/lint/audit-catalog.ts +288 -3
  239. package/src/lint/audit-lineage.ts +384 -1
  240. package/src/lint/audit.test.ts +210 -3
  241. package/src/lint/post-synth/blocks.ts +109 -0
  242. package/src/lint/post-synth/fixtures/TF001/negative-cloud.tf +28 -0
  243. package/src/lint/post-synth/fixtures/TF001/negative.tf +30 -0
  244. package/src/lint/post-synth/fixtures/TF001/positive-local.tf +31 -0
  245. package/src/lint/post-synth/fixtures/TF001/positive.tf +24 -0
  246. package/src/lint/post-synth/fixtures/TF002/negative.tf +17 -0
  247. package/src/lint/post-synth/fixtures/TF002/positive-legacy.tf +10 -0
  248. package/src/lint/post-synth/fixtures/TF002/positive-no-version.tf +12 -0
  249. package/src/lint/post-synth/fixtures/TF002/positive.tf +7 -0
  250. package/src/lint/post-synth/fixtures/TF003/negative.tf +10 -0
  251. package/src/lint/post-synth/fixtures/TF003/positive.tf +8 -0
  252. package/src/lint/post-synth/fixtures/TF004/negative-git.tf +3 -0
  253. package/src/lint/post-synth/fixtures/TF004/negative-local.tf +3 -0
  254. package/src/lint/post-synth/fixtures/TF004/negative.tf +4 -0
  255. package/src/lint/post-synth/fixtures/TF004/positive.tf +3 -0
  256. package/src/lint/post-synth/fixtures/TF005/negative-local.tf +3 -0
  257. package/src/lint/post-synth/fixtures/TF005/negative-registry.tf +3 -0
  258. package/src/lint/post-synth/fixtures/TF005/negative-sha.tf +3 -0
  259. package/src/lint/post-synth/fixtures/TF005/negative.tf +3 -0
  260. package/src/lint/post-synth/fixtures/TF005/positive-branch.tf +3 -0
  261. package/src/lint/post-synth/fixtures/TF005/positive-non-semver.tf +3 -0
  262. package/src/lint/post-synth/fixtures/TF005/positive.tf +3 -0
  263. package/src/lint/post-synth/fixtures/TF006/negative.tf +5 -0
  264. package/src/lint/post-synth/fixtures/TF006/positive-empty-default.tf +11 -0
  265. package/src/lint/post-synth/fixtures/TF006/positive.tf +6 -0
  266. package/src/lint/post-synth/fixtures/TF007/negative.tf +10 -0
  267. package/src/lint/post-synth/fixtures/TF007/positive.tf +9 -0
  268. package/src/lint/post-synth/fixtures/TF008/negative-variable.tf +10 -0
  269. package/src/lint/post-synth/fixtures/TF008/negative.tf +8 -0
  270. package/src/lint/post-synth/fixtures/TF008/positive-other-provider.tf +10 -0
  271. package/src/lint/post-synth/fixtures/TF008/positive.tf +5 -0
  272. package/src/lint/post-synth/fixtures/TF009/negative.tf +10 -0
  273. package/src/lint/post-synth/fixtures/TF009/positive.tf +4 -0
  274. package/src/lint/post-synth/fixtures/TF010/negative.tf +5 -0
  275. package/src/lint/post-synth/fixtures/TF010/positive.tf +4 -0
  276. package/src/lint/post-synth/fixtures/TF011/negative.tf +5 -0
  277. package/src/lint/post-synth/fixtures/TF011/positive-blank.tf +5 -0
  278. package/src/lint/post-synth/fixtures/TF011/positive.tf +4 -0
  279. package/src/lint/post-synth/fixtures/TF012/negative.tf +4 -0
  280. package/src/lint/post-synth/fixtures/TF012/positive.tf +3 -0
  281. package/src/lint/post-synth/fixtures/TF013/negative.tf +8 -0
  282. package/src/lint/post-synth/fixtures/TF013/positive-data.tf +8 -0
  283. package/src/lint/post-synth/fixtures/TF013/positive.tf +8 -0
  284. package/src/lint/post-synth/fixtures/TF014/negative/main.tf +26 -0
  285. package/src/lint/post-synth/fixtures/TF014/negative/modules/cdn/main.tf +19 -0
  286. package/src/lint/post-synth/fixtures/TF014/positive/main.tf +16 -0
  287. package/src/lint/post-synth/fixtures/TF014/positive/modules/cdn/main.tf +15 -0
  288. package/src/lint/post-synth/fixtures/TF015/negative/main.tf +13 -0
  289. package/src/lint/post-synth/fixtures/TF015/negative/modules/cdn/main.tf +16 -0
  290. package/src/lint/post-synth/fixtures/TF015/positive/main.tf +13 -0
  291. package/src/lint/post-synth/fixtures/TF015/positive/modules/cdn/main.tf +14 -0
  292. package/src/lint/post-synth/fixtures/TF016/negative-template.tf +7 -0
  293. package/src/lint/post-synth/fixtures/TF016/negative.tf +16 -0
  294. package/src/lint/post-synth/fixtures/TF016/positive-shared-file.tf +12 -0
  295. package/src/lint/post-synth/fixtures/TF016/positive.tf +13 -0
  296. package/src/lint/post-synth/fixtures/TF017/negative.tf +4 -0
  297. package/src/lint/post-synth/fixtures/TF017/positive.tf +5 -0
  298. package/src/lint/post-synth/fixtures/TF018/negative.tf +9 -0
  299. package/src/lint/post-synth/fixtures/TF018/positive-data.tf +9 -0
  300. package/src/lint/post-synth/fixtures/TF018/positive.tf +4 -0
  301. package/src/lint/post-synth/fixtures/TF019/negative.tf +14 -0
  302. package/src/lint/post-synth/fixtures/TF019/positive-output.tf +5 -0
  303. package/src/lint/post-synth/fixtures/TF019/positive.tf +16 -0
  304. package/src/lint/post-synth/fixtures/TF020/negative.tf +43 -0
  305. package/src/lint/post-synth/fixtures/TF020/positive.tf +32 -0
  306. package/src/lint/post-synth/fixtures/TF020/scoped/main.tf +21 -0
  307. package/src/lint/post-synth/fixtures/TF020/scoped/modules/cdn/main.tf +13 -0
  308. package/src/lint/post-synth/fixtures/TF021/negative.tf +31 -0
  309. package/src/lint/post-synth/fixtures/TF021/positive-length.tf +8 -0
  310. package/src/lint/post-synth/fixtures/TF021/positive.tf +8 -0
  311. package/src/lint/post-synth/fixtures/TF022/negative-locator.tf +7 -0
  312. package/src/lint/post-synth/fixtures/TF022/negative.tf +10 -0
  313. package/src/lint/post-synth/fixtures/TF022/positive-nested.tf +10 -0
  314. package/src/lint/post-synth/fixtures/TF022/positive.tf +6 -0
  315. package/src/lint/post-synth/fixtures/TF023/negative/main.tf +15 -0
  316. package/src/lint/post-synth/fixtures/TF023/positive/main.tf +9 -0
  317. package/src/lint/post-synth/fixtures/TF023/positive/state.json +24 -0
  318. package/src/lint/post-synth/fixtures/TF024/live-clean/main.tf +9 -0
  319. package/src/lint/post-synth/fixtures/TF024/live-with-backend/main.tf +14 -0
  320. package/src/lint/post-synth/fixtures/TF024/live-with-cloud/main.tf +16 -0
  321. package/src/lint/post-synth/fixtures/TF025/live-clean/main.tf +13 -0
  322. package/src/lint/post-synth/fixtures/TF025/live-with-workspace-ref/main.tf +13 -0
  323. package/src/lint/post-synth/fixtures/TF026/live-default/main.tf +9 -0
  324. package/src/lint/post-synth/fixtures/TF026/live-explicit-delete/main.tf +13 -0
  325. package/src/lint/post-synth/fixtures/TF026/live-keep/main.tf +13 -0
  326. package/src/lint/post-synth/fixtures/TF027/live-default/main.tf +9 -0
  327. package/src/lint/post-synth/fixtures/TF027/live-untagged-delete/main.tf +13 -0
  328. package/src/lint/post-synth/fixtures/TF027/live-untagged-delete-scoped/main.tf +17 -0
  329. package/src/lint/post-synth/fixtures/TF027/live-untagged-report/main.tf +13 -0
  330. package/src/lint/post-synth/fixtures/TF028/live/main.tf +9 -0
  331. package/src/lint/post-synth/fixtures/TF028/stock/main.tf +10 -0
  332. package/src/lint/post-synth/fixtures/load.ts +108 -0
  333. package/src/lint/post-synth/index.ts +52 -0
  334. package/src/lint/post-synth/live-refusals-config-format.test.ts +143 -0
  335. package/src/lint/post-synth/module-rules.test.ts +153 -0
  336. package/src/lint/post-synth/module-source.test.ts +75 -0
  337. package/src/lint/post-synth/module-source.ts +121 -0
  338. package/src/lint/post-synth/post-synth.test.ts +73 -16
  339. package/src/lint/post-synth/scope.ts +107 -0
  340. package/src/lint/post-synth/single-block.test.ts +263 -0
  341. package/src/lint/post-synth/suppression.test.ts +110 -0
  342. package/src/lint/post-synth/tf001.ts +98 -18
  343. package/src/lint/post-synth/tf002.test.ts +93 -0
  344. package/src/lint/post-synth/tf002.ts +151 -0
  345. package/src/lint/post-synth/tf003.test.ts +75 -0
  346. package/src/lint/post-synth/tf003.ts +71 -0
  347. package/src/lint/post-synth/tf004.test.ts +47 -0
  348. package/src/lint/post-synth/tf004.ts +63 -0
  349. package/src/lint/post-synth/tf005.test.ts +57 -0
  350. package/src/lint/post-synth/tf005.ts +76 -0
  351. package/src/lint/post-synth/tf006.ts +53 -0
  352. package/src/lint/post-synth/tf007.ts +78 -0
  353. package/src/lint/post-synth/tf008.ts +75 -0
  354. package/src/lint/post-synth/tf009.ts +59 -0
  355. package/src/lint/post-synth/tf010.ts +51 -0
  356. package/src/lint/post-synth/tf011.ts +49 -0
  357. package/src/lint/post-synth/tf012.ts +47 -0
  358. package/src/lint/post-synth/tf013.ts +63 -0
  359. package/src/lint/post-synth/tf014.ts +72 -0
  360. package/src/lint/post-synth/tf015.ts +72 -0
  361. package/src/lint/post-synth/tf016.ts +75 -0
  362. package/src/lint/post-synth/tf017.ts +50 -0
  363. package/src/lint/post-synth/tf018.ts +72 -0
  364. package/src/lint/post-synth/tf019.ts +72 -0
  365. package/src/lint/post-synth/tf020.ts +123 -0
  366. package/src/lint/post-synth/tf021.ts +126 -0
  367. package/src/lint/post-synth/tf022.ts +61 -0
  368. package/src/lint/post-synth/tf024.test.ts +42 -0
  369. package/src/lint/post-synth/tf024.ts +70 -0
  370. package/src/lint/post-synth/tf025.test.ts +46 -0
  371. package/src/lint/post-synth/tf025.ts +101 -0
  372. package/src/lint/post-synth/tf026.test.ts +56 -0
  373. package/src/lint/post-synth/tf026.ts +84 -0
  374. package/src/lint/post-synth/tf027.test.ts +62 -0
  375. package/src/lint/post-synth/tf027.ts +74 -0
  376. package/src/lint/post-synth/tf028.test.ts +92 -0
  377. package/src/lint/post-synth/tf028.ts +96 -0
  378. package/src/lint/presets.test.ts +72 -0
  379. package/src/lint/rules/fixtures/TF101/negative-op.ts +2 -0
  380. package/src/lint/rules/fixtures/TF101/positive-op.ts +2 -0
  381. package/src/lint/rules/fixtures/load.ts +53 -0
  382. package/src/lint/rules/plan-before-apply.test.ts +112 -7
  383. package/src/lint/rules/plan-before-apply.ts +11 -0
  384. package/src/lint/secret-shape.test.ts +150 -0
  385. package/src/lint/secret-shape.ts +159 -0
  386. package/src/live-ownership.ts +60 -0
  387. package/src/lsp/completions.test.ts +3 -2
  388. package/src/lsp/option-keys.ts +12 -6
  389. package/src/op/activities/choudoufu.acceptance.test.ts +127 -0
  390. package/src/op/activities/choudoufu.test.ts +725 -0
  391. package/src/op/activities/index.ts +40 -4
  392. package/src/op/activities/live-detect.test.ts +143 -0
  393. package/src/op/activities/live-detect.ts +162 -0
  394. package/src/op/activities/registry.test.ts +11 -3
  395. package/src/op/activities/terraform.test.ts +7 -3
  396. package/src/op/activities/terraform.ts +861 -69
  397. package/src/op/activity-contracts.test.ts +147 -0
  398. package/src/op/activity-contracts.ts +178 -0
  399. package/src/op/adoption.test.ts +170 -0
  400. package/src/op/adoption.ts +241 -0
  401. package/src/op/builders.test.ts +60 -5
  402. package/src/op/builders.ts +95 -5
  403. package/src/op/resolve-root-mode.test.ts +85 -0
  404. package/src/op/resolve-root-mode.ts +86 -0
  405. package/src/plugin.test.ts +106 -0
  406. package/src/plugin.ts +186 -29
  407. package/src/skills/chant-terraform.md +1 -1
  408. package/src/validate.ts +10 -1
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Activity contracts for this lexicon's own `op/activities` (chant #2101).
3
+ *
4
+ * The schema-shaped sibling of `./activities/index.ts`: that module is
5
+ * resolved by convention at `@intentius/chant-lexicon-terraform/op/activities`
6
+ * for the run-time registry, and this one at
7
+ * `@intentius/chant-lexicon-terraform/op/activity-contracts` for build-time
8
+ * validation. `loadActivityContracts`
9
+ * (`packages/core/src/op/activity-contract-registry.ts`) merges what it finds
10
+ * here into the map core's own OPS012 and OPS013 validate every `Chant::Op`
11
+ * step against. Since #2122 moved those checks into core they fire on every
12
+ * project that declares an Op, so an Op built out of terraform steps is
13
+ * checked wherever it is built. Before this existed, both examples that carry
14
+ * an Op had to keep it outside `src/` where `chant dev check-lexicon`'s
15
+ * example build could not see it.
16
+ *
17
+ * Each contract's `args` schema mirrors the corresponding `*Args` interface in
18
+ * `./activities/terraform.ts`, and each `returns` schema the corresponding
19
+ * `*Result`. Authored with `z.strictObject(...)`, never `z.object(...)`: the
20
+ * default form silently drops an unrecognized key instead of rejecting it, so
21
+ * a misspelled `planfile` would vanish rather than fail the build. The
22
+ * `returns` schemas are the half OPS013 needs — `plan.out.planFile` feeding an
23
+ * Apply step, `plan.out.text` feeding a `reconcilePr` body — so a field a step
24
+ * references has to be spelled here for the reference to validate.
25
+ *
26
+ * `json` is `z.unknown()` throughout: it is terraform's own `-json` document,
27
+ * whose shape is the provider's, not chant's. A dot-path reference into it
28
+ * therefore does not resolve, which is deliberate. Reference `text`, or one of
29
+ * the counts projected out of the document, instead of reaching into
30
+ * terraform's JSON from an Op.
31
+ */
32
+ export declare const terraformInitContract: import("@intentius/chant/op").ActivityContract<{
33
+ root: string;
34
+ upgrade?: boolean | undefined;
35
+ reconfigure?: boolean | undefined;
36
+ cwd?: string | undefined;
37
+ }, {
38
+ dir: string;
39
+ workspace?: string | undefined;
40
+ }>;
41
+ export declare const terraformPlanContract: import("@intentius/chant/op").ActivityContract<{
42
+ root: string;
43
+ planFile?: string | undefined;
44
+ destroy?: boolean | undefined;
45
+ cwd?: string | undefined;
46
+ }, {
47
+ changed: boolean;
48
+ planFile: string;
49
+ dir: string;
50
+ json: unknown;
51
+ text: string;
52
+ adds: number;
53
+ changes: number;
54
+ destroys: number;
55
+ }>;
56
+ export declare const terraformApplyContract: import("@intentius/chant/op").ActivityContract<{
57
+ root: string;
58
+ planFile?: string | undefined;
59
+ cwd?: string | undefined;
60
+ }, {
61
+ dir: string;
62
+ applied: boolean;
63
+ planFile?: string | undefined;
64
+ refused?: "approval-mismatch" | "wrong-estate" | undefined;
65
+ refusal?: string | undefined;
66
+ }>;
67
+ export declare const terraformShowContract: import("@intentius/chant/op").ActivityContract<{
68
+ root: string;
69
+ planFile?: string | undefined;
70
+ cwd?: string | undefined;
71
+ }, {
72
+ source: "plan" | "state";
73
+ json: unknown;
74
+ text: string;
75
+ dir: string;
76
+ adds: number;
77
+ changes: number;
78
+ destroys: number;
79
+ planFile?: string | undefined;
80
+ }>;
81
+ export declare const choudoufuLivePlanContract: import("@intentius/chant/op").ActivityContract<{
82
+ root: string;
83
+ estate?: string | undefined;
84
+ adoptionOnly?: boolean | undefined;
85
+ cwd?: string | undefined;
86
+ }, {
87
+ unowned: number;
88
+ adoptable: number;
89
+ drift: boolean;
90
+ json: unknown;
91
+ text: string;
92
+ ledger: string;
93
+ finding: string;
94
+ adoptions: {
95
+ [x: string]: unknown;
96
+ }[];
97
+ contested: {
98
+ [x: string]: unknown;
99
+ }[];
100
+ ambiguous: number;
101
+ dir: string;
102
+ documentPath: string;
103
+ estate: string;
104
+ adds: number;
105
+ changes: number;
106
+ destroys: number;
107
+ }>;
108
+ export declare const choudoufuLiveLsContract: import("@intentius/chant/op").ActivityContract<{
109
+ root: string;
110
+ estate?: string | undefined;
111
+ consistent?: boolean | undefined;
112
+ cwd?: string | undefined;
113
+ }, {
114
+ json: unknown;
115
+ dir: string;
116
+ estate: string;
117
+ }>;
118
+ export declare const choudoufuLiveCheckContract: import("@intentius/chant/op").ActivityContract<{
119
+ root: string;
120
+ cwd?: string | undefined;
121
+ }, {
122
+ refused: boolean;
123
+ json: unknown;
124
+ text: string;
125
+ dir: string;
126
+ }>;
127
+ export declare const choudoufuAdoptContract: import("@intentius/chant/op").ActivityContract<{
128
+ adoptions: {
129
+ [x: string]: unknown;
130
+ }[];
131
+ root: string;
132
+ contested?: {
133
+ [x: string]: unknown;
134
+ }[] | undefined;
135
+ cwd?: string | undefined;
136
+ }, {
137
+ mechanism: "tag-write";
138
+ adopted: string[];
139
+ adoptedCount: number;
140
+ refused: {
141
+ addr: string;
142
+ identity: string;
143
+ reason: string;
144
+ }[];
145
+ ambiguous: number;
146
+ dir: string;
147
+ }>;
148
+ //# sourceMappingURL=activity-contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-contracts.d.ts","sourceRoot":"","sources":["../../src/op/activity-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+BH,eAAO,MAAM,qBAAqB;;;;;;;;EASjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;EAgBjC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;EAWlC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;EAYjC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;EAwBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;EASnC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;EAKtC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAgBlC,CAAC"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * The adoption ledger: which live resources this estate's markers can claim,
3
+ * read off `live-plan -json`'s document and rendered as text (#2105).
4
+ *
5
+ * Pure. No filesystem, no child process, no HCL parse — everything here is a
6
+ * projection of GitHub issue #788's `unowned` section, which is the one place
7
+ * choudoufu states both halves of the answer: the live resource sitting at a
8
+ * declared instance's identity, and the `tofu-estate`/`tofu-address` pair that
9
+ * would adopt it. Two tags is the whole ownership contract (choudoufu's
10
+ * `live/MARKERS.md`), so those two values are the whole of what an adoption
11
+ * needs to know.
12
+ *
13
+ * ## Why chant renders a ledger at all
14
+ *
15
+ * choudoufu prints its own, under `live-plan -adoption-only`, and it is the
16
+ * better report for a human at a terminal: it counts the marker-carrying and
17
+ * the identity-by-declaration halves of the declared population separately and
18
+ * says why each unadoptable instance is unadoptable. But `-adoption-only` and
19
+ * `-json` are refused together (`internal/command/live_plan.go`: "this run
20
+ * cannot produce both reports at once"), and an Op that reports adoptables
21
+ * needs the machine-readable document anyway — for the counts it publishes as
22
+ * outcome attributes, and for the addresses an adoption step acts on. So the
23
+ * ledger below is rendered from the document that run already has, in the row
24
+ * form `-adoption-only` prints, rather than paying for a third live read.
25
+ *
26
+ * ## Ambiguity
27
+ *
28
+ * `unowned[]` is one entry per live resource, keyed by the declared instance
29
+ * whose identity found it, so two live resources at one declared identity are
30
+ * two entries carrying the same `addr`. That is the ambiguous case: no single
31
+ * tag write claims the address, and picking one of the two is a decision about
32
+ * the estate rather than something a tool infers. {@link readAdoptionLedger}
33
+ * separates those into `contested` and never lets them into `adoptions`, and
34
+ * `TerraformAdoptOp` passes the contested list to its Adopt step so the Op's
35
+ * result names what it refused as well as what it wrote.
36
+ */
37
+ /** One live resource a marker write would bind to a declared instance. */
38
+ export interface AdoptionCandidate {
39
+ /** The declared instance address whose identity found the live resource. */
40
+ addr: string;
41
+ /** The live resource's type, as choudoufu's `unowned[].type`. */
42
+ type: string;
43
+ /** The identity the live resource was read with — the handle a human, or a tagging call, needs. */
44
+ identity: string;
45
+ /** The `tofu-estate` value that adopts it. */
46
+ markerEstate: string;
47
+ /** The `tofu-address` value that adopts it, escaped as choudoufu stores it. */
48
+ markerAddress: string;
49
+ /**
50
+ * The paste-ready tagging command choudoufu printed for this address under
51
+ * `live-plan -adoption-only`, when it printed one. Absent for a type whose
52
+ * service has its own tagging call this fork does not spell out (IAM,
53
+ * Route53, S3 and friends): the two marker values above are still the whole
54
+ * contract, but the caller has to write them itself.
55
+ */
56
+ command?: string;
57
+ }
58
+ /** What {@link readAdoptionLedger} found in one `live-plan -json` document. */
59
+ export interface AdoptionLedger {
60
+ /** Candidates at an address exactly one live resource sits at. The adoptable set. */
61
+ adoptions: AdoptionCandidate[];
62
+ /**
63
+ * Every candidate at an address more than one live resource sits at. Never
64
+ * adopted: reported so a human can delete one or write the marker by hand.
65
+ * Both (or all) candidates for a contested address appear, so the report
66
+ * shows what the choice is between.
67
+ */
68
+ contested: AdoptionCandidate[];
69
+ /** How many distinct declared addresses are contested. */
70
+ ambiguous: number;
71
+ }
72
+ /**
73
+ * Project a `live-plan -json` document's `unowned` section into the adoptable
74
+ * and the contested sets.
75
+ *
76
+ * An entry counts as a candidate only when choudoufu offered both marker
77
+ * values. Both empty means adoption was not this run's to offer — the resource
78
+ * belongs to another estate (`tofu_estate` names it), or the run had no estate
79
+ * name of its own — and such an entry is neither adoptable nor contested here,
80
+ * because there is no tag write to refuse.
81
+ *
82
+ * `commands` maps a declared address to the paste-ready tagging command
83
+ * choudoufu printed for it, from {@link parseAdoptionCommands}; omit it when
84
+ * the run had no `-adoption-only` render to read one out of.
85
+ */
86
+ export declare function readAdoptionLedger(document: unknown, commands?: ReadonlyMap<string, string>): AdoptionLedger;
87
+ /**
88
+ * Pair each declared address in a `live-plan -adoption-only` render with the
89
+ * tagging command choudoufu printed under it.
90
+ *
91
+ * The render's "Adoptable now" rows are ` <addr> <- <type> <identity>`
92
+ * followed by indented detail lines, one of which is ` adopt with: <cmd>`
93
+ * (`internal/command/views/live_adoption.go`). choudoufu builds that command
94
+ * to be pasted verbatim: every interpolated value is shell-quoted, the tagging
95
+ * verb comes from its own botocore-derived table rather than a guess, and the
96
+ * provider configuration's region and endpoint ride along as `--region` and
97
+ * `--endpoint-url`, so the write lands where the resource is rather than
98
+ * wherever an operator's AWS CLI profile points. Re-deriving any of that from
99
+ * the two marker values alone would be a worse command, so this reads the one
100
+ * choudoufu already wrote.
101
+ *
102
+ * An address the render offered no command for is simply absent from the map.
103
+ */
104
+ export declare function parseAdoptionCommands(ledgerText: string): Map<string, string>;
105
+ /**
106
+ * Render {@link readAdoptionLedger}'s answer as the text an issue or PR body
107
+ * carries under the plan.
108
+ *
109
+ * One line per adoptable match, naming the declared address, the live resource
110
+ * it binds, and the two tag values that adopt it, in the token forms
111
+ * `-adoption-only` prints them in (`<addr> <- <type> <identity>`,
112
+ * `tofu-estate=`, `tofu-address=`). Contested addresses follow, listed and not
113
+ * offered. An empty ledger still renders a line: "nothing adoptable" is a
114
+ * result a reader wants, and a section that vanishes reads as one that was
115
+ * never computed.
116
+ */
117
+ export declare function renderAdoptionLedger(ledger: AdoptionLedger, estate?: string): string;
118
+ //# sourceMappingURL=adoption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adoption.d.ts","sourceRoot":"","sources":["../../src/op/adoption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B;;;;;OAKG;IACH,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;CACnB;AAcD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,CAqC5G;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoB7E;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAgDpF"}
@@ -15,7 +15,7 @@
15
15
  * path a second time.
16
16
  */
17
17
  import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
18
- import type { TerraformInitArgs, TerraformPlanArgs, TerraformApplyArgs, TerraformShowArgs } from "./activities/terraform.js";
18
+ import type { TerraformInitArgs, TerraformPlanArgs, TerraformApplyArgs, TerraformShowArgs, ChoudoufuLivePlanArgs, ChoudoufuLiveLsArgs, ChoudoufuLiveCheckArgs, ChoudoufuAdoptArgs } from "./activities/terraform.js";
19
19
  /** Extra opts every wrapper below accepts alongside its activity's own fields. */
20
20
  type StepOpts = {
21
21
  profile?: ActivityStep["profile"];
@@ -38,13 +38,55 @@ export declare const terraformInit: (root: string, opts?: WithStepRefs<Omit<Terr
38
38
  */
39
39
  export declare const terraformPlan: (root: string, opts?: WithStepRefs<Omit<TerraformPlanArgs, "root">> & StepOpts) => NamedActivityStep;
40
40
  /**
41
- * `terraform apply <planFile>` in the named root — the fully typed twin of the
41
+ * `terraform apply <planFile>` in the named root, the fully typed twin of the
42
42
  * `terraformApply` activity. `opts` is {@link TerraformApplyArgs} itself,
43
- * minus the positional `root`, so `planFile` stays required at the call site
44
- * and the activity's bare-apply refusal is a compile error rather than a
45
- * runtime one. Defaults to the `longInfra` profile.
43
+ * minus the positional `root`. `planFile` is optional in the type and
44
+ * required in practice, on a live root as much as a stock one: the activity
45
+ * refuses a missing one, and on a live root the file is the approval artifact
46
+ * choudoufu v0.13.0 re-plans against and refuses on a mismatch (choudoufu
47
+ * #878). Defaults to the `longInfra` profile.
46
48
  */
47
- export declare const terraformApply: (root: string, opts: WithStepRefs<Omit<TerraformApplyArgs, "root">> & StepOpts) => NamedActivityStep;
49
+ export declare const terraformApply: (root: string, opts?: WithStepRefs<Omit<TerraformApplyArgs, "root">> & StepOpts) => NamedActivityStep;
50
+ /**
51
+ * `choudoufu live-plan -detailed-exitcode -json` in the named root, plus the
52
+ * human render. The fully typed twin of the `choudoufuLivePlan` activity
53
+ * (#2103). `opts` is {@link ChoudoufuLivePlanArgs} itself, minus the
54
+ * positional `root`; `estate` is optional, auto-detected from the root's
55
+ * `live` block or `estate.chdf.hcl` sidecar when omitted, and a root that
56
+ * declares one is run with no `-estate` at all, which is the only form
57
+ * choudoufu admits there (choudoufu #894, fixed in v0.14.0).
58
+ * Defaults to the `longInfra` profile: like `terraformPlan`, this reads the
59
+ * live system in full (the estate-wide sweep).
60
+ *
61
+ * Give this step an `id` to read `.out.drift`, `.out.unowned`,
62
+ * `.out.adoptable` or `.out.documentPath` from a later step.
63
+ */
64
+ export declare const choudoufuLivePlan: (root: string, opts?: WithStepRefs<Omit<ChoudoufuLivePlanArgs, "root">> & StepOpts) => NamedActivityStep;
65
+ /**
66
+ * `choudoufu live-ls -estate=<estate> -json [-consistent]` in the named root,
67
+ * the fully typed twin of the `choudoufuLiveLs` activity (#2103). `opts` is
68
+ * {@link ChoudoufuLiveLsArgs} itself, minus the positional `root`. Defaults to
69
+ * the `fastIdempotent` profile: `live-ls` reads a tagging-API listing and
70
+ * calls no other provider.
71
+ */
72
+ export declare const choudoufuLiveLs: (root: string, opts?: WithStepRefs<Omit<ChoudoufuLiveLsArgs, "root">> & StepOpts) => NamedActivityStep;
73
+ /**
74
+ * `choudoufu live-check -json` in the named root, the fully typed twin of the
75
+ * `choudoufuLiveCheck` activity (#2103). `opts` is {@link ChoudoufuLiveCheckArgs}
76
+ * itself, minus the positional `root`. Defaults to the `fastIdempotent`
77
+ * profile: no cloud calls, no state.
78
+ */
79
+ export declare const choudoufuLiveCheck: (root: string, opts?: WithStepRefs<Omit<ChoudoufuLiveCheckArgs, "root">> & StepOpts) => NamedActivityStep;
80
+ /**
81
+ * Write the ownership markers that claim an adoption ledger's matches, in the
82
+ * named root. The fully typed twin of the `choudoufuAdopt` activity (#2105).
83
+ * `opts` is {@link ChoudoufuAdoptArgs} itself, minus the positional `root`, so
84
+ * `adoptions` is required at the call site — an adopt step with nothing to
85
+ * adopt is an authoring mistake, not a no-op worth defaulting to. Defaults to
86
+ * the `longInfra` profile: one tagging round trip per resource, against the
87
+ * cloud.
88
+ */
89
+ export declare const choudoufuAdopt: (root: string, opts: WithStepRefs<Omit<ChoudoufuAdoptArgs, "root">> & StepOpts) => NamedActivityStep;
48
90
  /**
49
91
  * `terraform show` in the named root, over state or over a saved plan. `opts`
50
92
  * is {@link TerraformShowArgs} itself, minus the positional `root`. Defaults
@@ -1 +1 @@
1
- {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,kFAAkF;AAClF,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,MAAM,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAOF,CAAC"}
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAEhC,kFAAkF;AAClF,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC/D,iBAGF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAClE,iBAOF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAChE,iBAOF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KACnE,iBAOF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,MAAM,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAOF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAOF,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Best-effort, synchronous read of whether a named `terraform.roots` entry is
3
+ * live: `terraform.binary` is `"choudoufu"` and the root's directory declares
4
+ * an estate, either a `live { }` block or an `estate.chdf.hcl` sidecar (#2103).
5
+ *
6
+ * Three callers decide something at build time, before any activity runs, and
7
+ * none can afford the async work `../op/activities/terraform.ts`'s own
8
+ * `resolveRoot` does (`loadChantConfigUpward`, a full `chant.config.ts`/`.json`
9
+ * walk):
10
+ *
11
+ * - `TerraformApplyOp` (`../composites/terraform-apply-op.ts`) reads the
12
+ * mode to word the Gate phase's approval description, and to refuse a
13
+ * root whose `policy` block sets `undeclared_untagged = "delete"`. The
14
+ * mode no longer picks a phase shape: #2157 made the live and stock Apply
15
+ * steps one step, so both roots build the same phases.
16
+ * - `TerraformWatchOp` (`../composites/terraform-watch-op.ts`) cross-checks
17
+ * its hand-set `live` flag against the root's real mode and refuses a
18
+ * mismatch (#2216).
19
+ * - TF101 (`../lint/rules/plan-before-apply.ts`) decides whether a
20
+ * `terraformApply` call it is statically inspecting is exempt from the
21
+ * plan-file pairing it otherwise enforces.
22
+ *
23
+ * All three run in the build process (`chant build`/`chant lint`) rather than
24
+ * in an activity at run time, so a synchronous read is available, but only the
25
+ * cheap half of it: `findProjectConfig` (`@intentius/chant/project-root`) is a
26
+ * plain, already-synchronous upward filesystem walk, but a `chant.config.ts`
27
+ * is project-authored code, and evaluating it synchronously outside chant's
28
+ * own config-sandbox machinery is more than any caller's best-effort question
29
+ * is worth. So this reads `chant.config.json` only; a project on a `.ts`
30
+ * config, or with no config discoverable at all, or naming no matching root,
31
+ * resolves to `undefined`, and "unknown" reads as "stock" to every caller.
32
+ *
33
+ * That default is conservative for the two callers that only ever add a
34
+ * requirement by knowing more: TF101 keeps enforcing the plan-file pairing,
35
+ * and the watch Op keeps accepting the flag it was given. It is the
36
+ * permissive direction for the apply Op's policy refusal and for the watch
37
+ * Op's mismatch, which is why neither refusal is left to this function alone:
38
+ * TF027 and TF028 (`../lint/post-synth/`) ask the same questions of the
39
+ * parsed HCL the build already stamped `mode` onto, whatever the config file
40
+ * is written in, and those checks are the guarantee (#2216). Every project in
41
+ * this repository is on a `chant.config.ts`, so a refusal that resolves the
42
+ * mode through this function alone never fires for anyone.
43
+ */
44
+ export interface ResolvedRootMode {
45
+ /** `"live"` when `terraform.binary` is `"choudoufu"` and the root declares an estate; `"state"` otherwise. */
46
+ mode: "live" | "state";
47
+ /** The root module directory, resolved to an absolute path. */
48
+ dir: string;
49
+ }
50
+ /**
51
+ * Resolve `rootName`'s mode against the nearest `chant.config.json` found by
52
+ * walking up from `cwd` (default `process.cwd()`, matching every other
53
+ * `cwd`-defaulting option in this lexicon). `undefined` when that cannot be
54
+ * done with a plain, synchronous read: no config found, the config found is
55
+ * `chant.config.ts`, the config declares no such root, or the root's
56
+ * directory does not exist.
57
+ */
58
+ export declare function resolveRootModeSync(rootName: string, cwd?: string): ResolvedRootMode | undefined;
59
+ //# sourceMappingURL=resolve-root-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-root-mode.d.ts","sourceRoot":"","sources":["../../src/op/resolve-root-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAQH,MAAM,WAAW,gBAAgB;IAC/B,8GAA8G;IAC9G,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAoBhG"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAwB9D;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,aA4H7B,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA+DlF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,aAkP7B,CAAC"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Shared reading helpers for the single-block post-synth checks (#2110).
3
+ *
4
+ * Thirteen of the fourteen rules in that issue do the same three things: pick
5
+ * the entities of one block type out of `ctx.entities`, read one attribute of
6
+ * each body, and report. This module is those three things, so a rule file is
7
+ * its condition and its message and nothing else. It exports no
8
+ * `PostSynthCheck`, so the generated barrel skips it (see
9
+ * `packages/core/src/codegen/generate-post-synth-barrel.ts`).
10
+ */
11
+
12
+ import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
13
+ import { isResourceDeclarable } from "@intentius/chant/declarable";
14
+ import type { BlockBody, TerraformEntity } from "../../hcl/parse";
15
+
16
+ /** One parsed block, with the entity key the diagnostic reports against. */
17
+ export interface TerraformBlock {
18
+ /** `ctx.entities` key: `<root>/<address>`. */
19
+ key: string;
20
+ address: string;
21
+ body: BlockBody;
22
+ file: string;
23
+ root: string;
24
+ /** The raw text of the file this block came from (see `TerraformEntity.props`). */
25
+ source: string;
26
+ }
27
+
28
+ /** Every block of one entity type, in `ctx.entities` order. */
29
+ export function blocksOfType(ctx: PostSynthContext, entityType: string): TerraformBlock[] {
30
+ const blocks: TerraformBlock[] = [];
31
+ for (const [key, entity] of ctx.entities) {
32
+ if (entity.entityType !== entityType) continue;
33
+ if (!isResourceDeclarable(entity)) continue;
34
+ const props = (entity as TerraformEntity).props as Partial<TerraformEntity["props"]>;
35
+ blocks.push({
36
+ key,
37
+ address: typeof props.address === "string" ? props.address : key,
38
+ body: (typeof props.body === "object" && props.body !== null ? props.body : {}) as BlockBody,
39
+ file: typeof props.file === "string" ? props.file : "",
40
+ root: typeof props.root === "string" ? props.root : "",
41
+ source: typeof props.source === "string" ? props.source : "",
42
+ });
43
+ }
44
+ return blocks;
45
+ }
46
+
47
+ /** Blocks of several types at once, in the order the types are given. */
48
+ export function blocksOfTypes(ctx: PostSynthContext, entityTypes: string[]): TerraformBlock[] {
49
+ return entityTypes.flatMap((t) => blocksOfType(ctx, t));
50
+ }
51
+
52
+ /** The name half of a `var.<name>` / `output.<name>` address. */
53
+ export function blockName(address: string): string {
54
+ const dot = address.indexOf(".");
55
+ return dot === -1 ? address : address.slice(dot + 1);
56
+ }
57
+
58
+ /**
59
+ * The bodies of a nested block (`lifecycle`, `validation`, a provider's
60
+ * `assume_role`). hcl2json encodes a repeatable block as an array of bodies
61
+ * and a singleton as a bare object, so both are normalized to an array here.
62
+ */
63
+ export function nestedBodies(body: BlockBody, key: string): BlockBody[] {
64
+ const value = body[key];
65
+ if (Array.isArray(value)) return value.filter((v): v is BlockBody => typeof v === "object" && v !== null && !Array.isArray(v));
66
+ if (typeof value === "object" && value !== null) return [value as BlockBody];
67
+ return [];
68
+ }
69
+
70
+ /** Is this attribute value a string that says nothing? */
71
+ export function isBlank(value: unknown): boolean {
72
+ return value === undefined || value === null || (typeof value === "string" && value.trim() === "");
73
+ }
74
+
75
+ /** One scalar attribute found by {@link walkAttributes}. */
76
+ export interface Attribute {
77
+ /** The attribute's own name (the last path segment). */
78
+ name: string;
79
+ /** Dotted path from the block body, e.g. `connection.password`. */
80
+ path: string;
81
+ value: unknown;
82
+ }
83
+
84
+ /**
85
+ * Every scalar attribute in a block body, descending through nested blocks so
86
+ * a credential inside `connection {}` or `assume_role {}` is not invisible.
87
+ * Depth-limited: a Terraform block nests a handful of levels at most, and an
88
+ * unbounded walk over a large body buys nothing.
89
+ */
90
+ export function walkAttributes(body: BlockBody, maxDepth = 3): Attribute[] {
91
+ const out: Attribute[] = [];
92
+ const visit = (value: unknown, path: string, name: string, depth: number): void => {
93
+ if (Array.isArray(value)) {
94
+ if (depth > maxDepth) return;
95
+ for (const item of value) visit(item, path, name, depth);
96
+ return;
97
+ }
98
+ if (typeof value === "object" && value !== null) {
99
+ if (depth >= maxDepth) return;
100
+ for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
101
+ visit(v, path === "" ? k : `${path}.${k}`, k, depth + 1);
102
+ }
103
+ return;
104
+ }
105
+ if (path !== "") out.push({ name, path, value });
106
+ };
107
+ visit(body, "", "", 0);
108
+ return out;
109
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Classify a `module` block's `source` string, shared by TF004 (registry
3
+ * module without a version) and TF005 (git/hg module unpinned or pinned to
4
+ * a branch). Neither rule evaluates HCL: both read `source` as the literal
5
+ * string hcl2json hands back, so a source built from a variable or a
6
+ * function call is never classified (`"other"`), matching tflint's own
7
+ * `SourceKnown` guard on `module.Source`.
8
+ *
9
+ * `registry` mirrors `hashicorp/terraform-registry-address`'s
10
+ * `ParseModuleSource` (MPL-2.0,
11
+ * https://github.com/hashicorp/terraform-registry-address/blob/main/module.go):
12
+ * three slash-separated parts (`namespace/name/target-system`), or four with
13
+ * a leading hostname that contains a dot and is not `github.com` or
14
+ * `bitbucket.org` (those are reserved for direct VCS installs, never a
15
+ * registry). `git` covers the sources tflint's `terraform_module_pinned_source`
16
+ * treats as git/hg: an explicit `git::`/`hg::` force prefix, the `github.com`
17
+ * and `bitbucket.org` shorthands its `GitHubDetector`/`BitBucketDetector`
18
+ * recognize, scp-style `git@host:path` addresses, and any source ending in
19
+ * `.git`. `local` is `./` or `../` (checkov's `UNKNOWN` case for module
20
+ * pinning: a local path cannot be pinned to anything and is never flagged).
21
+ */
22
+
23
+ export type ModuleSourceKind = "local" | "registry" | "git" | "other";
24
+
25
+ export interface ModuleSourceClassification {
26
+ kind: ModuleSourceKind;
27
+ /** The `?ref=`/`&ref=` value (falling back to `rev`), when `kind` is `"git"`. */
28
+ ref?: string;
29
+ }
30
+
31
+ const REGISTRY_NAME = /^[0-9A-Za-z](?:[0-9A-Za-z_-]{0,62}[0-9A-Za-z])?$/;
32
+ const REGISTRY_TARGET_SYSTEM = /^[0-9a-z]{1,64}$/;
33
+ const RESERVED_VCS_HOSTS = new Set(["github.com", "bitbucket.org"]);
34
+
35
+ /** Split a raw query string (no leading `?`) into its key/value pairs, last write wins. */
36
+ function parseQuery(query: string): Map<string, string> {
37
+ const params = new Map<string, string>();
38
+ for (const pair of query.split("&")) {
39
+ if (pair === "") continue;
40
+ const eq = pair.indexOf("=");
41
+ const key = eq === -1 ? pair : pair.slice(0, eq);
42
+ const value = eq === -1 ? "" : decodeURIComponent(pair.slice(eq + 1));
43
+ params.set(decodeURIComponent(key), value);
44
+ }
45
+ return params;
46
+ }
47
+
48
+ /** Strip a `//<subdir>` package-subdirectory suffix, ignoring one embedded in the scheme (`https://`). */
49
+ function stripSubdir(base: string): string {
50
+ const schemeEnd = base.indexOf("://");
51
+ const searchFrom = schemeEnd === -1 ? 0 : schemeEnd + 3;
52
+ const idx = base.indexOf("//", searchFrom);
53
+ return idx === -1 ? base : base.slice(0, idx);
54
+ }
55
+
56
+ function isRegistryAddress(rest: string): boolean {
57
+ const parts = stripSubdir(rest).split("/");
58
+ let namespace: string, name: string, targetSystem: string;
59
+ if (parts.length === 3) {
60
+ [namespace, name, targetSystem] = parts;
61
+ } else if (parts.length === 4) {
62
+ const host = parts[0];
63
+ if (!host.includes(".") || RESERVED_VCS_HOSTS.has(host.toLowerCase())) return false;
64
+ [, namespace, name, targetSystem] = parts;
65
+ } else {
66
+ return false;
67
+ }
68
+ return REGISTRY_NAME.test(namespace) && REGISTRY_NAME.test(name) && REGISTRY_TARGET_SYSTEM.test(targetSystem);
69
+ }
70
+
71
+ /** Is `rest` (source with any `git::`/`hg::` force prefix already stripped) a git/hg-shaped source? */
72
+ function isGitShaped(rest: string): boolean {
73
+ if (/^[\w.-]+@[^:/]+:/.test(rest)) return true; // scp-style, e.g. git@github.com:org/repo.git
74
+ const withoutScheme = rest.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "");
75
+ if (/^(github\.com|bitbucket\.org)\//i.test(withoutScheme)) return true;
76
+ if (/\.git($|[/?])/i.test(withoutScheme)) return true;
77
+ return false;
78
+ }
79
+
80
+ export function classifyModuleSource(source: string): ModuleSourceClassification {
81
+ const trimmed = source.trim();
82
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith(".\\") || trimmed.startsWith("..\\")) {
83
+ return { kind: "local" };
84
+ }
85
+
86
+ const queryIdx = trimmed.indexOf("?");
87
+ const base = queryIdx === -1 ? trimmed : trimmed.slice(0, queryIdx);
88
+ const query = queryIdx === -1 ? "" : trimmed.slice(queryIdx + 1);
89
+
90
+ const forced = /^(git|hg)::/i.exec(base);
91
+ const rest = forced ? base.slice(forced[0].length) : base;
92
+
93
+ if (forced || isGitShaped(rest)) {
94
+ const params = parseQuery(query);
95
+ const ref = params.get("ref") || params.get("rev") || undefined;
96
+ return { kind: "git", ref };
97
+ }
98
+
99
+ if (isRegistryAddress(rest)) return { kind: "registry" };
100
+
101
+ return { kind: "other" };
102
+ }
103
+
104
+ const TAG_LIKE = /^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
105
+ const FULL_SHA = /^[0-9a-f]{40}$/i;
106
+ const DEFAULT_BRANCHES = new Set(["main", "master", "develop", "trunk"]);
107
+
108
+ /**
109
+ * Is `ref` pinned tightly enough for TF005: a semver-shaped tag or a full
110
+ * 40-hex commit SHA. Stricter than checkov's `CKV_TF_1`/`CKV_TF_2`, which
111
+ * accept any `?ref=` containing `\d\.\d` (so `v1.2-dev` passes there); the
112
+ * page documents the difference.
113
+ */
114
+ export function isPinnedRef(ref: string): boolean {
115
+ return TAG_LIKE.test(ref) || FULL_SHA.test(ref);
116
+ }
117
+
118
+ /** Is `ref` one of the well-known mutable branch names tflint's `flexible` style rejects, plus `trunk`. */
119
+ export function isDefaultBranch(ref: string): boolean {
120
+ return DEFAULT_BRANCHES.has(ref);
121
+ }