@intentius/chant 0.7.0 → 0.8.1

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 (424) hide show
  1. package/dist/attrref.d.ts +35 -0
  2. package/dist/attrref.d.ts.map +1 -0
  3. package/dist/audit/catalog.d.ts +65 -0
  4. package/dist/audit/catalog.d.ts.map +1 -0
  5. package/dist/audit/core.d.ts +76 -0
  6. package/dist/audit/core.d.ts.map +1 -0
  7. package/dist/audit/discover.d.ts +76 -0
  8. package/dist/audit/discover.d.ts.map +1 -0
  9. package/dist/audit/fetch.d.ts +90 -0
  10. package/dist/audit/fetch.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +53 -0
  12. package/dist/audit/proof.d.ts.map +1 -0
  13. package/dist/audit/report-html.d.ts +32 -0
  14. package/dist/audit/report-html.d.ts.map +1 -0
  15. package/dist/audit/report-model.d.ts +119 -0
  16. package/dist/audit/report-model.d.ts.map +1 -0
  17. package/dist/audit/report.d.ts +31 -0
  18. package/dist/audit/report.d.ts.map +1 -0
  19. package/dist/audit/rules-doc.d.ts +11 -0
  20. package/dist/audit/rules-doc.d.ts.map +1 -0
  21. package/dist/build.d.ts +120 -0
  22. package/dist/build.d.ts.map +1 -0
  23. package/dist/builder.d.ts +56 -0
  24. package/dist/builder.d.ts.map +1 -0
  25. package/dist/child-project.d.ts +34 -0
  26. package/dist/child-project.d.ts.map +1 -0
  27. package/dist/cli/commands/audit.d.ts +60 -0
  28. package/dist/cli/commands/audit.d.ts.map +1 -0
  29. package/dist/cli/commands/build.d.ts +70 -0
  30. package/dist/cli/commands/build.d.ts.map +1 -0
  31. package/dist/cli/commands/check-lexicon.d.ts +19 -0
  32. package/dist/cli/commands/check-lexicon.d.ts.map +1 -0
  33. package/dist/cli/commands/describe.d.ts +39 -0
  34. package/dist/cli/commands/describe.d.ts.map +1 -0
  35. package/dist/cli/commands/diff.d.ts +32 -0
  36. package/dist/cli/commands/diff.d.ts.map +1 -0
  37. package/dist/cli/commands/doctor.d.ts +11 -0
  38. package/dist/cli/commands/doctor.d.ts.map +1 -0
  39. package/dist/cli/commands/import.d.ts +68 -0
  40. package/dist/cli/commands/import.d.ts.map +1 -0
  41. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +9 -0
  42. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -0
  43. package/dist/cli/commands/init-lexicon/templates/docs.d.ts +9 -0
  44. package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -0
  45. package/dist/cli/commands/init-lexicon/templates/examples.d.ts +8 -0
  46. package/dist/cli/commands/init-lexicon/templates/examples.d.ts.map +1 -0
  47. package/dist/cli/commands/init-lexicon/templates/lint.d.ts +8 -0
  48. package/dist/cli/commands/init-lexicon/templates/lint.d.ts.map +1 -0
  49. package/dist/cli/commands/init-lexicon/templates/lsp.d.ts +6 -0
  50. package/dist/cli/commands/init-lexicon/templates/lsp.d.ts.map +1 -0
  51. package/dist/cli/commands/init-lexicon/templates/plugin.d.ts +12 -0
  52. package/dist/cli/commands/init-lexicon/templates/plugin.d.ts.map +1 -0
  53. package/dist/cli/commands/init-lexicon/templates/project.d.ts +19 -0
  54. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -0
  55. package/dist/cli/commands/init-lexicon/templates/spec.d.ts +6 -0
  56. package/dist/cli/commands/init-lexicon/templates/spec.d.ts.map +1 -0
  57. package/dist/cli/commands/init-lexicon/templates/tests.d.ts +12 -0
  58. package/dist/cli/commands/init-lexicon/templates/tests.d.ts.map +1 -0
  59. package/dist/cli/commands/init-lexicon.d.ts +37 -0
  60. package/dist/cli/commands/init-lexicon.d.ts.map +1 -0
  61. package/dist/cli/commands/init.d.ts +48 -0
  62. package/dist/cli/commands/init.d.ts.map +1 -0
  63. package/dist/cli/commands/licenses.d.ts +23 -0
  64. package/dist/cli/commands/licenses.d.ts.map +1 -0
  65. package/dist/cli/commands/lint.d.ts +52 -0
  66. package/dist/cli/commands/lint.d.ts.map +1 -0
  67. package/dist/cli/commands/list.d.ts +38 -0
  68. package/dist/cli/commands/list.d.ts.map +1 -0
  69. package/dist/cli/commands/migrate.d.ts +51 -0
  70. package/dist/cli/commands/migrate.d.ts.map +1 -0
  71. package/dist/cli/commands/onboard.d.ts +19 -0
  72. package/dist/cli/commands/onboard.d.ts.map +1 -0
  73. package/dist/cli/commands/update.d.ts +29 -0
  74. package/dist/cli/commands/update.d.ts.map +1 -0
  75. package/dist/cli/commands/vendor.d.ts +84 -0
  76. package/dist/cli/commands/vendor.d.ts.map +1 -0
  77. package/dist/cli/conflict-check.d.ts +18 -0
  78. package/dist/cli/conflict-check.d.ts.map +1 -0
  79. package/dist/cli/debug.d.ts +5 -0
  80. package/dist/cli/debug.d.ts.map +1 -0
  81. package/dist/cli/format.d.ts +36 -0
  82. package/dist/cli/format.d.ts.map +1 -0
  83. package/dist/cli/handlers/build.d.ts +3 -0
  84. package/dist/cli/handlers/build.d.ts.map +1 -0
  85. package/dist/cli/handlers/dev.d.ts +7 -0
  86. package/dist/cli/handlers/dev.d.ts.map +1 -0
  87. package/dist/cli/handlers/graph.d.ts +8 -0
  88. package/dist/cli/handlers/graph.d.ts.map +1 -0
  89. package/dist/cli/handlers/init.d.ts +4 -0
  90. package/dist/cli/handlers/init.d.ts.map +1 -0
  91. package/dist/cli/handlers/lifecycle.d.ts +39 -0
  92. package/dist/cli/handlers/lifecycle.d.ts.map +1 -0
  93. package/dist/cli/handlers/lint.d.ts +3 -0
  94. package/dist/cli/handlers/lint.d.ts.map +1 -0
  95. package/dist/cli/handlers/migrate.d.ts +3 -0
  96. package/dist/cli/handlers/migrate.d.ts.map +1 -0
  97. package/dist/cli/handlers/misc.d.ts +8 -0
  98. package/dist/cli/handlers/misc.d.ts.map +1 -0
  99. package/dist/cli/handlers/run-client.d.ts +107 -0
  100. package/dist/cli/handlers/run-client.d.ts.map +1 -0
  101. package/dist/cli/handlers/run-report.d.ts +5 -0
  102. package/dist/cli/handlers/run-report.d.ts.map +1 -0
  103. package/dist/cli/handlers/run.d.ts +27 -0
  104. package/dist/cli/handlers/run.d.ts.map +1 -0
  105. package/dist/cli/handlers/serve.d.ts +5 -0
  106. package/dist/cli/handlers/serve.d.ts.map +1 -0
  107. package/dist/cli/handlers/vendor.d.ts +9 -0
  108. package/dist/cli/handlers/vendor.d.ts.map +1 -0
  109. package/dist/cli/index.d.ts +4 -0
  110. package/dist/cli/index.d.ts.map +1 -0
  111. package/dist/cli/lsp/capabilities.d.ts +21 -0
  112. package/dist/cli/lsp/capabilities.d.ts.map +1 -0
  113. package/dist/cli/lsp/diagnostics.d.ts +30 -0
  114. package/dist/cli/lsp/diagnostics.d.ts.map +1 -0
  115. package/dist/cli/lsp/server.d.ts +106 -0
  116. package/dist/cli/lsp/server.d.ts.map +1 -0
  117. package/dist/cli/main.d.ts +7 -0
  118. package/dist/cli/main.d.ts.map +1 -0
  119. package/dist/cli/mcp/lifecycle-tools.d.ts +15 -0
  120. package/dist/cli/mcp/lifecycle-tools.d.ts.map +1 -0
  121. package/dist/cli/mcp/op-tools.d.ts +7 -0
  122. package/dist/cli/mcp/op-tools.d.ts.map +1 -0
  123. package/dist/cli/mcp/resource-handlers.d.ts +28 -0
  124. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -0
  125. package/dist/cli/mcp/resources/context.d.ts +6 -0
  126. package/dist/cli/mcp/resources/context.d.ts.map +1 -0
  127. package/dist/cli/mcp/server.d.ts +44 -0
  128. package/dist/cli/mcp/server.d.ts.map +1 -0
  129. package/dist/cli/mcp/tools/build.d.ts +31 -0
  130. package/dist/cli/mcp/tools/build.d.ts.map +1 -0
  131. package/dist/cli/mcp/tools/explain.d.ts +27 -0
  132. package/dist/cli/mcp/tools/explain.d.ts.map +1 -0
  133. package/dist/cli/mcp/tools/import.d.ts +26 -0
  134. package/dist/cli/mcp/tools/import.d.ts.map +1 -0
  135. package/dist/cli/mcp/tools/lint.d.ts +26 -0
  136. package/dist/cli/mcp/tools/lint.d.ts.map +1 -0
  137. package/dist/cli/mcp/tools/scaffold.d.ts +31 -0
  138. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -0
  139. package/dist/cli/mcp/tools/search.d.ts +31 -0
  140. package/dist/cli/mcp/tools/search.d.ts.map +1 -0
  141. package/dist/cli/mcp/types.d.ts +42 -0
  142. package/dist/cli/mcp/types.d.ts.map +1 -0
  143. package/dist/cli/plugins.d.ts +21 -0
  144. package/dist/cli/plugins.d.ts.map +1 -0
  145. package/dist/cli/registry.d.ts +100 -0
  146. package/dist/cli/registry.d.ts.map +1 -0
  147. package/dist/cli/reporters/stylish.d.ts +26 -0
  148. package/dist/cli/reporters/stylish.d.ts.map +1 -0
  149. package/dist/cli/watch.d.ts +29 -0
  150. package/dist/cli/watch.d.ts.map +1 -0
  151. package/dist/codegen/bound-property-types.d.ts +38 -0
  152. package/dist/codegen/bound-property-types.d.ts.map +1 -0
  153. package/dist/codegen/coverage.d.ts +57 -0
  154. package/dist/codegen/coverage.d.ts.map +1 -0
  155. package/dist/codegen/docs-file-markers.d.ts +16 -0
  156. package/dist/codegen/docs-file-markers.d.ts.map +1 -0
  157. package/dist/codegen/docs-rule-scanning.d.ts +14 -0
  158. package/dist/codegen/docs-rule-scanning.d.ts.map +1 -0
  159. package/dist/codegen/docs-rules.d.ts +17 -0
  160. package/dist/codegen/docs-rules.d.ts.map +1 -0
  161. package/dist/codegen/docs-sections.d.ts +11 -0
  162. package/dist/codegen/docs-sections.d.ts.map +1 -0
  163. package/dist/codegen/docs-sidebar.d.ts +6 -0
  164. package/dist/codegen/docs-sidebar.d.ts.map +1 -0
  165. package/dist/codegen/docs-types.d.ts +84 -0
  166. package/dist/codegen/docs-types.d.ts.map +1 -0
  167. package/dist/codegen/docs.d.ts +28 -0
  168. package/dist/codegen/docs.d.ts.map +1 -0
  169. package/dist/codegen/fetch.d.ts +76 -0
  170. package/dist/codegen/fetch.d.ts.map +1 -0
  171. package/dist/codegen/generate-post-synth-barrel.d.ts +32 -0
  172. package/dist/codegen/generate-post-synth-barrel.d.ts.map +1 -0
  173. package/dist/codegen/generate-registry.d.ts +40 -0
  174. package/dist/codegen/generate-registry.d.ts.map +1 -0
  175. package/dist/codegen/generate-runtime-index.d.ts +40 -0
  176. package/dist/codegen/generate-runtime-index.d.ts.map +1 -0
  177. package/dist/codegen/generate-typescript.d.ts +48 -0
  178. package/dist/codegen/generate-typescript.d.ts.map +1 -0
  179. package/dist/codegen/generate.d.ts +92 -0
  180. package/dist/codegen/generate.d.ts.map +1 -0
  181. package/dist/codegen/json-patch.d.ts +12 -0
  182. package/dist/codegen/json-patch.d.ts.map +1 -0
  183. package/dist/codegen/json-schema.d.ts +82 -0
  184. package/dist/codegen/json-schema.d.ts.map +1 -0
  185. package/dist/codegen/naming.d.ts +64 -0
  186. package/dist/codegen/naming.d.ts.map +1 -0
  187. package/dist/codegen/package.d.ts +64 -0
  188. package/dist/codegen/package.d.ts.map +1 -0
  189. package/dist/codegen/topo-sort.d.ts +13 -0
  190. package/dist/codegen/topo-sort.d.ts.map +1 -0
  191. package/dist/codegen/typecheck.d.ts +10 -0
  192. package/dist/codegen/typecheck.d.ts.map +1 -0
  193. package/dist/codegen/validate.d.ts +45 -0
  194. package/dist/codegen/validate.d.ts.map +1 -0
  195. package/dist/composite.d.ts +116 -0
  196. package/dist/composite.d.ts.map +1 -0
  197. package/dist/config.d.ts +78 -0
  198. package/dist/config.d.ts.map +1 -0
  199. package/dist/declarable.d.ts +34 -0
  200. package/dist/declarable.d.ts.map +1 -0
  201. package/dist/detectLexicon.d.ts +10 -0
  202. package/dist/detectLexicon.d.ts.map +1 -0
  203. package/dist/discovery/cache.d.ts +36 -0
  204. package/dist/discovery/cache.d.ts.map +1 -0
  205. package/dist/discovery/collect.d.ts +17 -0
  206. package/dist/discovery/collect.d.ts.map +1 -0
  207. package/dist/discovery/cycles.d.ts +23 -0
  208. package/dist/discovery/cycles.d.ts.map +1 -0
  209. package/dist/discovery/files.d.ts +7 -0
  210. package/dist/discovery/files.d.ts.map +1 -0
  211. package/dist/discovery/graph.d.ts +8 -0
  212. package/dist/discovery/graph.d.ts.map +1 -0
  213. package/dist/discovery/import.d.ts +9 -0
  214. package/dist/discovery/import.d.ts.map +1 -0
  215. package/dist/discovery/index.d.ts +25 -0
  216. package/dist/discovery/index.d.ts.map +1 -0
  217. package/dist/discovery/resolve.d.ts +10 -0
  218. package/dist/discovery/resolve.d.ts.map +1 -0
  219. package/dist/errors.d.ts +49 -0
  220. package/dist/errors.d.ts.map +1 -0
  221. package/dist/import/base-parser.d.ts +19 -0
  222. package/dist/import/base-parser.d.ts.map +1 -0
  223. package/dist/import/generator.d.ts +20 -0
  224. package/dist/import/generator.d.ts.map +1 -0
  225. package/dist/import/ir-utils.d.ts +25 -0
  226. package/dist/import/ir-utils.d.ts.map +1 -0
  227. package/dist/import/parser.d.ts +39 -0
  228. package/dist/import/parser.d.ts.map +1 -0
  229. package/dist/index.d.ts +66 -0
  230. package/dist/index.d.ts.map +1 -0
  231. package/dist/intrinsic-interpolation.d.ts +24 -0
  232. package/dist/intrinsic-interpolation.d.ts.map +1 -0
  233. package/dist/intrinsic.d.ts +24 -0
  234. package/dist/intrinsic.d.ts.map +1 -0
  235. package/dist/lexicon-integrity.d.ts +25 -0
  236. package/dist/lexicon-integrity.d.ts.map +1 -0
  237. package/dist/lexicon-manifest.d.ts +9 -0
  238. package/dist/lexicon-manifest.d.ts.map +1 -0
  239. package/dist/lexicon-output.d.ts +66 -0
  240. package/dist/lexicon-output.d.ts.map +1 -0
  241. package/dist/lexicon-plugin-helpers.d.ts +59 -0
  242. package/dist/lexicon-plugin-helpers.d.ts.map +1 -0
  243. package/dist/lexicon-schema.d.ts +82 -0
  244. package/dist/lexicon-schema.d.ts.map +1 -0
  245. package/dist/lexicon.d.ts +383 -0
  246. package/dist/lexicon.d.ts.map +1 -0
  247. package/dist/lifecycle/affected.d.ts +57 -0
  248. package/dist/lifecycle/affected.d.ts.map +1 -0
  249. package/dist/lifecycle/change-set.d.ts +90 -0
  250. package/dist/lifecycle/change-set.d.ts.map +1 -0
  251. package/dist/lifecycle/digest.d.ts +21 -0
  252. package/dist/lifecycle/digest.d.ts.map +1 -0
  253. package/dist/lifecycle/git.d.ts +72 -0
  254. package/dist/lifecycle/git.d.ts.map +1 -0
  255. package/dist/lifecycle/index.d.ts +8 -0
  256. package/dist/lifecycle/index.d.ts.map +1 -0
  257. package/dist/lifecycle/live-diff.d.ts +67 -0
  258. package/dist/lifecycle/live-diff.d.ts.map +1 -0
  259. package/dist/lifecycle/snapshot.d.ts +20 -0
  260. package/dist/lifecycle/snapshot.d.ts.map +1 -0
  261. package/dist/lifecycle/types.d.ts +61 -0
  262. package/dist/lifecycle/types.d.ts.map +1 -0
  263. package/dist/lint/config.d.ts +100 -0
  264. package/dist/lint/config.d.ts.map +1 -0
  265. package/dist/lint/declarative.d.ts +56 -0
  266. package/dist/lint/declarative.d.ts.map +1 -0
  267. package/dist/lint/discover.d.ts +35 -0
  268. package/dist/lint/discover.d.ts.map +1 -0
  269. package/dist/lint/engine.d.ts +21 -0
  270. package/dist/lint/engine.d.ts.map +1 -0
  271. package/dist/lint/named-checks.d.ts +19 -0
  272. package/dist/lint/named-checks.d.ts.map +1 -0
  273. package/dist/lint/parser.d.ts +9 -0
  274. package/dist/lint/parser.d.ts.map +1 -0
  275. package/dist/lint/policy.d.ts +22 -0
  276. package/dist/lint/policy.d.ts.map +1 -0
  277. package/dist/lint/post-synth.d.ts +69 -0
  278. package/dist/lint/post-synth.d.ts.map +1 -0
  279. package/dist/lint/presets/strict.json +19 -0
  280. package/dist/lint/rule-loader.d.ts +16 -0
  281. package/dist/lint/rule-loader.d.ts.map +1 -0
  282. package/dist/lint/rule-registry.d.ts +37 -0
  283. package/dist/lint/rule-registry.d.ts.map +1 -0
  284. package/dist/lint/rule.d.ts +82 -0
  285. package/dist/lint/rule.d.ts.map +1 -0
  286. package/dist/lint/rules/composite-scope.d.ts +18 -0
  287. package/dist/lint/rules/composite-scope.d.ts.map +1 -0
  288. package/dist/lint/rules/cor017-composite-name-match.d.ts +3 -0
  289. package/dist/lint/rules/cor017-composite-name-match.d.ts.map +1 -0
  290. package/dist/lint/rules/cor018-composite-prefer-lexicon-type.d.ts +3 -0
  291. package/dist/lint/rules/cor018-composite-prefer-lexicon-type.d.ts.map +1 -0
  292. package/dist/lint/rules/declarable-naming-convention.d.ts +3 -0
  293. package/dist/lint/rules/declarable-naming-convention.d.ts.map +1 -0
  294. package/dist/lint/rules/evl001-non-literal-expression.d.ts +3 -0
  295. package/dist/lint/rules/evl001-non-literal-expression.d.ts.map +1 -0
  296. package/dist/lint/rules/evl002-control-flow-resource.d.ts +3 -0
  297. package/dist/lint/rules/evl002-control-flow-resource.d.ts.map +1 -0
  298. package/dist/lint/rules/evl003-dynamic-property-access.d.ts +3 -0
  299. package/dist/lint/rules/evl003-dynamic-property-access.d.ts.map +1 -0
  300. package/dist/lint/rules/evl004-spread-non-const.d.ts +3 -0
  301. package/dist/lint/rules/evl004-spread-non-const.d.ts.map +1 -0
  302. package/dist/lint/rules/evl005-resource-block-body.d.ts +3 -0
  303. package/dist/lint/rules/evl005-resource-block-body.d.ts.map +1 -0
  304. package/dist/lint/rules/evl007-invalid-siblings.d.ts +3 -0
  305. package/dist/lint/rules/evl007-invalid-siblings.d.ts.map +1 -0
  306. package/dist/lint/rules/evl009-composite-no-constant.d.ts +3 -0
  307. package/dist/lint/rules/evl009-composite-no-constant.d.ts.map +1 -0
  308. package/dist/lint/rules/evl010-composite-no-transform.d.ts +3 -0
  309. package/dist/lint/rules/evl010-composite-no-transform.d.ts.map +1 -0
  310. package/dist/lint/rules/export-required.d.ts +3 -0
  311. package/dist/lint/rules/export-required.d.ts.map +1 -0
  312. package/dist/lint/rules/file-declarable-limit.d.ts +3 -0
  313. package/dist/lint/rules/file-declarable-limit.d.ts.map +1 -0
  314. package/dist/lint/rules/flat-declarations.d.ts +3 -0
  315. package/dist/lint/rules/flat-declarations.d.ts.map +1 -0
  316. package/dist/lint/rules/index.d.ts +31 -0
  317. package/dist/lint/rules/index.d.ts.map +1 -0
  318. package/dist/lint/rules/no-cyclic-declarable-ref.d.ts +3 -0
  319. package/dist/lint/rules/no-cyclic-declarable-ref.d.ts.map +1 -0
  320. package/dist/lint/rules/no-redundant-type-import.d.ts +10 -0
  321. package/dist/lint/rules/no-redundant-type-import.d.ts.map +1 -0
  322. package/dist/lint/rules/no-redundant-value-cast.d.ts +3 -0
  323. package/dist/lint/rules/no-redundant-value-cast.d.ts.map +1 -0
  324. package/dist/lint/rules/no-string-ref.d.ts +3 -0
  325. package/dist/lint/rules/no-string-ref.d.ts.map +1 -0
  326. package/dist/lint/rules/no-unused-declarable-import.d.ts +3 -0
  327. package/dist/lint/rules/no-unused-declarable-import.d.ts.map +1 -0
  328. package/dist/lint/rules/no-unused-declarable.d.ts +3 -0
  329. package/dist/lint/rules/no-unused-declarable.d.ts.map +1 -0
  330. package/dist/lint/rules/single-concern-file.d.ts +3 -0
  331. package/dist/lint/rules/single-concern-file.d.ts.map +1 -0
  332. package/dist/lint/selectors.d.ts +21 -0
  333. package/dist/lint/selectors.d.ts.map +1 -0
  334. package/dist/lsp/lexicon-providers.d.ts +61 -0
  335. package/dist/lsp/lexicon-providers.d.ts.map +1 -0
  336. package/dist/lsp/types.d.ts +64 -0
  337. package/dist/lsp/types.d.ts.map +1 -0
  338. package/dist/mcp/types.d.ts +21 -0
  339. package/dist/mcp/types.d.ts.map +1 -0
  340. package/dist/op/activity-registry.d.ts +57 -0
  341. package/dist/op/activity-registry.d.ts.map +1 -0
  342. package/dist/op/builders.d.ts +69 -0
  343. package/dist/op/builders.d.ts.map +1 -0
  344. package/dist/op/discover.d.ts +16 -0
  345. package/dist/op/discover.d.ts.map +1 -0
  346. package/dist/op/index.d.ts +11 -0
  347. package/dist/op/index.d.ts.map +1 -0
  348. package/dist/op/local-executor.d.ts +54 -0
  349. package/dist/op/local-executor.d.ts.map +1 -0
  350. package/dist/op/local-output.d.ts +16 -0
  351. package/dist/op/local-output.d.ts.map +1 -0
  352. package/dist/op/resource.d.ts +7 -0
  353. package/dist/op/resource.d.ts.map +1 -0
  354. package/dist/op/types.d.ts +71 -0
  355. package/dist/op/types.d.ts.map +1 -0
  356. package/dist/ownership.d.ts +75 -0
  357. package/dist/ownership.d.ts.map +1 -0
  358. package/dist/project-validation.d.ts +28 -0
  359. package/dist/project-validation.d.ts.map +1 -0
  360. package/dist/provenance.d.ts +26 -0
  361. package/dist/provenance.d.ts.map +1 -0
  362. package/dist/pseudo-parameter.d.ts +32 -0
  363. package/dist/pseudo-parameter.d.ts.map +1 -0
  364. package/dist/resource-attributes.d.ts +17 -0
  365. package/dist/resource-attributes.d.ts.map +1 -0
  366. package/dist/runtime-adapter.d.ts +41 -0
  367. package/dist/runtime-adapter.d.ts.map +1 -0
  368. package/dist/runtime.d.ts +23 -0
  369. package/dist/runtime.d.ts.map +1 -0
  370. package/dist/serializer-walker.d.ts +21 -0
  371. package/dist/serializer-walker.d.ts.map +1 -0
  372. package/dist/serializer.d.ts +64 -0
  373. package/dist/serializer.d.ts.map +1 -0
  374. package/dist/sort.d.ts +8 -0
  375. package/dist/sort.d.ts.map +1 -0
  376. package/dist/stack-output.d.ts +52 -0
  377. package/dist/stack-output.d.ts.map +1 -0
  378. package/dist/toml-emit.d.ts +22 -0
  379. package/dist/toml-emit.d.ts.map +1 -0
  380. package/dist/toml-parse.d.ts +14 -0
  381. package/dist/toml-parse.d.ts.map +1 -0
  382. package/dist/toml-utils.d.ts +20 -0
  383. package/dist/toml-utils.d.ts.map +1 -0
  384. package/dist/toml.d.ts +9 -0
  385. package/dist/toml.d.ts.map +1 -0
  386. package/dist/types.d.ts +47 -0
  387. package/dist/types.d.ts.map +1 -0
  388. package/dist/utils.d.ts +30 -0
  389. package/dist/utils.d.ts.map +1 -0
  390. package/dist/validation.d.ts +42 -0
  391. package/dist/validation.d.ts.map +1 -0
  392. package/dist/yaml.d.ts +42 -0
  393. package/dist/yaml.d.ts.map +1 -0
  394. package/package.json +31 -6
  395. package/src/audit/bundle-decoupling.test.ts +56 -0
  396. package/src/audit/catalog.test.ts +16 -1
  397. package/src/audit/catalog.ts +244 -4
  398. package/src/audit/core.test.ts +15 -0
  399. package/src/audit/core.ts +0 -0
  400. package/src/audit/detect-bundle.test.ts +35 -0
  401. package/src/audit/discover.test.ts +72 -0
  402. package/src/audit/discover.ts +329 -0
  403. package/src/audit/edge-init-safety.test.ts +43 -0
  404. package/src/audit/fetch.test.ts +136 -55
  405. package/src/audit/fetch.ts +175 -91
  406. package/src/audit/remote-discovery.test.ts +80 -0
  407. package/src/audit/report-html.ts +14 -6
  408. package/src/audit/report-model.ts +13 -1
  409. package/src/audit/report.test.ts +3 -1
  410. package/src/audit/report.ts +13 -5
  411. package/src/cli/commands/__fixtures__/audit-mixed/.github/workflows/ci.yml +5 -0
  412. package/src/cli/commands/__fixtures__/audit-mixed/Dockerfile +2 -0
  413. package/src/cli/commands/__fixtures__/audit-mixed/cfn/template.json +1 -0
  414. package/src/cli/commands/__fixtures__/audit-mixed/k8s/deploy.yaml +12 -0
  415. package/src/cli/commands/audit.test.ts +27 -19
  416. package/src/cli/commands/audit.ts +28 -272
  417. package/src/codegen/bound-property-types.test.ts +57 -0
  418. package/src/codegen/bound-property-types.ts +110 -0
  419. package/src/codegen/generate-post-synth-barrel.test.ts +37 -0
  420. package/src/codegen/generate-post-synth-barrel.ts +75 -0
  421. package/src/codegen/post-synth-barrel-guards.test.ts +63 -0
  422. package/src/codegen/validate.ts +13 -1
  423. package/src/lint/discover.ts +1 -1
  424. package/src/meta/peer-deps.test.ts +29 -0
