@kungfu-tech/buildchain 4.1.0-alpha.0 → 4.1.0-alpha.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 (292) hide show
  1. package/AGENTS.md +30 -41
  2. package/CONTRIBUTING.md +6 -7
  3. package/architecture/action-taxonomy.json +5 -21
  4. package/architecture/agent-change-map.md +74 -56
  5. package/architecture/build-orchestration.json +8 -1
  6. package/architecture/ci-lane-change-budget.json +179 -69
  7. package/architecture/floating-consumer-policy.json +7 -17
  8. package/architecture/internal-capabilities.json +58 -72
  9. package/architecture/maintainability-debt.json +138 -52
  10. package/architecture/maintainability-policy.json +6 -15
  11. package/architecture/promotion-job-topology.json +39 -20
  12. package/architecture/release-topology.json +26 -37
  13. package/architecture/runtime-entry.json +26 -0
  14. package/architecture/runtime-resume-lineage.json +23 -0
  15. package/architecture/stage-capsule-qualification.json +2 -2
  16. package/architecture/universal-workflow-bootstrap.json +10 -25
  17. package/architecture/universal-workflow-capability-policy.json +61 -0
  18. package/architecture/universal-workflow-fault-campaign.json +18 -24
  19. package/architecture/workflow-taxonomy.json +0 -11
  20. package/contracts/fixtures/{v4-runtime-ref-resume-authority-v1 → runtime-resume-lineage-v2}/scenario.json +2 -3
  21. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +2 -2
  22. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  23. package/contracts/promotion-invocation-v1.schema.json +0 -44
  24. package/contracts/promotion-request-v1.schema.json +0 -39
  25. package/contracts/runtime-resume-lineage-v2.schema.json +182 -0
  26. package/dist/site/buildchain-contract.json +472 -361
  27. package/dist/site/buildchain-site.json +99 -99
  28. package/dist/site/capability-registry.json +3 -3
  29. package/dist/site/cli-registry.json +4 -4
  30. package/dist/site/controller-registry.json +94 -78
  31. package/dist/site/kfd-claims.json +224 -343
  32. package/dist/site/kfd-upstream-aggregate.json +1 -1
  33. package/dist/site/manual-registry.json +15 -15
  34. package/dist/site/node-api-registry.json +239 -354
  35. package/dist/site/page-registry.json +80 -80
  36. package/dist/site/public-surface-audit.json +203 -254
  37. package/dist/site/publication-authority-registry.json +1 -24
  38. package/dist/site/publication-registry.json +4 -4
  39. package/dist/site/release-provenance.json +1 -1
  40. package/dist/site/site-manifest.json +19 -19
  41. package/dist/site/workflow-registry.json +197 -357
  42. package/docs/MAP.md +3 -3
  43. package/docs/auditable-demo.md +4 -4
  44. package/docs/cli-reference.md +2 -2
  45. package/docs/code-organization.md +5 -4
  46. package/docs/controller-evidence.md +2 -2
  47. package/docs/dev-alpha-candidate-patrol.md +5 -5
  48. package/docs/dev-delivery-warrant.md +14 -24
  49. package/docs/engineering-housekeeper.md +3 -3
  50. package/docs/github-artifact-attestation.md +9 -12
  51. package/docs/github-governance-authority.md +4 -4
  52. package/docs/node-api-reference.md +153 -167
  53. package/docs/publication-artifacts.md +3 -4
  54. package/docs/publication-authority.md +2 -2
  55. package/docs/release-candidate.md +21 -27
  56. package/docs/release-governance.md +10 -10
  57. package/docs/release-promotion-request.md +11 -18
  58. package/docs/release-propagation.md +5 -6
  59. package/docs/release-tail-provider-plane.md +2 -3
  60. package/docs/reusable-build-surface.md +13 -7
  61. package/docs/runtime-entry.md +111 -0
  62. package/docs/runtime-train-validation.md +30 -41
  63. package/docs/v4-publication-rehearsal.md +5 -5
  64. package/docs/v4-stage-capsule.md +9 -10
  65. package/docs/web-surface-deployments.md +16 -20
  66. package/docs/workflow-catalog.md +0 -1
  67. package/package.json +6 -6
  68. package/packages/core/adoption/commands/init-repo.mjs +2 -2
  69. package/packages/core/adoption/cross-platform-adopter-qualification.js +2 -13
  70. package/packages/core/adoption/qualification/actions.js +3 -5
  71. package/packages/core/adoption/qualification/admission.js +2 -3
  72. package/packages/core/build/artifact/attestation.js +0 -1
  73. package/packages/core/build/artifact/contracts.js +1 -4
  74. package/packages/core/build/artifact/store.js +6 -5
  75. package/packages/core/build/artifact-signing.js +4 -10
  76. package/packages/core/build/binary/actions.js +15 -9
  77. package/packages/core/build/binary-publication-dispatch.js +2 -6
  78. package/packages/core/build/demo/action-context.js +2 -11
  79. package/packages/core/build/demo/binary-action.js +8 -10
  80. package/packages/core/build/gate/controller.js +0 -2
  81. package/packages/core/build/github-attestation/action.js +2 -7
  82. package/packages/core/build/github-attestation/admission.js +0 -8
  83. package/packages/core/build/github-attestation/transaction.js +1 -2
  84. package/packages/core/build/lifecycle/stage-action.js +2 -0
  85. package/packages/core/build/lifecycle/stage.js +6 -3
  86. package/packages/core/build/macos-credential-island/dmg-assembly.js +0 -2
  87. package/packages/core/build/macos-credential-island/lib.js +2 -6
  88. package/packages/core/build/plan/action-context.js +0 -7
  89. package/packages/core/build/plan/action.js +7 -11
  90. package/packages/core/build/plan/admission.js +6 -73
  91. package/packages/core/build/plan/configuration.js +1 -1
  92. package/packages/core/build/plan/environment.js +1 -1
  93. package/packages/core/build/plan/identity.js +1 -5
  94. package/packages/core/build/plan/resolve.js +7 -1
  95. package/packages/core/build/recovery/checkpoint.js +158 -0
  96. package/packages/core/build/recovery/transaction.js +51 -0
  97. package/packages/core/build/signing/authority-actions.js +2 -11
  98. package/packages/core/build/signing/control.js +0 -5
  99. package/packages/core/build/signing/controller-transaction.js +0 -1
  100. package/packages/core/build/signing/delegation.js +2 -4
  101. package/packages/core/build/signing/dispatch.js +10 -56
  102. package/packages/core/build/signing/intake.js +0 -4
  103. package/packages/core/build/signing/prepare.js +1 -1
  104. package/packages/core/build/signing/request.js +3 -8
  105. package/packages/core/build/source/checkout-action.js +6 -10
  106. package/packages/core/build/source/controller.js +1 -4
  107. package/packages/core/build/source/lifecycle.js +3 -13
  108. package/packages/core/build/stage-capsule/actions.js +3 -13
  109. package/packages/core/build/stage-capsule/campaign/resume.js +10 -5
  110. package/packages/core/build/stage-capsule/rehearsal/verify.js +3 -4
  111. package/packages/core/build/stage-capsule-resume-planner.js +0 -1
  112. package/packages/core/build/summary/aggregation.js +5 -5
  113. package/packages/core/build/summary/finalization.js +1 -1
  114. package/packages/core/build/verification/actions.js +3 -12
  115. package/packages/core/build/verification/runner.js +22 -20
  116. package/packages/core/consumer/floating-consumer-evidence.js +3 -21
  117. package/packages/core/consumer/floating-consumer-policy.js +2 -93
  118. package/packages/core/consumer/floating-consumer-release-passport.js +1 -34
  119. package/packages/core/consumer/policy-admission.js +1 -3
  120. package/packages/core/contracts/buildchain-contract.js +12 -146
  121. package/packages/core/contracts/workflow-yaml-contract.js +11 -1
  122. package/packages/core/dev-delivery/candidate/admission.js +3 -4
  123. package/packages/core/dev-delivery/candidate/coordinates.js +0 -8
  124. package/packages/core/dev-delivery/commands/dev-delivery-request.sh +5 -13
  125. package/packages/core/dev-delivery/commands/dev-delivery-source-proof-reuse.mjs +0 -3
  126. package/packages/core/dev-delivery/dev-delivery-contract-surface.js +4 -52
  127. package/packages/core/dev-delivery/dev-delivery-execution-transfer.js +2 -15
  128. package/packages/core/dev-delivery/native/action-context.js +4 -32
  129. package/packages/core/dev-delivery/native/provider-boundary.js +0 -2
  130. package/packages/core/dev-delivery/native/transactions.js +1 -2
  131. package/packages/core/dev-delivery/queue/reconciliation-action.js +6 -10
  132. package/packages/core/dev-delivery/source-proof/predicates.js +0 -6
  133. package/packages/core/dev-delivery/source-proof/reuse.js +0 -2
  134. package/packages/core/dev-delivery/source-proof/seal.js +0 -2
  135. package/packages/core/governance/alpha-candidate/action.js +1 -10
  136. package/packages/core/governance/audit/actions.js +1 -3
  137. package/packages/core/governance/audit/collection.js +1 -3
  138. package/packages/core/governance/audit/identity.js +3 -31
  139. package/packages/core/governance/audit/transactions.js +2 -4
  140. package/packages/core/governance/buildchain-publication-authority.js +0 -1
  141. package/packages/core/governance/commands/audit-github-governance.mjs +3 -2
  142. package/packages/core/governance/github-governance-authority.js +0 -5
  143. package/packages/core/governance/receipt-admission.js +0 -15
  144. package/packages/core/index.js +1 -1
  145. package/packages/core/observability/controller/identity.js +4 -5
  146. package/packages/core/observability/controller-evidence.js +5 -10
  147. package/packages/core/paper/commands/paper.mjs +6 -6
  148. package/packages/core/paper/operations/plans.js +2 -2
  149. package/packages/core/paper/operations/provisioning-validation.js +1 -1
  150. package/packages/core/paper/operations/scaffold-workflows.js +29 -12
  151. package/packages/core/paper/operations/scaffold.js +97 -69
  152. package/packages/core/paper/paper-agent-entry.js +0 -11
  153. package/packages/core/paper/paper-runtime-channels.js +21 -66
  154. package/packages/core/paper/paper-scaffold-content.js +1 -1
  155. package/packages/core/paper/paper.js +9 -5
  156. package/packages/core/paper/publication/candidate.js +0 -9
  157. package/packages/core/paper/publication-controller.js +2 -4
  158. package/packages/core/providers/github/artifact-attestation.js +1 -1
  159. package/packages/core/publication/authority/actions.js +1 -5
  160. package/packages/core/publication/authority/assembly.js +1 -6
  161. package/packages/core/publication/authority/governance.js +2 -9
  162. package/packages/core/publication/authority/verification.js +2 -17
  163. package/packages/core/publication/binary/action.js +5 -7
  164. package/packages/core/publication/candidate/qualification-action.js +1 -6
  165. package/packages/core/publication/candidate/stage-capsules.js +1 -1
  166. package/packages/core/publication/npm/preview-action.js +9 -15
  167. package/packages/core/publication/oci/preview-actions.js +1 -10
  168. package/packages/core/publication/publication-artifact-candidate.js +2 -2
  169. package/packages/core/publication/publication-authority.js +2 -2
  170. package/packages/core/publication/publication-rehearsal-projection.js +3 -3
  171. package/packages/core/publication/settlement/actions.js +2 -11
  172. package/packages/core/release/binary/coordinates-action.js +0 -13
  173. package/packages/core/release/binary/coordinates.js +2 -19
  174. package/packages/core/release/commands/promotion-channel-router.mjs +12 -56
  175. package/packages/core/release/commands/resume-from-candidate-run.mjs +2 -3
  176. package/packages/core/release/dev-alpha-active-release-train.js +0 -5
  177. package/packages/core/release/line/action.js +2 -13
  178. package/packages/core/release/next-development/actions.js +2 -5
  179. package/packages/core/release/passport/consumer-validation.js +1 -28
  180. package/packages/core/release/promote-candidate/development-source.js +7 -8
  181. package/packages/core/release/promotion/actions.js +7 -38
  182. package/packages/core/release/promotion/admission.js +3 -50
  183. package/packages/core/release/promotion/candidate.js +2 -4
  184. package/packages/core/release/promotion/channel.js +13 -101
  185. package/packages/core/release/promotion/qualification-action.js +2 -13
  186. package/packages/core/release/promotion/routing.js +16 -81
  187. package/packages/core/release/promotion/selection.js +1 -9
  188. package/packages/core/release/promotion-request.js +1 -40
  189. package/packages/core/release/qualification/actions.js +0 -8
  190. package/packages/core/release/qualification/public-build.js +1 -1
  191. package/packages/core/release/recovery/candidate.js +15 -21
  192. package/packages/core/release/recovery/capsules.js +2 -10
  193. package/packages/core/release/recovery/lineage.js +305 -0
  194. package/packages/core/release/recovery/provenance.js +1 -2
  195. package/packages/core/release/recovery/publication.js +4 -14
  196. package/packages/core/release/recovery/readback.js +19 -32
  197. package/packages/core/release/recovery/runtime.js +4 -95
  198. package/packages/core/release/release-candidate-recovery.js +4 -9
  199. package/packages/core/release/release-candidate.js +2 -5
  200. package/packages/core/release/reseal/actions.js +3 -22
  201. package/packages/core/release/reseal/admission.js +0 -2
  202. package/packages/core/release/reseal/finalize-platform.js +0 -2
  203. package/packages/core/release/tail-reseal-github.js +1 -2
  204. package/packages/core/release/tail-reseal-receipt.js +0 -1
  205. package/packages/core/release/tail-reseal.js +2 -20
  206. package/packages/core/release/version-state.js +4 -13
  207. package/packages/core/runtime/buildchain-domain.wasm +0 -0
  208. package/packages/core/runtime/checkout-identity.js +0 -13
  209. package/packages/core/runtime/domain-wasm-artifact.js +2 -2
  210. package/packages/core/runtime/entry/actions.js +121 -0
  211. package/packages/core/runtime/entry/activation.js +86 -0
  212. package/packages/core/runtime/entry/github.js +52 -0
  213. package/packages/core/runtime/entry/recovery.js +37 -0
  214. package/packages/core/runtime/entry/selection.js +110 -0
  215. package/packages/core/web/controller.js +1 -1
  216. package/packages/core/web/publication-admission-action.js +1 -8
  217. package/packages/core/web/web-surface-publication-candidate.js +2 -5
  218. package/packages/core/workflow/admission/actions.js +6 -26
  219. package/packages/core/workflow/admission/recovery.js +3 -43
  220. package/packages/core/workflow/admission/transactions.js +8 -24
  221. package/packages/core/workflow/commands/buildchain-cli-help.mjs +1 -1
  222. package/packages/core/workflow/commands/universal-workflow-engine.mjs +2 -7
  223. package/packages/core/workflow/dogfood/actions.js +0 -17
  224. package/packages/core/workflow/engine/action.js +0 -5
  225. package/packages/core/workflow/engine/conformance.js +1 -1
  226. package/packages/core/workflow/engine/execution.js +2 -6
  227. package/packages/core/workflow/engine/identity.js +1 -6
  228. package/packages/core/workflow/engine/release-environment.js +11 -35
  229. package/packages/core/workflow/engine/release-promotion.js +2 -2
  230. package/packages/core/workflow/settlement/actions.js +0 -12
  231. package/packages/core/workflow/universal-self-dogfood.js +2 -16
  232. package/packages/core/workflow/universal-workflow-bootstrap.js +16 -241
  233. package/packages/core/workflow/workflow-taxonomy.mjs +2 -2
  234. package/scripts/check-dev-delivery-actions.mjs +17 -8
  235. package/scripts/check-floating-consumer-policy-contract.mjs +6 -6
  236. package/scripts/check-inventory.mjs +1 -10
  237. package/scripts/check-public-dogfood-contract.mjs +34 -21
  238. package/scripts/check-release-topology.mjs +2 -6
  239. package/scripts/check-runtime-entry.mjs +133 -0
  240. package/scripts/check-universal-workflow-bootstrap.mjs +45 -281
  241. package/scripts/check-workflows.sh +0 -7
  242. package/scripts/generate-bootstrap-admission.mjs +1 -1
  243. package/scripts/generate-channel-promotion-workflow.mjs +4 -4
  244. package/scripts/inventory/binary.mjs +4 -4
  245. package/scripts/inventory/promotion.mjs +5 -3
  246. package/scripts/runtime-source-boundaries.mjs +70 -0
  247. package/scripts/site-capability-metadata.mjs +2 -2
  248. package/scripts/workflow-action-graph.mjs +5 -18
  249. package/scripts/workflow-self-reference.mjs +20 -0
  250. package/templates/native-dev-delivery.yml +4 -4
  251. package/templates/universal-buildchain-bootstrap.yml +12 -2
  252. package/architecture/runtime-ref-resume-authority.json +0 -64
  253. package/architecture/universal-workflow-train-admission.json +0 -76
  254. package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +0 -235
  255. package/docs/v4-runtime-ref-resume-authority.md +0 -69
  256. package/packages/core/consumer/channel-selection.js +0 -211
  257. package/packages/core/consumer/commands/buildchain-channel-router.mjs +0 -81
  258. package/packages/core/consumer/invocation-selector.js +0 -4
  259. package/packages/core/consumer/runtime-ref-resume-authority.js +0 -621
  260. package/packages/core/consumer/workflow-definition-authority.js +0 -64
  261. package/packages/core/contracts/runtime-contract-action.js +0 -48
  262. package/packages/core/release/commands/promotion-identity-resolver.mjs +0 -77
  263. package/packages/core/release/commands/verify-promotion-router-binding.sh +0 -36
  264. package/packages/core/release/promotion/identities.js +0 -56
  265. package/packages/core/release/runtime-override-authorization.js +0 -242
  266. package/packages/core/runtime/commands/runtime-ref-core.mjs +0 -171
  267. package/packages/core/runtime/provider-closure.js +0 -60
  268. package/packages/core/runtime/runtime-selection-action.js +0 -34
  269. package/packages/core/runtime/runtime-selection.js +0 -136
  270. package/packages/core/runtime/workflow-runtime.js +0 -11
  271. package/packages/core/workflow/admission/review.js +0 -188
  272. package/packages/core/workflow/commands/universal-workflow-backflow.mjs +0 -26
  273. package/packages/core/workflow/installation.js +0 -33
  274. package/packages/core/workflow/settlement/backflow.js +0 -187
  275. package/scripts/generate-bootstrap-recovery.mjs +0 -94
  276. package/templates/bootstrap-recovery/actions/build/source/admit/action.yml +0 -17
  277. package/templates/bootstrap-recovery/actions/build/source/admit/dist/index.js +0 -63
  278. package/templates/bootstrap-recovery/actions/runtime/dependencies/install/action.yml +0 -18
  279. package/templates/bootstrap-recovery/actions/runtime/dependencies/install/dist/index.js +0 -63
  280. package/templates/bootstrap-recovery/actions/runtime/environment/prepare/action.yml +0 -21
  281. package/templates/bootstrap-recovery/actions/workflow/admission/inspect/action.yml +0 -27
  282. package/templates/bootstrap-recovery/actions/workflow/admission/inspect/dist/index.js +0 -64
  283. package/templates/bootstrap-recovery/actions/workflow/admission/review/action.yml +0 -15
  284. package/templates/bootstrap-recovery/actions/workflow/admission/review/dist/index.js +0 -65
  285. package/templates/bootstrap-recovery/actions/workflow/recovery/admit/action.yml +0 -47
  286. package/templates/bootstrap-recovery/actions/workflow/recovery/execute/action.yml +0 -48
  287. package/templates/bootstrap-recovery/actions/workflow/recovery/settle/action.yml +0 -54
  288. package/templates/bootstrap-recovery/actions/workflow/settlement/seal/action.yml +0 -17
  289. package/templates/bootstrap-recovery/actions/workflow/settlement/seal/dist/index.js +0 -65
  290. package/templates/bootstrap-recovery/manifest.json +0 -68
  291. package/templates/bootstrap-recovery/package.json +0 -9
  292. package/templates/universal-buildchain-bootstrap-recovery.yml +0 -115
