@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
@@ -61,6 +61,10 @@ const SUPPORTED_SIGNING_PROFILES = new Set([
61
61
  "windows-authenticode",
62
62
  "detached-signature-v1",
63
63
  ]);
64
+ const SUPPORTED_SIGNING_ENTITLEMENTS_PROFILES = new Set([
65
+ "none",
66
+ "jit-executable-v1",
67
+ ]);
64
68
  const SUPPORTED_SIGNING_ARTIFACT_KINDS = new Set([
65
69
  "auto", "binary", "archive", "blob", "directory", "mach-o", "app-bundle",
66
70
  "framework-bundle", "plugin-bundle", "xpc-bundle", "dylib", "pkg", "dmg",
@@ -99,6 +103,27 @@ function normalizeStringArray(value, label) {
99
103
  return value.map((entry, index) => assertString(entry, `${label}[${index}]`));
100
104
  }
101
105
 
106
+ function normalizeSigningEntitlementsPaths(value, label) {
107
+ const paths = normalizeStringArray(value, label);
108
+ for (const [index, entry] of paths.entries()) {
109
+ const parts = entry.split("/");
110
+ if (
111
+ entry.startsWith("/") ||
112
+ entry.includes("\\") ||
113
+ entry.includes(",") ||
114
+ parts.some((part) => part === "" || part === "." || part === "..")
115
+ ) {
116
+ throw new Error(
117
+ `${label}[${index}] must be a safe archive-relative path`,
118
+ );
119
+ }
120
+ }
121
+ if (new Set(paths).size !== paths.length) {
122
+ throw new Error(`${label} must not contain duplicate paths`);
123
+ }
124
+ return paths;
125
+ }
126
+
102
127
  function getByDottedKey(target, key) {
103
128
  return String(key)
104
129
  .split(".")
@@ -211,6 +236,16 @@ export function normalizeBuildchainConfig(config) {
211
236
  if (normalized.publication !== undefined) {
212
237
  normalized.publication = normalizePublicationSection(normalized.publication);
213
238
  }
239
+ if (normalized.publication_rehearsal !== undefined) {
240
+ normalized.publication_rehearsal = normalizePublicationRehearsalSection(
241
+ normalized.publication_rehearsal,
242
+ );
243
+ }
244
+ if (normalized.adopter_delivery !== undefined) {
245
+ normalized.adopter_delivery = normalizeAdopterDeliverySection(
246
+ normalized.adopter_delivery,
247
+ );
248
+ }
214
249
  if (normalized.consumers !== undefined) {
215
250
  normalized.consumers = normalizeConsumersSection(normalized.consumers);
216
251
  }
@@ -362,7 +397,16 @@ function normalizeSigningSection(signing) {
362
397
  const artifacts = signing.artifacts.map((artifact, index) => {
363
398
  const label = `signing.artifacts[${index}]`;
364
399
  assertPlainObject(artifact, label);
365
- const allowedKeys = new Set(["id", "path", "profile", "kind", "platforms", "required"]);
400
+ const allowedKeys = new Set([
401
+ "id",
402
+ "path",
403
+ "profile",
404
+ "entitlements_profile",
405
+ "entitlements_paths",
406
+ "kind",
407
+ "platforms",
408
+ "required",
409
+ ]);
366
410
  for (const key of Object.keys(artifact)) {
367
411
  if (!allowedKeys.has(key)) {
368
412
  throw new Error(`${label}.${key} is not supported; declare desired signature state only`);
@@ -377,10 +421,41 @@ function normalizeSigningSection(signing) {
377
421
  if (!SUPPORTED_SIGNING_ARTIFACT_KINDS.has(kind)) {
378
422
  throw new Error(`${label}.kind is not a supported signing artifact kind`);
379
423
  }
424
+ const entitlementsProfile =
425
+ artifact.entitlements_profile === undefined
426
+ ? "none"
427
+ : assertString(
428
+ artifact.entitlements_profile,
429
+ `${label}.entitlements_profile`,
430
+ );
431
+ if (!SUPPORTED_SIGNING_ENTITLEMENTS_PROFILES.has(entitlementsProfile)) {
432
+ throw new Error(
433
+ `${label}.entitlements_profile must be one of none or jit-executable-v1`,
434
+ );
435
+ }
436
+ if (entitlementsProfile !== "none" && kind !== "archive") {
437
+ throw new Error(
438
+ `${label}.entitlements_profile ${entitlementsProfile} requires kind = "archive"`,
439
+ );
440
+ }
441
+ const entitlementsPaths = normalizeSigningEntitlementsPaths(
442
+ artifact.entitlements_paths,
443
+ `${label}.entitlements_paths`,
444
+ );
445
+ if (
446
+ (entitlementsProfile === "none" && entitlementsPaths.length !== 0) ||
447
+ (entitlementsProfile !== "none" && entitlementsPaths.length === 0)
448
+ ) {
449
+ throw new Error(
450
+ `${label}.entitlements_paths must be non-empty exactly when entitlements_profile is enabled`,
451
+ );
452
+ }
380
453
  return {
381
454
  id: artifact.id === undefined ? artifactPath : assertString(artifact.id, `${label}.id`),
382
455
  path: artifactPath,
383
456
  profile,
457
+ entitlementsProfile,
458
+ entitlementsPaths,
384
459
  kind,
385
460
  platforms: normalizeStringArray(artifact.platforms, `${label}.platforms`),
386
461
  required: optionalBoolean(artifact.required, true),
@@ -635,6 +710,80 @@ function normalizePublicationSection(publication) {
635
710
  };
636
711
  }
637
712
 
713
+ function normalizePublicationRehearsalSection(rehearsal) {
714
+ assertPlainObject(rehearsal, "publication_rehearsal");
715
+ const allowed = ["contract", "capsule_path", "candidate_root", "state_path", "evidence_path", "effect_default"];
716
+ const unknown = Object.keys(rehearsal).filter((key) => !allowed.includes(key));
717
+ if (unknown.length > 0) {
718
+ throw new Error(`publication_rehearsal contains unsupported fields: ${unknown.join(", ")}`);
719
+ }
720
+ const normalized = {
721
+ contract: assertString(rehearsal.contract, "publication_rehearsal.contract"),
722
+ capsulePath: posixPath(assertString(rehearsal.capsule_path, "publication_rehearsal.capsule_path")),
723
+ candidateRoot: posixPath(assertString(rehearsal.candidate_root, "publication_rehearsal.candidate_root")),
724
+ statePath: posixPath(assertString(rehearsal.state_path, "publication_rehearsal.state_path")),
725
+ evidencePath: posixPath(assertString(rehearsal.evidence_path, "publication_rehearsal.evidence_path")),
726
+ effectDefault: assertString(rehearsal.effect_default, "publication_rehearsal.effect_default"),
727
+ };
728
+ if (
729
+ normalized.contract !== "buildchain-v4-publication-rehearsal-capsule/v1" ||
730
+ normalized.effectDefault !== "disabled"
731
+ ) {
732
+ throw new Error("publication_rehearsal must use the v4 capsule contract with effect_default = disabled");
733
+ }
734
+ for (const [key, value] of Object.entries({
735
+ capsule_path: normalized.capsulePath,
736
+ candidate_root: normalized.candidateRoot,
737
+ state_path: normalized.statePath,
738
+ evidence_path: normalized.evidencePath,
739
+ })) {
740
+ if (value.startsWith("/") || value.includes("\\") || value.split("/").includes("..")) {
741
+ throw new Error(`publication_rehearsal.${key} must be repository-relative`);
742
+ }
743
+ }
744
+ return normalized;
745
+ }
746
+
747
+ function normalizeAdopterDeliverySection(delivery) {
748
+ assertPlainObject(delivery, "adopter_delivery");
749
+ const allowed = ["contract", "input_path", "readback_path", "bootstrap_path", "archive_path", "result_path", "driver_selector", "artifact_profile_selector"];
750
+ const unknown = Object.keys(delivery).filter((key) => !allowed.includes(key));
751
+ if (unknown.length > 0) {
752
+ throw new Error(`adopter_delivery contains unsupported fields: ${unknown.join(", ")}`);
753
+ }
754
+ const normalized = {
755
+ contract: assertString(delivery.contract, "adopter_delivery.contract"),
756
+ inputPath: posixPath(assertString(delivery.input_path, "adopter_delivery.input_path")),
757
+ readbackPath: posixPath(assertString(delivery.readback_path, "adopter_delivery.readback_path")),
758
+ bootstrapPath: posixPath(assertString(delivery.bootstrap_path, "adopter_delivery.bootstrap_path")),
759
+ archivePath: posixPath(assertString(delivery.archive_path, "adopter_delivery.archive_path")),
760
+ resultPath: posixPath(assertString(delivery.result_path, "adopter_delivery.result_path")),
761
+ driverSelector: assertString(delivery.driver_selector, "adopter_delivery.driver_selector"),
762
+ artifactProfileSelector: assertString(delivery.artifact_profile_selector, "adopter_delivery.artifact_profile_selector"),
763
+ };
764
+ if (normalized.contract !== "kungfu-buildchain-v4-adopter-delivery/v1") {
765
+ throw new Error("adopter_delivery contract is unsupported");
766
+ }
767
+ if (
768
+ !["json-assertion", "kfd-category", "legacy-kfd"].includes(normalized.driverSelector) ||
769
+ !["git-commit", "package"].includes(normalized.artifactProfileSelector)
770
+ ) {
771
+ throw new Error("adopter_delivery selector is unsupported");
772
+ }
773
+ for (const [key, value] of Object.entries({
774
+ input_path: normalized.inputPath,
775
+ readback_path: normalized.readbackPath,
776
+ bootstrap_path: normalized.bootstrapPath,
777
+ archive_path: normalized.archivePath,
778
+ result_path: normalized.resultPath,
779
+ })) {
780
+ if (value.startsWith("/") || value.includes("\\") || value.split("/").includes("..")) {
781
+ throw new Error(`adopter_delivery.${key} must be repository-relative`);
782
+ }
783
+ }
784
+ return normalized;
785
+ }
786
+
638
787
  function normalizePublicationArchive(archive = undefined) {
639
788
  if (archive === undefined) {
640
789
  return undefined;
@@ -7,8 +7,18 @@ import {
7
7
  normalizeBuildchainRef,
8
8
  parseBuildchainRefIdentity,
9
9
  } from "./buildchain-channel-identity.js";
10
+ import {
11
+ createHistoricalBuildchainCompatibilityFacts,
12
+ createHistoricalBuildchainCompatibilityProofs,
13
+ } from "./buildchain-compatibility-fact.js";
14
+ import {
15
+ assertBuildchainCompatibilityProjection,
16
+ createBuildchainCompatibilityProofRegistry,
17
+ } from "./buildchain-compatibility-authority.js";
18
+ import { evaluateBuildchainContractLock as evaluateFactBackedBuildchainContractLock } from "./buildchain-compatibility-proof.js";
10
19
  import { createControllerRegistry } from "./controller-evidence.js";
11
20
  import { enumerateWorkflowInputs } from "./public-surface-audit.js";
21
+ import { devDeliveryWorkflowContractSurface } from "./dev-delivery-contract-surface.js";
12
22
 
13
23
  export {
14
24
  BUILDCHAIN_CHANNELS,
@@ -17,11 +27,47 @@ export {
17
27
  parseBuildchainRefIdentity,
18
28
  };
19
29
 
30
+ export {
31
+ BUILDCHAIN_COMPATIBILITY_FACT_REGISTRY_SCHEMA,
32
+ BUILDCHAIN_COMPATIBILITY_FACT_SCHEMA,
33
+ BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA,
34
+ BUILDCHAIN_COMPATIBILITY_PROOF_SCHEMA,
35
+ BUILDCHAIN_COMPATIBILITY_RELEASE_EVIDENCE_SCHEMA,
36
+ createBuildchainCompatibilityFact,
37
+ createBuildchainCompatibilityFactRegistry,
38
+ createBuildchainCompatibilityProof,
39
+ createHistoricalBuildchainCompatibilityFacts,
40
+ createHistoricalBuildchainCompatibilityProofs,
41
+ verifyBuildchainCompatibilityFact,
42
+ verifyBuildchainCompatibilityFactRegistry,
43
+ verifyBuildchainCompatibilityProof,
44
+ } from "./buildchain-compatibility-fact.js";
45
+ export {
46
+ assertBuildchainCompatibilityProjection,
47
+ createBuildchainCompatibilityPathQuery,
48
+ createBuildchainCompatibilityProofRegistry,
49
+ createBuildchainCompatibilityReleaseEvidence,
50
+ resolveBuildchainCompatibilityProof,
51
+ verifyBuildchainCompatibilityPath,
52
+ } from "./buildchain-compatibility-authority.js";
53
+ export {
54
+ BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
55
+ BUILDCHAIN_LEGACY_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
56
+ createBuildchainCompatibilityVerificationReceipt,
57
+ verifyBuildchainCompatibilityVerificationReceipt,
58
+ } from "./buildchain-compatibility-proof.js";
59
+
20
60
  export const BUILDCHAIN_RUNTIME_CONTRACT_WORLD = "kungfu-buildchain-runtime-contract-world";
21
61
  export const BUILDCHAIN_CONTRACT_LOCK = "kungfu-buildchain-contract-lock";
22
62
 
23
63
  const DEFAULT_POLICY = "major-compatible";
24
- const FLOATING_CLASSES = new Set(["stable", "alpha"]);
64
+
65
+ function compatibilityAuthority() {
66
+ return {
67
+ compatibilityFacts: createHistoricalBuildchainCompatibilityFacts(),
68
+ compatibilityProofs: createHistoricalBuildchainCompatibilityProofs(),
69
+ };
70
+ }
25
71
 
26
72
  function optionalString(value) {
27
73
  return value === undefined || value === null ? "" : String(value);
@@ -125,8 +171,7 @@ export function createBuildchainContractWorld({
125
171
  packageJson = undefined,
126
172
  controllerRegistry = undefined,
127
173
  } = {}) {
128
- const pkg = packageJson || readJson(path.join(root, "package.json"), {});
129
- const majorLine = majorLineFromPackageVersion(pkg.version);
174
+ const pkg = packageJson || readJson(path.join(root, "package.json"), {}), majorLine = majorLineFromPackageVersion(pkg.version);
130
175
  const workflowDescriptors = controllerRegistry ? [] : enumerateWorkflowInputs({ root });
131
176
  const controllerWorkflowIds = new Set([
132
177
  "check",
@@ -217,6 +262,7 @@ export function createBuildchainContractWorld({
217
262
  "alpha and stable channel selections use separate consumer contract locks by default",
218
263
  ],
219
264
  }),
265
+ surface(root, devDeliveryWorkflowContractSurface(pkg, majorLine)),
220
266
  surface(root, {
221
267
  id: "release-candidate-promote",
222
268
  kind: "workflow",
@@ -795,26 +841,60 @@ export function createBuildchainContractWorld({
795
841
  version: pkg.version || "",
796
842
  repository: pkg.repository?.url || pkg.repository || "https://github.com/kungfu-systems/buildchain",
797
843
  },
798
- majorLine,
799
- compatibilityPolicy: DEFAULT_POLICY,
844
+ majorLine, compatibilityPolicy: DEFAULT_POLICY,
845
+ ...compatibilityAuthority(),
800
846
  surfaces,
801
847
  };
802
848
  return finalizeBuildchainContractWorld(base);
803
849
  }
804
850
 
805
851
  export function finalizeBuildchainContractWorld(contractWorld) {
852
+ if (!Array.isArray(contractWorld?.compatibilityFacts) || !Array.isArray(contractWorld?.compatibilityProofs)) {
853
+ throw new Error("contract world requires compatibility Facts and their proof projection");
854
+ }
855
+ const sourceSurfaces = (contractWorld.surfaces || []).map((entry) => ({ ...entry }));
856
+ const proofRegistry = createBuildchainCompatibilityProofRegistry({
857
+ proofs: contractWorld.compatibilityProofs,
858
+ surfaces: sourceSurfaces,
859
+ majorLine: contractWorld.majorLine,
860
+ });
861
+ if (JSON.stringify(contractWorld.compatibilityFacts) !== JSON.stringify(proofRegistry.facts)) {
862
+ throw new Error("contract world compatibility Facts drift from the verified registry");
863
+ }
806
864
  const world = {
807
865
  ...contractWorld,
808
- surfaces: (contractWorld.surfaces || []).map((entry) => ({ ...entry })),
866
+ compatibilityFacts: proofRegistry.facts,
867
+ compatibilityFactRegistryRoot: proofRegistry.factRegistryRoot,
868
+ compatibilityFactCutRoot: proofRegistry.factCutRoot,
869
+ compatibilityProofs: proofRegistry.proofs,
870
+ compatibilityProofRegistryRoot: proofRegistry.registryRoot,
871
+ surfaces: sourceSurfaces.map((entry) => {
872
+ const surfaceEntry = { ...entry };
873
+ delete surfaceEntry.compatibleBreakingDigests;
874
+ delete surfaceEntry.compatibilityProofRoots;
875
+ delete surfaceEntry.compatibilityFactRoots;
876
+ const projection = proofRegistry.projections[entry.id] || [];
877
+ if (projection.length > 0) {
878
+ surfaceEntry.compatibleBreakingDigests = projection.map((item) => item.breakingDigest);
879
+ surfaceEntry.compatibilityProofRoots = projection.map((item) => item.proofRoot);
880
+ surfaceEntry.compatibilityFactRoots = projection.map((item) => item.factRoot);
881
+ }
882
+ return surfaceEntry;
883
+ }),
809
884
  };
810
885
  const compatibilityModel = {
811
886
  schemaVersion: world.schemaVersion,
812
887
  contract: world.contract,
813
888
  majorLine: world.majorLine,
889
+ compatibilityFactRegistryRoot: world.compatibilityFactRegistryRoot,
890
+ compatibilityFactCutRoot: world.compatibilityFactCutRoot,
891
+ compatibilityProofRegistryRoot: world.compatibilityProofRegistryRoot,
814
892
  surfaces: world.surfaces.map((entry) => ({
815
893
  id: entry.id,
816
894
  kind: entry.kind,
817
895
  breakingDigest: entry.breakingDigest,
896
+ compatibilityProofRoots: entry.compatibilityProofRoots || [],
897
+ compatibilityFactRoots: entry.compatibilityFactRoots || [],
818
898
  })),
819
899
  };
820
900
  const digestModel = {
@@ -846,6 +926,9 @@ export function createBuildchainContractLock({
846
926
  contract: contractWorld.contract,
847
927
  contractDigest: contractWorld.contractDigest,
848
928
  compatibilityDigest: contractWorld.compatibilityDigest,
929
+ compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
930
+ compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
931
+ compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
849
932
  majorLine: contractWorld.majorLine,
850
933
  compatibilityPolicy,
851
934
  acceptedAt,
@@ -853,6 +936,8 @@ export function createBuildchainContractLock({
853
936
  id: entry.id,
854
937
  kind: entry.kind,
855
938
  breakingDigest: entry.breakingDigest,
939
+ compatibilityProofRoots: entry.compatibilityProofRoots || [],
940
+ compatibilityFactRoots: entry.compatibilityFactRoots || [],
856
941
  })),
857
942
  },
858
943
  };
@@ -889,143 +974,8 @@ export function readBuildchainContractLock(filePath) {
889
974
  return value;
890
975
  }
891
976
 
892
- function surfaceMap(surfaces = []) {
893
- return new Map(surfaces.map((entry) => [entry.id, entry]));
894
- }
895
-
896
- function evaluateChannelBinding({
897
- lock,
898
- workflowShellRef,
899
- runtimeRef,
900
- expectedChannel,
901
- expectedMajor,
902
- allowOpaqueRuntime,
903
- }) {
904
- if (!workflowShellRef && !expectedChannel && !expectedMajor) return null;
905
- return evaluateBuildchainChannelBinding({
906
- workflowShellRef,
907
- runtimeRef,
908
- lockRef: lock?.buildchain?.ref || "",
909
- lockMajorLine: lock?.buildchain?.majorLine || "",
910
- expectedChannel,
911
- expectedMajor,
912
- allowOpaqueRuntime,
913
- });
914
- }
915
-
916
- export function evaluateBuildchainContractLock({
917
- lock,
918
- current,
919
- runtimeRef = "",
920
- runtimeSha = "",
921
- runtimeClass = "",
922
- compatibilityPolicy = "",
923
- workflowShellRef = "",
924
- expectedChannel = "",
925
- expectedMajor = "",
926
- allowOpaqueRuntime = false,
927
- } = {}) {
928
- if (!current || current.contract !== BUILDCHAIN_RUNTIME_CONTRACT_WORLD) {
929
- throw new Error("current must be a Buildchain runtime contract world");
930
- }
931
- const binding = evaluateChannelBinding({
932
- lock,
933
- workflowShellRef,
934
- runtimeRef,
935
- expectedChannel,
936
- expectedMajor,
937
- allowOpaqueRuntime,
938
- });
939
- if (binding?.ok === false) {
940
- return {
941
- ok: false,
942
- status: binding.status,
943
- drift: false,
944
- compatible: false,
945
- issueRecommended: false,
946
- reasons: binding.reasons,
947
- channelBinding: binding,
948
- };
949
- }
950
- const floatingRuntime = FLOATING_CLASSES.has(runtimeClass);
951
- if (!floatingRuntime) {
952
- return {
953
- ok: true,
954
- status: "non-floating-runtime",
955
- drift: false,
956
- compatible: true,
957
- issueRecommended: false,
958
- reason: `runtime class ${runtimeClass || "unknown"} is not a stable floating ref`,
959
- };
960
- }
961
- if (!lock) {
962
- return {
963
- ok: true,
964
- status: "missing-lock",
965
- drift: false,
966
- compatible: true,
967
- issueRecommended: false,
968
- reason: "consumer repository has no Buildchain contract lock",
969
- };
970
- }
971
- const accepted = lock.buildchain || {};
972
- const policy = compatibilityPolicy || accepted.compatibilityPolicy || DEFAULT_POLICY;
973
- const shaDrift = !!accepted.resolvedSha && !!runtimeSha && accepted.resolvedSha !== runtimeSha;
974
- const contractDrift = !!accepted.contractDigest && accepted.contractDigest !== current.contractDigest;
975
- if (!shaDrift && !contractDrift) {
976
- return {
977
- ok: true,
978
- status: "unchanged",
979
- drift: false,
980
- compatible: true,
981
- issueRecommended: false,
982
- policy,
983
- accepted,
984
- current: contractSummary(current, runtimeRef, runtimeSha),
985
- };
986
- }
987
- const reasons = [];
988
- if (accepted.contract !== current.contract) {
989
- reasons.push(`contract changed from ${accepted.contract || "(unknown)"} to ${current.contract}`);
990
- }
991
- if (accepted.majorLine && accepted.majorLine !== current.majorLine) {
992
- reasons.push(`major line changed from ${accepted.majorLine} to ${current.majorLine}`);
993
- }
994
- if (policy === "exact" && accepted.contractDigest !== current.contractDigest) {
995
- reasons.push("exact policy requires the contract digest to remain unchanged");
996
- }
997
- if (!["major-compatible", "allow-additive", "exact"].includes(policy)) {
998
- reasons.push(`unsupported compatibility policy: ${policy}`);
999
- }
1000
- const currentSurfaces = surfaceMap(current.surfaces);
1001
- for (const oldSurface of accepted.surfaces || []) {
1002
- const nextSurface = currentSurfaces.get(oldSurface.id);
1003
- if (!nextSurface) {
1004
- reasons.push(`surface removed: ${oldSurface.id}`);
1005
- continue;
1006
- }
1007
- const compatibleBreakingDigests = new Set(nextSurface.compatibleBreakingDigests || []);
1008
- if (
1009
- nextSurface.breakingDigest !== oldSurface.breakingDigest
1010
- && !compatibleBreakingDigests.has(oldSurface.breakingDigest)
1011
- ) {
1012
- reasons.push(`surface breaking digest changed: ${oldSurface.id}`);
1013
- }
1014
- }
1015
- const compatible = reasons.length === 0;
1016
- return {
1017
- ok: compatible,
1018
- status: compatible ? "compatible-drift" : "breaking-drift",
1019
- drift: shaDrift || contractDrift,
1020
- shaDrift,
1021
- contractDrift,
1022
- compatible,
1023
- issueRecommended: true,
1024
- policy,
1025
- reasons,
1026
- accepted,
1027
- current: contractSummary(current, runtimeRef, runtimeSha),
1028
- };
977
+ export function evaluateBuildchainContractLock(options = {}) {
978
+ return evaluateFactBackedBuildchainContractLock(options);
1029
979
  }
1030
980
 
1031
981
  export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "") {
@@ -1035,6 +985,9 @@ export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "")
1035
985
  contract: contractWorld.contract,
1036
986
  contractDigest: contractWorld.contractDigest,
1037
987
  compatibilityDigest: contractWorld.compatibilityDigest,
988
+ compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
989
+ compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
990
+ compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
1038
991
  majorLine: contractWorld.majorLine,
1039
992
  surfaceCount: Array.isArray(contractWorld.surfaces) ? contractWorld.surfaces.length : 0,
1040
993
  };