@intentius/chant 0.13.1 → 0.15.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 (450) hide show
  1. package/dist/audit/catalog.d.ts +45 -5
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/proof.d.ts +3 -0
  4. package/dist/audit/proof.d.ts.map +1 -1
  5. package/dist/audit/report-model.d.ts +4 -1
  6. package/dist/audit/report-model.d.ts.map +1 -1
  7. package/dist/audit/report.d.ts +3 -0
  8. package/dist/audit/report.d.ts.map +1 -1
  9. package/dist/audit/rules-doc.d.ts +8 -2
  10. package/dist/audit/rules-doc.d.ts.map +1 -1
  11. package/dist/cli/commands/audit.d.ts.map +1 -1
  12. package/dist/cli/commands/doctor.d.ts.map +1 -1
  13. package/dist/cli/commands/lexicon-rolling-upgrade.d.ts +37 -0
  14. package/dist/cli/commands/lexicon-rolling-upgrade.d.ts.map +1 -0
  15. package/dist/cli/commands/lexicon-surface-diff.d.ts +48 -0
  16. package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -0
  17. package/dist/cli/commands/lint.d.ts.map +1 -1
  18. package/dist/cli/commands/pinned-upgrade.d.ts +41 -0
  19. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -0
  20. package/dist/cli/handlers/build.d.ts.map +1 -1
  21. package/dist/cli/handlers/components.d.ts +39 -0
  22. package/dist/cli/handlers/components.d.ts.map +1 -0
  23. package/dist/cli/handlers/dev.d.ts +3 -0
  24. package/dist/cli/handlers/dev.d.ts.map +1 -1
  25. package/dist/cli/handlers/graph.d.ts +4 -2
  26. package/dist/cli/handlers/graph.d.ts.map +1 -1
  27. package/dist/cli/handlers/misc.d.ts.map +1 -1
  28. package/dist/cli/handlers/run.d.ts +49 -0
  29. package/dist/cli/handlers/run.d.ts.map +1 -1
  30. package/dist/cli/main.d.ts.map +1 -1
  31. package/dist/cli/registry.d.ts +35 -0
  32. package/dist/cli/registry.d.ts.map +1 -1
  33. package/dist/codegen/fetch.d.ts +22 -0
  34. package/dist/codegen/fetch.d.ts.map +1 -1
  35. package/dist/codegen/lexicon-regen.d.ts +110 -0
  36. package/dist/codegen/lexicon-regen.d.ts.map +1 -0
  37. package/dist/codegen/pinned-upgrade.d.ts +153 -0
  38. package/dist/codegen/pinned-upgrade.d.ts.map +1 -0
  39. package/dist/codegen/rolling-upgrade.d.ts +138 -0
  40. package/dist/codegen/rolling-upgrade.d.ts.map +1 -0
  41. package/dist/codegen/surface-snapshot.d.ts +173 -0
  42. package/dist/codegen/surface-snapshot.d.ts.map +1 -0
  43. package/dist/codegen/version-bump.d.ts +21 -0
  44. package/dist/codegen/version-bump.d.ts.map +1 -0
  45. package/dist/components/auto-release.d.ts +93 -0
  46. package/dist/components/auto-release.d.ts.map +1 -0
  47. package/dist/components/builders.d.ts +37 -0
  48. package/dist/components/builders.d.ts.map +1 -0
  49. package/dist/components/capability-plugin-loader.d.ts +111 -0
  50. package/dist/components/capability-plugin-loader.d.ts.map +1 -0
  51. package/dist/components/capability-plugin-schema.d.ts +24 -0
  52. package/dist/components/capability-plugin-schema.d.ts.map +1 -0
  53. package/dist/components/capability-plugin.d.ts +85 -0
  54. package/dist/components/capability-plugin.d.ts.map +1 -0
  55. package/dist/components/capability.d.ts +89 -0
  56. package/dist/components/capability.d.ts.map +1 -0
  57. package/dist/components/cli-support.d.ts +204 -0
  58. package/dist/components/cli-support.d.ts.map +1 -0
  59. package/dist/components/component.d.ts +179 -0
  60. package/dist/components/component.d.ts.map +1 -0
  61. package/dist/components/config-defaults.d.ts +41 -0
  62. package/dist/components/config-defaults.d.ts.map +1 -0
  63. package/dist/components/discover.d.ts +60 -0
  64. package/dist/components/discover.d.ts.map +1 -0
  65. package/dist/components/driver-output.d.ts +20 -0
  66. package/dist/components/driver-output.d.ts.map +1 -0
  67. package/dist/components/driver.d.ts +209 -0
  68. package/dist/components/driver.d.ts.map +1 -0
  69. package/dist/components/index.d.ts +22 -0
  70. package/dist/components/index.d.ts.map +1 -0
  71. package/dist/components/manifest-persistence.d.ts +79 -0
  72. package/dist/components/manifest-persistence.d.ts.map +1 -0
  73. package/dist/components/pilots/alb-ecs.pilot.d.ts +27 -0
  74. package/dist/components/pilots/alb-ecs.pilot.d.ts.map +1 -0
  75. package/dist/components/pilots/dynamodb.pilot.d.ts +22 -0
  76. package/dist/components/pilots/dynamodb.pilot.d.ts.map +1 -0
  77. package/dist/components/pilots/jar-emr.pilot.d.ts +37 -0
  78. package/dist/components/pilots/jar-emr.pilot.d.ts.map +1 -0
  79. package/dist/components/pilots/lambda.pilot.d.ts +35 -0
  80. package/dist/components/pilots/lambda.pilot.d.ts.map +1 -0
  81. package/dist/components/pilots/neo4j-fanout.pilot.d.ts +17 -0
  82. package/dist/components/pilots/neo4j-fanout.pilot.d.ts.map +1 -0
  83. package/dist/components/pilots/project.d.ts +13 -0
  84. package/dist/components/pilots/project.d.ts.map +1 -0
  85. package/dist/components/presets/ecs-fargate.d.ts +59 -0
  86. package/dist/components/presets/ecs-fargate.d.ts.map +1 -0
  87. package/dist/components/presets/index.d.ts +29 -0
  88. package/dist/components/presets/index.d.ts.map +1 -0
  89. package/dist/components/presets/lambda.d.ts +35 -0
  90. package/dist/components/presets/lambda.d.ts.map +1 -0
  91. package/dist/components/presets/single-host-compose.d.ts +43 -0
  92. package/dist/components/presets/single-host-compose.d.ts.map +1 -0
  93. package/dist/components/registry.d.ts +29 -0
  94. package/dist/components/registry.d.ts.map +1 -0
  95. package/dist/components/starter-plugin.d.ts +51 -0
  96. package/dist/components/starter-plugin.d.ts.map +1 -0
  97. package/dist/components/temporal-codegen-loader.d.ts +27 -0
  98. package/dist/components/temporal-codegen-loader.d.ts.map +1 -0
  99. package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts +35 -0
  100. package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts.map +1 -0
  101. package/dist/components/verbs/__tests__/mock-process-runner.d.ts +45 -0
  102. package/dist/components/verbs/__tests__/mock-process-runner.d.ts.map +1 -0
  103. package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts +33 -0
  104. package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts.map +1 -0
  105. package/dist/components/verbs/bom-writer.d.ts +155 -0
  106. package/dist/components/verbs/bom-writer.d.ts.map +1 -0
  107. package/dist/components/verbs/build-archive.d.ts +205 -0
  108. package/dist/components/verbs/build-archive.d.ts.map +1 -0
  109. package/dist/components/verbs/build.d.ts +150 -0
  110. package/dist/components/verbs/build.d.ts.map +1 -0
  111. package/dist/components/verbs/cloud-executor.d.ts +88 -0
  112. package/dist/components/verbs/cloud-executor.d.ts.map +1 -0
  113. package/dist/components/verbs/component-bom.d.ts +103 -0
  114. package/dist/components/verbs/component-bom.d.ts.map +1 -0
  115. package/dist/components/verbs/index.d.ts +49 -0
  116. package/dist/components/verbs/index.d.ts.map +1 -0
  117. package/dist/components/verbs/license-policy.d.ts +56 -0
  118. package/dist/components/verbs/license-policy.d.ts.map +1 -0
  119. package/dist/components/verbs/lockfile-sbom-generator.d.ts +81 -0
  120. package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -0
  121. package/dist/components/verbs/process-runner.d.ts +64 -0
  122. package/dist/components/verbs/process-runner.d.ts.map +1 -0
  123. package/dist/components/verbs/reproducibility.d.ts +80 -0
  124. package/dist/components/verbs/reproducibility.d.ts.map +1 -0
  125. package/dist/components/verbs/sbom-generator.d.ts +157 -0
  126. package/dist/components/verbs/sbom-generator.d.ts.map +1 -0
  127. package/dist/components/verbs/sbom.d.ts +79 -0
  128. package/dist/components/verbs/sbom.d.ts.map +1 -0
  129. package/dist/components/verbs/shell.d.ts +35 -0
  130. package/dist/components/verbs/shell.d.ts.map +1 -0
  131. package/dist/components/verbs/sign.d.ts +222 -0
  132. package/dist/components/verbs/sign.d.ts.map +1 -0
  133. package/dist/components/verbs/stub.d.ts +18 -0
  134. package/dist/components/verbs/stub.d.ts.map +1 -0
  135. package/dist/components/verbs/tool-sbom-generator.d.ts +51 -0
  136. package/dist/components/verbs/tool-sbom-generator.d.ts.map +1 -0
  137. package/dist/components/verbs/verify.d.ts +106 -0
  138. package/dist/components/verbs/verify.d.ts.map +1 -0
  139. package/dist/components/verbs/vex.d.ts +65 -0
  140. package/dist/components/verbs/vex.d.ts.map +1 -0
  141. package/dist/components/verbs/vuln-gate.d.ts +91 -0
  142. package/dist/components/verbs/vuln-gate.d.ts.map +1 -0
  143. package/dist/components/verbs/vuln-scan.d.ts +116 -0
  144. package/dist/components/verbs/vuln-scan.d.ts.map +1 -0
  145. package/dist/components/verbs/wait-verify.d.ts +85 -0
  146. package/dist/components/verbs/wait-verify.d.ts.map +1 -0
  147. package/dist/config.d.ts +205 -0
  148. package/dist/config.d.ts.map +1 -1
  149. package/dist/index.d.ts +4 -0
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/lexicon.d.ts +78 -0
  152. package/dist/lexicon.d.ts.map +1 -1
  153. package/dist/lifecycle/build-ledger-store.d.ts +121 -0
  154. package/dist/lifecycle/build-ledger-store.d.ts.map +1 -0
  155. package/dist/lifecycle/build-ledger.d.ts +225 -0
  156. package/dist/lifecycle/build-ledger.d.ts.map +1 -0
  157. package/dist/lifecycle/git.d.ts +84 -0
  158. package/dist/lifecycle/git.d.ts.map +1 -1
  159. package/dist/lifecycle/index.d.ts +5 -0
  160. package/dist/lifecycle/index.d.ts.map +1 -1
  161. package/dist/lifecycle/oras-referrer-lookup.d.ts +41 -0
  162. package/dist/lifecycle/oras-referrer-lookup.d.ts.map +1 -0
  163. package/dist/lifecycle/release-ledger.d.ts +122 -0
  164. package/dist/lifecycle/release-ledger.d.ts.map +1 -0
  165. package/dist/lifecycle/status.d.ts +150 -0
  166. package/dist/lifecycle/status.d.ts.map +1 -0
  167. package/dist/lint/component-checks.d.ts +95 -0
  168. package/dist/lint/component-checks.d.ts.map +1 -0
  169. package/dist/lint/engine.d.ts +23 -0
  170. package/dist/lint/engine.d.ts.map +1 -1
  171. package/dist/lint/presets/strict.json +8 -1
  172. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts +4 -0
  173. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts.map +1 -0
  174. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts +4 -0
  175. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts.map +1 -0
  176. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts +4 -0
  177. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts.map +1 -0
  178. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts +4 -0
  179. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts.map +1 -0
  180. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts +4 -0
  181. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts.map +1 -0
  182. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts +10 -0
  183. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts.map +1 -0
  184. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts +3 -0
  185. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts.map +1 -0
  186. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts +4 -0
  187. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts.map +1 -0
  188. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts +4 -0
  189. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts.map +1 -0
  190. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts +4 -0
  191. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts.map +1 -0
  192. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts +4 -0
  193. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts.map +1 -0
  194. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts +4 -0
  195. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts.map +1 -0
  196. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +4 -0
  197. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -0
  198. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +4 -0
  199. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -0
  200. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts +4 -0
  201. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts.map +1 -0
  202. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts +4 -0
  203. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts.map +1 -0
  204. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts +4 -0
  205. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts.map +1 -0
  206. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts +4 -0
  207. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts.map +1 -0
  208. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts +4 -0
  209. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts.map +1 -0
  210. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts +4 -0
  211. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts.map +1 -0
  212. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts +3 -0
  213. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts.map +1 -0
  214. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts +4 -0
  215. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts.map +1 -0
  216. package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts +20 -0
  217. package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts.map +1 -0
  218. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts +28 -0
  219. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts.map +1 -0
  220. package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts +39 -0
  221. package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts.map +1 -0
  222. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +37 -0
  223. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +1 -0
  224. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts +43 -0
  225. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts.map +1 -0
  226. package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts +22 -0
  227. package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts.map +1 -0
  228. package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts +33 -0
  229. package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts.map +1 -0
  230. package/dist/lint/rules/comp/index.d.ts +18 -0
  231. package/dist/lint/rules/comp/index.d.ts.map +1 -0
  232. package/dist/lint/rules/comp/support.d.ts +71 -0
  233. package/dist/lint/rules/comp/support.d.ts.map +1 -0
  234. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  235. package/dist/op/activity-registry.d.ts +11 -6
  236. package/dist/op/activity-registry.d.ts.map +1 -1
  237. package/dist/op/activity-runtime.d.ts +24 -0
  238. package/dist/op/activity-runtime.d.ts.map +1 -0
  239. package/dist/op/builders.d.ts +59 -0
  240. package/dist/op/builders.d.ts.map +1 -1
  241. package/dist/op/index.d.ts +2 -1
  242. package/dist/op/index.d.ts.map +1 -1
  243. package/dist/ownership.d.ts +20 -14
  244. package/dist/ownership.d.ts.map +1 -1
  245. package/package.json +14 -1
  246. package/src/audit/catalog.test.ts +74 -22
  247. package/src/audit/catalog.ts +74 -471
  248. package/src/audit/proof.ts +4 -2
  249. package/src/audit/report-html.test.ts +14 -7
  250. package/src/audit/report-model.ts +20 -9
  251. package/src/audit/report.test.ts +36 -13
  252. package/src/audit/report.ts +2 -0
  253. package/src/audit/rules-doc.test.ts +8 -6
  254. package/src/audit/rules-doc.ts +13 -5
  255. package/src/cli/commands/audit.ts +23 -18
  256. package/src/cli/commands/component-lint.test.ts +158 -0
  257. package/src/cli/commands/doctor.test.ts +116 -2
  258. package/src/cli/commands/doctor.ts +46 -0
  259. package/src/cli/commands/lexicon-rolling-upgrade.ts +198 -0
  260. package/src/cli/commands/lexicon-surface-diff.test.ts +104 -0
  261. package/src/cli/commands/lexicon-surface-diff.ts +185 -0
  262. package/src/cli/commands/lint.ts +142 -1
  263. package/src/cli/commands/pinned-upgrade.ts +204 -0
  264. package/src/cli/handlers/build.ts +58 -1
  265. package/src/cli/handlers/components.test.ts +504 -0
  266. package/src/cli/handlers/components.ts +404 -0
  267. package/src/cli/handlers/dev.ts +60 -1
  268. package/src/cli/handlers/graph.ts +47 -2
  269. package/src/cli/handlers/misc.ts +45 -1
  270. package/src/cli/handlers/run.test.ts +967 -3
  271. package/src/cli/handlers/run.ts +618 -11
  272. package/src/cli/main.test.ts +66 -0
  273. package/src/cli/main.ts +105 -2
  274. package/src/cli/registry.ts +35 -0
  275. package/src/codegen/fetch.test.ts +84 -3
  276. package/src/codegen/fetch.ts +76 -2
  277. package/src/codegen/lexicon-regen.test.ts +298 -0
  278. package/src/codegen/lexicon-regen.ts +545 -0
  279. package/src/codegen/pinned-upgrade.test.ts +399 -0
  280. package/src/codegen/pinned-upgrade.ts +423 -0
  281. package/src/codegen/rolling-upgrade.test.ts +333 -0
  282. package/src/codegen/rolling-upgrade.ts +320 -0
  283. package/src/codegen/surface-snapshot.test.ts +461 -0
  284. package/src/codegen/surface-snapshot.ts +546 -0
  285. package/src/codegen/version-bump.test.ts +47 -0
  286. package/src/codegen/version-bump.ts +39 -0
  287. package/src/components/README.md +130 -0
  288. package/src/components/SPRAWL-VALIDATION.md +181 -0
  289. package/src/components/__fixtures__/alb-ecs-service.json +51 -0
  290. package/src/components/__fixtures__/dynamodb-infra.json +32 -0
  291. package/src/components/__fixtures__/emr-job-consumer.json +26 -0
  292. package/src/components/__fixtures__/jar-lib-producer.json +16 -0
  293. package/src/components/__fixtures__/lambda-image-processor.json +28 -0
  294. package/src/components/__fixtures__/neo4j-fanout.json +34 -0
  295. package/src/components/__fixtures__/single-host-compose.json +29 -0
  296. package/src/components/auto-release.test.ts +217 -0
  297. package/src/components/auto-release.ts +216 -0
  298. package/src/components/builders.test.ts +45 -0
  299. package/src/components/builders.ts +71 -0
  300. package/src/components/capability-plugin-loader.ts +218 -0
  301. package/src/components/capability-plugin-schema.ts +56 -0
  302. package/src/components/capability-plugin.test.ts +235 -0
  303. package/src/components/capability-plugin.ts +108 -0
  304. package/src/components/capability.ts +117 -0
  305. package/src/components/cli-support.test.ts +579 -0
  306. package/src/components/cli-support.ts +481 -0
  307. package/src/components/component-schema.test.ts +265 -0
  308. package/src/components/component.schema.json +235 -0
  309. package/src/components/component.test.ts +251 -0
  310. package/src/components/component.ts +255 -0
  311. package/src/components/config-defaults.test.ts +263 -0
  312. package/src/components/config-defaults.ts +145 -0
  313. package/src/components/discover.test.ts +352 -0
  314. package/src/components/discover.ts +167 -0
  315. package/src/components/driver-output.ts +71 -0
  316. package/src/components/driver.test.ts +638 -0
  317. package/src/components/driver.ts +690 -0
  318. package/src/components/index.ts +113 -0
  319. package/src/components/manifest-persistence.test.ts +152 -0
  320. package/src/components/manifest-persistence.ts +164 -0
  321. package/src/components/pilots/README.md +33 -0
  322. package/src/components/pilots/alb-ecs.pilot.ts +63 -0
  323. package/src/components/pilots/dynamodb.pilot.ts +59 -0
  324. package/src/components/pilots/jar-emr.pilot.ts +69 -0
  325. package/src/components/pilots/lambda.pilot.ts +55 -0
  326. package/src/components/pilots/neo4j-fanout.pilot.ts +92 -0
  327. package/src/components/pilots/pilots-lint-clean.test.ts +78 -0
  328. package/src/components/pilots/pilots.test.ts +126 -0
  329. package/src/components/pilots/project.ts +13 -0
  330. package/src/components/presets/comp007-reduction.test.ts +122 -0
  331. package/src/components/presets/ecs-fargate.test.ts +84 -0
  332. package/src/components/presets/ecs-fargate.ts +103 -0
  333. package/src/components/presets/index.ts +32 -0
  334. package/src/components/presets/lambda.test.ts +35 -0
  335. package/src/components/presets/lambda.ts +53 -0
  336. package/src/components/presets/single-host-compose.test.ts +65 -0
  337. package/src/components/presets/single-host-compose.ts +64 -0
  338. package/src/components/registry.test.ts +112 -0
  339. package/src/components/registry.ts +37 -0
  340. package/src/components/starter-plugin.ts +105 -0
  341. package/src/components/temporal-codegen-loader.ts +41 -0
  342. package/src/components/verbs/__fixtures__/package-lock.json +45 -0
  343. package/src/components/verbs/__fixtures__/pom.xml +37 -0
  344. package/src/components/verbs/__fixtures__/schemas/cyclonedx-1.5.schema.json +3800 -0
  345. package/src/components/verbs/__fixtures__/schemas/cyclonedx-spdx-license.schema.json +621 -0
  346. package/src/components/verbs/__fixtures__/schemas/jsf-0.82.schema.json +240 -0
  347. package/src/components/verbs/__fixtures__/schemas/spdx-2.3.schema.json +740 -0
  348. package/src/components/verbs/__tests__/mock-cloud-executor.ts +102 -0
  349. package/src/components/verbs/__tests__/mock-process-runner.ts +79 -0
  350. package/src/components/verbs/__tests__/mock-sbom-generator.ts +85 -0
  351. package/src/components/verbs/bom-writer.test.ts +331 -0
  352. package/src/components/verbs/bom-writer.ts +386 -0
  353. package/src/components/verbs/build-archive.test.ts +251 -0
  354. package/src/components/verbs/build-archive.ts +296 -0
  355. package/src/components/verbs/build.test.ts +222 -0
  356. package/src/components/verbs/build.ts +252 -0
  357. package/src/components/verbs/cloud-executor.ts +181 -0
  358. package/src/components/verbs/component-bom.test.ts +219 -0
  359. package/src/components/verbs/component-bom.ts +189 -0
  360. package/src/components/verbs/index.ts +49 -0
  361. package/src/components/verbs/license-policy.ts +115 -0
  362. package/src/components/verbs/lockfile-sbom-generator.test.ts +195 -0
  363. package/src/components/verbs/lockfile-sbom-generator.ts +236 -0
  364. package/src/components/verbs/process-runner.test.ts +79 -0
  365. package/src/components/verbs/process-runner.ts +113 -0
  366. package/src/components/verbs/reproducibility.test.ts +24 -0
  367. package/src/components/verbs/reproducibility.ts +100 -0
  368. package/src/components/verbs/sbom-generator.test.ts +96 -0
  369. package/src/components/verbs/sbom-generator.ts +209 -0
  370. package/src/components/verbs/sbom.test.ts +184 -0
  371. package/src/components/verbs/sbom.ts +152 -0
  372. package/src/components/verbs/shell.test.ts +36 -0
  373. package/src/components/verbs/shell.ts +51 -0
  374. package/src/components/verbs/sign.test.ts +210 -0
  375. package/src/components/verbs/sign.ts +350 -0
  376. package/src/components/verbs/stub.ts +34 -0
  377. package/src/components/verbs/tool-sbom-generator.test.ts +194 -0
  378. package/src/components/verbs/tool-sbom-generator.ts +192 -0
  379. package/src/components/verbs/verify.test.ts +159 -0
  380. package/src/components/verbs/verify.ts +179 -0
  381. package/src/components/verbs/vex.ts +182 -0
  382. package/src/components/verbs/vuln-gate.test.ts +201 -0
  383. package/src/components/verbs/vuln-gate.ts +170 -0
  384. package/src/components/verbs/vuln-scan.test.ts +145 -0
  385. package/src/components/verbs/vuln-scan.ts +266 -0
  386. package/src/components/verbs/wait-verify.test.ts +111 -0
  387. package/src/components/verbs/wait-verify.ts +171 -0
  388. package/src/config.test.ts +74 -1
  389. package/src/config.ts +219 -0
  390. package/src/index.ts +32 -0
  391. package/src/lexicon.ts +88 -0
  392. package/src/lifecycle/build-ledger-store.test.ts +217 -0
  393. package/src/lifecycle/build-ledger-store.ts +165 -0
  394. package/src/lifecycle/build-ledger.test.ts +349 -0
  395. package/src/lifecycle/build-ledger.ts +305 -0
  396. package/src/lifecycle/git.test.ts +118 -0
  397. package/src/lifecycle/git.ts +149 -14
  398. package/src/lifecycle/index.ts +5 -0
  399. package/src/lifecycle/oras-referrer-lookup.test.ts +116 -0
  400. package/src/lifecycle/oras-referrer-lookup.ts +110 -0
  401. package/src/lifecycle/release-ledger.test.ts +209 -0
  402. package/src/lifecycle/release-ledger.ts +185 -0
  403. package/src/lifecycle/status.test.ts +330 -0
  404. package/src/lifecycle/status.ts +278 -0
  405. package/src/lint/component-checks.ts +148 -0
  406. package/src/lint/config.test.ts +21 -0
  407. package/src/lint/engine.ts +11 -2
  408. package/src/lint/presets/relaxed.json +8 -1
  409. package/src/lint/presets/strict.json +8 -1
  410. package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.ts +9 -0
  411. package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.ts +9 -0
  412. package/src/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.ts +11 -0
  413. package/src/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.ts +13 -0
  414. package/src/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.ts +11 -0
  415. package/src/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.ts +27 -0
  416. package/src/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.ts +10 -0
  417. package/src/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.ts +23 -0
  418. package/src/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.ts +10 -0
  419. package/src/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.ts +19 -0
  420. package/src/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.ts +10 -0
  421. package/src/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.ts +20 -0
  422. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +23 -0
  423. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +10 -0
  424. package/src/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.ts +14 -0
  425. package/src/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.ts +18 -0
  426. package/src/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.ts +10 -0
  427. package/src/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.ts +14 -0
  428. package/src/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.ts +13 -0
  429. package/src/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.ts +13 -0
  430. package/src/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.ts +12 -0
  431. package/src/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.ts +18 -0
  432. package/src/lint/rules/comp/comp.test.ts +378 -0
  433. package/src/lint/rules/comp/comp001-publishes-never-applies.ts +78 -0
  434. package/src/lint/rules/comp/comp002-dangling-wiring-ref.ts +94 -0
  435. package/src/lint/rules/comp/comp003-mutating-no-rollback.ts +115 -0
  436. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +66 -0
  437. package/src/lint/rules/comp/comp005-capability-kind-is-noun.ts +113 -0
  438. package/src/lint/rules/comp/comp006-shell-needs-reason.ts +55 -0
  439. package/src/lint/rules/comp/comp007-composition-sprawl.ts +71 -0
  440. package/src/lint/rules/comp/index.ts +37 -0
  441. package/src/lint/rules/comp/support.ts +173 -0
  442. package/src/lsp/lexicon-providers.test.ts +55 -0
  443. package/src/lsp/lexicon-providers.ts +13 -3
  444. package/src/op/activity-registry.test.ts +38 -0
  445. package/src/op/activity-registry.ts +31 -12
  446. package/src/op/activity-runtime.ts +73 -0
  447. package/src/op/builders.ts +99 -0
  448. package/src/op/index.ts +3 -1
  449. package/src/ownership.test.ts +24 -26
  450. package/src/ownership.ts +26 -38
