@kungfu-tech/buildchain 4.0.0 → 4.0.1-alpha.10

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 (228) hide show
  1. package/AGENTS.md +13 -5
  2. package/actions/promote-buildchain-ref/README.md +11 -6
  3. package/actions/release-tail/README.md +8 -0
  4. package/architecture/ci-lane-change-budget.json +187 -0
  5. package/architecture/decisions/0002-next-development-transition.md +101 -0
  6. package/architecture/decisions/0003-two-phase-delivery-warrant.md +152 -0
  7. package/architecture/internal-capabilities.json +219 -7
  8. package/architecture/maintainability-policy.json +246 -29
  9. package/architecture/release-tail-contract-inventory.json +5 -2
  10. package/architecture/v3-core-mechanism-inventory.json +91 -0
  11. package/architecture/v4-adopter-delivery-parity.json +32 -5
  12. package/architecture/v4-capability-state-machine-manifest.json +73 -0
  13. package/architecture/v4-compatibility-facts-parity.json +77 -0
  14. package/architecture/v4-delivery-authority-parity.json +250 -0
  15. package/architecture/v4-delivery-warrant-shadow-fixtures.json +41 -9
  16. package/architecture/v4-floating-consumer-policy.json +81 -0
  17. package/architecture/v4-floating-consumer-policy.md +32 -0
  18. package/architecture/v4-next-development-parity.json +192 -0
  19. package/architecture/v4-publication-rehearsal-parity.json +84 -0
  20. package/architecture/v4-release-train-parity.json +1 -0
  21. package/architecture/v4-runtime-ref-resume-authority.json +64 -0
  22. package/architecture/v4-stage-capsule-qualification.json +2 -2
  23. package/architecture/v4-tail-reseal-parity.json +150 -0
  24. package/bin/buildchain.mjs +32 -3
  25. package/bin/internal/adopter-delivery-cli.mjs +70 -0
  26. package/bin/internal/command-registry.mjs +3 -0
  27. package/bin/internal/compatibility-facts-cli.mjs +101 -0
  28. package/bin/internal/trust-release-release-handlers.mjs +5 -0
  29. package/contracts/dev-delivery-authority-v2.schema.json +662 -0
  30. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  31. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  32. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  33. package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
  34. package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
  35. package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
  36. package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
  37. package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
  38. package/contracts/fixtures/v4-compatibility-facts-v1/shared.json +1129 -0
  39. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +59 -0
  40. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
  41. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
  42. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
  43. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
  44. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
  45. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
  46. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
  47. package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
  48. package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
  49. package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
  50. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +229 -0
  51. package/contracts/next-development-request-v1.schema.json +66 -0
  52. package/contracts/next-development-transition-v1.schema.json +292 -0
  53. package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
  54. package/contracts/v4-compatibility-facts-v1.schema.json +230 -0
  55. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +107 -0
  56. package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  57. package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
  58. package/contracts/v4-tail-reseal-v1.schema.json +276 -0
  59. package/dist/site/agent-index.json +5 -0
  60. package/dist/site/artifact-schemas.json +10 -0
  61. package/dist/site/buildchain-contract.json +1562 -44
  62. package/dist/site/buildchain-site.json +684 -42
  63. package/dist/site/capability-registry.json +17 -14
  64. package/dist/site/cli-registry.json +205 -3
  65. package/dist/site/controller-registry.json +62 -6
  66. package/dist/site/kfd-claims.json +551 -22
  67. package/dist/site/kfd-upstream-aggregate.json +1 -1
  68. package/dist/site/manual-registry.json +55 -9
  69. package/dist/site/node-api-registry.json +15247 -8690
  70. package/dist/site/page-registry.json +647 -29
  71. package/dist/site/public-surface-audit.json +876 -55
  72. package/dist/site/publication-authority-registry.json +44 -8
  73. package/dist/site/publication-registry.json +4 -4
  74. package/dist/site/release-provenance.json +26 -0
  75. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +662 -0
  76. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
  77. package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
  78. package/dist/site/schemas/v4-compatibility-facts-v1.schema.json +230 -0
  79. package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  80. package/dist/site/site-manifest.json +37 -13
  81. package/dist/site/workflow-registry.json +200 -22
  82. package/docs/MAP.md +10 -2
  83. package/docs/cli-reference.md +404 -13
  84. package/docs/cli.md +8 -0
  85. package/docs/dev-alpha-candidate-patrol.md +8 -0
  86. package/docs/dev-delivery-qualification-landing-adr.md +251 -0
  87. package/docs/dev-delivery-warrant.md +361 -30
  88. package/docs/lifecycle-protocol.md +41 -0
  89. package/docs/next-development-transition.md +118 -0
  90. package/docs/node-api-reference.md +748 -322
  91. package/docs/release-tail-provider-plane.md +30 -0
  92. package/docs/reusable-build-surface.md +41 -0
  93. package/docs/runtime-train-validation.md +10 -0
  94. package/docs/v4-adopter-delivery.md +133 -0
  95. package/docs/v4-compatibility-facts.md +91 -0
  96. package/docs/v4-publication-rehearsal.md +130 -0
  97. package/docs/v4-runtime-ref-resume-authority.md +69 -0
  98. package/docs/v4-tail-reseal.md +73 -0
  99. package/docs/versioning.md +4 -2
  100. package/package.json +36 -6
  101. package/packages/core/adopter-delivery-passport.js +259 -0
  102. package/packages/core/adopter-delivery-vectors.js +158 -0
  103. package/packages/core/adopter-delivery-vectors.json +77 -0
  104. package/packages/core/artifact-signing.js +61 -0
  105. package/packages/core/buildchain-agent-manuals.js +3 -0
  106. package/packages/core/buildchain-compatibility-authority.js +336 -0
  107. package/packages/core/buildchain-compatibility-fact.js +394 -0
  108. package/packages/core/buildchain-compatibility-facts.json +217 -0
  109. package/packages/core/buildchain-compatibility-proof.js +566 -0
  110. package/packages/core/buildchain-config.js +150 -1
  111. package/packages/core/buildchain-contract.js +96 -143
  112. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  113. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  114. package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
  115. package/packages/core/buildchain-publication-authority.js +1 -0
  116. package/packages/core/channel-candidate.js +8 -0
  117. package/packages/core/channel-promotion-baseline.js +55 -0
  118. package/packages/core/ci-lane-change-budget.js +247 -0
  119. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  120. package/packages/core/dev-delivery-authority-candidate.js +270 -0
  121. package/packages/core/dev-delivery-authority-evidence.js +146 -0
  122. package/packages/core/dev-delivery-authority-landing.js +461 -0
  123. package/packages/core/dev-delivery-authority-observation.js +48 -0
  124. package/packages/core/dev-delivery-authority-qualification.js +591 -0
  125. package/packages/core/dev-delivery-authority-settlement.js +213 -0
  126. package/packages/core/dev-delivery-authority-state.js +583 -0
  127. package/packages/core/dev-delivery-candidate-identity.js +13 -0
  128. package/packages/core/dev-delivery-contract-surface.js +76 -0
  129. package/packages/core/dev-delivery-execution-failure.js +133 -0
  130. package/packages/core/dev-delivery-execution-transfer.js +592 -0
  131. package/packages/core/dev-delivery-landing-admission-core.js +119 -0
  132. package/packages/core/dev-delivery-landing-readback.js +598 -0
  133. package/packages/core/dev-delivery-landing-terminal-evidence.js +271 -0
  134. package/packages/core/dev-delivery-landing-testing-port.js +6 -0
  135. package/packages/core/dev-delivery-native-execution.js +110 -0
  136. package/packages/core/dev-delivery-native-proof.js +562 -0
  137. package/packages/core/dev-delivery-process-boundary.js +563 -0
  138. package/packages/core/dev-delivery-proof.js +37 -3
  139. package/packages/core/dev-delivery-provider-attempt.js +127 -0
  140. package/packages/core/dev-delivery-provider-heartbeat.js +382 -0
  141. package/packages/core/dev-delivery-warrant-cancellation.js +1 -0
  142. package/packages/core/dev-delivery-warrant-qualification.js +145 -0
  143. package/packages/core/dev-delivery-warrant-settlement.js +237 -36
  144. package/packages/core/dev-delivery-warrant-state.js +587 -0
  145. package/packages/core/dev-delivery-warrant.js +328 -370
  146. package/packages/core/github-governance-authority.js +1 -0
  147. package/packages/core/index.js +7 -0
  148. package/packages/core/kungfu-temporal-fact.js +557 -0
  149. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  150. package/packages/core/next-development-candidate-reservation.js +186 -0
  151. package/packages/core/next-development-controller.js +728 -0
  152. package/packages/core/next-development-projection.js +287 -0
  153. package/packages/core/next-development-transition.js +738 -0
  154. package/packages/core/paper-agent-entry.js +11 -5
  155. package/packages/core/paper.js +16 -5
  156. package/packages/core/publication-authority.js +5 -5
  157. package/packages/core/published-delivery-authority.js +266 -0
  158. package/packages/core/release-candidate-recovery.js +66 -11
  159. package/packages/core/release-candidate.js +79 -19
  160. package/packages/core/release-passport.js +271 -38
  161. package/packages/core/v4-adopter-delivery-parity.js +3 -3
  162. package/packages/core/v4-adopter-delivery.js +359 -0
  163. package/packages/core/v4-canonical-contracts.js +5 -0
  164. package/packages/core/v4-delivery-warrant-read-candidate.js +10 -3
  165. package/packages/core/v4-floating-consumer-evidence.js +338 -0
  166. package/packages/core/v4-floating-consumer-policy.js +569 -0
  167. package/packages/core/v4-floating-consumer-release-passport.js +153 -0
  168. package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
  169. package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
  170. package/packages/core/v4-publication-rehearsal.js +481 -0
  171. package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
  172. package/packages/core/v4-runtime-selector-persistence.js +228 -0
  173. package/packages/core/v4-tail-reseal-contract.js +26 -0
  174. package/packages/core/v4-tail-reseal-github.js +178 -0
  175. package/packages/core/v4-tail-reseal-receipt.js +225 -0
  176. package/packages/core/v4-tail-reseal.js +594 -0
  177. package/packages/core/workflow-yaml-contract.js +72 -2
  178. package/scripts/audit-publication-control-plane.mjs +31 -31
  179. package/scripts/buildchain-cli-help.mjs +41 -2
  180. package/scripts/check-ci-lane-change-budget.mjs +100 -0
  181. package/scripts/check-inventory.mjs +14 -3
  182. package/scripts/check-v4-floating-consumer-policy-contract.mjs +217 -0
  183. package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
  184. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  185. package/scripts/dev-delivery-authority-command-adapters.mjs +206 -0
  186. package/scripts/dev-delivery-authority-provider.mjs +28 -0
  187. package/scripts/dev-delivery-authority.mjs +490 -0
  188. package/scripts/dev-delivery-native-run.mjs +177 -0
  189. package/scripts/dev-delivery-process-boundary.mjs +260 -0
  190. package/scripts/dev-delivery-proof.mjs +67 -2
  191. package/scripts/dev-delivery-provider-heartbeat.mjs +215 -0
  192. package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
  193. package/scripts/dev-delivery-source-proof-reuse.mjs +547 -0
  194. package/scripts/dev-delivery-two-phase-resume.mjs +345 -0
  195. package/scripts/dev-delivery-two-phase.mjs +573 -0
  196. package/scripts/dev-delivery-warrant-options.mjs +266 -0
  197. package/scripts/dev-delivery-warrant-store.mjs +231 -0
  198. package/scripts/dev-delivery-warrant.mjs +232 -194
  199. package/scripts/dev-pr-auto-merge.mjs +37 -48
  200. package/scripts/dev-pr-delivery-warrant.mjs +216 -2
  201. package/scripts/dev-pr-prequeue-guard.mjs +399 -0
  202. package/scripts/dev-qualification-patrol.mjs +9 -9
  203. package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
  204. package/scripts/ensure-github-release.mjs +3 -3
  205. package/scripts/generate-channel-build-workflow.mjs +3 -0
  206. package/scripts/generate-channel-promotion-workflow.mjs +114 -14
  207. package/scripts/generate-next-development-guidance.mjs +49 -0
  208. package/scripts/generate-release-candidate-passport.mjs +192 -32
  209. package/scripts/generate-site-bundle.mjs +69 -4
  210. package/scripts/init-repo.mjs +26 -4
  211. package/scripts/inspect-artifact-signing-requests.mjs +6 -0
  212. package/scripts/next-development-self-dogfood-harness.mjs +460 -0
  213. package/scripts/next-development-self-dogfood.mjs +597 -0
  214. package/scripts/next-development-transition.mjs +47 -0
  215. package/scripts/npm-publish-transaction.mjs +103 -91
  216. package/scripts/promotion-channel-router.mjs +4 -4
  217. package/scripts/release-candidate-anchor-provenance.mjs +99 -0
  218. package/scripts/release-tail.mjs +51 -3
  219. package/scripts/release-train-self-dogfood.mjs +94 -92
  220. package/scripts/resume-from-candidate-run.mjs +565 -41
  221. package/scripts/seal-artifact-signing-requests.mjs +6 -0
  222. package/scripts/site-capability-metadata.mjs +43 -0
  223. package/scripts/stable-candidate-qualification.mjs +9 -10
  224. package/scripts/v4-consumer-policy.mjs +231 -0
  225. package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
  226. package/scripts/v4-tail-reseal-macos-rehearsal.mjs +134 -0
  227. package/scripts/v4-tail-reseal.mjs +416 -0
  228. package/templates/native-dev-delivery.yml +143 -0
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ import { verifyV4FloatingConsumerPolicyReceipt } from "./v4-floating-consumer-policy.js";
2
3
  import { normalizeControllerReceiptReferences, validateControllerReceiptReference } from "./controller-evidence.js";
