@intentius/chant 0.124.31 → 0.124.33

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 (509) hide show
  1. package/bin/chant +7 -2
  2. package/dist/ci-jobs.d.ts +4 -0
  3. package/dist/ci-jobs.d.ts.map +1 -1
  4. package/dist/ci-jobs.js +9 -2
  5. package/dist/cli/commands/check-lexicon-plugin.d.ts +7 -4
  6. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  7. package/dist/cli/commands/check-lexicon-plugin.js +10 -7
  8. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  9. package/dist/cli/commands/check-lexicon.js +18 -12
  10. package/dist/cli/commands/import.d.ts +10 -0
  11. package/dist/cli/commands/import.d.ts.map +1 -1
  12. package/dist/cli/commands/import.js +37 -0
  13. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  14. package/dist/cli/commands/init-lexicon/templates/project.js +4 -3
  15. package/dist/cli/commands/onboard.d.ts.map +1 -1
  16. package/dist/cli/commands/onboard.js +8 -4
  17. package/dist/cli/commands/update.d.ts.map +1 -1
  18. package/dist/cli/commands/update.js +2 -1
  19. package/dist/cli/dependencies.d.ts +18 -0
  20. package/dist/cli/dependencies.d.ts.map +1 -0
  21. package/dist/cli/dependencies.js +120 -0
  22. package/dist/cli/handlers/build.d.ts.map +1 -1
  23. package/dist/cli/handlers/build.js +38 -4
  24. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  25. package/dist/cli/handlers/fan-out.js +12 -4
  26. package/dist/cli/handlers/graph.d.ts.map +1 -1
  27. package/dist/cli/handlers/graph.js +16 -6
  28. package/dist/cli/handlers/lifecycle-health.d.ts +16 -0
  29. package/dist/cli/handlers/lifecycle-health.d.ts.map +1 -0
  30. package/dist/cli/handlers/lifecycle-health.js +150 -0
  31. package/dist/cli/handlers/lifecycle.d.ts +26 -0
  32. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  33. package/dist/cli/handlers/lifecycle.js +1 -1
  34. package/dist/cli/handlers/lint.d.ts.map +1 -1
  35. package/dist/cli/handlers/lint.js +6 -0
  36. package/dist/cli/handlers/operator.d.ts +2 -2
  37. package/dist/cli/handlers/operator.js +3 -3
  38. package/dist/cli/handlers/pr.d.ts +16 -0
  39. package/dist/cli/handlers/pr.d.ts.map +1 -1
  40. package/dist/cli/handlers/pr.js +610 -32
  41. package/dist/cli/handlers/promote.d.ts.map +1 -1
  42. package/dist/cli/handlers/promote.js +19 -2
  43. package/dist/cli/handlers/release.d.ts +16 -1
  44. package/dist/cli/handlers/release.d.ts.map +1 -1
  45. package/dist/cli/handlers/release.js +83 -11
  46. package/dist/cli/handlers/run.d.ts +13 -1
  47. package/dist/cli/handlers/run.d.ts.map +1 -1
  48. package/dist/cli/handlers/run.js +38 -15
  49. package/dist/cli/main.d.ts.map +1 -1
  50. package/dist/cli/main.js +121 -33
  51. package/dist/cli/parse-args.d.ts.map +1 -1
  52. package/dist/cli/parse-args.js +37 -0
  53. package/dist/cli/registry.d.ts +29 -6
  54. package/dist/cli/registry.d.ts.map +1 -1
  55. package/dist/cli/registry.js +6 -2
  56. package/dist/codegen/generate-post-synth-barrel.js +2 -2
  57. package/dist/codegen/lexicon-regen.d.ts +4 -0
  58. package/dist/codegen/lexicon-regen.d.ts.map +1 -1
  59. package/dist/codegen/lexicon-regen.js +1 -1
  60. package/dist/codegen/pinned-upgrade.js +2 -2
  61. package/dist/components/capability.d.ts +44 -3
  62. package/dist/components/capability.d.ts.map +1 -1
  63. package/dist/components/capability.js +21 -0
  64. package/dist/components/changed-files.d.ts +7 -1
  65. package/dist/components/changed-files.d.ts.map +1 -1
  66. package/dist/components/changed-files.js +9 -1
  67. package/dist/components/deploy-inputs.d.ts +91 -0
  68. package/dist/components/deploy-inputs.d.ts.map +1 -0
  69. package/dist/components/deploy-inputs.js +184 -0
  70. package/dist/components/driver.d.ts +38 -0
  71. package/dist/components/driver.d.ts.map +1 -1
  72. package/dist/components/driver.js +56 -6
  73. package/dist/components/fan-out-record.d.ts +6 -1
  74. package/dist/components/fan-out-record.d.ts.map +1 -1
  75. package/dist/components/fan-out-record.js +24 -0
  76. package/dist/components/fan-out-run.d.ts +20 -0
  77. package/dist/components/fan-out-run.d.ts.map +1 -1
  78. package/dist/components/fan-out-run.js +21 -1
  79. package/dist/components/gate-plan.d.ts +8 -0
  80. package/dist/components/gate-plan.d.ts.map +1 -1
  81. package/dist/components/gate-plan.js +6 -0
  82. package/dist/components/pr-pipeline.d.ts +98 -12
  83. package/dist/components/pr-pipeline.d.ts.map +1 -1
  84. package/dist/components/pr-pipeline.js +146 -23
  85. package/dist/components/pr-run.d.ts +128 -30
  86. package/dist/components/pr-run.d.ts.map +1 -1
  87. package/dist/components/pr-run.js +290 -70
  88. package/dist/components/release-compile.d.ts +37 -2
  89. package/dist/components/release-compile.d.ts.map +1 -1
  90. package/dist/components/release-compile.js +64 -8
  91. package/dist/components/release-promote.d.ts +17 -3
  92. package/dist/components/release-promote.d.ts.map +1 -1
  93. package/dist/components/release-promote.js +79 -18
  94. package/dist/components/verbs/bom-writer.d.ts +1 -1
  95. package/dist/components/verbs/bom-writer.d.ts.map +1 -1
  96. package/dist/components/verbs/lockfile-sbom-generator.d.ts +20 -0
  97. package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -1
  98. package/dist/components/verbs/lockfile-sbom-generator.js +41 -4
  99. package/dist/components/wave-plan.d.ts +15 -2
  100. package/dist/components/wave-plan.d.ts.map +1 -1
  101. package/dist/components/wave-plan.js +44 -5
  102. package/dist/discovery/fold-import.d.ts.map +1 -1
  103. package/dist/discovery/fold-import.js +16 -6
  104. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  105. package/dist/discovery/sandbox/bundle.js +6 -0
  106. package/dist/discovery/specifier-resolve.d.ts.map +1 -1
  107. package/dist/discovery/specifier-resolve.js +8 -2
  108. package/dist/fold/fold.d.ts.map +1 -1
  109. package/dist/fold/fold.js +68 -1
  110. package/dist/fold/subset.d.ts +37 -0
  111. package/dist/fold/subset.d.ts.map +1 -1
  112. package/dist/fold/subset.js +88 -0
  113. package/dist/graph-detail.d.ts.map +1 -1
  114. package/dist/graph-detail.js +32 -7
  115. package/dist/health.d.ts +110 -0
  116. package/dist/health.d.ts.map +1 -0
  117. package/dist/health.js +105 -0
  118. package/dist/health.schema.json +191 -0
  119. package/dist/lexicon-module.d.ts +10 -0
  120. package/dist/lexicon-module.d.ts.map +1 -1
  121. package/dist/lexicon-module.js +53 -8
  122. package/dist/lexicon-plugin-helpers.d.ts.map +1 -1
  123. package/dist/lexicon-plugin-helpers.js +6 -4
  124. package/dist/lexicon.d.ts +29 -0
  125. package/dist/lexicon.d.ts.map +1 -1
  126. package/dist/lifecycle/affected.d.ts.map +1 -1
  127. package/dist/lifecycle/affected.js +7 -1
  128. package/dist/lifecycle/merge-record.d.ts +104 -0
  129. package/dist/lifecycle/merge-record.d.ts.map +1 -0
  130. package/dist/lifecycle/merge-record.js +102 -0
  131. package/dist/lifecycle/publish-attachments.d.ts +8 -5
  132. package/dist/lifecycle/publish-attachments.d.ts.map +1 -1
  133. package/dist/lifecycle/publish-attachments.js +27 -13
  134. package/dist/lifecycle/publish-npm.d.ts +3 -2
  135. package/dist/lifecycle/publish-npm.d.ts.map +1 -1
  136. package/dist/lifecycle/publish-npm.js +4 -3
  137. package/dist/lifecycle/release-at.d.ts +40 -0
  138. package/dist/lifecycle/release-at.d.ts.map +1 -0
  139. package/dist/lifecycle/release-at.js +83 -0
  140. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  141. package/dist/lifecycle/release-cut.js +23 -12
  142. package/dist/lifecycle/release-ledger.d.ts +21 -0
  143. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  144. package/dist/lifecycle/release-ledger.js +24 -0
  145. package/dist/lifecycle/release-publish.d.ts +28 -12
  146. package/dist/lifecycle/release-publish.d.ts.map +1 -1
  147. package/dist/lifecycle/release-publish.js +29 -17
  148. package/dist/lifecycle/release-store.d.ts +25 -2
  149. package/dist/lifecycle/release-store.d.ts.map +1 -1
  150. package/dist/lifecycle/release-store.js +40 -13
  151. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  152. package/dist/lifecycle/run-ledger.js +1 -0
  153. package/dist/lifecycle/work-dir.d.ts +45 -0
  154. package/dist/lifecycle/work-dir.d.ts.map +1 -0
  155. package/dist/lifecycle/work-dir.js +78 -0
  156. package/dist/lint/discover.d.ts +17 -9
  157. package/dist/lint/discover.d.ts.map +1 -1
  158. package/dist/lint/discover.js +62 -54
  159. package/dist/lint/rules/op/index.d.ts +2 -1
  160. package/dist/lint/rules/op/index.d.ts.map +1 -1
  161. package/dist/lint/rules/op/index.js +4 -2
  162. package/dist/lint/rules/op/ops018-shell-image-digest.d.ts +10 -0
  163. package/dist/lint/rules/op/ops018-shell-image-digest.d.ts.map +1 -0
  164. package/dist/lint/rules/op/ops018-shell-image-digest.js +38 -0
  165. package/dist/module-source.d.ts +57 -0
  166. package/dist/module-source.d.ts.map +1 -0
  167. package/dist/module-source.js +104 -0
  168. package/dist/op/activities/activity-contracts.d.ts +5 -0
  169. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  170. package/dist/op/activities/activity-contracts.js +3 -0
  171. package/dist/op/activities/factory.js +1 -1
  172. package/dist/op/activities/shell.d.ts +38 -0
  173. package/dist/op/activities/shell.d.ts.map +1 -1
  174. package/dist/op/activities/shell.js +89 -3
  175. package/dist/op/builders.d.ts +7 -0
  176. package/dist/op/builders.d.ts.map +1 -1
  177. package/dist/op/builders.js +7 -0
  178. package/dist/op/discover.d.ts.map +1 -1
  179. package/dist/op/discover.js +13 -3
  180. package/dist/op/gate.d.ts.map +1 -1
  181. package/dist/op/gate.js +3 -0
  182. package/dist/op/op-waves-run.d.ts.map +1 -1
  183. package/dist/op/op-waves-run.js +20 -5
  184. package/dist/op/operator.d.ts +2 -2
  185. package/dist/op/operator.js +2 -2
  186. package/dist/op/runtime.d.ts +2 -0
  187. package/dist/op/runtime.d.ts.map +1 -1
  188. package/dist/op/steward.d.ts +6 -4
  189. package/dist/op/steward.d.ts.map +1 -1
  190. package/dist/op/steward.js +5 -3
  191. package/dist/op/work-lease-run.d.ts +20 -7
  192. package/dist/op/work-lease-run.d.ts.map +1 -1
  193. package/dist/op/work-lease-run.js +56 -12
  194. package/dist/pr-forge.d.ts +10 -0
  195. package/dist/pr-forge.d.ts.map +1 -1
  196. package/dist/pr-forge.js +39 -0
  197. package/dist/pr-loop.d.ts +155 -7
  198. package/dist/pr-loop.d.ts.map +1 -1
  199. package/dist/pr-loop.js +137 -11
  200. package/dist/pr-report-url.d.ts +4 -4
  201. package/dist/pr-report-url.d.ts.map +1 -1
  202. package/dist/pr-report-url.js +5 -5
  203. package/dist/runner-start.d.ts +179 -0
  204. package/dist/runner-start.d.ts.map +1 -0
  205. package/dist/runner-start.js +277 -0
  206. package/dist/ts-loader.d.ts +38 -4
  207. package/dist/ts-loader.d.ts.map +1 -1
  208. package/dist/ts-loader.js +190 -16
  209. package/dist/wave-runtime.mjs +238 -231
  210. package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts +34 -0
  211. package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts.map +1 -0
  212. package/dist/workspace/chant-migrations/fountain-retired-kinds.js +176 -0
  213. package/dist/workspace/chant-migrations.d.ts.map +1 -1
  214. package/dist/workspace/chant-migrations.js +2 -0
  215. package/dist/workspace/check.schema.json +70 -2
  216. package/dist/workspace/checks/boxes.d.ts +6 -6
  217. package/dist/workspace/checks/boxes.js +9 -9
  218. package/dist/workspace/checks/security.d.ts +35 -0
  219. package/dist/workspace/checks/security.d.ts.map +1 -0
  220. package/dist/workspace/checks/security.js +305 -0
  221. package/dist/workspace/checks.d.ts +2 -0
  222. package/dist/workspace/checks.d.ts.map +1 -1
  223. package/dist/workspace/checks.js +5 -0
  224. package/dist/workspace/ci-builds.d.ts +163 -0
  225. package/dist/workspace/ci-builds.d.ts.map +1 -0
  226. package/dist/workspace/ci-builds.js +315 -0
  227. package/dist/workspace/ci-green-cli.d.ts +2 -1
  228. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  229. package/dist/workspace/ci-green-cli.js +25 -5
  230. package/dist/workspace/ci-green-forge.d.ts +18 -4
  231. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  232. package/dist/workspace/ci-green-forge.js +12 -0
  233. package/dist/workspace/ci-green-workflow.d.ts +55 -1
  234. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  235. package/dist/workspace/ci-green-workflow.js +128 -1
  236. package/dist/workspace/ci-green.d.ts +117 -16
  237. package/dist/workspace/ci-green.d.ts.map +1 -1
  238. package/dist/workspace/ci-green.js +358 -43
  239. package/dist/workspace/ci-last-green.schema.json +49 -0
  240. package/dist/workspace/ci-list.schema.json +47 -7
  241. package/dist/workspace/ci-report-url.d.ts +18 -0
  242. package/dist/workspace/ci-report-url.d.ts.map +1 -0
  243. package/dist/workspace/ci-report-url.js +33 -0
  244. package/dist/workspace/ci-run-index.d.ts +13 -1
  245. package/dist/workspace/ci-run-index.d.ts.map +1 -1
  246. package/dist/workspace/ci-run-index.js +6 -4
  247. package/dist/workspace/ci-run-index.schema.json +6 -4
  248. package/dist/workspace/ci-run.d.ts +85 -6
  249. package/dist/workspace/ci-run.d.ts.map +1 -1
  250. package/dist/workspace/ci-run.js +262 -64
  251. package/dist/workspace/ci-runner-key.d.ts +16 -3
  252. package/dist/workspace/ci-runner-key.d.ts.map +1 -1
  253. package/dist/workspace/ci-runner-key.js +30 -10
  254. package/dist/workspace/ci-runner-start.d.ts +77 -0
  255. package/dist/workspace/ci-runner-start.d.ts.map +1 -0
  256. package/dist/workspace/ci-runner-start.js +185 -0
  257. package/dist/workspace/ci-serve.d.ts +130 -11
  258. package/dist/workspace/ci-serve.d.ts.map +1 -1
  259. package/dist/workspace/ci-serve.js +323 -40
  260. package/dist/workspace/declaration.d.ts +25 -0
  261. package/dist/workspace/declaration.d.ts.map +1 -1
  262. package/dist/workspace/declaration.js +14 -2
  263. package/dist/workspace/declaration.schema.json +30 -2
  264. package/dist/workspace/export.d.ts +1 -1
  265. package/dist/workspace/export.d.ts.map +1 -1
  266. package/dist/workspace/export.js +7 -3
  267. package/dist/workspace/ls.d.ts +8 -1
  268. package/dist/workspace/ls.d.ts.map +1 -1
  269. package/dist/workspace/ls.js +2 -1
  270. package/dist/workspace/ls.schema.json +9 -2
  271. package/dist/workspace/member-pipeline.d.ts +1 -0
  272. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  273. package/dist/workspace/member-pipeline.js +2 -0
  274. package/dist/workspace/merge-record.schema.json +49 -0
  275. package/dist/workspace/pin-integrity.d.ts.map +1 -1
  276. package/dist/workspace/pin-integrity.js +3 -2
  277. package/dist/workspace/pr-report.schema.json +75 -8
  278. package/dist/workspace/reason-codes.d.ts +18 -1
  279. package/dist/workspace/reason-codes.d.ts.map +1 -1
  280. package/dist/workspace/reason-codes.js +20 -2
  281. package/dist/workspace/release-candidates.d.ts +129 -0
  282. package/dist/workspace/release-candidates.d.ts.map +1 -0
  283. package/dist/workspace/release-candidates.js +233 -0
  284. package/dist/workspace/release-candidates.schema.json +353 -0
  285. package/dist/workspace/run-event.schema.json +3 -1
  286. package/dist/workspace/security.d.ts +40 -0
  287. package/dist/workspace/security.d.ts.map +1 -0
  288. package/dist/workspace/security.js +99 -0
  289. package/dist/workspace/status.schema.json +3 -1
  290. package/dist/workspace/write-scope.d.ts +9 -0
  291. package/dist/workspace/write-scope.d.ts.map +1 -1
  292. package/dist/workspace/write-scope.js +11 -1
  293. package/package.json +8 -1
  294. package/src/__fixtures__/pr-loop/pr-apply-wave-waiting.note.golden.md +48 -0
  295. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +1 -1
  296. package/src/ci-jobs.ts +11 -2
  297. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +3 -3
  298. package/src/cli/commands/audit.test.ts +2 -2
  299. package/src/cli/commands/check-lexicon-plugin.test.ts +9 -0
  300. package/src/cli/commands/check-lexicon-plugin.ts +11 -8
  301. package/src/cli/commands/check-lexicon.test.ts +1 -1
  302. package/src/cli/commands/check-lexicon.ts +16 -11
  303. package/src/cli/commands/import.ts +40 -0
  304. package/src/cli/commands/init-lexicon/templates/project.ts +4 -3
  305. package/src/cli/commands/init-lexicon.test.ts +8 -5
  306. package/src/cli/commands/onboard.test.ts +45 -0
  307. package/src/cli/commands/onboard.ts +8 -4
  308. package/src/cli/commands/update.test.ts +6 -0
  309. package/src/cli/commands/update.ts +4 -1
  310. package/src/cli/compiled-cli.e2e.test.ts +76 -11
  311. package/src/cli/dependencies.e2e.test.ts +101 -0
  312. package/src/cli/dependencies.test.ts +93 -0
  313. package/src/cli/dependencies.ts +122 -0
  314. package/src/cli/handlers/build.test.ts +105 -0
  315. package/src/cli/handlers/build.ts +35 -4
  316. package/src/cli/handlers/fan-out.test.ts +73 -0
  317. package/src/cli/handlers/fan-out.ts +11 -4
  318. package/src/cli/handlers/graph.test.ts +76 -0
  319. package/src/cli/handlers/graph.ts +19 -12
  320. package/src/cli/handlers/lifecycle-health.test.ts +123 -0
  321. package/src/cli/handlers/lifecycle-health.ts +157 -0
  322. package/src/cli/handlers/lifecycle.ts +1 -1
  323. package/src/cli/handlers/lint.test.ts +42 -0
  324. package/src/cli/handlers/lint.ts +6 -0
  325. package/src/cli/handlers/operator.ts +3 -3
  326. package/src/cli/handlers/pr-deploy-inputs.test.ts +209 -0
  327. package/src/cli/handlers/pr-record.test.ts +201 -0
  328. package/src/cli/handlers/pr-waves.test.ts +449 -0
  329. package/src/cli/handlers/pr.test.ts +156 -0
  330. package/src/cli/handlers/pr.ts +648 -33
  331. package/src/cli/handlers/promote.test.ts +43 -1
  332. package/src/cli/handlers/promote.ts +19 -3
  333. package/src/cli/handlers/release-cut-at.e2e.test.ts +115 -0
  334. package/src/cli/handlers/release-publish-targets.e2e.test.ts +2 -2
  335. package/src/cli/handlers/release-verify.e2e.test.ts +12 -10
  336. package/src/cli/handlers/release.e2e.test.ts +19 -28
  337. package/src/cli/handlers/release.ts +81 -11
  338. package/src/cli/handlers/run-components-exit.test.ts +99 -0
  339. package/src/cli/handlers/run-signer.test.ts +79 -0
  340. package/src/cli/handlers/run.ts +34 -16
  341. package/src/cli/main.test.ts +18 -0
  342. package/src/cli/main.ts +120 -33
  343. package/src/cli/parse-args.ts +28 -0
  344. package/src/cli/registry.ts +35 -8
  345. package/src/codegen/generate-post-synth-barrel.ts +2 -2
  346. package/src/codegen/lexicon-regen.ts +1 -1
  347. package/src/codegen/pinned-upgrade.ts +2 -2
  348. package/src/codegen/post-synth-barrel-guards.test.ts +6 -11
  349. package/src/components/capability.ts +51 -3
  350. package/src/components/changed-files.test.ts +16 -1
  351. package/src/components/changed-files.ts +9 -1
  352. package/src/components/deploy-inputs.test.ts +108 -0
  353. package/src/components/deploy-inputs.ts +225 -0
  354. package/src/components/driver.test.ts +36 -1
  355. package/src/components/driver.ts +87 -4
  356. package/src/components/fan-out-record.ts +29 -1
  357. package/src/components/fan-out-run.test.ts +35 -0
  358. package/src/components/fan-out-run.ts +40 -1
  359. package/src/components/gate-plan.ts +9 -0
  360. package/src/components/pr-pipeline.test.ts +100 -0
  361. package/src/components/pr-pipeline.ts +184 -28
  362. package/src/components/pr-run.test.ts +323 -18
  363. package/src/components/pr-run.ts +355 -76
  364. package/src/components/release-compile.test.ts +34 -0
  365. package/src/components/release-compile.ts +89 -8
  366. package/src/components/release-promote.test.ts +55 -2
  367. package/src/components/release-promote.ts +93 -23
  368. package/src/components/verbs/bom-writer.ts +1 -1
  369. package/src/components/verbs/lockfile-sbom-generator.test.ts +36 -0
  370. package/src/components/verbs/lockfile-sbom-generator.ts +43 -5
  371. package/src/components/wave-plan.ts +48 -8
  372. package/src/discovery/fold-host-method.test.ts +87 -0
  373. package/src/discovery/fold-import.ts +15 -5
  374. package/src/discovery/fold-package-composite.test.ts +27 -0
  375. package/src/discovery/fold-specifiers.test.ts +8 -0
  376. package/src/discovery/sandbox/bundle.ts +6 -0
  377. package/src/discovery/specifier-resolve.ts +8 -2
  378. package/src/fold/fold.test.ts +72 -0
  379. package/src/fold/fold.ts +71 -0
  380. package/src/fold/subset.test.ts +31 -0
  381. package/src/fold/subset.ts +99 -0
  382. package/src/graph-detail.test.ts +57 -0
  383. package/src/graph-detail.ts +33 -7
  384. package/src/health.schema.json +191 -0
  385. package/src/health.test.ts +62 -0
  386. package/src/health.ts +178 -0
  387. package/src/lexicon-dist.e2e.test.ts +254 -0
  388. package/src/lexicon-module.test.ts +47 -0
  389. package/src/lexicon-module.ts +49 -7
  390. package/src/lexicon-plugin-helpers.ts +6 -4
  391. package/src/lexicon.ts +43 -1
  392. package/src/lifecycle/affected.test.ts +7 -0
  393. package/src/lifecycle/affected.ts +6 -1
  394. package/src/lifecycle/merge-record.test.ts +111 -0
  395. package/src/lifecycle/merge-record.ts +154 -0
  396. package/src/lifecycle/publish-attachments.ts +25 -13
  397. package/src/lifecycle/publish-npm.ts +4 -3
  398. package/src/lifecycle/publish-targets.test.ts +34 -4
  399. package/src/lifecycle/release-at.test.ts +48 -0
  400. package/src/lifecycle/release-at.ts +100 -0
  401. package/src/lifecycle/release-cut.test.ts +41 -0
  402. package/src/lifecycle/release-cut.ts +22 -11
  403. package/src/lifecycle/release-ledger.ts +34 -0
  404. package/src/lifecycle/release-publish.test.ts +43 -13
  405. package/src/lifecycle/release-publish.ts +38 -18
  406. package/src/lifecycle/release-store.ts +57 -13
  407. package/src/lifecycle/run-ledger.test.ts +13 -0
  408. package/src/lifecycle/run-ledger.ts +1 -0
  409. package/src/lifecycle/work-dir.test.ts +77 -0
  410. package/src/lifecycle/work-dir.ts +82 -0
  411. package/src/lint/discover.test.ts +46 -2
  412. package/src/lint/discover.ts +55 -49
  413. package/src/lint/rules/op/index.ts +4 -2
  414. package/src/lint/rules/op/ops018-shell-image-digest.test.ts +60 -0
  415. package/src/lint/rules/op/ops018-shell-image-digest.ts +48 -0
  416. package/src/module-source.test.ts +85 -0
  417. package/src/module-source.ts +112 -0
  418. package/src/op/activities/activity-contracts.ts +3 -0
  419. package/src/op/activities/factory.ts +1 -1
  420. package/src/op/activities/shell-container.e2e.test.ts +67 -0
  421. package/src/op/activities/shell.test.ts +44 -1
  422. package/src/op/activities/shell.ts +110 -3
  423. package/src/op/builders.ts +7 -0
  424. package/src/op/discover-root.test.ts +31 -2
  425. package/src/op/discover.ts +14 -4
  426. package/src/op/gate.test.ts +30 -0
  427. package/src/op/gate.ts +3 -0
  428. package/src/op/op-waves-run.ts +20 -5
  429. package/src/op/op-waves.test.ts +49 -0
  430. package/src/op/operator.ts +2 -2
  431. package/src/op/runtime.ts +2 -0
  432. package/src/op/step-console.test.ts +4 -2
  433. package/src/op/steward.ts +6 -4
  434. package/src/op/work-lease-run.test.ts +88 -2
  435. package/src/op/work-lease-run.ts +52 -12
  436. package/src/pr-forge-bundle.test.ts +2 -2
  437. package/src/pr-forge.test.ts +42 -0
  438. package/src/pr-forge.ts +40 -0
  439. package/src/pr-loop-bundle.test.ts +2 -1
  440. package/src/pr-loop.test.ts +146 -1
  441. package/src/pr-loop.ts +278 -17
  442. package/src/pr-report-url.ts +7 -7
  443. package/src/runner-start-bundle.test.ts +29 -0
  444. package/src/runner-start.test.ts +179 -0
  445. package/src/runner-start.ts +329 -0
  446. package/src/terraform/__fixtures__/advise.test.ts +21 -2
  447. package/src/ts-loader.test.ts +89 -1
  448. package/src/ts-loader.ts +180 -13
  449. package/src/workspace/changes.test.ts +1 -1
  450. package/src/workspace/chant-migrations/fountain-retired-kinds.test.ts +33 -0
  451. package/src/workspace/chant-migrations/fountain-retired-kinds.ts +190 -0
  452. package/src/workspace/chant-migrations.e2e.test.ts +5 -0
  453. package/src/workspace/chant-migrations.ts +2 -0
  454. package/src/workspace/check-contract.test.ts +3 -2
  455. package/src/workspace/check.schema.json +70 -2
  456. package/src/workspace/checks/boxes.ts +9 -9
  457. package/src/workspace/checks/security.test.ts +138 -0
  458. package/src/workspace/checks/security.ts +305 -0
  459. package/src/workspace/checks.ts +5 -0
  460. package/src/workspace/ci-builds.e2e.test.ts +208 -0
  461. package/src/workspace/ci-builds.test.ts +174 -0
  462. package/src/workspace/ci-builds.ts +385 -0
  463. package/src/workspace/ci-green-builds.test.ts +180 -0
  464. package/src/workspace/ci-green-cli.test.ts +54 -0
  465. package/src/workspace/ci-green-cli.ts +26 -5
  466. package/src/workspace/ci-green-forge.ts +30 -4
  467. package/src/workspace/ci-green-runs.test.ts +53 -11
  468. package/src/workspace/ci-green-workflow.test.ts +84 -1
  469. package/src/workspace/ci-green-workflow.ts +139 -2
  470. package/src/workspace/ci-green.test.ts +6 -3
  471. package/src/workspace/ci-green.ts +408 -48
  472. package/src/workspace/ci-last-green.schema.json +49 -0
  473. package/src/workspace/ci-list.schema.json +47 -7
  474. package/src/workspace/ci-report-url.test.ts +220 -0
  475. package/src/workspace/ci-report-url.ts +33 -0
  476. package/src/workspace/ci-run-index.schema.json +6 -4
  477. package/src/workspace/ci-run-index.test.ts +42 -3
  478. package/src/workspace/ci-run-index.ts +19 -5
  479. package/src/workspace/ci-run.test.ts +203 -8
  480. package/src/workspace/ci-run.ts +295 -63
  481. package/src/workspace/ci-runner-key.test.ts +55 -17
  482. package/src/workspace/ci-runner-key.ts +36 -11
  483. package/src/workspace/ci-runner-start.test.ts +151 -0
  484. package/src/workspace/ci-runner-start.ts +193 -0
  485. package/src/workspace/ci-serve-builds.test.ts +86 -0
  486. package/src/workspace/ci-serve.test.ts +209 -6
  487. package/src/workspace/ci-serve.ts +341 -42
  488. package/src/workspace/declaration.schema.json +30 -2
  489. package/src/workspace/declaration.test.ts +40 -0
  490. package/src/workspace/declaration.ts +40 -3
  491. package/src/workspace/export.ts +6 -3
  492. package/src/workspace/ls.schema.json +9 -2
  493. package/src/workspace/ls.ts +10 -4
  494. package/src/workspace/member-pipeline.ts +2 -1
  495. package/src/workspace/merge-record.schema.json +49 -0
  496. package/src/workspace/pin-integrity.test.ts +5 -0
  497. package/src/workspace/pin-integrity.ts +3 -2
  498. package/src/workspace/pr-report.schema.json +75 -8
  499. package/src/workspace/reason-codes.test.ts +2 -0
  500. package/src/workspace/reason-codes.ts +20 -2
  501. package/src/workspace/release-candidates.schema.json +353 -0
  502. package/src/workspace/release-candidates.test.ts +106 -0
  503. package/src/workspace/release-candidates.ts +315 -0
  504. package/src/workspace/run-event.schema.json +3 -1
  505. package/src/workspace/security.test.ts +70 -0
  506. package/src/workspace/security.ts +118 -0
  507. package/src/workspace/status.schema.json +3 -1
  508. package/src/workspace/write-scope.test.ts +29 -1
  509. package/src/workspace/write-scope.ts +12 -1