@@ -0,0 +1,263 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { applyConfigDefaults } from "./config-defaults";
3
+ import type { DriverComponent } from "./driver";
4
+ import type { ChantConfig } from "../config";
5
+
6
+ function component(deploy: DriverComponent["deploy"]): DriverComponent {
7
+ return { name: "svc", dependsOn: [], deploy };
8
+ }
9
+
10
+ describe("applyConfigDefaults", () => {
11
+ test("generate-sbom: picks up sbom.format from config when the step omits it", () => {
12
+ const config: ChantConfig = { sbom: { format: "cyclonedx" } };
13
+ const comp = component([
14
+ { phase: "Build", steps: [{ kind: "generate-sbom", artifactType: "image", path: "img" }] },
15
+ ]);
16
+
17
+ const result = applyConfigDefaults(comp, config);
18
+ const step = result.deploy[0]!.steps[0] as { format?: string };
19
+ expect(step.format).toBe("cyclonedx");
20
+ });
21
+
22
+ test("generate-sbom: a step's own format overrides config", () => {
23
+ const config: ChantConfig = { sbom: { format: "cyclonedx" } };
24
+ const comp = component([
25
+ { phase: "Build", steps: [{ kind: "generate-sbom", artifactType: "image", path: "img", format: "spdx" }] },
26
+ ]);
27
+
28
+ const result = applyConfigDefaults(comp, config);
29
+ const step = result.deploy[0]!.steps[0] as { format?: string };
30
+ expect(step.format).toBe("spdx");
31
+ });
32
+
33
+ test("generate-sbom: falls back to DEFAULT_SBOM_FORMAT when neither step nor config sets it", () => {
34
+ const config: ChantConfig = {};
35
+ const comp = component([
36
+ { phase: "Build", steps: [{ kind: "generate-sbom", artifactType: "image", path: "img" }] },
37
+ ]);
38
+
39
+ const result = applyConfigDefaults(comp, config);
40
+ const step = result.deploy[0]!.steps[0] as { format?: string };
41
+ expect(step.format).toBe("spdx");
42
+ });
43
+
44
+ test("sign: fills keyless oidcIssuer from config's signing.oidcIssuer", () => {
45
+ const config: ChantConfig = { signing: { oidcIssuer: "https://token.actions.githubusercontent.com" } };
46
+ const comp = component([
47
+ { phase: "Publish", steps: [{ kind: "sign", imageRef: "repo@sha256:abc" }] },
48
+ ]);
49
+
50
+ const result = applyConfigDefaults(comp, config);
51
+ const step = result.deploy[0]!.steps[0] as { keyless?: { oidcIssuer?: string } };
52
+ expect(step.keyless?.oidcIssuer).toBe("https://token.actions.githubusercontent.com");
53
+ });
54
+
55
+ test("sign: a step's own keyless config is left untouched", () => {
56
+ const config: ChantConfig = { signing: { oidcIssuer: "https://token.actions.githubusercontent.com" } };
57
+ const comp = component([
58
+ {
59
+ phase: "Publish",
60
+ steps: [{ kind: "sign", imageRef: "repo@sha256:abc", keyless: { oidcIssuer: "https://custom.example.com" } }],
61
+ },
62
+ ]);
63
+
64
+ const result = applyConfigDefaults(comp, config);
65
+ const step = result.deploy[0]!.steps[0] as { keyless?: { oidcIssuer?: string } };
66
+ expect(step.keyless?.oidcIssuer).toBe("https://custom.example.com");
67
+ });
68
+
69
+ test("sign: a step's own key opts out of config keyless defaults entirely", () => {
70
+ const config: ChantConfig = { signing: { oidcIssuer: "https://token.actions.githubusercontent.com" } };
71
+ const comp = component([
72
+ { phase: "Publish", steps: [{ kind: "sign", imageRef: "repo@sha256:abc", key: { key: "kms://my-key" } }] },
73
+ ]);
74
+
75
+ const result = applyConfigDefaults(comp, config);
76
+ const step = result.deploy[0]!.steps[0] as { key?: { key: string }; keyless?: unknown };
77
+ expect(step.key).toEqual({ key: "kms://my-key" });
78
+ expect(step.keyless).toBeUndefined();
79
+ });
80
+
81
+ test("sign: config's key-based override (keyless: false + key) fills the step's key", () => {
82
+ const config: ChantConfig = { signing: { keyless: false, key: "kms://project-key" } };
83
+ const comp = component([
84
+ { phase: "Publish", steps: [{ kind: "sign", imageRef: "repo@sha256:abc" }] },
85
+ ]);
86
+
87
+ const result = applyConfigDefaults(comp, config);
88
+ const step = result.deploy[0]!.steps[0] as { key?: { key: string } };
89
+ expect(step.key).toEqual({ key: "kms://project-key" });
90
+ });
91
+
92
+ test("attest-provenance: also picks up the configured oidcIssuer", () => {
93
+ const config: ChantConfig = { signing: { oidcIssuer: "https://token.actions.githubusercontent.com" } };
94
+ const comp = component([
95
+ {
96
+ phase: "Publish",
97
+ steps: [{
98
+ kind: "attest-provenance",
99
+ imageRef: "repo@sha256:abc",
100
+ provenance: { sourceRef: "git@abc", artifactDigest: "sha256:abc" },
101
+ builderId: "https://github.com/actions/runner",
102
+ }],
103
+ },
104
+ ]);
105
+
106
+ const result = applyConfigDefaults(comp, config);
107
+ const step = result.deploy[0]!.steps[0] as { keyless?: { oidcIssuer?: string } };
108
+ expect(step.keyless?.oidcIssuer).toBe("https://token.actions.githubusercontent.com");
109
+ });
110
+
111
+ test("verify: fills expectedIssuer/expectedIdentity from config's signing section without repeating them per-step", () => {
112
+ const config: ChantConfig = {
113
+ signing: {
114
+ oidcIssuer: "https://token.actions.githubusercontent.com",
115
+ identity: "https://github.com/acme/repo/.github/workflows/release.yml@refs/heads/main",
116
+ },
117
+ };
118
+ const comp = component([
119
+ { phase: "Verify", steps: [{ kind: "verify", imageRef: "repo@sha256:abc", policy: {} }] },
120
+ ]);
121
+
122
+ const result = applyConfigDefaults(comp, config);
123
+ const step = result.deploy[0]!.steps[0] as {
124
+ policy?: { expectedIssuer?: string; expectedIdentity?: string };
125
+ };
126
+ expect(step.policy?.expectedIssuer).toBe("https://token.actions.githubusercontent.com");
127
+ expect(step.policy?.expectedIdentity).toBe(
128
+ "https://github.com/acme/repo/.github/workflows/release.yml@refs/heads/main",
129
+ );
130
+ });
131
+
132
+ test("verify: a per-step policy value overrides config", () => {
133
+ const config: ChantConfig = {
134
+ signing: {
135
+ oidcIssuer: "https://token.actions.githubusercontent.com",
136
+ identity: "https://github.com/acme/repo/.github/workflows/release.yml@refs/heads/main",
137
+ },
138
+ };
139
+ const comp = component([
140
+ {
141
+ phase: "Verify",
142
+ steps: [{
143
+ kind: "verify",
144
+ imageRef: "repo@sha256:abc",
145
+ policy: { expectedIssuer: "https://custom-issuer.example.com" },
146
+ }],
147
+ },
148
+ ]);
149
+
150
+ const result = applyConfigDefaults(comp, config);
151
+ const step = result.deploy[0]!.steps[0] as { policy?: { expectedIssuer?: string; expectedIdentity?: string } };
152
+ expect(step.policy?.expectedIssuer).toBe("https://custom-issuer.example.com");
153
+ // Untouched field still fills from config.
154
+ expect(step.policy?.expectedIdentity).toBe(
155
+ "https://github.com/acme/repo/.github/workflows/release.yml@refs/heads/main",
156
+ );
157
+ });
158
+
159
+ test("verify: a step with no policy field at all still gets one filled from config", () => {
160
+ const config: ChantConfig = { signing: { oidcIssuer: "https://issuer.example.com", identity: "id" } };
161
+ const comp = component([
162
+ { phase: "Verify", steps: [{ kind: "verify", imageRef: "repo@sha256:abc" }] },
163
+ ]);
164
+
165
+ const result = applyConfigDefaults(comp, config);
166
+ const step = result.deploy[0]!.steps[0] as { policy?: { expectedIssuer?: string } };
167
+ expect(step.policy?.expectedIssuer).toBe("https://issuer.example.com");
168
+ });
169
+
170
+ test("vuln-gate: a vulnPolicy in config changes the step's effective policy", () => {
171
+ const config: ChantConfig = { vulnPolicy: { failSeverity: "high", warnSeverity: "medium" } };
172
+ const comp = component([
173
+ { phase: "Gate", steps: [{ kind: "vuln-gate", sbom: { bytes: "", mediaType: "", packageCount: 0, generator: "x", format: "spdx" } }] },
174
+ ]);
175
+
176
+ const result = applyConfigDefaults(comp, config);
177
+ const step = result.deploy[0]!.steps[0] as { policy?: { failSeverity?: string; warnSeverity?: string } };
178
+ expect(step.policy?.failSeverity).toBe("high");
179
+ expect(step.policy?.warnSeverity).toBe("medium");
180
+ });
181
+
182
+ test("vuln-gate: the step's own policy field wins over config for that field", () => {
183
+ const config: ChantConfig = { vulnPolicy: { failSeverity: "high", warnSeverity: "medium" } };
184
+ const comp = component([
185
+ {
186
+ phase: "Gate",
187
+ steps: [{
188
+ kind: "vuln-gate",
189
+ sbom: { bytes: "", mediaType: "", packageCount: 0, generator: "x", format: "spdx" },
190
+ policy: { failSeverity: "critical" },
191
+ }],
192
+ },
193
+ ]);
194
+
195
+ const result = applyConfigDefaults(comp, config);
196
+ const step = result.deploy[0]!.steps[0] as { policy?: { failSeverity?: string; warnSeverity?: string } };
197
+ // Step wins on the field it set...
198
+ expect(step.policy?.failSeverity).toBe("critical");
199
+ // ...but config still fills the field the step left unset.
200
+ expect(step.policy?.warnSeverity).toBe("medium");
201
+ });
202
+
203
+ test("recurses into nested fan-out phases and onFailure compensation phases", () => {
204
+ const config: ChantConfig = { sbom: { format: "cyclonedx" } };
205
+ const comp = component([
206
+ {
207
+ phase: "Rollout",
208
+ steps: [
209
+ {
210
+ phase: "instance-1",
211
+ steps: [{ kind: "generate-sbom", artifactType: "image", path: "img" }],
212
+ },
213
+ ],
214
+ onFailure: [
215
+ { phase: "Compensate", steps: [{ kind: "generate-sbom", artifactType: "image", path: "img2" }] },
216
+ ],
217
+ },
218
+ ]);
219
+
220
+ const result = applyConfigDefaults(comp, config);
221
+ const nested = result.deploy[0]!.steps[0] as { steps: Array<{ format?: string }> };
222
+ expect(nested.steps[0]!.format).toBe("cyclonedx");
223
+ const compensated = result.deploy[0]!.onFailure![0]!.steps[0] as { format?: string };
224
+ expect(compensated.format).toBe("cyclonedx");
225
+ });
226
+
227
+ test("leaves gate steps untouched", () => {
228
+ const config: ChantConfig = { sbom: { format: "cyclonedx" } };
229
+ const comp = component([
230
+ { phase: "Approve", steps: [{ kind: "gate", signalName: "release-approval" }] },
231
+ ]);
232
+
233
+ const result = applyConfigDefaults(comp, config);
234
+ expect(result.deploy[0]!.steps[0]).toEqual({ kind: "gate", signalName: "release-approval" });
235
+ });
236
+
237
+ test("applies defaults to rollback phases too", () => {
238
+ const config: ChantConfig = { vulnPolicy: { failSeverity: "high" } };
239
+ const comp: DriverComponent = {
240
+ name: "svc",
241
+ dependsOn: [],
242
+ deploy: [{ phase: "Apply", steps: [{ kind: "deploy-thing" }] }],
243
+ rollback: [
244
+ { phase: "Rollback", steps: [{ kind: "vuln-gate", sbom: { bytes: "", mediaType: "", packageCount: 0, generator: "x", format: "spdx" } }] },
245
+ ],
246
+ };
247
+
248
+ const result = applyConfigDefaults(comp, config);
249
+ const step = result.rollback![0]!.steps[0] as { policy?: { failSeverity?: string } };
250
+ expect(step.policy?.failSeverity).toBe("high");
251
+ });
252
+
253
+ test("does not mutate the original component", () => {
254
+ const config: ChantConfig = { sbom: { format: "cyclonedx" } };
255
+ const comp = component([
256
+ { phase: "Build", steps: [{ kind: "generate-sbom", artifactType: "image", path: "img" }] },
257
+ ]);
258
+
259
+ applyConfigDefaults(comp, config);
260
+ const original = comp.deploy[0]!.steps[0] as { format?: string };
261
+ expect(original.format).toBeUndefined();
262
+ });
263
+ });
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Config-defaults pass (#629, epic #551 follow-up to #606/#622/#626) — the
3
+ * missing link between `chant.config.ts`'s `sbom`/`signing`/`vulnPolicy`
4
+ * sections and the steps that actually consume them.
5
+ *
6
+ * Before this module, `resolveSigningDefaults`/`resolveVulnPolicy`
7
+ * (../config.ts) were never called anywhere in the `chant run --components`
8
+ * path, and `resolveSbomFormat` was only ever called in post-hoc display
9
+ * code. A component author had to hand-code `format`/`keyless`/`oidcIssuer`/
10
+ * `policy` into every `generate-sbom`/`sign`/`attest-provenance`/`verify`/
11
+ * `vuln-gate` step, even when the project already declared a project-wide
12
+ * default in `chant.config.ts` — the config sections were decorative.
13
+ *
14
+ * `applyConfigDefaults` walks a `DriverComponent`'s `deploy` composition
15
+ * (including nested fan-out phases and `onFailure` compensation phases) and
16
+ * returns a new component with each recognized step's config-driven fields
17
+ * filled in *only where the step didn't already set them* — per-step value
18
+ * wins over config wins over the capability's own built-in default, the
19
+ * precedence every one of the `resolve*` docstrings in ../config.ts already
20
+ * claims. This module is the caller that finally makes that claim true.
21
+ *
22
+ * Kept entirely outside `./driver.ts`: the driver stays capability-agnostic
23
+ * (it dispatches by `kind` and knows nothing about `sbom`/`signing`/
24
+ * `vulnPolicy`) — this pass transforms the component's plain-data composition
25
+ * *before* it ever reaches the driver, the same "resolve config, then hand a
26
+ * capability-agnostic caller a fully-formed input" convention `resolveSbomFormat`'s
27
+ * own docstring already describes for its callers.
28
+ */
29
+
30
+ import type { ChantConfig } from "../config";
31
+ import { resolveSbomFormat, resolveSigningDefaults, resolveVulnPolicy } from "../config";
32
+ import type { DriverComponent, DriverGate, DriverPhase, DriverStep } from "./driver";
33
+
34
+ function isGateStep(step: DriverStep | DriverGate | DriverPhase): step is DriverGate {
35
+ return (step as { kind?: unknown }).kind === "gate";
36
+ }
37
+
38
+ function isPhaseStep(step: DriverStep | DriverGate | DriverPhase): step is DriverPhase {
39
+ return typeof (step as { phase?: unknown }).phase === "string" && Array.isArray((step as DriverPhase).steps);
40
+ }
41
+
42
+ /**
43
+ * Fill one step's config-resolved defaults in place (into a shallow clone),
44
+ * per its `kind` — the only place this module branches on capability kind,
45
+ * matching how `../verbs/sbom.ts`'s `generate` is the only branch point for
46
+ * artifact type. Fields the step already set are never overwritten.
47
+ */
48
+ function applyStepDefaults(step: DriverStep, config: ChantConfig): DriverStep {
49
+ switch (step.kind) {
50
+ case "generate-sbom": {
51
+ const format = (step as { format?: unknown }).format as
52
+ | Parameters<typeof resolveSbomFormat>[1]
53
+ | undefined;
54
+ return { ...step, format: resolveSbomFormat(config, format) };
55
+ }
56
+
57
+ case "sign":
58
+ case "attest-provenance": {
59
+ const defaults = resolveSigningDefaults(config);
60
+ const next: DriverStep = { ...step };
61
+ // Only fill `keyless`/`key` when the step didn't already declare its own
62
+ // signing method — an explicit `key` (or `keyless`) on the step always
63
+ // wins over the project default, mirroring `resolveSigningDefaults`'s
64
+ // own "caller supplies any per-call override" contract.
65
+ if (next.keyless === undefined && next.key === undefined) {
66
+ if (!defaults.keyless && defaults.key) {
67
+ next.key = defaults.key;
68
+ } else if (defaults.identityPolicyDefaults.expectedIssuer !== undefined) {
69
+ // Keyless flow: thread the configured OIDC issuer through as a
70
+ // `keyless` override so `cosign sign/attest --oidc-issuer` picks it
71
+ // up, without clobbering any keyless sub-fields the step itself set.
72
+ const existingKeyless = (next.keyless as Record<string, unknown> | undefined) ?? {};
73
+ next.keyless = { oidcIssuer: defaults.identityPolicyDefaults.expectedIssuer, ...existingKeyless };
74
+ }
75
+ }
76
+ return next;
77
+ }
78
+
79
+ case "verify": {
80
+ const defaults = resolveSigningDefaults(config).identityPolicyDefaults;
81
+ const existingPolicy = (step.policy as Record<string, unknown> | undefined) ?? {};
82
+ const policy: Record<string, unknown> = { ...existingPolicy };
83
+ if (policy.expectedIssuer === undefined && defaults.expectedIssuer !== undefined) {
84
+ policy.expectedIssuer = defaults.expectedIssuer;
85
+ }
86
+ if (policy.expectedIdentity === undefined && defaults.expectedIdentity !== undefined) {
87
+ policy.expectedIdentity = defaults.expectedIdentity;
88
+ }
89
+ if (policy.identityIsRegexp === undefined && defaults.identityIsRegexp !== undefined) {
90
+ policy.identityIsRegexp = defaults.identityIsRegexp;
91
+ }
92
+ if (policy.key === undefined && defaults.key !== undefined) {
93
+ policy.key = defaults.key;
94
+ }
95
+ return { ...step, policy };
96
+ }
97
+
98
+ case "vuln-gate": {
99
+ const configPolicy = resolveVulnPolicy(config);
100
+ const existingPolicy = (step.policy as Record<string, unknown> | undefined) ?? {};
101
+ // Config policy fills the gaps; the step's own `policy` wins field-by-field.
102
+ const policy: Record<string, unknown> = { ...configPolicy, ...existingPolicy };
103
+ return { ...step, policy };
104
+ }
105
+
106
+ default:
107
+ return step;
108
+ }
109
+ }
110
+
111
+ /** Recursively apply step defaults across one entry (a step, a gate, or a nested fan-out phase). Gates are returned unchanged — they carry no capability input to resolve. */
112
+ function applyEntryDefaults(
113
+ entry: DriverStep | DriverGate | DriverPhase,
114
+ config: ChantConfig,
115
+ ): DriverStep | DriverGate | DriverPhase {
116
+ if (isGateStep(entry)) return entry;
117
+ if (isPhaseStep(entry)) return applyPhaseDefaults(entry, config);
118
+ return applyStepDefaults(entry, config);
119
+ }
120
+
121
+ /** Apply step defaults across one phase's `steps` (recursing into nested fan-out phases) and its `onFailure` compensation phases. */
122
+ function applyPhaseDefaults(phase: DriverPhase, config: ChantConfig): DriverPhase {
123
+ return {
124
+ ...phase,
125
+ steps: phase.steps.map((entry) => applyEntryDefaults(entry, config)),
126
+ ...(phase.onFailure ? { onFailure: phase.onFailure.map((p) => applyPhaseDefaults(p, config)) } : {}),
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Return `component` with `chant.config.ts`'s `sbom`/`signing`/`vulnPolicy`
132
+ * defaults filled into its `deploy` (and `rollback`, which shares the same
133
+ * `DriverPhase[]` shape and can equally carry a `verify`/`vuln-gate` step)
134
+ * composition, wherever a step didn't already specify the value itself.
135
+ * Non-destructive: returns a new component/phase/step tree, never mutates
136
+ * `component` in place, so a caller holding the original discovered
137
+ * `DriverComponent` (e.g. for `chant describe`) is unaffected.
138
+ */
139
+ export function applyConfigDefaults(component: DriverComponent, config: ChantConfig): DriverComponent {
140
+ return {
141
+ ...component,
142
+ deploy: component.deploy.map((phase) => applyPhaseDefaults(phase, config)),
143
+ ...(component.rollback ? { rollback: component.rollback.map((phase) => applyPhaseDefaults(phase, config)) } : {}),
144
+ };
145
+ }