@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
@@ -16,32 +16,51 @@
16
16
  */
17
17
  export type ActivityFn = (args: Record<string, unknown>, signal?: AbortSignal) => Promise<unknown>;
18
18
 
19
+ /** Add every exported function from an activity module to `into`, keyed by name. */
20
+ function collectActivities(mod: Record<string, unknown>, into: Map<string, ActivityFn>): void {
21
+ for (const [name, value] of Object.entries(mod)) {
22
+ if (typeof value === "function") {
23
+ into.set(name, value as ActivityFn);
24
+ }
25
+ }
26
+ }
27
+
19
28
  /**
20
- * Dynamically import the Temporal lexicon's activity library and return a map
21
- * of every exported function keyed by its export name (`shellCmd`, `chantBuild`,
22
- * `kubectlApply`, …).
29
+ * Build the activity map for local execution by importing activity libraries and
30
+ * keying every exported function by name (`shellCmd`, `kubectlApply`, `gcpApply`, …).
31
+ *
32
+ * The base activities always live in the temporal lexicon. Cloud-specific
33
+ * appliers live in their own lexicon (aws → `flociUp`/`flociDown`, gcp →
34
+ * `gcpApply`, azure → `azGroupEnsure`/`azGroupDelete`), so `lexicons` — the
35
+ * project's configured lexicon list — is consulted to pull those in. A lexicon
36
+ * that ships no `op/activities` module is skipped.
23
37
  *
24
- * Throws a friendly error if the lexicon is not installed — local execution
25
- * needs the activity implementations even though it never starts a worker.
38
+ * Throws only if the temporal base library is missing — local execution needs
39
+ * the activity implementations even though it never starts a worker.
26
40
  */
