@kungfu-tech/buildchain 4.0.1-alpha.2 → 4.0.1-alpha.21

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 (203) hide show
  1. package/actions/release-tail/README.md +8 -0
  2. package/architecture/ci-lane-change-budget.json +187 -0
  3. package/architecture/decisions/0002-next-development-transition.md +101 -0
  4. package/architecture/decisions/0003-two-phase-delivery-warrant.md +152 -0
  5. package/architecture/internal-capabilities.json +211 -8
  6. package/architecture/maintainability-policy.json +113 -28
  7. package/architecture/release-tail-contract-inventory.json +5 -2
  8. package/architecture/v3-core-mechanism-inventory.json +91 -0
  9. package/architecture/v4-adopter-delivery-parity.json +32 -5
  10. package/architecture/v4-capability-state-machine-manifest.json +73 -0
  11. package/architecture/v4-compatibility-facts-parity.json +77 -0
  12. package/architecture/v4-delivery-authority-parity.json +250 -0
  13. package/architecture/v4-delivery-warrant-shadow-fixtures.json +41 -9
  14. package/architecture/v4-floating-consumer-policy.json +6 -0
  15. package/architecture/v4-next-development-parity.json +192 -0
  16. package/architecture/v4-publication-rehearsal-parity.json +84 -0
  17. package/architecture/v4-release-train-parity.json +1 -0
  18. package/architecture/v4-tail-reseal-parity.json +150 -0
  19. package/bin/buildchain.mjs +32 -3
  20. package/bin/internal/adopter-delivery-cli.mjs +70 -0
  21. package/bin/internal/command-registry.mjs +3 -0
  22. package/bin/internal/compatibility-facts-cli.mjs +101 -0
  23. package/contracts/dev-delivery-authority-v2.schema.json +662 -0
  24. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  25. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  26. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  27. package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
  28. package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
  29. package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
  30. package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
  31. package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
  32. package/contracts/fixtures/v4-compatibility-facts-v1/shared.json +1129 -0
  33. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +7 -1
  34. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
  35. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
  36. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
  37. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
  38. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
  39. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
  40. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
  41. package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
  42. package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
  43. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +229 -0
  44. package/contracts/next-development-request-v1.schema.json +66 -0
  45. package/contracts/next-development-transition-v1.schema.json +292 -0
  46. package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
  47. package/contracts/v4-compatibility-facts-v1.schema.json +230 -0
  48. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +4 -2
  49. package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  50. package/contracts/v4-tail-reseal-v1.schema.json +276 -0
  51. package/dist/site/agent-index.json +5 -0
  52. package/dist/site/artifact-schemas.json +10 -0
  53. package/dist/site/buildchain-contract.json +1475 -27
  54. package/dist/site/buildchain-site.json +627 -31
  55. package/dist/site/capability-registry.json +17 -14
  56. package/dist/site/cli-registry.json +205 -3
  57. package/dist/site/kfd-claims.json +490 -16
  58. package/dist/site/kfd-upstream-aggregate.json +1 -1
  59. package/dist/site/manual-registry.json +52 -6
  60. package/dist/site/node-api-registry.json +14736 -8851
  61. package/dist/site/page-registry.json +593 -21
  62. package/dist/site/public-surface-audit.json +837 -48
  63. package/dist/site/publication-authority-registry.json +44 -8
  64. package/dist/site/publication-registry.json +4 -4
  65. package/dist/site/release-provenance.json +24 -0
  66. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +662 -0
  67. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
  68. package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
  69. package/dist/site/schemas/v4-compatibility-facts-v1.schema.json +230 -0
  70. package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  71. package/dist/site/site-manifest.json +34 -10
  72. package/dist/site/workflow-registry.json +160 -10
  73. package/docs/MAP.md +8 -2
  74. package/docs/cli-reference.md +404 -13
  75. package/docs/cli.md +8 -0
  76. package/docs/dev-alpha-candidate-patrol.md +8 -0
  77. package/docs/dev-delivery-qualification-landing-adr.md +251 -0
  78. package/docs/dev-delivery-warrant.md +351 -38
  79. package/docs/next-development-transition.md +118 -0
  80. package/docs/node-api-reference.md +646 -293
  81. package/docs/release-tail-provider-plane.md +30 -0
  82. package/docs/v4-adopter-delivery.md +133 -0
  83. package/docs/v4-compatibility-facts.md +91 -0
  84. package/docs/v4-publication-rehearsal.md +130 -0
  85. package/docs/v4-tail-reseal.md +73 -0
  86. package/docs/versioning.md +4 -3
  87. package/package.json +34 -6
  88. package/packages/core/adopter-delivery-passport.js +259 -0
  89. package/packages/core/adopter-delivery-vectors.js +158 -0
  90. package/packages/core/adopter-delivery-vectors.json +77 -0
  91. package/packages/core/buildchain-agent-manuals.js +3 -0
  92. package/packages/core/buildchain-compatibility-authority.js +336 -0
  93. package/packages/core/buildchain-compatibility-fact.js +394 -0
  94. package/packages/core/buildchain-compatibility-facts.json +217 -0
  95. package/packages/core/buildchain-compatibility-proof.js +566 -0
  96. package/packages/core/buildchain-config.js +84 -0
  97. package/packages/core/buildchain-contract.js +96 -143
  98. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  99. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  100. package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
  101. package/packages/core/buildchain-publication-authority.js +1 -0
  102. package/packages/core/channel-candidate.js +8 -0
  103. package/packages/core/channel-promotion-baseline.js +55 -0
  104. package/packages/core/ci-lane-change-budget.js +247 -0
  105. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  106. package/packages/core/dev-delivery-authority-candidate.js +270 -0
  107. package/packages/core/dev-delivery-authority-evidence.js +146 -0
  108. package/packages/core/dev-delivery-authority-landing.js +461 -0
  109. package/packages/core/dev-delivery-authority-observation.js +48 -0
  110. package/packages/core/dev-delivery-authority-qualification.js +591 -0
  111. package/packages/core/dev-delivery-authority-settlement.js +213 -0
  112. package/packages/core/dev-delivery-authority-state.js +583 -0
  113. package/packages/core/dev-delivery-candidate-identity.js +13 -0
  114. package/packages/core/dev-delivery-contract-surface.js +76 -0
  115. package/packages/core/dev-delivery-execution-failure.js +133 -0
  116. package/packages/core/dev-delivery-execution-transfer.js +592 -0
  117. package/packages/core/dev-delivery-landing-admission-core.js +119 -0
  118. package/packages/core/dev-delivery-landing-readback.js +598 -0
  119. package/packages/core/dev-delivery-landing-terminal-evidence.js +271 -0
  120. package/packages/core/dev-delivery-landing-testing-port.js +6 -0
  121. package/packages/core/dev-delivery-native-execution.js +110 -0
  122. package/packages/core/dev-delivery-native-proof.js +562 -0
  123. package/packages/core/dev-delivery-process-boundary.js +563 -0
  124. package/packages/core/dev-delivery-provider-attempt.js +127 -0
  125. package/packages/core/dev-delivery-provider-heartbeat.js +382 -0
  126. package/packages/core/dev-delivery-warrant-cancellation.js +1 -0
  127. package/packages/core/dev-delivery-warrant-qualification.js +145 -0
  128. package/packages/core/dev-delivery-warrant-settlement.js +237 -36
  129. package/packages/core/dev-delivery-warrant-state.js +587 -0
  130. package/packages/core/dev-delivery-warrant.js +328 -370
  131. package/packages/core/github-governance-authority.js +1 -0
  132. package/packages/core/index.js +5 -0
  133. package/packages/core/kungfu-temporal-fact.js +557 -0
  134. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  135. package/packages/core/next-development-candidate-reservation.js +186 -0
  136. package/packages/core/next-development-controller.js +728 -0
  137. package/packages/core/next-development-projection.js +287 -0
  138. package/packages/core/next-development-transition.js +738 -0
  139. package/packages/core/paper-agent-entry.js +11 -5
  140. package/packages/core/paper.js +16 -5
  141. package/packages/core/published-delivery-authority.js +266 -0
  142. package/packages/core/release-candidate-recovery.js +70 -15
  143. package/packages/core/release-candidate.js +2 -2
  144. package/packages/core/release-passport.js +36 -9
  145. package/packages/core/v4-adopter-delivery-parity.js +3 -3
  146. package/packages/core/v4-adopter-delivery.js +359 -0
  147. package/packages/core/v4-canonical-contracts.js +5 -0
  148. package/packages/core/v4-delivery-warrant-read-candidate.js +10 -3
  149. package/packages/core/v4-floating-consumer-evidence.js +18 -4
  150. package/packages/core/v4-floating-consumer-policy.js +143 -20
  151. package/packages/core/v4-floating-consumer-release-passport.js +32 -5
  152. package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
  153. package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
  154. package/packages/core/v4-publication-rehearsal.js +481 -0
  155. package/packages/core/v4-tail-reseal-contract.js +26 -0
  156. package/packages/core/v4-tail-reseal-github.js +178 -0
  157. package/packages/core/v4-tail-reseal-receipt.js +225 -0
  158. package/packages/core/v4-tail-reseal.js +594 -0
  159. package/packages/core/workflow-yaml-contract.js +24 -2
  160. package/scripts/buildchain-cli-help.mjs +41 -2
  161. package/scripts/check-ci-lane-change-budget.mjs +100 -0
  162. package/scripts/check-inventory.mjs +14 -3
  163. package/scripts/check-v4-floating-consumer-policy-contract.mjs +23 -4
  164. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  165. package/scripts/dev-delivery-authority-command-adapters.mjs +206 -0
  166. package/scripts/dev-delivery-authority-provider.mjs +28 -0
  167. package/scripts/dev-delivery-authority.mjs +490 -0
  168. package/scripts/dev-delivery-native-run.mjs +177 -0
  169. package/scripts/dev-delivery-process-boundary.mjs +260 -0
  170. package/scripts/dev-delivery-proof.mjs +67 -2
  171. package/scripts/dev-delivery-provider-heartbeat.mjs +215 -0
  172. package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
  173. package/scripts/dev-delivery-source-proof-reuse.mjs +13 -97
  174. package/scripts/dev-delivery-two-phase-resume.mjs +345 -0
  175. package/scripts/dev-delivery-two-phase.mjs +573 -0
  176. package/scripts/dev-delivery-warrant-options.mjs +266 -0
  177. package/scripts/dev-delivery-warrant-store.mjs +231 -0
  178. package/scripts/dev-delivery-warrant.mjs +232 -194
  179. package/scripts/dev-pr-auto-merge.mjs +1 -1
  180. package/scripts/dev-pr-delivery-warrant.mjs +11 -0
  181. package/scripts/dev-qualification-patrol.mjs +9 -9
  182. package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
  183. package/scripts/generate-channel-promotion-workflow.mjs +2 -2
  184. package/scripts/generate-next-development-guidance.mjs +49 -0
  185. package/scripts/generate-release-candidate-passport.mjs +152 -0
  186. package/scripts/generate-site-bundle.mjs +69 -4
  187. package/scripts/init-repo.mjs +22 -4
  188. package/scripts/next-development-self-dogfood-harness.mjs +460 -0
  189. package/scripts/next-development-self-dogfood.mjs +597 -0
  190. package/scripts/next-development-transition.mjs +47 -0
  191. package/scripts/npm-publish-transaction.mjs +2 -2
  192. package/scripts/promotion-channel-router.mjs +4 -4
  193. package/scripts/release-candidate-anchor-provenance.mjs +99 -0
  194. package/scripts/release-tail.mjs +51 -3
  195. package/scripts/release-train-self-dogfood.mjs +94 -92
  196. package/scripts/resume-from-candidate-run.mjs +557 -30
  197. package/scripts/site-capability-metadata.mjs +41 -0
  198. package/scripts/stable-candidate-qualification.mjs +9 -10
  199. package/scripts/v4-consumer-policy.mjs +5 -5
  200. package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
  201. package/scripts/v4-tail-reseal-macos-rehearsal.mjs +134 -0
  202. package/scripts/v4-tail-reseal.mjs +416 -0
  203. package/templates/native-dev-delivery.yml +143 -0