@@ -1,7 +1,13 @@
1
1
  import { describe, test, expect } from "vitest";
2
2
  import { fileURLToPath } from "url";
3
- import { auditCommand, discoverCiFiles, discoverManifests, discoverDocker, discoverCloudFormation, discoverArm, discoverGcp, discoverHelm, tokenForHost, coverageNotes } from "./audit";
4
- import { MissingLexiconError, type AuditInput } from "../../audit/core";
3
+ import { auditCommand, tokenForHost, coverageNotes } from "./audit";
4
+ import { discoverByDetection, loadAuditPlugins } from "../../audit/discover";
5
+ import { MissingLexiconError, type AuditInput, type AuditLexicon } from "../../audit/core";
6
+
7
+ /** Discover with all audit lexicons loaded, then keep one lexicon's inputs. */
8
+ async function discoverLexicon(repo: string, lexicon: AuditLexicon): Promise<AuditInput[]> {
9
+ return discoverByDetection(repo, await loadAuditPlugins()).filter((i) => i.lexicon === lexicon);
10
+ }
5
11
  import { readFileSync, existsSync, rmSync } from "fs";
6
12
  import { tmpdir } from "os";
7
13
  import { join } from "path";
@@ -32,7 +38,7 @@ describe("auditCommand", () => {
32
38
 
33
39
  test("discovers and audits Kubernetes manifests", async () => {
34
40
  const repo = fileURLToPath(new URL("./__fixtures__/audit-k8s", import.meta.url));
35
- const files = discoverManifests(repo);
41
+ const files = await discoverLexicon(repo, "k8s");
36
42
  expect(files.map((f) => f.path)).toContain("manifests/deploy.yaml");
37
43
  expect(files.every((f) => f.lexicon === "k8s")).toBe(true);
38
44
 
@@ -45,7 +51,7 @@ describe("auditCommand", () => {
45
51
 
46
52
  test("discovers and audits Docker artifacts (nested Dockerfile + compose)", async () => {
47
53
  const repo = fileURLToPath(new URL("./__fixtures__/audit-docker", import.meta.url));
48
- const files = discoverDocker(repo);
54
+ const files = await discoverLexicon(repo, "docker");
49
55
  const paths = files.map((f) => f.path).sort();
50
56
  expect(paths).toContain("app/Dockerfile");
51
57
  expect(paths).toContain("docker-compose.yml");
@@ -60,7 +66,7 @@ describe("auditCommand", () => {
60
66
 
61
67
  test("discovers and audits CloudFormation (JSON and YAML)", async () => {
62
68
  const repo = fileURLToPath(new URL("./__fixtures__/audit-aws", import.meta.url));
63
- const files = discoverCloudFormation(repo);
69
+ const files = await discoverLexicon(repo, "aws");
64
70
  const paths = files.map((f) => f.path).sort();
65
71
  expect(paths).toContain("template.json");
66
72
  expect(paths).toContain("stack.yaml");
@@ -77,7 +83,7 @@ describe("auditCommand", () => {
77
83
 
78
84
  test("discovers and audits Azure ARM templates", async () => {
79
85
  const repo = fileURLToPath(new URL("./__fixtures__/audit-azure", import.meta.url));
80
- expect(discoverArm(repo).map((f) => f.path)).toContain("azuredeploy.json");
86
+ expect((await discoverLexicon(repo, "azure")).map((f) => f.path)).toContain("azuredeploy.json");
81
87
  const result = await auditCommand({ path: repo, format: "stylish" });
82
88
  expect(result.success).toBe(true);
83
89
  const ids = new Set(result.findings.map((f) => f.checkId));
@@ -86,10 +92,10 @@ describe("auditCommand", () => {
86
92
 
87
93
  test("discovers and audits GCP Config Connector (not misclassified as k8s)", async () => {
88
94
  const repo = fileURLToPath(new URL("./__fixtures__/audit-gcp", import.meta.url));
89
- const gcp = discoverGcp(repo);
95
+ const gcp = await discoverLexicon(repo, "gcp");
90
96
  expect(gcp.map((f) => f.path).sort()).toEqual(["bucket.yaml", "firewall.yaml"]);
91
97
  // cnrm manifests must NOT also be picked up as k8s.
92
- expect(discoverManifests(repo)).toEqual([]);
98
+ expect(await discoverLexicon(repo, "k8s")).toEqual([]);
93
99
 
94
100
  const result = await auditCommand({ path: repo, format: "stylish" });
95
101
  expect(result.success).toBe(true);
@@ -101,7 +107,7 @@ describe("auditCommand", () => {
101
107
 
102
108
  test("discovers and audits a Helm chart (as a bundle, not loose manifests)", async () => {
103
109
  const repo = fileURLToPath(new URL("./__fixtures__/audit-helm", import.meta.url));
104
- const charts = discoverHelm(repo);
110
+ const charts = await discoverLexicon(repo, "helm");
105
111
  expect(charts).toHaveLength(1);
106
112
  expect(charts[0].lexicon).toBe("helm");
107
113
  expect(charts[0].files!["Chart.yaml"]).toContain("name: mychart");
@@ -116,8 +122,8 @@ describe("auditCommand", () => {
116
122
  expect([...ids].some((id) => id.startsWith("WK8"))).toBe(false);
117
123
  });
118
124
 
119
- test("discovers CI files under a repo root", () => {
120
- const files = discoverCiFiles(REPO);
125
+ test("discovers CI files under a repo root", async () => {
126
+ const files = await discoverLexicon(REPO, "github");
121
127
  expect(files.map((f) => f.path)).toContain(".github/workflows/ci.yml");
122
128
  expect(files.every((f) => f.lexicon === "github")).toBe(true);
123
129
  });
@@ -168,7 +174,7 @@ describe("auditCommand", () => {
168
174
  expect(result.success).toBe(true);
169
175
  expect(result.wroteTo).toBe(out);
170
176
  expect(existsSync(out)).toBe(true);
171
- expect(readFileSync(out, "utf-8")).toContain("# CI security audit");
177
+ expect(readFileSync(out, "utf-8")).toContain("# chant audit");
172
178
  rmSync(out);
173
179
  });
174
180
 
@@ -191,7 +197,7 @@ describe("auditCommand", () => {
191
197
  const result = await auditCommand({ path: tmp });
192
198
  expect(result.success).toBe(true);
193
199
  expect(result.exitCode).toBe(0);
194
- expect(result.output).toContain("No CI files found");
200
+ expect(result.output).toContain("No auditable files found");
195
201
  rmSync(tmp, { recursive: true, force: true });
196
202
  });
197
203
 
@@ -200,12 +206,13 @@ describe("auditCommand", () => {
200
206
  const yaml = "name: CI\non:\n push:\npermissions: write-all\njobs:\n build:\n runs-on: ubuntu-latest\n";
201
207
  const impl = (async (url: string | URL | Request) => {
202
208
  const u = String(url);
209
+ if (u.includes("/git/trees/")) {
210
+ return new Response(JSON.stringify({ tree: [{ path: ".github/workflows/ci.yml", type: "blob", size: 100 }] }), { status: 200 });
211
+ }
203
212
  if (u.includes("/contents/.github/workflows/ci.yml")) {
204
213
  return new Response(JSON.stringify({ name: "ci.yml", path: ".github/workflows/ci.yml", type: "file", content: b64(yaml), encoding: "base64" }), { status: 200 });
205
214
  }
206
- if (u.includes("/contents/.github/workflows")) {
207
- return new Response(JSON.stringify([{ name: "ci.yml", path: ".github/workflows/ci.yml", type: "file", size: 100 }]), { status: 200 });
208
- }
215
+ if (/\/repos\/acme\/widgets(\?|$)/.test(u)) return new Response(JSON.stringify({ default_branch: "main" }), { status: 200 });
209
216
  return new Response("not found", { status: 404 });
210
217
  }) as unknown as typeof fetch;
211
218
 
@@ -222,12 +229,13 @@ describe("auditCommand", () => {
222
229
  const impl = (async (url: string | URL | Request) => {
223
230
  const u = String(url);
224
231
  if (u.includes("/commits/v4")) return new Response(JSON.stringify({ sha }), { status: 200 });
232
+ if (u.includes("/git/trees/")) {
233
+ return new Response(JSON.stringify({ tree: [{ path: ".github/workflows/ci.yml", type: "blob", size: 100 }] }), { status: 200 });
234
+ }
225
235
  if (u.includes("/contents/.github/workflows/ci.yml")) {
226
236
  return new Response(JSON.stringify({ name: "ci.yml", path: ".github/workflows/ci.yml", type: "file", content: b64(yaml), encoding: "base64" }), { status: 200 });
227
237
  }
228
- if (u.includes("/contents/.github/workflows")) {
229
- return new Response(JSON.stringify([{ name: "ci.yml", path: ".github/workflows/ci.yml", type: "file", size: 100 }]), { status: 200 });
230
- }
238
+ if (/\/repos\/acme\/widgets(\?|$)/.test(u)) return new Response(JSON.stringify({ default_branch: "main" }), { status: 200 });
231
239
  return new Response("not found", { status: 404 });
232
240
  }) as unknown as typeof fetch;
233
241
 
@@ -1,19 +1,18 @@
1
1
  /**
2
- * `chant audit` — run chant's CI security checks against an existing repo's
2
+ * `chant audit` — run chant's security, correctness, and best-practice checks against an existing repo's
3
3
  * pipeline YAML and emit a tiered report. Does not require a chant project;
4
4
  * it reads `.github/workflows`, `.gitlab-ci.yml`, and `.forgejo/workflows`
5
5
  * directly and runs the real post-synth checks via the audit core.
6
6
  */
7
7
 
8
- import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
9
- import { join, relative, basename } from "path";
10
- import { parseYAML } from "../../yaml";
11
- import { auditFiles, type AuditInput, type AuditFinding, type AuditLexicon, type ChecksProvider } from "../../audit/core";
8
+ import { existsSync, statSync, writeFileSync } from "fs";
9
+ import { auditFiles, type AuditInput, type AuditFinding, type ChecksProvider } from "../../audit/core";
10
+ import { discoverByDetection, classifyFiles, loadAuditPlugins, AUDIT_LEXICONS } from "../../audit/discover";
12
11
  import { RULE_CATALOG } from "../../audit/catalog";
13
12
  import { renderMarkdown } from "../../audit/report";
14
13
  import { renderHtml, type ReportTheme } from "../../audit/report-html";
15
14
  import { buildReportJson, type AuditSnapshot } from "../../audit/report-model";
16
- import { fetchCiFiles, resolveActionSha, resolveImageDigest, resolveRepoCommit, parseRepoUrl, FetchError } from "../../audit/fetch";
15
+ import { fetchRepoFiles, resolveActionSha, resolveImageDigest, resolveRepoCommit, parseRepoUrl, FetchError } from "../../audit/fetch";
17
16
  import { extractUnpinnedActions, extractUnpinnedImages } from "../../audit/proof";
18
17
  import type { ProveOptions } from "../../audit/proof";
19
18
  import type { Severity } from "../../lint/rule";
@@ -89,255 +88,6 @@ function githubToken(env: NodeJS.ProcessEnv = process.env): string | undefined {
89
88
  return env.GITHUB_TOKEN ?? env.CHANT_AUDIT_GITHUB_TOKEN;
90
89
  }
91
90
 
92
- function isYaml(name: string): boolean {
93
- return name.endsWith(".yml") || name.endsWith(".yaml");
94
- }
95
-
96
- function collectDir(root: string, dir: string, lexicon: AuditLexicon, out: AuditInput[]): void {
97
- const abs = join(root, dir);
98
- if (!existsSync(abs) || !statSync(abs).isDirectory()) return;
99
- for (const name of readdirSync(abs).sort()) {
100
- if (!isYaml(name)) continue;
101
- const full = join(abs, name);
102
- if (!statSync(full).isFile()) continue;
103
- out.push({ path: relative(root, full), content: readFileSync(full, "utf-8"), lexicon });
104
- }
105
- }
106
-
107
- /** Discover CI files under a repo root. */
108
- export function discoverCiFiles(root: string): AuditInput[] {
109
- const inputs: AuditInput[] = [];
110
- collectDir(root, ".github/workflows", "github", inputs);
111
- collectDir(root, ".forgejo/workflows", "forgejo", inputs);
112
- const gitlab = join(root, ".gitlab-ci.yml");
113
- if (existsSync(gitlab) && statSync(gitlab).isFile()) {
114
- inputs.push({ path: ".gitlab-ci.yml", content: readFileSync(gitlab, "utf-8"), lexicon: "gitlab" });
115
- }
116
- return inputs;
117
- }
118
-
119
- const WALK_SKIP = new Set(["node_modules", ".git", "dist", ".github", ".forgejo"]);
120
- const MAX_WALK_FILES = 1000;
121
-
122
- /** Recursively collect file paths under a root, skipping noise/dot dirs. */
123
- function walkFiles(dir: string, out: string[]): void {
124
- if (out.length >= MAX_WALK_FILES) return;
125
- let entries;
126
- try {
127
- entries = readdirSync(dir, { withFileTypes: true });
128
- } catch {
129
- return;
130
- }
131
- for (const e of entries.sort((a, b) => (a.name < b.name ? -1 : 1))) {
132
- if (out.length >= MAX_WALK_FILES) return;
133
- if (e.name.startsWith(".") && e.isDirectory()) continue;
134
- if (WALK_SKIP.has(e.name)) continue;
135
- const full = join(dir, e.name);
136
- if (e.isDirectory()) walkFiles(full, out);
137
- else out.push(full);
138
- }
139
- }
140
-
141
- function readSafe(full: string): string | undefined {
142
- try {
143
- return readFileSync(full, "utf-8");
144
- } catch {
145
- return undefined;
146
- }
147
- }
148
-
149
- const CNRM = "cnrm.cloud.google.com";
150
-
151
- /** True if any YAML doc is a Kubernetes manifest (excluding GCP Config Connector). */
152
- function looksLikeK8s(content: string): boolean {
153
- for (const doc of content.split(/\n---\n/)) {
154
- const t = doc.trim();
155
- if (!t) continue;
156
- try {
157
- const obj = parseYAML(t) as Record<string, unknown>;
158
- const apiVersion = obj?.apiVersion;
159
- if (typeof apiVersion === "string" && typeof obj.kind === "string" && !apiVersion.includes(CNRM)) return true;
160
- } catch {
161
- // not parseable as a single doc — skip
162
- }
163
- }
164
- return false;
165
- }
166
-
167
- /** True if any YAML doc is a GCP Config Connector resource (cnrm.cloud.google.com). */
168
- function looksLikeGcp(content: string): boolean {
169
- for (const doc of content.split(/\n---\n/)) {
170
- const t = doc.trim();
171
- if (!t) continue;
172
- try {
173
- const obj = parseYAML(t) as Record<string, unknown>;
174
- if (typeof obj?.apiVersion === "string" && obj.apiVersion.includes(CNRM)) return true;
175
- } catch {
176
- // skip
177
- }
178
- }
179
- return false;
180
- }
181
-
182
- /** Discover GCP Config Connector manifests under a repo root. */
183
- export function discoverGcp(root: string): AuditInput[] {
184
- const files: string[] = [];
185
- walkFiles(root, files);
186
- const inputs: AuditInput[] = [];
187
- for (const full of files) {
188
- if (!isYaml(basename(full))) continue;
189
- const content = readSafe(full);
190
- if (content !== undefined && looksLikeGcp(content)) {
191
- inputs.push({ path: relative(root, full), content, lexicon: "gcp" });
192
- }
193
- }
194
- return inputs;
195
- }
196
-
197
- /** Discover Kubernetes manifest files under a repo root (content-detected). */
198
- export function discoverManifests(root: string): AuditInput[] {
199
- const files: string[] = [];
200
- walkFiles(root, files);
201
- const inputs: AuditInput[] = [];
202
- for (const full of files) {
203
- if (!isYaml(basename(full))) continue;
204
- const content = readSafe(full);
205
- if (content !== undefined && looksLikeK8s(content)) {
206
- inputs.push({ path: relative(root, full), content, lexicon: "k8s" });
207
- }
208
- }
209
- return inputs;
210
- }
211
-
212
- function isDockerfileName(name: string): boolean {
213
- return name === "Dockerfile" || name.startsWith("Dockerfile.") || name.endsWith(".Dockerfile") || name.endsWith(".dockerfile");
214
- }
215
-
216
- function looksLikeCompose(content: string): boolean {
217
- try {
218
- const obj = parseYAML(content) as Record<string, unknown>;
219
- return Boolean(obj) && typeof obj === "object" && "services" in obj;
220
- } catch {
221
- return false;
222
- }
223
- }
224
-
225
- /** Parse JSON or YAML content into an object, or undefined. */
226
- function parseStructured(content: string): Record<string, unknown> | undefined {
227
- try {
228
- const j = JSON.parse(content);
229
- if (j && typeof j === "object") return j as Record<string, unknown>;
230
- } catch {
231
- // not JSON — try YAML
232
- }
233
- try {
234
- const y = parseYAML(content) as Record<string, unknown>;
235
- if (y && typeof y === "object") return y;
236
- } catch {
237
- // not YAML either
238
- }
239
- return undefined;
240
- }
241
-
242
- /** True if a parsed object is a CloudFormation template. */
243
- function looksLikeCloudFormation(obj: Record<string, unknown>): boolean {
244
- if (obj.AWSTemplateFormatVersion !== undefined) return true;
245
- const resources = obj.Resources;
246
- if (resources && typeof resources === "object") {
247
- for (const r of Object.values(resources as Record<string, unknown>)) {
248
- const type = r && typeof r === "object" ? (r as Record<string, unknown>).Type : undefined;
249
- if (typeof type === "string" && type.startsWith("AWS::")) return true;
250
- }
251
- }
252
- return false;
253
- }
254
-
255
- /**
256
- * Discover CloudFormation templates (JSON or YAML, `.json`/`.yaml`/`.yml`/`.template`).
257
- * The aws checks `JSON.parse` the template, so YAML templates are normalized to a
258
- * JSON string here (intrinsics like `!Ref` survive as strings — fine for the
259
- * structural security checks).
260
- */
261
- export function discoverCloudFormation(root: string): AuditInput[] {
262
- const files: string[] = [];
263
- walkFiles(root, files);
264
- const inputs: AuditInput[] = [];
265
- for (const full of files) {
266
- const name = basename(full);
267
- if (!/\.(json|ya?ml|template)$/i.test(name)) continue;
268
- const content = readSafe(full);
269
- if (content === undefined) continue;
270
- const parsed = parseStructured(content);
271
- if (parsed && looksLikeCloudFormation(parsed)) {
272
- inputs.push({ path: relative(root, full), content: JSON.stringify(parsed), lexicon: "aws" });
273
- }
274
- }
275
- return inputs;
276
- }
277
-
278
- /** True if a parsed object is an Azure ARM deployment template. */
279
- function looksLikeArm(obj: Record<string, unknown>): boolean {
280
- return typeof obj.$schema === "string" && obj.$schema.includes("deploymentTemplate") && Array.isArray(obj.resources);
281
- }
282
-
283
- /** Discover Azure ARM templates (`.json`) under a repo root. */
284
- export function discoverArm(root: string): AuditInput[] {
285
- const files: string[] = [];
286
- walkFiles(root, files);
287
- const inputs: AuditInput[] = [];
288
- for (const full of files) {
289
- if (!/\.json$/i.test(basename(full))) continue;
290
- const content = readSafe(full);
291
- if (content === undefined) continue;
292
- const parsed = parseStructured(content);
293
- if (parsed && looksLikeArm(parsed)) {
294
- inputs.push({ path: relative(root, full), content: JSON.stringify(parsed), lexicon: "azure" });
295
- }
296
- }
297
- return inputs;
298
- }
299
-
300
- /**
301
- * Discover Helm charts. A chart (directory with Chart.yaml) is one bundle: the
302
- * helm checks read `output.files` keyed by chart-relative path, so all of the
303
- * chart's files are collected into a single AuditInput.files map.
304
- */
305
- export function discoverHelm(root: string): AuditInput[] {
306
- const all: string[] = [];
307
- walkFiles(root, all);
308
- const chartDirs = all.filter((f) => basename(f) === "Chart.yaml").map((f) => f.slice(0, -("/Chart.yaml".length)));
309
- const inputs: AuditInput[] = [];
310
- for (const dir of chartDirs) {
311
- const prefix = dir + "/";
312
- const files: Record<string, string> = {};
313
- for (const f of all) {
314
- if (!f.startsWith(prefix)) continue;
315
- const content = readSafe(f);
316
- if (content !== undefined) files[f.slice(prefix.length)] = content;
317
- }
318
- if (files["Chart.yaml"] === undefined) continue;
319
- const chartPath = relative(root, dir) || ".";
320
- inputs.push({ path: chartPath, content: files["Chart.yaml"], lexicon: "helm", files });
321
- }
322
- return inputs;
323
- }
324
-
325
- /** Discover Docker artifacts: Dockerfiles (by name) and Compose files (by `services:`). */
326
- export function discoverDocker(root: string): AuditInput[] {
327
- const files: string[] = [];
328
- walkFiles(root, files);
329
- const inputs: AuditInput[] = [];
330
- for (const full of files) {
331
- const name = basename(full);
332
- const content = readSafe(full);
333
- if (content === undefined) continue;
334
- if (isDockerfileName(name) || (isYaml(name) && looksLikeCompose(content))) {
335
- inputs.push({ path: relative(root, full), content, lexicon: "docker" });
336
- }
337
- }
338
- return inputs;
339
- }
340
-
341
91
  function isMergeWorthy(f: AuditFinding): boolean {
342
92
  return RULE_CATALOG[f.checkId]?.tier === "merge-worthy";
343
93
  }
@@ -373,7 +123,7 @@ function renderStylish(findings: AuditFinding[], scanned: string[], notes: strin
373
123
  const mw = findings.filter(isMergeWorthy);
374
124
  const ro = findings.filter((f) => !isMergeWorthy(f));
375
125
  lines.push(
376
- `Audited ${scanned.length} CI file${scanned.length === 1 ? "" : "s"} — ` +
126
+ `Audited ${scanned.length} file${scanned.length === 1 ? "" : "s"} — ` +
377
127
  `${findings.length} finding${findings.length === 1 ? "" : "s"} ` +
378
128
  `(${mw.length} merge-worthy, ${ro.length} report-only).`,
379
129
  );
@@ -456,12 +206,19 @@ export async function auditCommand(options: AuditCommandOptions): Promise<AuditC
456
206
  const isUrl = /^https?:\/\//.test(options.path);
457
207
 
458
208
  let inputs: AuditInput[];
209
+ // Content-detected lexicons whose package isn't installed can't be detected
210
+ // (detection needs the plugin's `detectTemplate`), so a local audit would
211
+ // silently find nothing. Track the missing packages to turn that into a hint.
212
+ let missingHint = "";
459
213
  if (isUrl) {
460
214
  try {
461
- inputs = await fetchCiFiles(options.path, {
215
+ // Fetch the whole repo's candidate files (all lexicons, not just CI) and
216
+ // run them through the same classifier the local path uses (#420).
217
+ const files = await fetchRepoFiles(options.path, {
462
218
  token: options.token ?? tokenForHost(options.path),
463
219
  fetchImpl: options.fetchImpl,
464
220
  });
221
+ inputs = classifyFiles(files, await loadAuditPlugins());
465
222
  } catch (err) {
466
223
  const msg = err instanceof FetchError ? err.message : err instanceof Error ? err.message : String(err);
467
224
  return { success: false, output: "", findings: [], scanned: [], exitCode: 1, error: msg };
@@ -470,26 +227,25 @@ export async function auditCommand(options: AuditCommandOptions): Promise<AuditC
470
227
  if (!existsSync(options.path)) {
471
228
  return { success: false, output: "", findings: [], scanned: [], exitCode: 1, error: `Path not found: ${options.path}` };
472
229
  }
473
- // Helm claims whole chart directories; exclude chart-internal files from the
474
- // other discoverers so raw templates aren't double-audited as loose manifests.
475
- const helm = discoverHelm(options.path);
476
- const chartPrefixes = helm.map((h) => (h.path === "." ? "" : `${h.path}/`));
477
- const underChart = (p: string): boolean => chartPrefixes.some((pre) => (pre === "" ? true : p.startsWith(pre)));
478
- const others = [
479
- ...discoverCiFiles(options.path),
480
- ...discoverManifests(options.path),
481
- ...discoverDocker(options.path),
482
- ...discoverCloudFormation(options.path),
483
- ...discoverArm(options.path),
484
- ...discoverGcp(options.path),
485
- ].filter((i) => !underChart(i.path));
486
- inputs = [...others, ...helm];
230
+ // One walk, plugin-delegated detection. Each lexicon plugin's own
231
+ // `detectTemplate` classifies the files it recognizes; CI (path), Dockerfiles
232
+ // (name), and Helm charts (bundle) are handled by discoverByDetection's
233
+ // special-cases since content shape alone can't disambiguate them.
234
+ const plugins = await loadAuditPlugins();
235
+ const loaded = new Set(plugins.map((p) => p.name));
236
+ const missing = AUDIT_LEXICONS.filter((n) => !loaded.has(n));
237
+ if (missing.length > 0) {
238
+ missingHint =
239
+ ` Some lexicon packages are not installed, so files of those types were not detected: ${missing.join(", ")}.` +
240
+ ` Install what you need, e.g. npm i ${missing.map((n) => `@intentius/chant-lexicon-${n}`).join(" ")}`;
241
+ }
242
+ inputs = discoverByDetection(options.path, plugins);
487
243
  }
488
244
 
489
245
  const scanned = inputs.map((i) => i.path);
490
246
 
491
247
  if (inputs.length === 0) {
492
- return { success: true, output: `No CI files found under ${options.path}.`, findings: [], scanned: [], exitCode: 0 };
248
+ return { success: true, output: `No auditable files found under ${options.path}.${missingHint}`, findings: [], scanned: [], exitCode: 0 };
493
249
  }
494
250
 
495
251
  let findings: AuditFinding[];
@@ -0,0 +1,57 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { boundPropertyTypes, type BoundablePropertyType } from "./bound-property-types";
3
+
4
+ interface Prop {
5
+ name: string;
6
+ tsType: string;
7
+ }
8
+ interface PT extends BoundablePropertyType {
9
+ name: string;
10
+ specType: string;
11
+ properties: Prop[];
12
+ }
13
+
14
+ function pt(name: string, props: Array<[string, string]>): PT {
15
+ return { name, specType: name.split("_")[1] ?? name, properties: props.map(([n, t]) => ({ name: n, tsType: t })) };
16
+ }
17
+
18
+ describe("boundPropertyTypes", () => {
19
+ test("drops property types unreachable from resource props", () => {
20
+ const props: Prop[] = [{ name: "sku", tsType: "R_Sku" }];
21
+ const types = [pt("R_Sku", [["name", "string"]]), pt("R_Unused", [["x", "string"]])];
22
+ const kept = boundPropertyTypes("R", props, types, new Set(), { maxDepth: 2 });
23
+ expect(kept.map((t) => t.name)).toEqual(["R_Sku"]);
24
+ });
25
+
26
+ test("caps nesting depth and loosens references beyond the cap", () => {
27
+ const props: Prop[] = [{ name: "a", tsType: "R_A" }];
28
+ const types = [
29
+ pt("R_A", [["b", "R_B"]]),
30
+ pt("R_B", [["c", "R_C"]]),
31
+ pt("R_C", [["d", "string"]]),
32
+ ];
33
+ const kept = boundPropertyTypes("R", props, types, new Set(), { maxDepth: 1 });
34
+ // depth 1: R_A kept, its child R_B not expanded -> loosened, R_C dropped
35
+ expect(kept.map((t) => t.name)).toEqual(["R_A"]);
36
+ expect(kept[0].properties[0].tsType).toBe("Record<string, unknown>");
37
+ expect(props[0].tsType).toBe("R_A"); // resource prop ref to a kept type is preserved
38
+ });
39
+
40
+ test("force-keeps curated property types by substring regardless of reachability", () => {
41
+ const props: Prop[] = [];
42
+ const types = [pt("R_SecurityRulePropertiesFormat", [["x", "string"]]), pt("R_Other", [["y", "string"]])];
43
+ const kept = boundPropertyTypes("R", props, types, new Set(), {
44
+ maxDepth: 1,
45
+ curatedDefs: ["SecurityRule"],
46
+ });
47
+ expect(kept.map((t) => t.name)).toEqual(["R_SecurityRulePropertiesFormat"]);
48
+ });
49
+
50
+ test("preserves enum references when loosening", () => {
51
+ const props: Prop[] = [{ name: "a", tsType: "R_A" }];
52
+ const types = [pt("R_A", [["mode", "R_ModeEnum"], ["nested", "R_Deep"]]), pt("R_Deep", [["x", "string"]])];
53
+ const kept = boundPropertyTypes("R", props, types, new Set(["R_ModeEnum"]), { maxDepth: 1 });
54
+ expect(kept[0].properties[0].tsType).toBe("R_ModeEnum"); // enum kept
55
+ expect(kept[0].properties[1].tsType).toBe("Record<string, unknown>"); // deep type loosened
56
+ });
57
+ });
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Bound the set of generated property-type interfaces a lexicon emits.
3
+ *
4
+ * Cloud provider schemas (ARM, CloudFormation, …) embed a named definition for
5
+ * every nested object. Fully expanding all of them per-resource produces huge
6
+ * `.d.ts` declarations (azure was ~273MB — see #438). This helper keeps only
7
+ * the property types reachable from a resource's top-level properties within a
8
+ * depth bound, plus a curated force-keep set; references that fall outside the
9
+ * kept set are rewritten to `Record<string, unknown>`. Enum references are
10
+ * preserved. The input property refs are mutated in place. (#438, #440)
11
+ */
12
+
13
+ /** A reference carrying a TypeScript type string, mutated in place when loosened. */
14
+ export interface BoundablePropertyRef {
15
+ tsType: string;
16
+ }
17
+
18
+ /** A generated property type (named interface) and its properties. */
19
+ export interface BoundablePropertyType {
20
+ name: string;
21
+ specType: string;
22
+ properties: BoundablePropertyRef[];
23
+ }
24
+
25
+ export interface BoundPropertyTypeOptions {
26
+ /** Maximum nesting depth of emitted property-type interfaces. */
27
+ maxDepth: number;
28
+ /**
29
+ * Definition-name substrings to always keep regardless of reachability/depth
30
+ * (e.g. common nested shapes worth typing for authoring ergonomics). Matched
31
+ * by substring against each property type's `specType`.
32
+ */
33
+ curatedDefs?: Iterable<string>;
34
+ }
35
+
36
+ function escapeRegExp(s: string): string {
37
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
38
+ }
39
+
40
+ /** Extract `${shortName}_Ident` type-reference tokens from a tsType string. */
41
+ function referencedTypeNames(tsType: string, shortName: string): string[] {
42
+ const re = new RegExp("\\b" + escapeRegExp(shortName) + "_[A-Za-z0-9_]+", "g");
43
+ return tsType.match(re) ?? [];
44
+ }
45
+
46
+ /**
47
+ * Filter `propertyTypes` to the bounded set and loosen out-of-set references.
48
+ * Mutates the `tsType` of `resourceProps` and retained property types; returns
49
+ * the retained property types.
50
+ */
51
+ export function boundPropertyTypes<PT extends BoundablePropertyType>(
52
+ shortName: string,
53
+ resourceProps: BoundablePropertyRef[],
54
+ propertyTypes: PT[],
55
+ enumNames: Set<string>,
56
+ options: BoundPropertyTypeOptions,
57
+ ): PT[] {
58
+ const { maxDepth } = options;
59
+ const curated = options.curatedDefs ? [...options.curatedDefs] : [];
60
+ const byName = new Map(propertyTypes.map((pt) => [pt.name, pt] as const));
61
+ const reached = new Set<string>();
62
+ const queue: Array<{ name: string; depth: number }> = [];
63
+
64
+ const seed = (tsType: string, depth: number) => {
65
+ for (const n of referencedTypeNames(tsType, shortName)) {
66
+ if (byName.has(n) && !reached.has(n)) {
67
+ reached.add(n);
68
+ queue.push({ name: n, depth });
69
+ }
70
+ }
71
+ };
72
+
73
+ for (const p of resourceProps) seed(p.tsType, 1);
74
+ // Force-keep curated property types (depth-1 seeds), matched by substring so
75
+ // schema variant names (e.g. "SecurityRulePropertiesFormat") are retained.
76
+ if (curated.length > 0) {
77
+ for (const pt of propertyTypes) {
78
+ if (!reached.has(pt.name) && curated.some((c) => pt.specType.includes(c))) {
79
+ reached.add(pt.name);
80
+ queue.push({ name: pt.name, depth: 1 });
81
+ }
82
+ }
83
+ }
84
+ while (queue.length) {
85
+ const { name, depth } = queue.shift()!;
86
+ if (depth >= maxDepth) continue; // do not expand children beyond the cap
87
+ const pt = byName.get(name);
88
+ if (!pt) continue;
89
+ for (const p of pt.properties) seed(p.tsType, depth + 1);
90
+ }
91
+
92
+ // Rewrite references to property types we are not emitting (keep enums).
93
+ const loosen = (tsType: string): string => {
94
+ let out = tsType;
95
+ for (const n of referencedTypeNames(tsType, shortName)) {
96
+ if (reached.has(n) || enumNames.has(n) || !byName.has(n)) continue;
97
+ out = out.replace(new RegExp("\\b" + escapeRegExp(n) + "\\b", "g"), "Record<string, unknown>");
98
+ }
99
+ return out;
100
+ };
101
+
102
+ for (const p of resourceProps) p.tsType = loosen(p.tsType);
103
+ const retained: PT[] = [];
104
+ for (const pt of propertyTypes) {
105
+ if (!reached.has(pt.name)) continue;
106
+ for (const p of pt.properties) p.tsType = loosen(p.tsType);
107
+ retained.push(pt);
108
+ }
109
+ return retained;
110
+ }