27
- export async function loadActivities(): Promise<Map<string, ActivityFn>> {
28
- let mod: Record<string, unknown>;
41
+ export async function loadActivities(lexicons: string[] = []): Promise<Map<string, ActivityFn>> {
42
+ const activities = new Map<string, ActivityFn>();
43
+
29
44
  try {
30
45
  // Variable specifier so tsc does not statically resolve the optional dep.
31
46
  const spec = "@intentius/chant-lexicon-temporal/op/activities";
32
- mod = (await import(spec)) as Record<string, unknown>;
47
+ collectActivities((await import(spec)) as Record<string, unknown>, activities);
33
48
  } catch {
34
49
  throw new Error(
35
50
  "no activities registered — install `@intentius/chant-lexicon-temporal`",
36
51
  );
37
52
  }
38
53
 
39
- const activities = new Map<string, ActivityFn>();
40
- for (const [name, value] of Object.entries(mod)) {
41
- if (typeof value === "function") {
42
- activities.set(name, value as ActivityFn);
54
+ for (const name of lexicons) {
55
+ if (name === "temporal") continue;
56
+ try {
57
+ const spec = `@intentius/chant-lexicon-${name}/op/activities`;
58
+ collectActivities((await import(spec)) as Record<string, unknown>, activities);
59
+ } catch {
60
+ // Lexicon absent or contributes no activities — fine.
43
61
  }
44
62
  }
63
+
45
64
  return activities;
46
65
  }
47
66
 
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Activity runtime helpers shared by every Op activity implementation, wherever
3
+ * it lives — the base activities in the temporal lexicon and the cloud-specific
4
+ * appliers relocated into the aws/gcp/azure lexicons. Hosting them in core keeps
5
+ * a cloud lexicon from having to depend on the temporal lexicon just to
6
+ * heartbeat or sleep.
7
+ */
8
+
9
+ interface ActivityContext {
10
+ current(): { heartbeat(details?: unknown): void };
11
+ }
12
+
13
+ // undefined = not yet attempted; null = unavailable; object = resolved Context.
14
+ let cachedContext: ActivityContext | null | undefined;
15
+ let loading: Promise<void> | undefined;
16
+
17
+ function ensureContext(): void {
18
+ if (cachedContext !== undefined || loading) return;
19
+ // Variable specifier so bundlers/tsc do not statically require the optional dep.
20
+ const spec = "@temporalio/activity";
21
+ loading = import(spec)
22
+ .then((mod: unknown) => {
23
+ cachedContext = (mod as { Context?: ActivityContext }).Context ?? null;
24
+ })
25
+ .catch(() => {
26
+ cachedContext = null;
27
+ });
28
+ }
29
+
30
+ /**
31
+ * Emit an activity heartbeat if running under a Temporal worker; otherwise no-op.
32
+ *
33
+ * The first call kicks off a one-time lazy load of `@temporalio/activity` and
34
+ * returns immediately; once resolved, subsequent calls heartbeat. Heartbeats
35
+ * are periodic (every ~15s, well inside the 60s heartbeat timeout), so the
36
+ * single missed first tick is harmless. Under chant's local executor (no
37
+ * Temporal SDK present) it no-ops, and the module imports cleanly without the SDK.
38
+ */
39
+ export function safeHeartbeat(details?: unknown): void {
40
+ if (cachedContext === undefined) {
41
+ ensureContext();
42
+ return;
43
+ }
44
+ if (cachedContext === null) return;
45
+ try {
46
+ cachedContext.current().heartbeat(details);
47
+ } catch {
48
+ // Not inside an activity execution context — nothing to do.
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Sleep for `ms`, rejecting early if `signal` aborts. Polling activities use
54
+ * this between attempts so a local-executor timeout or Ctrl-C interrupts the
55
+ * wait instead of running it to completion.
56
+ */
57
+ export function sleep(ms: number, signal?: AbortSignal): Promise<void> {
58
+ return new Promise((resolve, reject) => {
59
+ if (signal?.aborted) {
60
+ reject(new Error("aborted"));
61
+ return;
62
+ }
63
+ const onAbort = () => {
64
+ clearTimeout(timer);
65
+ reject(new Error("aborted"));
66
+ };
67
+ const timer = setTimeout(() => {
68
+ signal?.removeEventListener("abort", onAbort);
69
+ resolve();
70
+ }, ms);
71
+ signal?.addEventListener("abort", onAbort, { once: true });
72
+ });
73
+ }
@@ -131,6 +131,105 @@ export const shell = (
131
131
  export const teardown = (path: string): ActivityStep =>
132
132
  activity("chantTeardown", { path }, "longInfra");
133
133
 
134
+ /**
135
+ * Create a local k3d cluster (vanilla Kubernetes in Docker) and merge its
136
+ * kubeconfig / switch context — k3d's defaults. Idempotent: skips creation if a
137
+ * cluster of the same name already exists. Defaults to the `longInfra` profile
138
+ * (creating a cluster may pull the k3s image); override via `opts.profile`.
139
+ *
140
+ * `opts` accepts `servers`, `agents`, `image`, `ports` (e.g.
141
+ * `["8080:80@loadbalancer"]`), `registryCreate`, `configFile`, and `timeout`.
142
+ */
143
+ export const k3dUp = (name: string, opts?: Record<string, unknown>): ActivityStep => {
144
+ const { args, profile } = takeProfile(opts);
145
+ return activity("k3dUp", { name, ...args }, profile ?? "longInfra");
146
+ };
147
+
148
+ /** Delete a local k3d cluster. Defaults to the `fastIdempotent` profile (override via `opts.profile`). */
149
+ export const k3dDown = (name: string, opts?: Record<string, unknown>): ActivityStep => {
150
+ const { args, profile } = takeProfile(opts);
151
+ return activity("k3dDown", { name, ...args }, profile ?? "fastIdempotent");
152
+ };
153
+
154
+ /**
155
+ * Boot a local Floci AWS emulator in Docker and point subsequent steps at it —
156
+ * sets `AWS_ENDPOINT_URL` + test creds in the process env so a following
157
+ * `cloudformation` apply targets the emulator (local executor). Idempotent:
158
+ * reuses a running container of the same name. Defaults to the `longInfra`
159
+ * profile (the image may pull); override via `opts.profile`.
160
+ *
161
+ * `opts` accepts `name`, `port`, `image`, `dockerSocket` (mount the docker
162
+ * socket for the ECR backing registry), `region`, `readyService`, `timeoutMs`.
163
+ */
164
+ export const flociUp = (opts?: Record<string, unknown>): ActivityStep => {
165
+ const { args, profile } = takeProfile(opts);
166
+ return activity("flociUp", args, profile ?? "longInfra");
167
+ };
168
+
169
+ /** Stop and remove the local Floci emulator container. Defaults to the `fastIdempotent` profile (override via `opts.profile`). */
170
+ export const flociDown = (opts?: Record<string, unknown>): ActivityStep => {
171
+ const { args, profile } = takeProfile(opts);
172
+ return activity("flociDown", args, profile ?? "fastIdempotent");
173
+ };
174
+
175
+ /**
176
+ * Ensure an Azure resource group exists before an ARM apply. `az deployment
177
+ * group create` (the `arm` apply target) fails without its group, so place this
178
+ * before the deploy phase. Idempotent. Defaults to the `fastIdempotent` profile
179
+ * (override via `opts.profile`). `opts` accepts `location` (default `eastus`).
180
+ */
181
+ export const azGroupEnsure = (resourceGroup: string, opts?: Record<string, unknown>): ActivityStep => {
182
+ const { args, profile } = takeProfile(opts);
183
+ return activity("azGroupEnsure", { resourceGroup, ...args }, profile ?? "fastIdempotent");
184
+ };
185
+
186
+ /** Delete an Azure resource group and its contents (non-blocking). Defaults to the `fastIdempotent` profile (override via `opts.profile`). */
187
+ export const azGroupDelete = (resourceGroup: string, opts?: Record<string, unknown>): ActivityStep => {
188
+ const { args, profile } = takeProfile(opts);
189
+ return activity("azGroupDelete", { resourceGroup, ...args }, profile ?? "fastIdempotent");
190
+ };
191
+
192
+ /**
193
+ * Apply chant's built ARM template directly to the ARM resource API — the Azure
194
+ * twin of {@link gcpApply}. Targets floci-az's resource CRUD (which `az deployment`
195
+ * can't, floci-az having no deployments provider) or real Azure by endpoint
196
+ * override; ensures the resource group first. Defaults to the `longInfra` profile.
197
+ *
198
+ * `opts` requires `resourceGroup`; accepts `location`, `endpoint` (floci-az
199
+ * `http://localhost:4577`), `subscriptionId`, and `prune` (owned-only prune of
200
+ * chant-managed resources no longer in the template — destructive, off by default).
201
+ */
202
+ export const azApply = (templatePath: string, opts?: Record<string, unknown>): ActivityStep => {
203
+ const { args, profile } = takeProfile(opts);
204
+ return activity("azApply", { templatePath, ...args }, profile ?? "longInfra");
205
+ };
206
+
207
+ /** Delete the Azure (ARM) resources in a built template — the inverse of {@link azApply}. Defaults to the `longInfra` profile (override via `opts.profile`). `opts` requires `resourceGroup`. */
208
+ export const azDelete = (templatePath: string, opts?: Record<string, unknown>): ActivityStep => {
209
+ const { args, profile } = takeProfile(opts);
210
+ return activity("azDelete", { templatePath, ...args }, profile ?? "longInfra");
211
+ };
212
+
213
+ /**
214
+ * Apply chant's built GCP (CNRM) resources directly to the GCS REST API,
215
+ * targeting a local floci-gcp emulator or real GCP by endpoint override — the
216
+ * native GCP applier (#706 starter #711), currently handling `StorageBucket`.
217
+ * Defaults to the `longInfra` profile (override via `opts.profile`).
218
+ *
219
+ * `opts` accepts `endpoint` (default `STORAGE_EMULATOR_HOST` env / real GCS) and
220
+ * `project` (default `GOOGLE_CLOUD_PROJECT` env / the CNRM project-id annotation).
221
+ */
222
+ export const gcpApply = (manifestPath: string, opts?: Record<string, unknown>): ActivityStep => {
223
+ const { args, profile } = takeProfile(opts);
224
+ return activity("gcpApply", { manifestPath, ...args }, profile ?? "longInfra");
225
+ };
226
+
227
+ /** Delete the GCP (CNRM) resources in a built manifest — the inverse of {@link gcpApply}. Defaults to the `longInfra` profile (override via `opts.profile`). */
228
+ export const gcpDelete = (manifestPath: string, opts?: Record<string, unknown>): ActivityStep => {
229
+ const { args, profile } = takeProfile(opts);
230
+ return activity("gcpDelete", { manifestPath, ...args }, profile ?? "longInfra");
231
+ };
232
+
134
233
  /**
135
234
  * Gate an apply on organizational policy: build the project and run its
136
235
  * `lint.policies` over the resolved resources, blocking the workflow on any
package/src/op/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { Op, phase, activity, gate, build, kubectlApply, helmInstall, waitForStack,
2
- gitlabPipeline, lifecycleSnapshot, shell, teardown, policyGate } from "./builders";
2
+ gitlabPipeline, lifecycleSnapshot, shell, teardown, k3dUp, k3dDown, flociUp, flociDown,
3
+ azGroupEnsure, azGroupDelete, azApply, azDelete, gcpApply, gcpDelete, policyGate } from "./builders";
3
4
  export { OpResource } from "./resource";
5
+ export { safeHeartbeat, sleep } from "./activity-runtime";
4
6
  export type { OpConfig, PhaseDefinition, StepDefinition, ActivityStep, GateStep } from "./types";
5
7
  export { discoverOps } from "./discover";
6
8
  export type { DiscoveredOp, OpDiscoveryResult } from "./discover";
@@ -1,42 +1,40 @@
1
1
  import { describe, expect, test } from "vitest";
2
2
  import {
3
3
  ownershipEntries,
4
- ownershipKeys,
5
4
  hasOwnershipMarker,
6
5
  readOwnership,
7
6
  classifyOwnership,
8
7
  tagArrayToMap,
8
+ LABEL_OWNERSHIP_KEYS,
9
9
  OWNERSHIP_MANAGED_BY_VALUE,
10
+ type ChannelKeys,
10
11
  } from "./ownership";
11
12
  import { resolveOwnershipMarker } from "./config";
12
13
 
14
+ // A stand-in for a lexicon-provided convention (e.g. AWS's colon keys), to
15
+ // prove the core helpers are generic over any `ChannelKeys` — the per-provider
16
+ // conventions themselves live in their lexicons (aws/azure), not here.
17
+ const COLON_KEYS: ChannelKeys = { managedBy: "chant:managed-by", stack: "chant:stack", env: "chant:env" };
18
+
13
19
  describe("ownershipEntries (#119)", () => {
14
- test("label channel carries managed-by + stack + env", () => {
15
- const e = ownershipEntries("label", { stack: "billing", env: "prod" });
20
+ test("the default label keys carry managed-by + stack + env", () => {
21
+ const e = ownershipEntries(LABEL_OWNERSHIP_KEYS, { stack: "billing", env: "prod" });
16
22
  expect(e["app.kubernetes.io/managed-by"]).toBe("chant");
17
23
  expect(e["chant.intentius.io/stack"]).toBe("billing");
18
24
  expect(e["chant.intentius.io/env"]).toBe("prod");
19
25
  });
20
26
 
21
- test("aws-tag channel uses colon keys", () => {
22
- const e = ownershipEntries("aws-tag", { stack: "billing" });
27
+ test("stamps whatever key names the provided ChannelKeys names, env omitted when unset", () => {
28
+ const e = ownershipEntries(COLON_KEYS, { stack: "billing" });
23
29
  expect(e["chant:managed-by"]).toBe("chant");
24
30
  expect(e["chant:stack"]).toBe("billing");
25
31
  expect(e["chant:env"]).toBeUndefined(); // env omitted when not set
26
32
  });
27
33
 
28
- test("azure-tag channel uses hyphen keys (no slash, which Azure forbids)", () => {
29
- const e = ownershipEntries("azure-tag", { stack: "billing", env: "stg" });
30
- expect(e["chant-managed-by"]).toBe("chant");
31
- expect(e["chant-stack"]).toBe("billing");
32
- expect(e["chant-env"]).toBe("stg");
33
- expect(Object.keys(e).some((k) => k.includes("/"))).toBe(false);
34
- });
35
-
36
34
  test("carries stack identity, not just managed=true", () => {
37
- const a = ownershipEntries("label", { stack: "stack-a" });
38
- const b = ownershipEntries("label", { stack: "stack-b" });
39
- expect(a[ownershipKeys("label").stack]).not.toBe(b[ownershipKeys("label").stack]);
35
+ const a = ownershipEntries(LABEL_OWNERSHIP_KEYS, { stack: "stack-a" });
36
+ const b = ownershipEntries(LABEL_OWNERSHIP_KEYS, { stack: "stack-b" });
37
+ expect(a[LABEL_OWNERSHIP_KEYS.stack]).not.toBe(b[LABEL_OWNERSHIP_KEYS.stack]);
40
38
  });
41
39
  });
42
40
 
@@ -47,29 +45,29 @@ describe("hasOwnershipMarker / readOwnership", () => {
47
45
  "chant:stack": "billing",
48
46
  "team": "payments", // foreign co-stamp
49
47
  };
50
- expect(hasOwnershipMarker(tags, "aws-tag")).toBe(true);
48
+ expect(hasOwnershipMarker(tags, COLON_KEYS)).toBe(true);
51
49
  });
52
50
 
53
51
  test("absent marker → not owned", () => {
54
- expect(hasOwnershipMarker({ team: "payments" }, "aws-tag")).toBe(false);
55
- expect(hasOwnershipMarker(undefined, "label")).toBe(false);
52
+ expect(hasOwnershipMarker({ team: "payments" }, COLON_KEYS)).toBe(false);
53
+ expect(hasOwnershipMarker(undefined, LABEL_OWNERSHIP_KEYS)).toBe(false);
56
54
  });
57
55
 
58
56
  test("readOwnership recovers stack/env from a marked resource", () => {
59
- const labels = ownershipEntries("label", { stack: "billing", env: "prod" });
60
- expect(readOwnership(labels, "label")).toEqual({ stack: "billing", env: "prod" });
57
+ const labels = ownershipEntries(LABEL_OWNERSHIP_KEYS, { stack: "billing", env: "prod" });
58
+ expect(readOwnership(labels, LABEL_OWNERSHIP_KEYS)).toEqual({ stack: "billing", env: "prod" });
61
59
  });
62
60
 
63
61
  test("readOwnership returns undefined when unmarked", () => {
64
- expect(readOwnership({ foo: "bar" }, "label")).toBeUndefined();
62
+ expect(readOwnership({ foo: "bar" }, LABEL_OWNERSHIP_KEYS)).toBeUndefined();
65
63
  });
66
64
  });
67
65
 
68
66
  describe("classifyOwnership / tagArrayToMap (#120)", () => {
69
67
  test("marker present → owned, absent → foreign", () => {
70
- expect(classifyOwnership({ "chant:managed-by": "chant" }, "aws-tag")).toBe("owned");
71
- expect(classifyOwnership({ team: "x" }, "aws-tag")).toBe("foreign");
72
- expect(classifyOwnership(undefined, "label")).toBe("foreign");
68
+ expect(classifyOwnership({ "chant:managed-by": "chant" }, COLON_KEYS)).toBe("owned");
69
+ expect(classifyOwnership({ team: "x" }, COLON_KEYS)).toBe("foreign");
70
+ expect(classifyOwnership(undefined, LABEL_OWNERSHIP_KEYS)).toBe("foreign");
73
71
  });
74
72
 
75
73
  test("tagArrayToMap converts CloudFormation {Key,Value} tags", () => {
@@ -78,7 +76,7 @@ describe("classifyOwnership / tagArrayToMap (#120)", () => {
78
76
  { Key: "chant:stack", Value: "billing" },
79
77
  ]);
80
78
  expect(map["chant:managed-by"]).toBe("chant");
81
- expect(classifyOwnership(map, "aws-tag")).toBe("owned");
79
+ expect(classifyOwnership(map, COLON_KEYS)).toBe("owned");
82
80
  });
83
81
 
84
82
  test("tagArrayToMap tolerates undefined / malformed entries", () => {
package/src/ownership.ts CHANGED
@@ -28,50 +28,39 @@ export interface OwnershipMarker {
28
28
  }
29
29
 
30
30
  /**
31
- * The native metadata channel a target stamps into. Tag-key syntax differs:
32
- * Kubernetes/GCP labels allow a `prefix/name` form; AWS tag keys allow `:`;
33
- * Azure tag keys forbid `/`, so they use a hyphenated form.
31
+ * The marker key names a target stamps into — the managed-by/stack/env tag or
32
+ * label keys. Tag-key syntax differs per provider (Kubernetes/GCP labels allow
33
+ * a `prefix/name` form; AWS tag keys allow `:`; Azure tag keys forbid `/`), so
34
+ * each cloud lexicon provides its own `ChannelKeys` and passes it to these
35
+ * helpers. Core owns the generic stamp/detect logic and the shared label
36
+ * convention (`LABEL_OWNERSHIP_KEYS`), not a per-provider key registry.
34
37
  */
35
- export type OwnershipChannel = "label" | "aws-tag" | "azure-tag";
36
-
37
- interface ChannelKeys {
38
+ export interface ChannelKeys {
38
39
  readonly managedBy: string;
39
40
  readonly stack: string;
40
41
  readonly env: string;
41
42
  }
42
43
 
43
- const CHANNEL_KEYS: Record<OwnershipChannel, ChannelKeys> = {
44
- label: {
45
- managedBy: "app.kubernetes.io/managed-by",
46
- stack: "chant.intentius.io/stack",
47
- env: "chant.intentius.io/env",
48
- },
49
- "aws-tag": {
50
- managedBy: "chant:managed-by",
51
- stack: "chant:stack",
52
- env: "chant:env",
53
- },
54
- "azure-tag": {
55
- managedBy: "chant-managed-by",
56
- stack: "chant-stack",
57
- env: "chant-env",
58
- },
44
+ /**
45
+ * The label-based ownership convention (`app.kubernetes.io/managed-by` +
46
+ * `chant.intentius.io/{stack,env}`) — the default, shared by every label-based
47
+ * lexicon (k8s, gcp, helm, and the Temporal apply activity's `kubectl --prune`
48
+ * selector). AWS and Azure tag keys are defined in their own lexicons.
49
+ */
50
+ export const LABEL_OWNERSHIP_KEYS: ChannelKeys = {
51
+ managedBy: "app.kubernetes.io/managed-by",
52
+ stack: "chant.intentius.io/stack",
53
+ env: "chant.intentius.io/env",
59
54
  };
60
55
 
61
- /** The marker key names used in a given channel. */
62
- export function ownershipKeys(channel: OwnershipChannel): ChannelKeys {
63
- return CHANNEL_KEYS[channel];
64
- }
65
-
66
56
  /**
67
- * The key/value entries to stamp for a channel: the managed-by marker, the
68
- * stack identity, and the env identity when present.
57
+ * The key/value entries to stamp: the managed-by marker, the stack identity,
58
+ * and the env identity when present.
69
59
  */
70
60
  export function ownershipEntries(
71
- channel: OwnershipChannel,
61
+ keys: ChannelKeys,
72
62
  marker: OwnershipMarker,
73
63
  ): Record<string, string> {
74
- const keys = CHANNEL_KEYS[channel];
75
64
  const entries: Record<string, string> = {
76
65
  [keys.managedBy]: OWNERSHIP_MANAGED_BY_VALUE,
77
66
  [keys.stack]: marker.stack,
@@ -86,10 +75,10 @@ export function ownershipEntries(
86
75
  */
87
76
  export function hasOwnershipMarker(
88
77
  tagsOrLabels: Record<string, unknown> | undefined,
89
- channel: OwnershipChannel,
78
+ keys: ChannelKeys,
90
79
  ): boolean {
91
80
  if (!tagsOrLabels) return false;
92
- return tagsOrLabels[CHANNEL_KEYS[channel].managedBy] === OWNERSHIP_MANAGED_BY_VALUE;
81
+ return tagsOrLabels[keys.managedBy] === OWNERSHIP_MANAGED_BY_VALUE;
93
82
  }
94
83
 
95
84
  /**
@@ -104,9 +93,9 @@ export function hasOwnershipMarker(
104
93
  */
105
94
  export function classifyOwnership(
106
95
  tagsOrLabels: Record<string, unknown> | undefined,
107
- channel: OwnershipChannel,
96
+ keys: ChannelKeys,
108
97
  ): "owned" | "foreign" {
109
- return hasOwnershipMarker(tagsOrLabels, channel) ? "owned" : "foreign";
98
+ return hasOwnershipMarker(tagsOrLabels, keys) ? "owned" : "foreign";
110
99
  }
111
100
 
112
101
  /**
@@ -129,10 +118,9 @@ export function tagArrayToMap(
129
118
  */
130
119
  export function readOwnership(
131
120
  tagsOrLabels: Record<string, unknown> | undefined,
132
- channel: OwnershipChannel,
121
+ keys: ChannelKeys,
133
122
  ): OwnershipMarker | undefined {
134
- if (!hasOwnershipMarker(tagsOrLabels, channel)) return undefined;
135
- const keys = CHANNEL_KEYS[channel];
123
+ if (!hasOwnershipMarker(tagsOrLabels, keys)) return undefined;
136
124
  const stack = tagsOrLabels![keys.stack];
137
125
  const env = tagsOrLabels![keys.env];
138
126
  return {