@@ -1,6 +1,10 @@
1
1
  import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
+ import {
5
+ createBuildchainContractWorld,
6
+ evaluateBuildchainContractLock,
7
+ } from "./buildchain-contract.js";
4
8
  import { parseYamlUses } from "./workflow-yaml-contract.js";
5
9
  import {
6
10
  V4_FLOATING_CONSUMER_POLICY,
@@ -22,6 +26,11 @@ const EXACT_SHA = /^[0-9a-f]{40}$/u;
22
26
  const SHA256_ROOT = /^sha256:[0-9a-f]{64}$/u;
23
27
  const BUILDCHAIN_REPOSITORY = "kungfu-systems/buildchain";
24
28
  const CHANNELS = Object.freeze({ v4: "stable", "v4-alpha": "alpha" });
29
+ const ALPHA_RECOVERY_BOOTSTRAP = Object.freeze({
30
+ selector: "alpha/v4/v4.0",
31
+ sourcePath: ".github/workflows/buildchain-ref-promotion-recovery.yml",
32
+ workflow: ".github/workflows/.release-candidate-promote.yml",
33
+ });
25
34
  const DEFAULT_STABLE_LOCK_PATH = ".buildchain/contract-lock.json";
26
35
  const DEFAULT_ALPHA_LOCK_PATH = ".buildchain/alpha-contract-lock.json";
27
36
  const TRANSIENT_ACTION =
@@ -29,6 +38,7 @@ const TRANSIENT_ACTION =
29
38
  const SCANNER_PATHS = Object.freeze([
30
39
  "architecture/v4-floating-consumer-policy.json",
31
40
  "contracts/v4-floating-consumer-policy-receipt-v1.schema.json",
41
+ "packages/core/buildchain-contract.js",
32
42
  "packages/core/v4-floating-consumer-policy.js",
33
43
  "packages/core/workflow-yaml-contract.js",
34
44
  "scripts/v4-consumer-policy.mjs",
@@ -272,7 +282,7 @@ function readContractLock(root, relative, expectedRef, label, failures) {
272
282
  }
273
283
  }
274
284
 
275
- function classifyBuildchainUses(records, failures) {
285
+ function classifyBuildchainUses(records, failures, { repository } = {}) {
276
286
  const uses = [];
277
287
  for (const record of records) {
278
288
  const parsed = coordinate(record.uses);
@@ -281,15 +291,27 @@ function classifyBuildchainUses(records, failures) {
281
291
  parsed.selector === "v4" ||
282
292
  parsed.selector === "v4-alpha" ||
283
293
  /^v4(?:[./-]|$)/u.test(parsed.selector) ||
294
+ parsed.selector === ALPHA_RECOVERY_BOOTSTRAP.selector ||
284
295
  EXACT_SHA.test(parsed.selector.toLowerCase()) ||
285
296
  parsed.selector.includes("${{");
286
297
  if (!v4Candidate) continue;
287
- const channel = CHANNELS[parsed.selector] || "";
298
+ const protectedBootstrap =
299
+ repository === BUILDCHAIN_REPOSITORY &&
300
+ normalizeWorkflowPath(parsed.path) ===
301
+ ALPHA_RECOVERY_BOOTSTRAP.workflow &&
302
+ record.sourcePath === ALPHA_RECOVERY_BOOTSTRAP.sourcePath &&
303
+ parsed.selector === ALPHA_RECOVERY_BOOTSTRAP.selector;
304
+ const channel =
305
+ CHANNELS[parsed.selector] || (protectedBootstrap ? "alpha" : "");
288
306
  uses.push({
289
307
  ...record,
290
308
  ...parsed,
291
309
  channel,
292
- selectorClass: channel ? "floating" : "rejected",
310
+ selectorClass: protectedBootstrap
311
+ ? "protected-bootstrap"
312
+ : channel
313
+ ? "floating"
314
+ : "rejected",
293
315
  });
294
316
  if (!channel) failures.push(selectorFailure(record, parsed.selector));
295
317
  }
@@ -315,8 +337,97 @@ function selectInvocation(uses, workflow, failures, source = "", channel = "") {
315
337
  return { expectedWorkflow, selected: invocations[0] };
316
338
  }
317
339
 
340
+ function scanInvocationSource({
341
+ sourceRoot,
342
+ invocationRoot,
343
+ sourceScan,
344
+ sourceUses,
345
+ failures,
346
+ repository,
347
+ }) {
348
+ if (invocationRoot === sourceRoot)
349
+ return { invocationScan: sourceScan, invocationUses: sourceUses };
350
+ try {
351
+ const invocationScan = enumerateUses(invocationRoot);
352
+ return {
353
+ invocationScan,
354
+ invocationUses: classifyBuildchainUses(invocationScan.records, failures, {
355
+ repository,
356
+ }),
357
+ };
358
+ } catch (error) {
359
+ failures.push({
360
+ code: "invocation-source-scan-failed",
361
+ message: error.message,
362
+ });
363
+ return {
364
+ invocationScan: { files: [], records: [] },
365
+ invocationUses: [],
366
+ };
367
+ }
368
+ }
369
+
370
+ function sourceScanRoot({
371
+ sourceRoot,
372
+ invocationRoot,
373
+ sourceScan,
374
+ invocationScan,
375
+ invocationUses,
376
+ }) {
377
+ const material =
378
+ invocationRoot === sourceRoot
379
+ ? sourceScan
380
+ : {
381
+ source: sourceScan,
382
+ invocation: {
383
+ files: invocationScan.files,
384
+ invocations: invocationUses,
385
+ },
386
+ };
387
+ return sha256(stableJson(material));
388
+ }
389
+
390
+ function verifySelectedLock({
391
+ selected,
392
+ stable,
393
+ alpha,
394
+ workflowSha,
395
+ failures,
396
+ }) {
397
+ const selectedLock = selected?.channel === "alpha" ? alpha : stable;
398
+ if (!selected?.channel || !selectedLock) return;
399
+ const authorityRef =
400
+ selected.selectorClass === "protected-bootstrap"
401
+ ? "v4-alpha"
402
+ : selected.selector;
403
+ try {
404
+ const compatibility = evaluateBuildchainContractLock({
405
+ lock: selectedLock,
406
+ current: createBuildchainContractWorld({ root: defaultRuntimeRoot() }),
407
+ runtimeRef: authorityRef,
408
+ runtimeSha: workflowSha,
409
+ runtimeClass: selected.channel,
410
+ workflowShellRef: authorityRef,
411
+ expectedChannel: selected.channel,
412
+ expectedMajor: "v4",
413
+ });
414
+ if (!compatibility.ok) {
415
+ failures.push({
416
+ code: "selected-lock-runtime-incompatible",
417
+ message: `${selected.channel} contract lock rejects resolved workflow shell ${workflowSha}: ${compatibility.reasons?.join("; ") || compatibility.status}`,
418
+ });
419
+ }
420
+ } catch (error) {
421
+ failures.push({
422
+ code: "selected-lock-contract-world-invalid",
423
+ message: `cannot evaluate ${selected.channel} contract lock against the resolved workflow shell: ${error.message}`,
424
+ });
425
+ }
426
+ }
427
+
318
428
  export function scanV4FloatingConsumerPolicy({
319
429
  root = process.cwd(),
430
+ invocationRoot = root,
320
431
  repository = "",
321
432
  sourceSha = "",
322
433
  invokedWorkflow = "",
@@ -330,6 +441,7 @@ export function scanV4FloatingConsumerPolicy({
330
441
  scannerRoot = "",
331
442
  } = {}) {
332
443
  const resolvedRoot = path.resolve(root);
444
+ const resolvedInvocationRoot = path.resolve(invocationRoot);
333
445
  if (!policy || policy.contract !== V4_FLOATING_CONSUMER_POLICY) {
334
446
  throw new Error(`policy must use ${V4_FLOATING_CONSUMER_POLICY}`);
335
447
  }
@@ -369,28 +481,34 @@ export function scanV4FloatingConsumerPolicy({
369
481
  } catch (error) {
370
482
  failures.push({ code: "source-scan-failed", message: error.message });
371
483
  }
372
- const buildchainUses = classifyBuildchainUses(scanned.records, failures);
484
+ const buildchainUses = classifyBuildchainUses(scanned.records, failures, {
485
+ repository,
486
+ });
487
+ const { invocationScan, invocationUses } = scanInvocationSource({
488
+ sourceRoot: resolvedRoot,
489
+ invocationRoot: resolvedInvocationRoot,
490
+ sourceScan: scanned,
491
+ sourceUses: buildchainUses,
492
+ failures,
493
+ repository,
494
+ });
373
495
  const sourcePath = String(invocationSourcePath || "")
374
496
  .split("@")[0]
375
497
  .replace(`${repository}/`, "");
376
498
  const { expectedWorkflow, selected } = selectInvocation(
377
- buildchainUses,
499
+ invocationUses,
378
500
  invokedWorkflow,
379
501
  failures,
380
502
  sourcePath,
381
503
  expectedInvocationChannel,
382
504
  );
383
- const selectedLock = selected?.channel === "alpha" ? alpha : stable;
384
- if (
385
- selected?.channel &&
386
- selectedLock?.buildchain?.resolvedSha?.toLowerCase() !==
387
- normalizedWorkflowSha
388
- ) {
389
- failures.push({
390
- code: "selected-lock-runtime-mismatch",
391
- message: `${selected.channel} contract lock does not bind resolved workflow shell ${normalizedWorkflowSha}`,
392
- });
393
- }
505
+ verifySelectedLock({
506
+ selected,
507
+ stable,
508
+ alpha,
509
+ workflowSha: normalizedWorkflowSha,
510
+ failures,
511
+ });
394
512
 
395
513
  const policyRoot = sha256(stableJson(policy));
396
514
  const resolvedScannerRoot = scannerRoot || policyRoot;
@@ -404,9 +522,14 @@ export function scanV4FloatingConsumerPolicy({
404
522
  stable: stable ? sha256(stableJson(stable)) : "",
405
523
  alpha: alpha ? sha256(stableJson(alpha)) : "",
406
524
  };
407
- const scanRoot = sha256(
408
- stableJson({ files: scanned.files, invocations: buildchainUses }),
409
- );
525
+ const sourceScan = { files: scanned.files, invocations: buildchainUses };
526
+ const scanRoot = sourceScanRoot({
527
+ sourceRoot: resolvedRoot,
528
+ invocationRoot: resolvedInvocationRoot,
529
+ sourceScan,
530
+ invocationScan,
531
+ invocationUses,
532
+ });
410
533
  const receipt = {
411
534
  schema: V4_FLOATING_CONSUMER_RECEIPT,
412
535
  status: failures.length ? "failed" : "passed",
@@ -439,7 +562,7 @@ export function scanV4FloatingConsumerPolicy({
439
562
  ok: failures.length === 0,
440
563
  failures,
441
564
  scannedFiles: scanned.files,
442
- invocations: buildchainUses,
565
+ invocations: invocationUses,
443
566
  receipt,
444
567
  receiptRoot,
445
568
  };
@@ -6,7 +6,6 @@ import {
6
6
  } from "./v4-floating-consumer-evidence.js";
7
7
 
8
8
  const SHA256_ROOT = /^sha256:[0-9a-f]{64}$/u;
9
-
10
9
  export function isV4PromotionRouting(value = undefined) {
11
10
  return [
12
11
  value?.router?.ref,
@@ -76,11 +75,33 @@ function normalizeCertification(value, expected) {
76
75
  }
77
76
  return { certificationRoot: verification.certificationRoot, certification };
78
77
  }
79
-
78
+ export function resolveV4ConsumerPolicyCertificationIdentity({
79
+ release = {},
80
+ routing = {},
81
+ runtimeResume = undefined,
82
+ sourceSha = "",
83
+ } = {}) {
84
+ const builtSourceSha =
85
+ release?.builtSourceSha || release?.built_source_sha || "";
86
+ const certification =
87
+ release?.certification?.certification || release?.certification;
88
+ const retainsCaller = certification?.caller?.sourceSha === sourceSha;
89
+ return {
90
+ sourceSha:
91
+ release?.treeEquivalent === true && builtSourceSha && !retainsCaller
92
+ ? builtSourceSha
93
+ : sourceSha,
94
+ runtimeSha:
95
+ runtimeResume?.lineage?.attempts?.build?.runtimeSha ||
96
+ routing?.runtime?.resolvedSha ||
97
+ "",
98
+ };
99
+ }
80
100
  export function requireV4ConsumerPolicyCertification({
81
101
  value,
82
102
  repository,
83
103
  sourceSha,
104
+ runtimeSha = "",
84
105
  routing,
85
106
  cwd,
86
107
  certificationRoot,
@@ -100,7 +121,7 @@ export function requireV4ConsumerPolicyCertification({
100
121
  return normalizeCertification(value, {
101
122
  repository,
102
123
  sourceSha,
103
- runtimeSha: routing?.runtime?.resolvedSha || "",
124
+ runtimeSha: runtimeSha || routing?.runtime?.resolvedSha || "",
104
125
  certificationRoot,
105
126
  ...(v4Routing ? resolveV4FloatingConsumerCallerLocks(value, cwd) : {}),
106
127
  });
@@ -112,12 +133,18 @@ export function releasePassportCertificationVerificationOptions({
112
133
  routing,
113
134
  }) {
114
135
  const authority = evidence?.certification?.authority || {};
136
+ const identity = resolveV4ConsumerPolicyCertificationIdentity({
137
+ release: { ...passport?.release, certification: evidence?.certification },
138
+ routing,
139
+ runtimeResume: passport?.v4RuntimeResume,
140
+ sourceSha: passport?.release?.sourceSha || "",
141
+ });
115
142
  return {
116
143
  certification: evidence?.certification,
117
144
  certificationRoot: evidence?.certificationRoot,
118
145
  repository: passport?.product?.repository || "",
119
- sourceSha: passport?.release?.sourceSha || "",
120
- resolvedRuntimeSha: routing?.runtime?.resolvedSha || "",
146
+ sourceSha: identity.sourceSha,
147
+ resolvedRuntimeSha: identity.runtimeSha,
121
148
  stableLockRoot: authority.contractLocks?.stable?.root || "",
122
149
  alphaLockRoot: authority.contractLocks?.alpha?.root || "",
123
150
  stableLockPath: authority.contractLocks?.stable?.path || "",