@@ -0,0 +1,179 @@
1
+ /**
2
+ * The runner-start statement (#4147): a provisioner's signed word that it
3
+ * started a runner for one CI job, which the job checks before it runs.
4
+ *
5
+ * A persistent self-hosted runner keeps files and processes between jobs,
6
+ * so a plan job that ran a pull request's code can leave something behind
7
+ * for the next apply. An apply job that requires this statement refuses to
8
+ * run, before it trades for any credentials, on a runner that no trusted
9
+ * provisioner says it started for this job.
10
+ *
11
+ * It differs from the Op-run statement (#4044, ./workspace/trust/op-run-statement.ts)
12
+ * in three ways. It is signed before the job runs, not when a run settles.
13
+ * The provisioner that starts the runner signs it, so the key never enters
14
+ * the job. And it names the CI job, run and attempt, so a statement issued
15
+ * for one job does not verify in another.
16
+ *
17
+ * The statement is an in-toto Statement v1 in a DSSE envelope
18
+ * (./workspace/trust/dsse.ts), signed with an Ed25519 key that
19
+ * `.chant/trust.json` lists under `runners`, whose principal holds the
20
+ * `runner` role there, the same keys and role a ci tag needs (#4031):
21
+ *
22
+ * - `subject`: the commit the job runs, by `digest.gitCommit`.
23
+ * - `predicate`: the signer's principal; `ci` with the system (`github`,
24
+ * `gitlab`, `forgejo`), the repository, and the run, attempt and job ids;
25
+ * `runner` with the runner's name and `singleJob: true`; and `issuedAt`.
26
+ *
27
+ * The job finds it in `CHANT_RUNNER_START` (the envelope's JSON) or in the
28
+ * file `CHANT_RUNNER_START_FILE` names, else in
29
+ * {@link DEFAULT_RUNNER_START_FILE}. The job's own ids come from the forge's
30
+ * variables ({@link ciJobFromEnv}).
31
+ *
32
+ * This module needs only `node:crypto` and `node:fs`, so a bundled stage can
33
+ * import it alone:
34
+ *
35
+ * ```ts
36
+ * import { verifyRunnerStartForJob } from "@intentius/chant/runner-start";
37
+ *
38
+ * const trust = JSON.parse(readFileSync(".chant/trust.json", "utf8"));
39
+ * const v = verifyRunnerStartForJob({ runners: trust.runners ?? [], roles: trust.roles ?? {} });
40
+ * if (v.status !== "verified") throw new Error(v.reason);
41
+ * ```
42
+ *
43
+ * `chant ci runner-start verify` and `chant ci run --require-runner-start`
44
+ * read the runners and roles from `.chant/trust.json` at base, which also
45
+ * drops a runner entry the signers file lists (./workspace/trust/policy.ts).
46
+ * A caller that passes trust.json's lists itself skips that check.
47
+ */
48
+ import type { KeyObject } from "node:crypto";
49
+ import { type DsseEnvelope } from "./workspace/trust/dsse.js";
50
+ export declare const RUNNER_START_PREDICATE = "https://intentius.io/chant/runner-start/v1";
51
+ /** The in-toto Statement v1 type, as ./workspace/trust/evidence.ts has it. */
52
+ declare const STATEMENT_TYPE = "https://in-toto.io/Statement/v1";
53
+ /** The role a runner-start statement's signer must hold in `.chant/trust.json`, as for a ci tag (#4031). */
54
+ export declare const RUNNER_START_SIGNER_ROLE = "runner";
55
+ /** The variable that holds the statement's envelope as JSON. */
56
+ export declare const RUNNER_START_ENV = "CHANT_RUNNER_START";
57
+ /** The variable that names a file holding the envelope, in place of {@link DEFAULT_RUNNER_START_FILE}. */
58
+ export declare const RUNNER_START_FILE_ENV = "CHANT_RUNNER_START_FILE";
59
+ /** Where the job looks for the envelope when neither variable is set. */
60
+ export declare const DEFAULT_RUNNER_START_FILE = "/run/chant/runner-start.json";
61
+ export type CiSystem = "github" | "gitlab" | "forgejo";
62
+ /** The CI job a runner was started for, or the job reading the statement. */
63
+ export interface CiJobIdentity {
64
+ system: CiSystem;
65
+ /** `owner/name` on GitHub and Forgejo, the project path on GitLab. */
66
+ repo: string;
67
+ /** The run: `GITHUB_RUN_ID`, or `CI_PIPELINE_ID` on GitLab. */
68
+ run: string;
69
+ /** The run's attempt: `GITHUB_RUN_ATTEMPT`. GitLab gives a retried job a new job id, so it is always `1` there. */
70
+ attempt: string;
71
+ /** The job: `GITHUB_JOB`, the job's key in the workflow, or `CI_JOB_ID` on GitLab. */
72
+ job: string;
73
+ /** The full commit id the job runs: `GITHUB_SHA`, or `CI_COMMIT_SHA`. */
74
+ commit: string;
75
+ /**
76
+ * The runner's name: `RUNNER_NAME` on GitHub and Forgejo. Required there,
77
+ * since `GITHUB_JOB` repeats across a matrix's jobs and the runner's name
78
+ * tells them apart. Not compared on GitLab, where `CI_JOB_ID` is unique.
79
+ */
80
+ runner?: string;
81
+ }
82
+ export interface RunnerStartStatement {
83
+ _type: typeof STATEMENT_TYPE;
84
+ subject: [{
85
+ name: string;
86
+ digest: {
87
+ gitCommit: string;
88
+ };
89
+ }];
90
+ predicateType: typeof RUNNER_START_PREDICATE;
91
+ predicate: {
92
+ signer: string;
93
+ ci: {
94
+ system: CiSystem;
95
+ repo: string;
96
+ run: string;
97
+ attempt: string;
98
+ job: string;
99
+ };
100
+ runner: {
101
+ name?: string;
102
+ singleJob: true;
103
+ };
104
+ issuedAt: string;
105
+ };
106
+ }
107
+ /** A key that may sign the statement, as `.chant/trust.json` lists it under `runners`. */
108
+ export interface RunnerStartKey {
109
+ principal: string;
110
+ /** `ssh-ed25519 <base64>`. */
111
+ key: string;
112
+ }
113
+ /** Whoever signs: the provisioner's key and the principal `.chant/trust.json` lists it for. */
114
+ export interface RunnerStartSigner {
115
+ principal: string;
116
+ key: KeyObject;
117
+ publicKey: string;
118
+ }
119
+ /** The job the forge's variables name, or why they name none. GitHub's names are also Forgejo's; `FORGEJO_ACTIONS` or `GITEA_ACTIONS` marks Forgejo, as in ./notify.ts. */
120
+ export declare function ciJobFromEnv(env?: Record<string, string | undefined>): {
121
+ ok: true;
122
+ job: CiJobIdentity;
123
+ } | {
124
+ ok: false;
125
+ reason: string;
126
+ };
127
+ /** The statement `signer` signs for a runner started for `job`. Throws for a job it cannot name. */
128
+ export declare function buildRunnerStartStatement(job: CiJobIdentity, signer: string, issuedAt?: Date): RunnerStartStatement;
129
+ /** The envelope the provisioner hands the runner, signed with its key. */
130
+ export declare function signRunnerStart(job: CiJobIdentity, signer: RunnerStartSigner, issuedAt?: Date): DsseEnvelope;
131
+ export type RunnerStartVerdict = {
132
+ status: "verified";
133
+ signer: string;
134
+ keyid: string;
135
+ issuedAt: string;
136
+ reason: string;
137
+ } | {
138
+ status: "missing" | "invalid" | "untrusted" | "mismatch" | "stale";
139
+ reason: string;
140
+ };
141
+ export interface VerifyRunnerStartInput {
142
+ /** The envelope, as JSON text or parsed. Undefined when the job found none. */
143
+ envelope: unknown;
144
+ /** The job reading it. */
145
+ job: CiJobIdentity;
146
+ /** `runners` from `.chant/trust.json` at base. */
147
+ runners: readonly RunnerStartKey[];
148
+ /** `roles` from `.chant/trust.json` at base. */
149
+ roles: Readonly<Record<string, readonly string[]>>;
150
+ /** Refuse a statement issued longer ago than this. Default: no limit, since a statement names one job attempt. */
151
+ maxAgeSeconds?: number;
152
+ now?: Date;
153
+ }
154
+ /**
155
+ * Verify a runner-start statement for `job`: a signature by a key listed
156
+ * under `runners` whose principal holds the `runner` role, over a statement
157
+ * for this system, repository, run, attempt, job, commit and, on GitHub and
158
+ * Forgejo, runner. Never throws.
159
+ */
160
+ export declare function verifyRunnerStart(input: VerifyRunnerStartInput): RunnerStartVerdict;
161
+ /** The envelope's JSON the job was given: `CHANT_RUNNER_START`, else the file `CHANT_RUNNER_START_FILE` names, else {@link DEFAULT_RUNNER_START_FILE}. Undefined when there is none. */
162
+ export declare function readRunnerStart(env?: Record<string, string | undefined>, readFile?: (path: string) => string): string | undefined;
163
+ /**
164
+ * One call for a job: find its statement ({@link readRunnerStart}), name the
165
+ * job from the forge's variables ({@link ciJobFromEnv}) and verify one
166
+ * against the other ({@link verifyRunnerStart}). Never throws.
167
+ */
168
+ export declare function verifyRunnerStartForJob(input: {
169
+ runners: readonly RunnerStartKey[];
170
+ roles: Readonly<Record<string, readonly string[]>>;
171
+ env?: Record<string, string | undefined>;
172
+ /** The commit the job runs, in place of the forge's variable. */
173
+ commit?: string;
174
+ readFile?: (path: string) => string;
175
+ maxAgeSeconds?: number;
176
+ now?: Date;
177
+ }): RunnerStartVerdict;
178
+ export {};
179
+ //# sourceMappingURL=runner-start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-start.d.ts","sourceRoot":"","sources":["../src/runner-start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * The runner-start statement (#4147): a provisioner's signed word that it
3
+ * started a runner for one CI job, which the job checks before it runs.
4
+ *
5
+ * A persistent self-hosted runner keeps files and processes between jobs,
6
+ * so a plan job that ran a pull request's code can leave something behind
7
+ * for the next apply. An apply job that requires this statement refuses to
8
+ * run, before it trades for any credentials, on a runner that no trusted
9
+ * provisioner says it started for this job.
10
+ *
11
+ * It differs from the Op-run statement (#4044, ./workspace/trust/op-run-statement.ts)
12
+ * in three ways. It is signed before the job runs, not when a run settles.
13
+ * The provisioner that starts the runner signs it, so the key never enters
14
+ * the job. And it names the CI job, run and attempt, so a statement issued
15
+ * for one job does not verify in another.
16
+ *
17
+ * The statement is an in-toto Statement v1 in a DSSE envelope
18
+ * (./workspace/trust/dsse.ts), signed with an Ed25519 key that
19
+ * `.chant/trust.json` lists under `runners`, whose principal holds the
20
+ * `runner` role there, the same keys and role a ci tag needs (#4031):
21
+ *
22
+ * - `subject`: the commit the job runs, by `digest.gitCommit`.
23
+ * - `predicate`: the signer's principal; `ci` with the system (`github`,
24
+ * `gitlab`, `forgejo`), the repository, and the run, attempt and job ids;
25
+ * `runner` with the runner's name and `singleJob: true`; and `issuedAt`.
26
+ *
27
+ * The job finds it in `CHANT_RUNNER_START` (the envelope's JSON) or in the
28
+ * file `CHANT_RUNNER_START_FILE` names, else in
29
+ * {@link DEFAULT_RUNNER_START_FILE}. The job's own ids come from the forge's
30
+ * variables ({@link ciJobFromEnv}).
31
+ *
32
+ * This module needs only `node:crypto` and `node:fs`, so a bundled stage can
33
+ * import it alone:
34
+ *
35
+ * ```ts
36
+ * import { verifyRunnerStartForJob } from "@intentius/chant/runner-start";
37
+ *
38
+ * const trust = JSON.parse(readFileSync(".chant/trust.json", "utf8"));
39
+ * const v = verifyRunnerStartForJob({ runners: trust.runners ?? [], roles: trust.roles ?? {} });
40
+ * if (v.status !== "verified") throw new Error(v.reason);
41
+ * ```
42
+ *
43
+ * `chant ci runner-start verify` and `chant ci run --require-runner-start`
44
+ * read the runners and roles from `.chant/trust.json` at base, which also
45
+ * drops a runner entry the signers file lists (./workspace/trust/policy.ts).
46
+ * A caller that passes trust.json's lists itself skips that check.
47
+ */
48
+ import { readFileSync } from "node:fs";
49
+ import { IN_TOTO_PAYLOAD_TYPE, signEnvelope, verifyEnvelope } from "./workspace/trust/dsse.js";
50
+ export const RUNNER_START_PREDICATE = "https://intentius.io/chant/runner-start/v1";
51
+ /** The in-toto Statement v1 type, as ./workspace/trust/evidence.ts has it. */
52
+ const STATEMENT_TYPE = "https://in-toto.io/Statement/v1";
53
+ /** The role a runner-start statement's signer must hold in `.chant/trust.json`, as for a ci tag (#4031). */
54
+ export const RUNNER_START_SIGNER_ROLE = "runner";
55
+ /** The variable that holds the statement's envelope as JSON. */
56
+ export const RUNNER_START_ENV = "CHANT_RUNNER_START";
57
+ /** The variable that names a file holding the envelope, in place of {@link DEFAULT_RUNNER_START_FILE}. */
58
+ export const RUNNER_START_FILE_ENV = "CHANT_RUNNER_START_FILE";
59
+ /** Where the job looks for the envelope when neither variable is set. */
60
+ export const DEFAULT_RUNNER_START_FILE = "/run/chant/runner-start.json";
61
+ const FULL_COMMIT = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
62
+ const SYSTEMS = ["github", "gitlab", "forgejo"];
63
+ /** The job the forge's variables name, or why they name none. GitHub's names are also Forgejo's; `FORGEJO_ACTIONS` or `GITEA_ACTIONS` marks Forgejo, as in ./notify.ts. */
64
+ export function ciJobFromEnv(env = process.env) {
65
+ const need = (names) => {
66
+ const missing = names.filter((n) => !env[n]);
67
+ return missing.length > 0 ? `the job's environment does not set ${missing.join(", ")}` : undefined;
68
+ };
69
+ if (env.GITLAB_CI === "true" || env.CI_PIPELINE_ID) {
70
+ const gap = need(["CI_PROJECT_PATH", "CI_PIPELINE_ID", "CI_JOB_ID", "CI_COMMIT_SHA"]);
71
+ if (gap)
72
+ return { ok: false, reason: gap };
73
+ return { ok: true, job: { system: "gitlab", repo: env.CI_PROJECT_PATH, run: env.CI_PIPELINE_ID, attempt: "1", job: env.CI_JOB_ID, commit: env.CI_COMMIT_SHA } };
74
+ }
75
+ if (env.GITHUB_ACTIONS === "true" || env.FORGEJO_ACTIONS === "true" || env.GITEA_ACTIONS === "true") {
76
+ const system = env.FORGEJO_ACTIONS === "true" || env.GITEA_ACTIONS === "true" ? "forgejo" : "github";
77
+ const gap = need(["GITHUB_REPOSITORY", "GITHUB_RUN_ID", "GITHUB_JOB", "GITHUB_SHA"]);
78
+ if (gap)
79
+ return { ok: false, reason: gap };
80
+ return {
81
+ ok: true,
82
+ job: {
83
+ system,
84
+ repo: env.GITHUB_REPOSITORY,
85
+ run: env.GITHUB_RUN_ID,
86
+ attempt: env.GITHUB_RUN_ATTEMPT || "1",
87
+ job: env.GITHUB_JOB,
88
+ commit: env.GITHUB_SHA,
89
+ ...(env.RUNNER_NAME ? { runner: env.RUNNER_NAME } : {}),
90
+ },
91
+ };
92
+ }
93
+ return { ok: false, reason: "this is not a GitHub, Forgejo or GitLab job: none of GITHUB_ACTIONS, FORGEJO_ACTIONS, GITEA_ACTIONS or GITLAB_CI is set" };
94
+ }
95
+ /** Why `job` cannot be signed for, or undefined. */
96
+ function jobProblem(job) {
97
+ if (!SYSTEMS.includes(job.system))
98
+ return `the CI system is ${JSON.stringify(job.system)}, not github, gitlab or forgejo`;
99
+ for (const field of ["repo", "run", "attempt", "job"]) {
100
+ if (typeof job[field] !== "string" || job[field].length === 0)
101
+ return `the job names no ${field}`;
102
+ }
103
+ if (!FULL_COMMIT.test(job.commit))
104
+ return `the job's commit ${JSON.stringify(job.commit)} is not a full commit id`;
105
+ if (job.system !== "gitlab" && !job.runner)
106
+ return `a ${job.system} job needs the runner's name, since GITHUB_JOB repeats across a matrix's jobs`;
107
+ return undefined;
108
+ }
109
+ /** The statement `signer` signs for a runner started for `job`. Throws for a job it cannot name. */
110
+ export function buildRunnerStartStatement(job, signer, issuedAt = new Date()) {
111
+ const problem = jobProblem(job);
112
+ if (problem)
113
+ throw new Error(`no runner-start statement: ${problem}`);
114
+ return {
115
+ _type: STATEMENT_TYPE,
116
+ subject: [{ name: job.commit, digest: { gitCommit: job.commit } }],
117
+ predicateType: RUNNER_START_PREDICATE,
118
+ predicate: {
119
+ signer,
120
+ ci: { system: job.system, repo: job.repo, run: job.run, attempt: job.attempt, job: job.job },
121
+ runner: { ...(job.runner ? { name: job.runner } : {}), singleJob: true },
122
+ issuedAt: issuedAt.toISOString(),
123
+ },
124
+ };
125
+ }
126
+ /** The envelope the provisioner hands the runner, signed with its key. */
127
+ export function signRunnerStart(job, signer, issuedAt = new Date()) {
128
+ const statement = buildRunnerStartStatement(job, signer.principal, issuedAt);
129
+ return signEnvelope(IN_TOTO_PAYLOAD_TYPE, Buffer.from(JSON.stringify(statement), "utf8"), signer.key, signer.publicKey);
130
+ }
131
+ const normalise = (name) => name.normalize("NFKC").trim().toLowerCase();
132
+ const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
133
+ const onlyKeys = (v, keys) => Object.keys(v).every((k) => keys.includes(k));
134
+ const isText = (v) => typeof v === "string" && v.length > 0;
135
+ /** The statement in `raw`, or why it is not one. Strict, so a verifier never acts on a field it does not know. */
136
+ function parseStatement(raw) {
137
+ if (!isObject(raw) || !onlyKeys(raw, ["_type", "subject", "predicateType", "predicate"]))
138
+ return "not a statement with only _type, subject, predicateType and predicate";
139
+ if (raw._type !== STATEMENT_TYPE)
140
+ return `_type is not ${STATEMENT_TYPE}`;
141
+ if (raw.predicateType !== RUNNER_START_PREDICATE)
142
+ return `predicateType is not ${RUNNER_START_PREDICATE}`;
143
+ const subject = raw.subject;
144
+ if (!Array.isArray(subject) || subject.length !== 1)
145
+ return "subject is not one commit";
146
+ const s = subject[0];
147
+ if (!isObject(s) || !onlyKeys(s, ["name", "digest"]) || !isObject(s.digest) || !onlyKeys(s.digest, ["gitCommit"]))
148
+ return "subject is not one commit";
149
+ if (typeof s.name !== "string" || !FULL_COMMIT.test(s.name) || s.digest.gitCommit !== s.name)
150
+ return "the subject is not a full commit id named by itself";
151
+ const p = raw.predicate;
152
+ if (!isObject(p) || !onlyKeys(p, ["signer", "ci", "runner", "issuedAt"]))
153
+ return "predicate has fields other than signer, ci, runner and issuedAt";
154
+ if (!isText(p.signer))
155
+ return "predicate.signer is missing";
156
+ const ci = p.ci;
157
+ if (!isObject(ci) || !onlyKeys(ci, ["system", "repo", "run", "attempt", "job"]))
158
+ return "predicate.ci has fields other than system, repo, run, attempt and job";
159
+ if (!SYSTEMS.includes(ci.system))
160
+ return "predicate.ci.system is not github, gitlab or forgejo";
161
+ for (const field of ["repo", "run", "attempt", "job"])
162
+ if (!isText(ci[field]))
163
+ return `predicate.ci.${field} is missing`;
164
+ const runner = p.runner;
165
+ if (!isObject(runner) || !onlyKeys(runner, ["name", "singleJob"]) || runner.singleJob !== true)
166
+ return "predicate.runner does not say singleJob: true";
167
+ if (runner.name !== undefined && !isText(runner.name))
168
+ return "predicate.runner.name is not a name";
169
+ if (!isText(p.issuedAt) || Number.isNaN(Date.parse(p.issuedAt)))
170
+ return "predicate.issuedAt is not a time";
171
+ return raw;
172
+ }
173
+ /**
174
+ * Verify a runner-start statement for `job`: a signature by a key listed
175
+ * under `runners` whose principal holds the `runner` role, over a statement
176
+ * for this system, repository, run, attempt, job, commit and, on GitHub and
177
+ * Forgejo, runner. Never throws.
178
+ */
179
+ export function verifyRunnerStart(input) {
180
+ const { job } = input;
181
+ const what = `the ${job.system} job ${job.job} of run ${job.run} (attempt ${job.attempt})`;
182
+ if (input.envelope === undefined || input.envelope === null || input.envelope === "") {
183
+ return { status: "missing", reason: `${what} has no runner-start statement: no provisioner says this runner was started for it` };
184
+ }
185
+ let envelope = input.envelope;
186
+ if (typeof envelope === "string") {
187
+ try {
188
+ envelope = JSON.parse(envelope);
189
+ }
190
+ catch {
191
+ return { status: "invalid", reason: `${what}: the runner-start statement is not JSON` };
192
+ }
193
+ }
194
+ const v = verifyEnvelope(envelope, input.runners);
195
+ if (!v.ok)
196
+ return { status: v.code === "envelope-untrusted" ? "untrusted" : "invalid", reason: `${what}: ${v.reason}` };
197
+ if (!(input.roles[RUNNER_START_SIGNER_ROLE] ?? []).some((p) => normalise(p) === normalise(v.principal))) {
198
+ return { status: "untrusted", reason: `${what}: the statement is signed by ${v.principal}'s key, and ${v.principal} holds no ${RUNNER_START_SIGNER_ROLE} role in .chant/trust.json at base` };
199
+ }
200
+ if (v.payloadType !== IN_TOTO_PAYLOAD_TYPE)
201
+ return { status: "invalid", reason: `${what}: payload type ${v.payloadType} is not ${IN_TOTO_PAYLOAD_TYPE}` };
202
+ let raw;
203
+ try {
204
+ raw = JSON.parse(v.payload.toString("utf8"));
205
+ }
206
+ catch {
207
+ return { status: "invalid", reason: `${what}: the statement's payload is not JSON` };
208
+ }
209
+ const parsed = parseStatement(raw);
210
+ if (typeof parsed === "string")
211
+ return { status: "invalid", reason: `${what}: the payload is not a ${RUNNER_START_PREDICATE} statement: ${parsed}` };
212
+ const p = parsed.predicate;
213
+ if (p.signer !== v.principal)
214
+ return { status: "invalid", reason: `${what}: the statement names signer ${JSON.stringify(p.signer)}, but ${v.principal}'s key signed it` };
215
+ const differs = [];
216
+ if (p.ci.system !== job.system)
217
+ differs.push(`it is for a ${p.ci.system} job`);
218
+ if (p.ci.repo !== job.repo)
219
+ differs.push(`it is for repository ${p.ci.repo}`);
220
+ if (p.ci.run !== job.run)
221
+ differs.push(`it is for run ${p.ci.run}`);
222
+ if (p.ci.attempt !== job.attempt)
223
+ differs.push(`it is for attempt ${p.ci.attempt}`);
224
+ if (p.ci.job !== job.job)
225
+ differs.push(`it is for job ${p.ci.job}`);
226
+ const commit = parsed.subject[0].name;
227
+ if (commit !== job.commit)
228
+ differs.push(`it is for commit ${commit.slice(0, 12)}, and the job runs ${job.commit.slice(0, 12)}`);
229
+ if (job.system !== "gitlab") {
230
+ if (!p.runner.name)
231
+ differs.push("it names no runner, and a job id alone does not tell a matrix's jobs apart");
232
+ else if (!job.runner)
233
+ differs.push(`it is for runner ${p.runner.name}, and the job's environment names no runner (RUNNER_NAME)`);
234
+ else if (p.runner.name !== job.runner)
235
+ differs.push(`it is for runner ${p.runner.name}, and this is ${job.runner}`);
236
+ }
237
+ if (differs.length > 0)
238
+ return { status: "mismatch", reason: `${what}: the runner-start statement signed by ${v.principal} is for another job: ${differs.join("; ")}` };
239
+ if (input.maxAgeSeconds !== undefined) {
240
+ const age = ((input.now ?? new Date()).getTime() - Date.parse(p.issuedAt)) / 1000;
241
+ if (age > input.maxAgeSeconds)
242
+ return { status: "stale", reason: `${what}: the runner-start statement was issued ${Math.round(age)}s ago, more than ${input.maxAgeSeconds}s` };
243
+ }
244
+ return { status: "verified", signer: v.principal, keyid: v.keyid, issuedAt: p.issuedAt, reason: `runner started for this job, signed by ${v.principal} (${RUNNER_START_SIGNER_ROLE})` };
245
+ }
246
+ /** The envelope's JSON the job was given: `CHANT_RUNNER_START`, else the file `CHANT_RUNNER_START_FILE` names, else {@link DEFAULT_RUNNER_START_FILE}. Undefined when there is none. */
247
+ export function readRunnerStart(env = process.env, readFile = (p) => readFileSync(p, "utf8")) {
248
+ const inline = env[RUNNER_START_ENV];
249
+ if (inline)
250
+ return inline;
251
+ try {
252
+ return readFile(env[RUNNER_START_FILE_ENV] || DEFAULT_RUNNER_START_FILE);
253
+ }
254
+ catch {
255
+ return undefined;
256
+ }
257
+ }
258
+ /**
259
+ * One call for a job: find its statement ({@link readRunnerStart}), name the
260
+ * job from the forge's variables ({@link ciJobFromEnv}) and verify one
261
+ * against the other ({@link verifyRunnerStart}). Never throws.
262
+ */
263
+ export function verifyRunnerStartForJob(input) {
264
+ const env = input.env ?? process.env;
265
+ const named = ciJobFromEnv(env);
266
+ if (!named.ok)
267
+ return { status: "missing", reason: `no job to check a runner-start statement for: ${named.reason}` };
268
+ const job = input.commit ? { ...named.job, commit: input.commit } : named.job;
269
+ return verifyRunnerStart({
270
+ envelope: readRunnerStart(env, input.readFile),
271
+ job,
272
+ runners: input.runners,
273
+ roles: input.roles,
274
+ ...(input.maxAgeSeconds !== undefined ? { maxAgeSeconds: input.maxAgeSeconds } : {}),
275
+ ...(input.now ? { now: input.now } : {}),
276
+ });
277
+ }
@@ -18,14 +18,31 @@
18
18
  *
19
19
  * Run from source (the repository's `bin/chant` through tsx, vitest), this
20
20
  * module is itself TypeScript, the TypeScript loader is already there, and
21
- * both functions do nothing.
21
+ * both functions do nothing, except that {@link installCompiledCli} resolves
22
+ * chant's packages to their source (#3981, {@link installSourceResolution}).
22
23
  */
23
24
  /**
24
25
  * Called once by the CLI's `main()`. Compiled, it records that TypeScript
25
- * loads lazily and installs the `src/*.ts` to `dist/*.js` redirect; from
26
- * source it does nothing.
26
+ * loads lazily and installs the `src/*.ts` to `dist/*.js` redirect. From
27
+ * source it installs {@link installSourceResolution}.
27
28
  */
28
29
  export declare function installCompiledCli(): void;
30
+ /**
31
+ * #3981 — the compiled module for a lexicon's `src/*.ts`: `<lexicon>/dist/*.js`
32
+ * when it exists, as a URL, else `undefined`. A lexicon ships both, and its
33
+ * exports name the compiled one; fold reads a composite from the source, and
34
+ * an import that source makes must land on the module the plugin and the
35
+ * project already loaded, with no TypeScript loader.
36
+ */
37
+ export declare function lexiconCompiledTwin(url: string): string | undefined;
38
+ /**
39
+ * #3981 — the `development` target a chant package's `exports` give
40
+ * `specifier`, found from `parentPath`'s directory up through each
41
+ * `node_modules`, or `undefined` when there is none or its file does not
42
+ * exist. Reads exact keys and single-`*` patterns, the shapes chant's
43
+ * packages use; anything else is left to Node.
44
+ */
45
+ export declare function chantPackageSourceTarget(specifier: string, parentPath: string): string | undefined;
29
46
  /**
30
47
  * Register tsx for the ESM and CommonJS loaders, once, before importing
31
48
  * anything that may be TypeScript. A no-op from source, where tsx (or vitest)
@@ -34,13 +51,30 @@ export declare function installCompiledCli(): void;
34
51
  * CommonJS hook from source knows not to add a second one.
35
52
  */
36
53
  export declare function ensureTypeScriptLoader(): boolean;
54
+ /**
55
+ * #3981 — register tsx only when the module about to be imported is not
56
+ * JavaScript. `pathOrUrl` is the resolved module, a path or a file URL. A
57
+ * compiled lexicon (`dist/*.js`) imports with plain node, so a command that
58
+ * loads only compiled modules never pays for tsx's hooks thread. A `.ts`
59
+ * module, or one with no extension, registers tsx as before. Returns what
60
+ * {@link ensureTypeScriptLoader} does, or whether tsx is already registered
61
+ * when the module is JavaScript.
62
+ */
63
+ export declare function ensureTypeScriptLoaderFor(pathOrUrl: string): boolean;
64
+ /**
65
+ * #3981 — whether a caller about to import a module of unknown kind should
66
+ * resolve it first: true only in the compiled CLI before tsx is registered.
67
+ * From source, and once tsx is in, every module loads either way.
68
+ */
69
+ export declare function typeScriptLoaderPending(): boolean;
37
70
  /**
38
71
  * The source directory for a module of chant's own: `dirname` of `moduleUrl`
39
72
  * from source, and the matching directory under `<package>/src` when the
40
73
  * module runs from `<package>/dist`. The sandbox drivers hand chant's own
41
74
  * modules to esbuild by path, and must name the TypeScript source the
42
75
  * project's own `@intentius/chant/*` imports resolve to. String arithmetic
43
- * only: no filesystem access, so it is safe inside a sandboxed child.
76
+ * only: no filesystem access, so it is safe inside a sandboxed child. The
77
+ * same mapping as {@link moduleSourceDir}, which lexicons use.
44
78
  */
45
79
  export declare function chantSourceDir(moduleUrl: string): string;
46
80
  //# sourceMappingURL=ts-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ts-loader.d.ts","sourceRoot":"","sources":["../src/ts-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAoCH;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAwBzC;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAShD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOxD"}
1
+ {"version":3,"file":"ts-loader.d.ts","sourceRoot":"","sources":["../src/ts-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAqCH;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CA+BzC;AAkCD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUnE;AAID;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA0ClG;AAoCD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAShD;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGpE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAGjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD"}