3
4
 
4
5
  export const RELEASE_CANDIDATE_PASSPORT_CONTRACT = "kungfu-buildchain-release-candidate-passport";
@@ -171,6 +172,64 @@ function normalizeGateProfileEvidence(gateAggregate = undefined) {
171
172
  };
172
173
  }
173
174
 
175
+ function isV4BuildchainRuntime(buildchain = {}) {
176
+ return [buildchain.ref, buildchain.workflowShellRef]
177
+ .some((value) => /^v4(?:-alpha)?$/u.test(String(value || "")))
178
+ || /^4\./u.test(String(buildchain.version || ""));
179
+ }
180
+
181
+ function normalizeConsumerPolicyEvidence(value, expected = {}) {
182
+ if (value === undefined || value === null || value === "") return undefined;
183
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
184
+ throw new Error("consumerPolicyReceipt must be an object");
185
+ }
186
+ const receipt = value.receipt || value;
187
+ const verification = verifyV4FloatingConsumerPolicyReceipt({
188
+ receipt,
189
+ receiptRoot: value.receiptRoot || "",
190
+ repository: expected.repository,
191
+ sourceSha: expected.sourceSha,
192
+ resolvedRuntimeSha: expected.runtimeSha,
193
+ });
194
+ if (!verification.ok) {
195
+ throw new Error(`consumer policy receipt invalid: ${verification.failures.map((failure) => failure.code).join(", ")}`);
196
+ }
197
+ return { receiptRoot: verification.receiptRoot, receipt };
198
+ }
199
+
200
+ function validateConsumerPolicyEvidence(passport, check) {
201
+ if (isV4BuildchainRuntime(passport.buildchain)) {
202
+ check(Boolean(passport.consumerPolicy), "Buildchain v4 release candidate requires consumer policy evidence");
203
+ }
204
+ if (!passport.consumerPolicy) return;
205
+ const verification = verifyV4FloatingConsumerPolicyReceipt({
206
+ receipt: passport.consumerPolicy.receipt,
207
+ receiptRoot: passport.consumerPolicy.receiptRoot,
208
+ repository: passport.repository,
209
+ sourceSha: passport.target?.ref === "publish-gate/anchor" ? passport.consumerPolicy.receipt?.caller?.sourceSha : passport.source?.headSha,
210
+ resolvedRuntimeSha: passport.buildchain?.sha,
211
+ });
212
+ for (const failure of verification.failures) {
213
+ check(false, `consumer policy evidence invalid: ${failure.code}`);
214
+ }
215
+ }
216
+
217
+ function validateEvidenceBoundCandidateHash(passport, check) {
218
+ if (!passport.familyEvidence && !passport.consumerPolicy) return;
219
+ const expectedCandidateHash = sha256Json({
220
+ repository: passport.repository,
221
+ target: passport.target,
222
+ source: passport.source,
223
+ platformMatrix: passport.platformMatrix,
224
+ buildchain: passport.buildchain,
225
+ ...(passport.gateProfileEvidence ? { gateProfileEvidence: passport.gateProfileEvidence } : {}),
226
+ ...(passport.familyEvidence ? { familyEvidence: passport.familyEvidence } : {}),
227
+ ...(passport.consumerPolicy ? { consumerPolicy: passport.consumerPolicy } : {}),
228
+ ...(passport.controllerReceipts ? { controllerReceipts: passport.controllerReceipts } : {}),
229
+ });
230
+ check(passport.candidateHash === expectedCandidateHash, "candidate hash mismatch");
231
+ }
232
+
174
233
  function normalizeFamilyReleaseEvidence(value = undefined) {
175
234
  if (value === undefined || value === null || value === "") return undefined;
176
235
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -320,6 +379,7 @@ export function createReleaseCandidatePassport({
320
379
  buildchain = {},
321
380
  gateAggregate = undefined,
322
381
  familyEvidence = undefined,
382
+ consumerPolicyReceipt = undefined,
323
383
  controllerReceipts = [],
324
384
  controllerReceiptReferences = [],
325
385
  workflow = {},
@@ -335,6 +395,20 @@ export function createReleaseCandidatePassport({
335
395
  const resolvedVersion = version || normalizedSummary.publishSource?.consumerVersion || inferVersionFromReleaseManifest(normalizedSummary);
336
396
  const gateProfileEvidence = normalizeGateProfileEvidence(gateAggregate);
337
397
  const normalizedFamilyEvidence = normalizeFamilyReleaseEvidence(familyEvidence);
398
+ const resolvedBuildchain = {
399
+ ref: optionalString(buildchain.ref || normalizedSummary.runtime?.ref),
400
+ sha: optionalString(buildchain.sha || normalizedSummary.runtime?.sha),
401
+ version: optionalString(buildchain.version),
402
+ workflowShellRef: optionalString(buildchain.workflowShellRef || normalizedSummary.runtime?.workflowShellRef),
403
+ };
404
+ const normalizedConsumerPolicy = normalizeConsumerPolicyEvidence(consumerPolicyReceipt, {
405
+ repository: repository || normalizedSummary.git?.repository || "",
406
+ sourceSha: normalizedSummary.publishSource?.ref === "publish-gate/anchor" ? (consumerPolicyReceipt?.receipt || consumerPolicyReceipt)?.caller?.sourceSha : sourceSha,
407
+ runtimeSha: resolvedBuildchain.sha,
408
+ });
409
+ if (isV4BuildchainRuntime(resolvedBuildchain) && !normalizedConsumerPolicy) {
410
+ throw new Error("Buildchain v4 release candidate passport requires a valid floating consumer policy receipt");
411
+ }
338
412
  const controllerReceiptEvidence = normalizeControllerReceiptReferences({
339
413
  receipts: controllerReceipts,
340
414
  references: controllerReceiptReferences,
@@ -366,12 +440,7 @@ export function createReleaseCandidatePassport({
366
440
  builtSourceSha: nonEmptyString(mergeRefSha || sourceSha, "builtSourceSha"),
367
441
  builtSourceTreeSha: resolvedTreeHash,
368
442
  },
369
- buildchain: {
370
- ref: optionalString(buildchain.ref || normalizedSummary.runtime?.ref),
371
- sha: optionalString(buildchain.sha || normalizedSummary.runtime?.sha),
372
- version: optionalString(buildchain.version),
373
- workflowShellRef: optionalString(buildchain.workflowShellRef || normalizedSummary.runtime?.workflowShellRef),
374
- },
443
+ buildchain: resolvedBuildchain,
375
444
  workflow: {
376
445
  name: optionalString(workflow.name),
377
446
  runId: optionalString(workflow.runId || normalizedSummary.git?.runId),
@@ -386,6 +455,7 @@ export function createReleaseCandidatePassport({
386
455
  },
387
456
  ...(gateProfileEvidence ? { gateProfileEvidence } : {}),
388
457
  ...(normalizedFamilyEvidence ? { familyEvidence: normalizedFamilyEvidence } : {}),
458
+ ...(normalizedConsumerPolicy ? { consumerPolicy: normalizedConsumerPolicy } : {}),
389
459
  ...(controllerReceiptEvidence.length > 0 ? { controllerReceipts: controllerReceiptEvidence } : {}),
390
460
  };
391
461
  candidate.candidateHash = sha256Json({
@@ -396,6 +466,7 @@ export function createReleaseCandidatePassport({
396
466
  buildchain: candidate.buildchain,
397
467
  ...(candidate.gateProfileEvidence ? { gateProfileEvidence: candidate.gateProfileEvidence } : {}),
398
468
  ...(candidate.familyEvidence ? { familyEvidence: candidate.familyEvidence } : {}),
469
+ ...(candidate.consumerPolicy ? { consumerPolicy: candidate.consumerPolicy } : {}),
399
470
  ...(candidate.controllerReceipts ? { controllerReceipts: candidate.controllerReceipts } : {}),
400
471
  });
401
472
  return candidate;
@@ -463,6 +534,7 @@ export function validateReleaseCandidatePassport({
463
534
  check(Boolean(passport.gateProfileEvidence.digest), "gate profile evidence digest is required");
464
535
  check(Boolean(passport.gateProfileEvidence.matrixDigest), "gate profile matrix digest is required");
465
536
  }
537
+ validateConsumerPolicyEvidence(passport, check);
466
538
  if (requireFamilyEvidence || familyEvidenceRoot || familyInitiativeId || familyAssignmentId) {
467
539
  check(Boolean(passport.familyEvidence), "family evidence is required");
468
540
  }
@@ -514,18 +586,6 @@ export function validateReleaseCandidatePassport({
514
586
  controllerIds.add(reference.controllerId);
515
587
  }
516
588
  }
517
- if (passport.familyEvidence) {
518
- const expectedCandidateHash = sha256Json({
519
- repository: passport.repository,
520
- target: passport.target,
521
- source: passport.source,
522
- platformMatrix: passport.platformMatrix,
523
- buildchain: passport.buildchain,
524
- ...(passport.gateProfileEvidence ? { gateProfileEvidence: passport.gateProfileEvidence } : {}),
525
- familyEvidence: passport.familyEvidence,
526
- ...(passport.controllerReceipts ? { controllerReceipts: passport.controllerReceipts } : {}),
527
- });
528
- check(passport.candidateHash === expectedCandidateHash, "candidate hash mismatch");
529
- }
589
+ validateEvidenceBoundCandidateHash(passport, check);
530
590
  return { ok: errors.length === 0, errors };
531
591
  }
@@ -33,6 +33,17 @@ import { normalizeControllerReceiptReferences } from "./controller-evidence.js";
33
33
  import {
34
34
  normalizeGitHubArtifactAttestationPolicy,
35
35
  } from "./github-artifact-attestation.js";
36
+ import { verifyV4FloatingConsumerPolicyCertification } from "./v4-floating-consumer-evidence.js";
37
+ import {
38
+ isV4PromotionRouting,
39
+ releasePassportCertificationVerificationOptions,
40
+ requireV4ConsumerPolicyCertification,
41
+ resolveV4ConsumerPolicyCertificationIdentity,
42
+ } from "./v4-floating-consumer-release-passport.js";
43
+ import {
44
+ verifyV4RuntimeAuthorizationReceipt,
45
+ verifyV4RuntimeResumeLineage,
46
+ } from "./v4-runtime-ref-resume-authority.js";
36
47
 
37
48
  export { RELEASE_CHECK_REPORT_CONTRACT, RELEASE_PASSPORT_CONTRACT };
38
49
  export const ARTIFACT_EVIDENCE_CONTRACT = "kungfu-buildchain-artifact-evidence";
@@ -390,6 +401,13 @@ function parseJsonInputWithMeta(value, fallback = undefined, { cwd = process.cwd
390
401
  };
391
402
  }
392
403
 
404
+ function parseV4ConsumerPolicyCertification(input, cwd) {
405
+ return parseJsonInputWithMeta(input, undefined, {
406
+ cwd,
407
+ label: "v4ConsumerPolicyCertificationJson",
408
+ });
409
+ }
410
+
393
411
  function mergeAuthoritativePassportBase(passport, basePassport = undefined, { requireKfd = false } = {}) {
394
412
  if (!basePassport) {
395
413
  if (requireKfd) {
@@ -422,11 +440,17 @@ function mergeAuthoritativePassportBase(passport, basePassport = undefined, { re
422
440
  kfd3: basePassport.evidence?.kfd3 || passport.evidence?.kfd3 || "",
423
441
  },
424
442
  };
425
- for (const key of ["versionImpact", "surfaceImpacts"]) {
426
- if (basePassport[key] !== undefined) {
427
- merged[key] = basePassport[key];
428
- }
429
- }
443
+ for (const key of [
444
+ "versionImpact",
445
+ "surfaceImpacts",
446
+ "promotionRouting",
447
+ "v4ConsumerPolicy",
448
+ "v4RuntimeResume",
449
+ "transaction",
450
+ "trustedPublishing",
451
+ "distTagPromotion",
452
+ ])
453
+ if (basePassport[key] !== undefined) merged[key] = basePassport[key];
430
454
  if (basePassport.controllerReceipts !== undefined) {
431
455
  merged.controllerReceipts = basePassport.controllerReceipts;
432
456
  }
@@ -1085,6 +1109,143 @@ function normalizePromotionRouting(value = undefined) {
1085
1109
  return JSON.parse(JSON.stringify(value));
1086
1110
  }
1087
1111
 
1112
+ function normalizePromotionEvidence({
1113
+ release = {},
1114
+ v4ConsumerPolicyCertification: certification,
1115
+ v4ConsumerPolicyCertificationRoot: certificationRoot,
1116
+ v4RuntimeResumeEvidence,
1117
+ repository,
1118
+ sourceSha,
1119
+ cwd,
1120
+ }) {
1121
+ const routing = normalizePromotionRouting(release.promotionRouting);
1122
+ const identity = resolveV4ConsumerPolicyCertificationIdentity({
1123
+ release,
1124
+ routing,
1125
+ runtimeResume: v4RuntimeResumeEvidence,
1126
+ sourceSha,
1127
+ });
1128
+ return {
1129
+ routing,
1130
+ consumerPolicy: requireV4ConsumerPolicyCertification({
1131
+ value: certification,
1132
+ repository,
1133
+ sourceSha: identity.sourceSha,
1134
+ runtimeSha: identity.runtimeSha,
1135
+ routing,
1136
+ cwd,
1137
+ certificationRoot,
1138
+ }),
1139
+ };
1140
+ }
1141
+
1142
+ function normalizeV4RuntimeResumeEvidence(value, expected = {}) {
1143
+ if (value === undefined || value === null || value === "") return undefined;
1144
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1145
+ throw new Error("v4RuntimeResumeEvidence must be a JSON object");
1146
+ }
1147
+ const authorizationVerification = verifyV4RuntimeAuthorizationReceipt({
1148
+ receipt: value.authorization,
1149
+ receiptRoot: value.authorizationRoot,
1150
+ repository: expected.repository,
1151
+ sourceSha: expected.sourceSha,
1152
+ runtimeSha: expected.resumeRuntimeSha,
1153
+ consumerPolicyReceiptRoot: expected.consumerPolicyReceiptRoot,
1154
+ });
1155
+ if (!authorizationVerification.ok) {
1156
+ throw new Error(`v4 runtime authorization invalid: ${authorizationVerification.failures.join(", ")}`);
1157
+ }
1158
+ const lineageVerification = verifyV4RuntimeResumeLineage({
1159
+ lineage: value.lineage,
1160
+ lineageRoot: value.lineageRoot,
1161
+ repository: expected.repository,
1162
+ sourceSha: expected.sourceSha,
1163
+ resumeRuntimeSha: expected.resumeRuntimeSha,
1164
+ consumerPolicyReceiptRoot: expected.consumerPolicyReceiptRoot,
1165
+ });
1166
+ if (!lineageVerification.ok) {
1167
+ throw new Error(`v4 runtime resume lineage invalid: ${lineageVerification.failures.join(", ")}`);
1168
+ }
1169
+ if (value.lineage?.authorizationRoot !== value.authorizationRoot) {
1170
+ throw new Error("v4 runtime resume lineage authorization root mismatch");
1171
+ }
1172
+ return {
1173
+ authorizationRoot: value.authorizationRoot,
1174
+ authorization: structuredClone(value.authorization),
1175
+ lineageRoot: value.lineageRoot,
1176
+ lineage: structuredClone(value.lineage),
1177
+ };
1178
+ }
1179
+
1180
+ function v4RuntimeResumeSourceSha(release, fallback = "") {
1181
+ const builtSourceSha = releaseField(
1182
+ release || {},
1183
+ "builtSourceSha",
1184
+ "built_source_sha",
1185
+ );
1186
+ return release?.treeEquivalent === true && builtSourceSha
1187
+ ? builtSourceSha
1188
+ : fallback;
1189
+ }
1190
+
1191
+
1192
+ function prepareBuildEvidence({
1193
+ buildSummary,
1194
+ buildFacts,
1195
+ platformArtifactManifests,
1196
+ distTagPromotionEvidence,
1197
+ }) {
1198
+ return {
1199
+ buildSummary: buildSummary
1200
+ ? normalizeEvidenceDocument(buildSummary, "buildSummary")
1201
+ : undefined,
1202
+ buildFacts: (buildFacts || [])
1203
+ .map((value, index) =>
1204
+ normalizeEvidenceDocument(value, `buildFacts[${index}]`),
1205
+ )
1206
+ .filter(Boolean),
1207
+ platformArtifactManifests: (platformArtifactManifests || [])
1208
+ .map((manifest, index) =>
1209
+ normalizePlatformArtifactManifest(manifest, index),
1210
+ )
1211
+ .filter(Boolean),
1212
+ distTagPromotionEvidence: distTagPromotionEvidence
1213
+ ? normalizeEvidenceDocument(
1214
+ distTagPromotionEvidence,
1215
+ "distTagPromotionEvidence",
1216
+ )
1217
+ : undefined,
1218
+ };
1219
+ }
1220
+
1221
+ function preparePromotionBuild(options) {
1222
+ return {
1223
+ promotion: normalizePromotionEvidence(options),
1224
+ buildEvidence: prepareBuildEvidence(options),
1225
+ };
1226
+ }
1227
+
1228
+ function normalizeReleaseSourceFields(release) {
1229
+ return {
1230
+ builtSourceSha: releaseField(release, "builtSourceSha", "built_source_sha"),
1231
+ builtSourceTreeSha: releaseField(
1232
+ release,
1233
+ "builtSourceTreeSha",
1234
+ "built_source_tree_sha",
1235
+ ),
1236
+ promotionChannelSha: releaseField(
1237
+ release,
1238
+ "promotionChannelSha",
1239
+ "promotion_channel_sha",
1240
+ ),
1241
+ promotionChannelTreeSha: releaseField(
1242
+ release,
1243
+ "promotionChannelTreeSha",
1244
+ "promotion_channel_tree_sha",
1245
+ ),
1246
+ };
1247
+ }
1248
+
1088
1249
  export function createArtifactEvidence({ assets = [], repository = "", tag = "", sourceSha = "", workflow = {}, kfdAdopter = undefined } = {}) {
1089
1250
  const normalizedAssets = assets.map((asset, index) => normalizeAsset(asset, index));
1090
1251
  return buildReleaseArtifactEvidence({ normalizedAssets, repository, tag, sourceSha, workflow, kfdAdopter });
@@ -1120,7 +1281,8 @@ function prepareReleaseKfdAdopterArtifacts({ kfdAdopter, assets, repository, tag
1120
1281
  };
1121
1282
  }
1122
1283
 
1123
- export function createReleasePassport({
1284
+ export function createReleasePassport(options = {}) {
1285
+ const {
1124
1286
  cwd = process.cwd(),
1125
1287
  repository = "",
1126
1288
  tag = "",
@@ -1161,13 +1323,16 @@ export function createReleasePassport({
1161
1323
  kfdSupportEvidencePath = "",
1162
1324
  invariantPassports = undefined,
1163
1325
  releaseEvidence = [],
1326
+ v4ConsumerPolicyCertification = undefined,
1327
+ v4ConsumerPolicyCertificationRoot = "",
1328
+ v4RuntimeResumeEvidence = undefined,
1164
1329
  kfdAgentHubEvidence = undefined,
1165
1330
  kfdAgentHubEvidencePath = "",
1166
1331
  controllerReceipts = [],
1167
1332
  controllerReceiptReferences = [],
1168
1333
  githubArtifactAttestations = [],
1169
1334
  checkedAt = "",
1170
- } = {}) {
1335
+ } = options;
1171
1336
  const normalizedTag = nonEmptyString(tag, "tag");
1172
1337
  const { normalized: normalizedKfdAdopter, artifactEvidence } = prepareReleaseKfdAdopterArtifacts({
1173
1338
  kfdAdopter, assets, repository, tag: normalizedTag, sourceSha, workflow,
@@ -1176,17 +1341,13 @@ export function createReleasePassport({
1176
1341
  const normalizedPackageSet = normalizePackageSet(packageSet, { packageName, packageVersion, publish });
1177
1342
  const normalizedTrustedPublishing = normalizeTrustedPublishing(trustedPublishing, { workflow, publish });
1178
1343
  const normalizedTransaction = normalizeTransaction(transaction);
1179
- const normalizedPromotionRouting = normalizePromotionRouting(release.promotionRouting);
1180
- const normalizedBuildSummary = buildSummary ? normalizeEvidenceDocument(buildSummary, "buildSummary") : undefined;
1181
- const normalizedBuildFacts = (buildFacts || [])
1182
- .map((fact, index) => normalizeEvidenceDocument(fact, `buildFacts[${index}]`))
1183
- .filter(Boolean);
1184
- const normalizedPlatformArtifactManifests = (platformArtifactManifests || [])
1185
- .map((manifest, index) => normalizePlatformArtifactManifest(manifest, index))
1186
- .filter(Boolean);
1187
- const normalizedDistTagPromotionEvidence = distTagPromotionEvidence
1188
- ? normalizeEvidenceDocument(distTagPromotionEvidence, "distTagPromotionEvidence")
1189
- : undefined;
1344
+ const { promotion, buildEvidence } = preparePromotionBuild(options);
1345
+ const normalizedV4RuntimeResume = normalizeV4RuntimeResumeEvidence(v4RuntimeResumeEvidence, {
1346
+ repository,
1347
+ sourceSha: v4RuntimeResumeSourceSha(release, sourceSha),
1348
+ resumeRuntimeSha: promotion.routing?.runtime?.resolvedSha || "",
1349
+ consumerPolicyReceiptRoot: promotion.consumerPolicy?.certification?.receiptRoot || "",
1350
+ });
1190
1351
  const normalizedImpact = normalizeImpactLedger(impact, { tag: normalizedTag, line });
1191
1352
  const generatedAt = optionalString(checkedAt) || nowIso();
1192
1353
  const kfd1Metadata = resolveKfd1Metadata();
@@ -1205,16 +1366,13 @@ export function createReleasePassport({
1205
1366
  support: kfdSupportEvidencePath,
1206
1367
  },
1207
1368
  });
1208
- const builtSourceSha = releaseField(release, "builtSourceSha", "built_source_sha");
1209
- const builtSourceTreeSha = releaseField(release, "builtSourceTreeSha", "built_source_tree_sha");
1210
- const promotionChannelSha = releaseField(release, "promotionChannelSha", "promotion_channel_sha");
1211
- const promotionChannelTreeSha = releaseField(release, "promotionChannelTreeSha", "promotion_channel_tree_sha");
1369
+ const sourceFields = normalizeReleaseSourceFields(release);
1212
1370
  const treeEquivalent = release.treeEquivalent === true;
1213
1371
  const recoveryTreeEquivalent = Boolean(
1214
1372
  treeEquivalent &&
1215
- builtSourceTreeSha &&
1216
- promotionChannelTreeSha &&
1217
- builtSourceTreeSha === promotionChannelTreeSha,
1373
+ sourceFields.builtSourceTreeSha &&
1374
+ sourceFields.promotionChannelTreeSha &&
1375
+ sourceFields.builtSourceTreeSha === sourceFields.promotionChannelTreeSha,
1218
1376
  );
1219
1377
  const normalizedControllerReceipts = normalizeControllerReceiptReferences({
1220
1378
  receipts: controllerReceipts,
@@ -1222,8 +1380,8 @@ export function createReleasePassport({
1222
1380
  expectedSourceSha: sourceSha,
1223
1381
  acceptedSourceShas: acceptedControllerSourceShas({
1224
1382
  treeEquivalent,
1225
- builtSourceSha,
1226
- promotionChannelSha,
1383
+ builtSourceSha: sourceFields.builtSourceSha,
1384
+ promotionChannelSha: sourceFields.promotionChannelSha,
1227
1385
  sourceSha,
1228
1386
  recoveryTreeEquivalent,
1229
1387
  }),
@@ -1285,9 +1443,9 @@ export function createReleasePassport({
1285
1443
  releaseSha,
1286
1444
  releaseMaterialSha,
1287
1445
  builtSourceSha: optionalString(release.builtSourceSha || release.built_source_sha),
1288
- builtSourceTreeSha,
1446
+ builtSourceTreeSha: sourceFields.builtSourceTreeSha,
1289
1447
  promotionChannelSha: optionalString(release.promotionChannelSha || release.promotion_channel_sha),
1290
- promotionChannelTreeSha,
1448
+ promotionChannelTreeSha: sourceFields.promotionChannelTreeSha,
1291
1449
  treeEquivalent: release.treeEquivalent === undefined ? undefined : Boolean(release.treeEquivalent),
1292
1450
  publishToolingSha: optionalString(
1293
1451
  release.publishToolingSha ||
@@ -1325,15 +1483,17 @@ export function createReleasePassport({
1325
1483
  ["versionMaterial", versionMaterial],
1326
1484
  ["trustedPublishing", normalizedTrustedPublishing],
1327
1485
  ["transaction", normalizedTransaction],
1328
- ["promotionRouting", normalizedPromotionRouting],
1329
- ["buildSummary", normalizedBuildSummary],
1330
- ["buildFacts", normalizedBuildFacts],
1331
- ["platformArtifactManifests", normalizedPlatformArtifactManifests],
1332
- ["distTagPromotion", normalizedDistTagPromotionEvidence],
1486
+ ["promotionRouting", promotion.routing],
1487
+ ["buildSummary", buildEvidence.buildSummary],
1488
+ ["buildFacts", buildEvidence.buildFacts],
1489
+ ["platformArtifactManifests", buildEvidence.platformArtifactManifests],
1490
+ ["distTagPromotion", buildEvidence.distTagPromotionEvidence],
1333
1491
  ...kfdParts.sectionEntries,
1334
1492
  ["kfdAgentHub", normalizedKfdAgentHub],
1335
1493
  ["invariantPassports", invariantPassports],
1336
1494
  ["releaseEvidence", releaseEvidence],
1495
+ ["v4ConsumerPolicy", promotion.consumerPolicy],
1496
+ ["v4RuntimeResume", normalizedV4RuntimeResume],
1337
1497
  ["controllerReceipts", normalizedControllerReceipts],
1338
1498
  ["githubArtifactAttestations", normalizedGitHubArtifactAttestations],
1339
1499
  ]),
@@ -1360,21 +1520,21 @@ export function createReleasePassport({
1360
1520
  artifactEvidence: artifactEvidencePath,
1361
1521
  publishEvidence: publishEvidencePath,
1362
1522
  transactionState: transactionStatePath,
1363
- buildSummary: normalizedBuildSummary?.path || "",
1364
- buildFacts: normalizedBuildFacts.map((fact) => ({
1523
+ buildSummary: buildEvidence.buildSummary?.path || "",
1524
+ buildFacts: buildEvidence.buildFacts.map((fact) => ({
1365
1525
  path: fact.path || "",
1366
1526
  sha256: fact.sha256 || "",
1367
1527
  contract: fact.fields?.contract || "",
1368
1528
  id: fact.fields?.id || "",
1369
1529
  digest: fact.fields?.digest || "",
1370
1530
  })),
1371
- platformArtifactManifests: normalizedPlatformArtifactManifests.map((manifest) => ({
1531
+ platformArtifactManifests: buildEvidence.platformArtifactManifests.map((manifest) => ({
1372
1532
  path: manifest.path,
1373
1533
  sha256: manifest.sha256,
1374
1534
  platform: manifest.platform,
1375
1535
  artifactName: manifest.artifactName,
1376
1536
  })),
1377
- distTagPromotionEvidence: normalizedDistTagPromotionEvidence?.path || "",
1537
+ distTagPromotionEvidence: buildEvidence.distTagPromotionEvidence?.path || "",
1378
1538
  ...kfdParts.evidence,
1379
1539
  kfdAgentHub: normalizedKfdAgentHub ? optionalString(kfdAgentHubEvidencePath || "kfd-agent-hub-evidence.json") : "",
1380
1540
  invariantPassports: invariantPassports ? "invariantPassports" : "",
@@ -1456,6 +1616,9 @@ export function collectGitHubReleasePassport({
1456
1616
  invariantPassportJsons = [],
1457
1617
  invariantPassportCommand = "",
1458
1618
  releaseEvidenceJsons = [],
1619
+ v4ConsumerPolicyCertificationJson = "",
1620
+ v4ConsumerPolicyCertificationRoot = "",
1621
+ v4RuntimeResumeEvidenceJson = "",
1459
1622
  kfdAgentHubEvidenceJson = "",
1460
1623
  controllerReceiptReferences = [],
1461
1624
  githubArtifactAttestationPolicyJsons = [],
@@ -1531,6 +1694,12 @@ export function collectGitHubReleasePassport({
1531
1694
  }),
1532
1695
  )
1533
1696
  .filter((meta) => meta.value);
1697
+ const v4ConsumerPolicyCertificationMeta =
1698
+ parseV4ConsumerPolicyCertification(v4ConsumerPolicyCertificationJson, cwd);
1699
+ const v4RuntimeResumeEvidence = parseJsonInput(v4RuntimeResumeEvidenceJson, undefined, {
1700
+ cwd,
1701
+ label: "v4RuntimeResumeEvidenceJson",
1702
+ });
1534
1703
  const kfdAgentHubEvidenceMeta = parseJsonInputWithMeta(
1535
1704
  kfdAgentHubEvidenceJson,
1536
1705
  undefined,
@@ -1656,6 +1825,9 @@ export function collectGitHubReleasePassport({
1656
1825
  kfdSupportEvidencePath: kfdSupport ? "kfd-support.json" : "",
1657
1826
  invariantPassports,
1658
1827
  releaseEvidence: releaseEvidenceAttachments.map(({ reference }) => reference),
1828
+ v4ConsumerPolicyCertification: v4ConsumerPolicyCertificationMeta.value,
1829
+ v4ConsumerPolicyCertificationRoot,
1830
+ v4RuntimeResumeEvidence,
1659
1831
  kfdAgentHubEvidence: kfdAgentHubEvidenceMeta.value
1660
1832
  ? { ...kfdAgentHubEvidenceMeta, path: "kfd-agent-hub-evidence.json" }
1661
1833
  : undefined,
@@ -2125,6 +2297,65 @@ function validateReleaseEvidenceAttachments({
2125
2297
  return { evidenceArtifacts, releaseEvidence };
2126
2298
  }
2127
2299
 
2300
+ function validateV4ConsumerPolicyPassportSection({ passport, issues }) {
2301
+ const routing = passport?.promotionRouting;
2302
+ const evidence = passport?.v4ConsumerPolicy;
2303
+ if (isV4PromotionRouting(routing) && !evidence) {
2304
+ issues.push(issue(
2305
+ "error",
2306
+ "v4ConsumerPolicy.missing",
2307
+ "Buildchain v4 Release Passport requires an external floating consumer policy certification",
2308
+ ));
2309
+ return;
2310
+ }
2311
+ if (!evidence) return;
2312
+ const verification = verifyV4FloatingConsumerPolicyCertification(
2313
+ releasePassportCertificationVerificationOptions({
2314
+ evidence,
2315
+ passport,
2316
+ routing,
2317
+ }),
2318
+ );
2319
+ for (const failure of verification.failures) {
2320
+ issues.push(issue("error", `v4ConsumerPolicy.${failure.code}`, failure.message));
2321
+ }
2322
+ }
2323
+
2324
+ function validateV4RuntimeResumePassportSection({ passport, issues }) {
2325
+ const evidence = passport?.v4RuntimeResume;
2326
+ if (!evidence) return;
2327
+ const consumerPolicyReceiptRoot = passport?.v4ConsumerPolicy?.certification?.receiptRoot || "";
2328
+ const authorization = verifyV4RuntimeAuthorizationReceipt({
2329
+ receipt: evidence.authorization,
2330
+ receiptRoot: evidence.authorizationRoot,
2331
+ repository: passport?.product?.repository || "",
2332
+ sourceSha: v4RuntimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
2333
+ runtimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
2334
+ consumerPolicyReceiptRoot,
2335
+ });
2336
+ for (const failure of authorization.failures) {
2337
+ issues.push(issue("error", `v4RuntimeResume.authorization.${failure}`, failure));
2338
+ }
2339
+ const lineage = verifyV4RuntimeResumeLineage({
2340
+ lineage: evidence.lineage,
2341
+ lineageRoot: evidence.lineageRoot,
2342
+ repository: passport?.product?.repository || "",
2343
+ sourceSha: v4RuntimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
2344
+ resumeRuntimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
2345
+ consumerPolicyReceiptRoot,
2346
+ });
2347
+ for (const failure of lineage.failures) {
2348
+ issues.push(issue("error", `v4RuntimeResume.lineage.${failure}`, failure));
2349
+ }
2350
+ if (evidence.lineage?.authorizationRoot !== evidence.authorizationRoot) {
2351
+ issues.push(issue(
2352
+ "error",
2353
+ "v4RuntimeResume.authorization-root-mismatch",
2354
+ "runtime resume lineage must bind the embedded authorization receipt root",
2355
+ ));
2356
+ }
2357
+ }
2358
+
2128
2359
  function validatePublishEvidenceSection({ passport, publishEvidence, normalizedPublishEvidence, issues }) {
2129
2360
  const publishEvidenceSupplied =
2130
2361
  Boolean(passport?.evidence?.publishEvidence) ||
@@ -2597,6 +2828,8 @@ export function createReleaseCheckReport({
2597
2828
  releaseEvidenceDocuments,
2598
2829
  issues,
2599
2830
  });
2831
+ validateV4ConsumerPolicyPassportSection({ passport, issues });
2832
+ validateV4RuntimeResumePassportSection({ passport, issues });
2600
2833
  validatePublishEvidenceSection({ passport, publishEvidence, normalizedPublishEvidence, issues });
2601
2834
  const evidenceIndex = indexEvidenceArtifacts(evidenceArtifacts);
2602
2835
  validateReleaseArtifacts({ artifacts, evidenceIndex, issues });
@@ -31,10 +31,10 @@ const root = path.resolve(
31
31
  );
32
32
 
33
33
  export const V4_ADOPTER_DELIVERY_PARITY_SOURCE = Object.freeze({
34
- v3Commit: "c3f58d76391c1c6ceddfc900a68e91c7ab82a575",
34
+ v3Commit: "6b96bdad8d9f8ccf9275f27d9370a226a9c78465",
35
35
  vectorSuiteRoot:
36
- "sha256:cf329805d928a9883cbafbdfdf21ef66c6a0889ed8dfe14356b4e0d25d6738f9",
37
- kfdPackage: "@kungfu-tech/kfd@1.0.0-alpha.62",
36
+ "sha256:c978707556406ffda4ef4192032332c01c2da1cebb6ad8c4f0edfc65d5cef0c7",
37
+ kfdPackage: "@kungfu-tech/kfd@1.0.0-alpha.65",
38
38
  });
39
39
 
40
40
  function clone(value) {