@@ -2,7 +2,6 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { getOctokit } from "@actions/github";
4
4
  import { installationRoot } from "../../runtime/installation-root.js";
5
- import { verifyCheckoutIdentity } from "../../runtime/checkout-identity.js";
6
5
  import { routePromotion } from "./routing.js";
7
6
  import { bindPromotionSelection } from "./selection.js";
8
7
  import { admitPromotionInvocation } from "./admission.js";
@@ -24,34 +23,16 @@ function context(env) {
24
23
  payload: JSON.parse(fs.readFileSync(env.GITHUB_EVENT_PATH, "utf8")),
25
24
  };
26
25
  }
27
- function requireRuntime(workspace, relative, sha) {
28
- const runtimeRoot = installationRoot(import.meta.url);
29
- if (
30
- fs.realpathSync(runtimeRoot) !==
31
- fs.realpathSync(path.join(workspace, relative))
32
- )
33
- throw new Error(
34
- "Promotion action is outside its admitted runtime checkout",
35
- );
36
- verifyCheckoutIdentity({
37
- directory: runtimeRoot,
38
- sha,
39
- label: "Promotion action runtime",
40
- });
41
- return runtimeRoot;
42
- }
26
+
43
27
  export async function routePromotionAction(core, env) {
44
28
  const workflowSha = get(core, "workflow-sha"),
45
29
  workspace = path.resolve(env.GITHUB_WORKSPACE);
46
- const runtimeRoot = requireRuntime(
47
- workspace,
48
- ".buildchain/workflow-shell",
49
- workflowSha,
50
- );
30
+ const runtimeRoot = installationRoot(import.meta.url);
51
31
  emit(
52
32
  core,
53
33
  await routePromotion({
54
34
  request: get(core, "request-json"),
35
+ runtime: JSON.parse(env.BUILDCHAIN_RUNTIME_SELECTION),
55
36
  workflowRepository: get(core, "workflow-repository"),
56
37
  workflowSha,
57
38
  workflowRef: get(core, "workflow-ref"),
@@ -67,11 +48,7 @@ export function bindPromotionSelectionAction(core, env) {
67
48
  const selection = JSON.parse(get(core, "selection-json")),
68
49
  request = JSON.parse(get(core, "request-json")),
69
50
  workspace = path.resolve(env.GITHUB_WORKSPACE);
70
- requireRuntime(
71
- workspace,
72
- ".buildchain/workflow-shell",
73
- selection["shell-sha"],
74
- );
51
+
75
52
  emit(
76
53
  core,
77
54
  bindPromotionSelection({
@@ -85,11 +62,7 @@ export function bindPromotionSelectionAction(core, env) {
85
62
  export async function admitPromotionInvocationAction(core, env) {
86
63
  const selection = JSON.parse(get(core, "selection-json")),
87
64
  workspace = path.resolve(env.GITHUB_WORKSPACE);
88
- requireRuntime(
89
- workspace,
90
- ".buildchain/policy-runtime",
91
- selection["router-sha"],
92
- );
65
+
93
66
  emit(
94
67
  core,
95
68
  await admitPromotionInvocation({
@@ -104,11 +77,7 @@ export async function admitPromotionInvocationAction(core, env) {
104
77
  }
105
78
  export function inspectPromotionInvocationAction(core, env) {
106
79
  const workflowSha = get(core, "workflow-sha");
107
- requireRuntime(
108
- path.resolve(env.GITHUB_WORKSPACE),
109
- ".buildchain/workflow-shell",
110
- workflowSha,
111
- );
80
+
112
81
  verifyPromotionInvocation(get(core, "request-json"), workflowSha);
113
82
  }
114
83
  export async function classifyPublicationHeadAction(core, env) {
@@ -117,7 +86,7 @@ export async function classifyPublicationHeadAction(core, env) {
117
86
  throw new Error(
118
87
  "Publication classification requires a workflow run with an exact source SHA",
119
88
  );
120
- requireRuntime(path.resolve(env.GITHUB_WORKSPACE), ".", event.head_sha);
89
+
121
90
  const result = await classifyProductPublication(
122
91
  { requestedSha: event.head_sha, targetRef: event.head_branch },
123
92
  productPublicationReader(
@@ -1,52 +1,5 @@
1
- import path from "node:path";
2
- import { authorizePromotionRuntimeOverride } from "../runtime-override-authorization.js";
3
1
  import { bindPromotionInvocation } from "../promotion-request.js";
4
- export async function admitPromotionInvocation({
5
- request,
6
- selection,
7
- workspace,
8
- consumerPolicyRoot,
9
- github,
10
- context,
11
- }) {
12
- let authorization = {};
13
- if (selection["override-used"] === "true") {
14
- const root = path.join(workspace, ".buildchain/consumer"),
15
- mode = request["resume-candidate-run-id"] ? "resume" : "dispatch";
16
- const result = await authorizePromotionRuntimeOverride({
17
- github,
18
- context,
19
- request: {
20
- consumerRoot: root,
21
- runtimeRepository: request["buildchain-repository"],
22
- consumerPolicyReceiptPath: path.join(
23
- root,
24
- ".buildchain/evidence/consumer-policy-receipt.json",
25
- ),
26
- consumerPolicyReceiptRoot: consumerPolicyRoot,
27
- sourceSha: request["target-sha"] || context.sha,
28
- requestedRef: selection["runtime-ref"],
29
- resolvedRuntimeSha: selection["runtime-sha"],
30
- reason: `trusted ${mode} runtime override ${selection["runtime-ref"]} for source ${request["target-sha"] || context.sha}`,
31
- mode,
32
- outputPath: path.join(
33
- root,
34
- ".buildchain/evidence/runtime-authorization.json",
35
- ),
36
- },
37
- });
38
- authorization = {
39
- "runtime-authorization-json": JSON.stringify({
40
- receipt: result.receipt,
41
- receiptRoot: result.receiptRoot,
42
- }),
43
- "runtime-authorization-root": result.receiptRoot,
44
- };
45
- }
46
- return {
47
- ...authorization,
48
- "invocation-json": JSON.stringify(
49
- bindPromotionInvocation(request, selection, authorization),
50
- ),
51
- };
2
+
3
+ export async function admitPromotionInvocation({ request, selection }) {
4
+ return { "invocation-json": JSON.stringify(bindPromotionInvocation(request, selection)) };
52
5
  }
@@ -46,16 +46,14 @@ export async function qualifyPromotionCandidate(
46
46
  targetSha: intent["requested-sha"],
47
47
  expectedSourceTree: request["resume-expected-source-tree"],
48
48
  expectedCandidateRoot: request["resume-expected-candidate-root"],
49
- candidateRuntimeSha: request["resume-expected-candidate-runtime-sha"],
50
- runtimeSha: request["resume-buildchain-runtime-sha"],
51
49
  transactionId: request["resume-transaction-id"],
52
50
  rematerializeOnResume: request["publish-rematerialize-on-resume"],
53
51
  releasePatterns: request["github-release-payload-patterns"],
54
52
  runtimeRoot,
55
53
  recoveryRunId,
56
54
  recoveryRunAttempt,
57
- authorizationJson: request["promotion-runtime-authorization-json"],
58
- authorizationRoot: request["promotion-runtime-authorization-root"],
55
+
56
+
59
57
  });
60
58
  return fresh({
61
59
  ...shared,
@@ -1,104 +1,16 @@
1
- import { resolveBuildchainChannel } from "../../consumer/channel-selection.js";
2
- import { parseBuildchainRefIdentity } from "../../consumer/buildchain-channel-identity.js";
3
- const TARGETS = [
4
- {
5
- pattern: /^alpha\/v(\d+)\/v\d+\.\d+$/,
6
- publicationChannel: "alpha",
7
- shellChannel: "alpha",
8
- },
9
- {
10
- pattern: /^release\/v(\d+)\/v\d+\.\d+$/,
11
- publicationChannel: "release",
12
- shellChannel: "stable",
13
- },
14
- {
15
- pattern: /^publish-gate\/major$/,
16
- publicationChannel: "major",
17
- shellChannel: "stable",
18
- },
1
+ const targets = [
2
+ { pattern: /^alpha\/v\d+\/v\d+\.\d+$/, publicationChannel: "alpha", channel: "alpha" },
3
+ { pattern: /^release\/v\d+\/v\d+\.\d+$/, publicationChannel: "release", channel: "stable" },
4
+ { pattern: /^publish-gate\/major$/, publicationChannel: "major", channel: "stable" },
19
5
  ];
20
6
 
21
- function normalized(value) {
22
- return String(value ?? "").trim();
23
- }
24
-
25
- function sameExactSha(left, right) {
26
- const first = normalized(left).toLowerCase();
27
- const second = normalized(right).toLowerCase();
28
- return /^[0-9a-f]{40}$/.test(first) && first === second;
29
- }
30
-
31
- function targetIntent(targetRef, requestedPublicationChannel = "") {
32
- const ref = normalized(targetRef).replace(/^refs\/heads\//, "");
33
- const target = TARGETS.find((entry) => entry.pattern.test(ref));
34
- if (!target)
35
- throw new Error(`unsupported promotion target ref: ${ref || "<empty>"}`);
36
- const requested = normalized(requestedPublicationChannel).toLowerCase();
37
- if (requested && requested !== target.publicationChannel) {
38
- throw new Error(
39
- `promotion channel ${requested} does not match target ref ${ref} (${target.publicationChannel})`,
40
- );
41
- }
42
- return {
43
- targetRef: ref,
44
- publicationChannel: target.publicationChannel,
45
- shellChannel: target.shellChannel,
46
- };
47
- }
48
-
49
- export function resolvePromotionChannel({
50
- requestedChannel = "auto",
51
- requestedRef = "",
52
- publicationChannel = "",
53
- targetRef = "",
54
- routerRef = "",
55
- routerSha = "",
56
- packageVersion = "",
57
- } = {}) {
58
- const intent = targetIntent(targetRef, publicationChannel);
59
- const selected = resolveBuildchainChannel({
60
- requestedChannel,
61
- requestedRef,
62
- publishChannel: intent.publicationChannel,
63
- eventName: "workflow_call",
64
- routerRef,
65
- packageVersion,
66
- });
67
- const runtimeIdentity = parseBuildchainRefIdentity(selected.buildchainRef);
68
- const opaqueOverride = new Set(["train", "authority", "exact-sha"]).has(
69
- runtimeIdentity.kind,
70
- );
71
- const trustedRouterPin =
72
- opaqueOverride && sameExactSha(selected.buildchainRef, routerSha);
73
- const overrideUsed = opaqueOverride && !trustedRouterPin;
74
- if (
75
- !overrideUsed &&
76
- !trustedRouterPin &&
77
- selected.channel !== intent.shellChannel
78
- ) {
79
- throw new Error(
80
- `promotion target ${intent.targetRef} requires ${intent.shellChannel} shell/runtime, got ${selected.channel}`,
81
- );
82
- }
83
- const shellRef =
84
- intent.shellChannel === "alpha"
85
- ? `v${selected.major}-alpha`
86
- : `v${selected.major}`;
87
- return {
88
- targetRef: intent.targetRef,
89
- publicationChannel: intent.publicationChannel,
90
- routerRef: normalized(routerRef),
91
- routerSha: normalized(routerSha).toLowerCase(),
92
- channel: intent.shellChannel,
93
- major: selected.major,
94
- shellRef,
95
- runtimeRef: selected.buildchainRef,
96
- overrideUsed,
97
- selectionSource: trustedRouterPin
98
- ? "trusted-router-sha"
99
- : selected.selectionSource,
100
- reason: trustedRouterPin
101
- ? `explicit Buildchain runtime ref ${selected.buildchainRef} matches the reusable workflow SHA`
102
- : selected.reason,
103
- };
7
+ // Publication intent belongs to the product branch. Runtime selection belongs
8
+ // to the entry and cannot be inferred again from the publication channel.
9
+ export function resolvePromotionChannel({ targetRef = "", publicationChannel = "" } = {}) {
10
+ const ref = String(targetRef).replace(/^refs\/heads\//u, "");
11
+ const target = targets.find(({ pattern }) => pattern.test(ref));
12
+ if (!target) throw new Error(`unsupported promotion target ref: ${ref || "<empty>"}`);
13
+ if (publicationChannel && publicationChannel !== target.publicationChannel)
14
+ throw new Error(`promotion channel ${publicationChannel} does not match target ref ${ref}`);
15
+ return { targetRef: ref, publicationChannel: target.publicationChannel, channel: target.channel };
104
16
  }
@@ -3,7 +3,6 @@ import path from "node:path";
3
3
  import { getOctokit } from "@actions/github";
4
4
  import { command } from "../../runtime/action-process.mjs";
5
5
  import { installationRoot } from "../../runtime/installation-root.js";
6
- import { verifyCheckoutIdentity } from "../../runtime/checkout-identity.js";
7
6
  import { verifyPromotionInvocation } from "../promotion-request.js";
8
7
  import { recoveryFailure } from "../release-candidate-recovery.js";
9
8
  import { productPublicationReader } from "../../providers/github/product-publication.js";
@@ -17,18 +16,8 @@ export async function qualifyPromotionAction(core, env) {
17
16
  const runtimeRoot = installationRoot(import.meta.url),
18
17
  workspace = path.resolve(env.GITHUB_WORKSPACE),
19
18
  runtimeSha = request["promotion-runtime-sha"];
20
- if (
21
- fs.realpathSync(runtimeRoot) !==
22
- fs.realpathSync(path.join(workspace, ".buildchain/runtime"))
23
- )
24
- throw new Error(
25
- "Promotion qualification requires the selected runtime implementation",
26
- );
27
- verifyCheckoutIdentity({
28
- directory: runtimeRoot,
29
- sha: runtimeSha,
30
- label: "Promotion qualification runtime",
31
- });
19
+
20
+
32
21
  const tree = command("git", ["-C", runtimeRoot, "rev-parse", "HEAD^{tree}"], {
33
22
  stdio: "pipe",
34
23
  }).trim();
@@ -1,94 +1,29 @@
1
1
  import { resolvePromotionChannel } from "./channel.js";
2
- import { resolvePromotionIdentities } from "./identities.js";
3
- import * as override from "../runtime-override-authorization.js";
4
2
  import { normalizePromotionRequest } from "../promotion-request.js";
5
3
 
6
- export async function routePromotion({
7
- github,
8
- context,
9
- request: requestValue,
10
- workflowRepository,
11
- workflowSha,
12
- workflowRef,
13
- packageVersion,
14
- }) {
4
+ export async function routePromotion({ context, request: requestValue, workflowRepository, workflowSha, workflowRef, runtime }) {
15
5
  const request = normalizePromotionRequest(requestValue);
16
- const repository = workflowRepository;
17
- const sha = String(workflowSha || "").toLowerCase();
18
- const coordinate = workflowRef || "";
19
- if (
20
- !/^[\w.-]+\/[\w.-]+$/.test(repository) ||
21
- !/^[0-9a-f]{40}$/.test(sha) ||
22
- !coordinate.startsWith(`${repository}/.github/workflows/`)
23
- )
24
- throw Error("Promotion requires its exact defining workflow identity");
25
- if (request["buildchain-repository"] !== repository)
26
- throw Error(
27
- "Promotion runtime repository must match its defining workflow repository",
28
- );
29
- const routerRef = coordinate
30
- .split("@")
31
- .at(-1)
32
- .replace(/^refs\/(?:heads|tags)\//, "");
33
- const requestedRef = String(request["buildchain-ref"] || sha).replace(
34
- /^refs\/(?:heads|tags)\//,
35
- "",
36
- );
37
- if (
38
- !/^(?:v4(?:-alpha)?|[0-9a-f]{40}|(?:train|authority)\/v4\/v4\.\d+\/[\w./-]+)$/.test(
39
- requestedRef,
40
- ) ||
41
- requestedRef.includes("..")
42
- )
43
- throw Error(
44
- "Promotion runtime selection is outside the current v4 authority",
45
- );
46
6
  const route = resolvePromotionChannel({
47
- requestedChannel: request["buildchain-channel"],
48
- requestedRef,
49
7
  publicationChannel: request.channel,
50
- targetRef:
51
- request["target-ref"] || context.ref.replace(/^refs\/heads\//, ""),
52
- routerRef,
53
- routerSha: sha,
54
- packageVersion,
8
+ targetRef: request["target-ref"] || context.ref.replace(/^refs\/heads\//u, ""),
55
9
  });
56
- if (route.overrideUsed)
57
- await override.authorizePromotionRuntimeOverride({ github, context });
58
- const [owner, repo] = repository.split("/");
59
- const identities = await resolvePromotionIdentities({
60
- routerRef,
61
- routerSha: sha,
62
- shellRef: route.shellRef,
63
- shellCallRef: sha,
64
- runtimeRef: route.runtimeRef,
65
- resolveRef: async (ref) =>
66
- (await github.rest.repos.getCommit({ owner, repo, ref })).data.sha,
67
- });
68
- if (
69
- request["resume-candidate-run-id"] &&
70
- identities.runtimeSha !==
71
- String(request["resume-buildchain-runtime-sha"] || "").toLowerCase()
72
- )
73
- throw Error(
74
- "Recovery runtime does not match resume-buildchain-runtime-sha",
75
- );
76
- const output = {
10
+ const entryRef = workflowRef.split("@").at(-1).replace(/^refs\/(?:heads|tags)\//u, "");
11
+ return {
77
12
  "request-json": JSON.stringify(request),
78
- repository,
13
+ repository: runtime.repository,
79
14
  channel: route.channel,
80
15
  "publication-channel": route.publicationChannel,
81
16
  "target-ref": route.targetRef,
82
- "router-ref": routerRef,
83
- "router-sha": sha,
84
- "shell-ref": route.shellRef,
85
- "shell-call-ref": sha,
86
- "shell-sha": sha,
87
- "runtime-ref": route.runtimeRef,
88
- "runtime-sha": identities.runtimeSha,
89
- "override-used": String(route.overrideUsed),
90
- "selection-source": route.selectionSource,
91
- reason: route.reason,
17
+ "router-ref": entryRef,
18
+ "router-sha": workflowSha,
19
+ "shell-ref": entryRef,
20
+ "shell-call-ref": workflowSha,
21
+ "shell-sha": workflowSha,
22
+ "contract-lock-path": runtime.contract?.path,
23
+ "runtime-ref": runtime.ref,
24
+ "runtime-sha": runtime.sha,
25
+ "override-used": String(runtime.origin === "runtime-parameter"),
26
+ "selection-source": runtime.origin,
27
+ reason: `Execute publication using the runtime selected by the entry (${runtime.origin})`,
92
28
  };
93
- return output;
94
29
  }
@@ -9,8 +9,6 @@ export function bindPromotionSelection(
9
9
  run = command,
10
10
  ) {
11
11
  for (const [directory, expected] of [
12
- ["workflow-shell", selection["shell-sha"]],
13
- ["runtime", selection["runtime-sha"]],
14
12
  ["source", sourceSha],
15
13
  ]) {
16
14
  verifyCheckoutIdentity(
@@ -23,13 +21,7 @@ export function bindPromotionSelection(
23
21
  );
24
22
  }
25
23
  const source = path.join(workspace, ".buildchain/source");
26
- const relative =
27
- request["buildchain-contract-lock-path"] ||
28
- request[
29
- selection.channel === "alpha"
30
- ? "buildchain-alpha-contract-lock-path"
31
- : "buildchain-stable-contract-lock-path"
32
- ];
24
+ const relative = selection["contract-lock-path"];
33
25
  if (
34
26
  !relative ||
35
27
  path.isAbsolute(relative) ||
@@ -55,7 +55,6 @@ export function normalizePromotionRequest(value, kind = "request") {
55
55
  export function bindPromotionInvocation(
56
56
  requestValue,
57
57
  selection,
58
- authorization = {},
59
58
  ) {
60
59
  const request = normalizePromotionRequest(requestValue);
61
60
  const projected = Object.fromEntries(
@@ -64,8 +63,6 @@ export function bindPromotionInvocation(
64
63
  ),
65
64
  );
66
65
  const routing = {
67
- "buildchain-ref": "runtime-sha",
68
- "buildchain-contract-lock-path": "contract-lock-path",
69
66
  "buildchain-expected-channel": "channel",
70
67
  channel: "publication-channel",
71
68
  "target-ref": "target-ref",
@@ -85,33 +82,11 @@ export function bindPromotionInvocation(
85
82
  throw new Error(`Promotion selection requires ${source}`);
86
83
  projected[key] = selection[source];
87
84
  }
88
- for (const key of ["runtime-sha", "shell-sha", "router-sha"])
89
- if (!/^[0-9a-f]{40}$/.test(selection[key]))
90
- throw new Error(`Promotion selection ${key} must be exact`);
91
- if (
92
- selection["router-sha"] !== selection["shell-sha"] ||
93
- selection["shell-call-ref"] !== selection["shell-sha"]
94
- )
95
- throw new Error("Publisher must use the exact defining workflow");
96
85
  if (!/^sha256:[0-9a-f]{64}$/.test(selection["contract-lock-digest"]))
97
86
  throw new Error("Promotion contract lock must be rooted");
98
87
  if (!["true", "false"].includes(selection["override-used"]))
99
88
  throw new Error("Promotion override decision is missing");
100
89
  projected["promotion-override-used"] = selection["override-used"] === "true";
101
- projected["promotion-runtime-authorization-json"] =
102
- authorization["runtime-authorization-json"] || "";
103
- projected["promotion-runtime-authorization-root"] =
104
- authorization["runtime-authorization-root"] || "";
105
- if (
106
- projected["promotion-override-used"] &&
107
- (!projected["promotion-runtime-authorization-json"] ||
108
- !/^sha256:[0-9a-f]{64}$/.test(
109
- projected["promotion-runtime-authorization-root"],
110
- ))
111
- )
112
- throw new Error(
113
- "Promotion override requires rooted consumer authorization",
114
- );
115
90
  projected["buildchain-expected-major"] = "4";
116
91
  projected["publication-authority-workflow-path"] =
117
92
  ".github/workflows/.release-promote.yml";
@@ -119,25 +94,11 @@ export function bindPromotionInvocation(
119
94
  return normalizePromotionRequest(projected, "invocation");
120
95
  }
121
96
 
122
- export function verifyPromotionInvocation(value, workflowSha) {
97
+ export function verifyPromotionInvocation(value) {
123
98
  if (typeof value === "string") value = JSON.parse(value);
124
99
  const normalized = normalizePromotionRequest(value, "invocation");
125
100
  if (Object.keys(value).length !== Object.keys(normalized).length)
126
101
  throw new Error("Promotion invocation must include all normalized fields");
127
- if (
128
- !/^[0-9a-f]{40}$/.test(workflowSha || "") ||
129
- normalized["promotion-shell-sha"] !== workflowSha ||
130
- normalized["promotion-router-sha"] !== workflowSha ||
131
- normalized["promotion-shell-ref"] !== workflowSha
132
- )
133
- throw new Error(
134
- "Promotion invocation is not bound to this defining workflow",
135
- );
136
- if (
137
- !/^[0-9a-f]{40}$/.test(normalized["promotion-runtime-sha"]) ||
138
- normalized["buildchain-ref"] !== normalized["promotion-runtime-sha"]
139
- )
140
- throw new Error("Promotion runtime must bind one exact admitted commit");
141
102
  if (
142
103
  !/^sha256:[0-9a-f]{64}$/.test(normalized["promotion-contract-lock-digest"])
143
104
  )
@@ -1,17 +1,9 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { installationRoot } from "../../runtime/installation-root.js";
4
3
  import { createGitHubQualificationClient } from "../../providers/github/qualification.js";
5
4
  import { qualifyPublicBuild } from "./public-build.js";
6
5
  function inputs(core, env) {
7
6
  const workspace = path.resolve(env.GITHUB_WORKSPACE);
8
- if (
9
- fs.realpathSync(installationRoot(import.meta.url)) !==
10
- fs.realpathSync(workspace)
11
- )
12
- throw new Error(
13
- "Stable candidate qualification requires the checked-out source implementation",
14
- );
15
7
  return {
16
8
  workspace,
17
9
  repositoryName: env.GITHUB_REPOSITORY,
@@ -37,7 +37,7 @@ export function resolveStableCandidateQualificationCandidate({
37
37
  runtime?.workflowShellRef !== "v4-alpha" ||
38
38
  runtime?.class !== "alpha" ||
39
39
  runtime?.override !== false ||
40
- runtime?.trustDecision !== "workflow-identity"
40
+ runtime?.trustDecision !== "entry-selection"
41
41
  ) {
42
42
  throw new Error(
43
43
  "public build summary does not bind the exact source run and alpha workflow identity",
@@ -54,9 +54,9 @@ function materializeRecoveryEvidence({
54
54
  runtimeRoot,
55
55
  recoveryRunId,
56
56
  recoveryRunAttempt,
57
- authorizationPath,
58
- authorizationJson,
59
- authorizationRoot,
57
+
58
+
59
+
60
60
  runId,
61
61
  run,
62
62
  selected,
@@ -104,9 +104,9 @@ function materializeRecoveryEvidence({
104
104
  runtimeRoot,
105
105
  recoveryRunId,
106
106
  recoveryRunAttempt,
107
- authorizationPath,
108
- authorizationJson,
109
- authorizationRoot,
107
+
108
+
109
+
110
110
  })
111
111
  : "";
112
112
  const tarballs = publication.npmArtifacts.map((entry) =>
@@ -219,7 +219,6 @@ async function qualifyRecoveredCandidate({
219
219
  publicationNames,
220
220
  bundleRoot,
221
221
  repoInfo,
222
- candidateRuntimeSha,
223
222
  publishArtifactKind,
224
223
  publishPackageMain,
225
224
  releasePatterns,
@@ -262,8 +261,7 @@ async function qualifyRecoveredCandidate({
262
261
  bundleRoot,
263
262
  repository: repoInfo.fullName,
264
263
  passport,
265
- candidateRuntimeSha,
266
- publishArtifactKind,
264
+ publishArtifactKind,
267
265
  publishPackageMain,
268
266
  releasePatterns,
269
267
  platformManifests: platformManifestEvidence.manifests,
@@ -273,8 +271,7 @@ async function qualifyRecoveredCandidate({
273
271
  rematerializeOnResume,
274
272
  });
275
273
  const stageCapsules = resolveRecoveredStageCapsules({
276
- candidateRuntimeSha,
277
- runtimeSha,
274
+ runtimeSha,
278
275
  sidecar: stageCapsuleSidecar,
279
276
  passport,
280
277
  downloads,
@@ -318,7 +315,6 @@ async function qualifyRecoveredCandidate({
318
315
  targetTree: targetCommit.tree?.sha,
319
316
  expectedSourceTree,
320
317
  expectedCandidateRoot,
321
- expectedRuntimeSha: candidateRuntimeSha,
322
318
  expectedTransactionId: transactionId,
323
319
  existingTransaction,
324
320
  run: normalizeCandidateRun(run, repoInfo.fullName),
@@ -371,7 +367,6 @@ export async function resumeFromCandidateRun({
371
367
  targetSha,
372
368
  expectedSourceTree = "",
373
369
  expectedCandidateRoot = "",
374
- candidateRuntimeSha,
375
370
  runtimeSha,
376
371
  transactionId = "",
377
372
  artifactName = "",
@@ -387,9 +382,9 @@ export async function resumeFromCandidateRun({
387
382
  recoveryRunId,
388
383
  recoveryRunAttempt = "1",
389
384
  runtimeRoot = installationRoot(import.meta.url),
390
- authorizationPath,
391
- authorizationJson,
392
- authorizationRoot,
385
+
386
+
387
+
393
388
  fetchImpl = globalThis.fetch,
394
389
  } = {}) {
395
390
  const repoInfo = splitRepository(repository);
@@ -466,8 +461,7 @@ export async function resumeFromCandidateRun({
466
461
  publicationNames,
467
462
  bundleRoot,
468
463
  repoInfo,
469
- candidateRuntimeSha,
470
- publishArtifactKind,
464
+ publishArtifactKind,
471
465
  publishPackageMain,
472
466
  releasePatterns,
473
467
  channel,
@@ -510,9 +504,9 @@ export async function resumeFromCandidateRun({
510
504
  runtimeRoot,
511
505
  recoveryRunId,
512
506
  recoveryRunAttempt,
513
- authorizationPath,
514
- authorizationJson,
515
- authorizationRoot,
507
+
508
+
509
+
516
510
  runId,
517
511
  run,
518
512
  selected,