@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
@@ -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
  };
@@ -0,0 +1,240 @@
1
+ import { adopterDeliveryGateDigest } from "./adopter-delivery-gate.js";
2
+ import { validateAdopterDeliveryGateResult } from "./adopter-delivery-passport.js";
3
+
4
+ export const BUILDCHAIN_DELIVERY_BOOTSTRAP_CONTRACT =
5
+ "kungfu-buildchain-delivery-infrastructure-bootstrap/v1";
6
+
7
+ const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
8
+ const SHA_PATTERN = /^[0-9a-f]{40}$/;
9
+ const SEMVER_PATTERN =
10
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
11
+
12
+ function issue(code, message) {
13
+ return { code, message };
14
+ }
15
+
16
+ function exactRoot(value) {
17
+ return ROOT_PATTERN.test(value ?? "");
18
+ }
19
+
20
+ function exactCut(cut) {
21
+ return (
22
+ cut &&
23
+ typeof cut === "object" &&
24
+ typeof cut.version === "string" &&
25
+ SHA_PATTERN.test(cut.sourceCommit ?? "") &&
26
+ exactRoot(cut.packageRoot) &&
27
+ exactRoot(cut.gateRoot) &&
28
+ typeof cut.protocol?.id === "string" &&
29
+ typeof cut.protocol?.version === "string" &&
30
+ exactRoot(cut.protocol?.root) &&
31
+ typeof cut.profile?.id === "string" &&
32
+ typeof cut.profile?.version === "string" &&
33
+ exactRoot(cut.profile?.root)
34
+ );
35
+ }
36
+
37
+ function parseSemver(value) {
38
+ const match = SEMVER_PATTERN.exec(value ?? "");
39
+ if (!match) return null;
40
+ return {
41
+ core: match.slice(1, 4).map(Number),
42
+ prerelease: match[4] ? match[4].split(".") : [],
43
+ };
44
+ }
45
+
46
+ function compareIdentifier(left, right) {
47
+ const leftNumber = /^\d+$/.test(left) ? Number(left) : null;
48
+ const rightNumber = /^\d+$/.test(right) ? Number(right) : null;
49
+ if (leftNumber !== null && rightNumber !== null) {
50
+ return Math.sign(leftNumber - rightNumber);
51
+ }
52
+ if (leftNumber !== null) return -1;
53
+ if (rightNumber !== null) return 1;
54
+ return left === right ? 0 : left < right ? -1 : 1;
55
+ }
56
+
57
+ function compareSemver(leftValue, rightValue) {
58
+ const left = parseSemver(leftValue);
59
+ const right = parseSemver(rightValue);
60
+ if (!left || !right) return null;
61
+ for (let index = 0; index < left.core.length; index += 1) {
62
+ if (left.core[index] !== right.core[index]) {
63
+ return Math.sign(left.core[index] - right.core[index]);
64
+ }
65
+ }
66
+ if (left.prerelease.length === 0 || right.prerelease.length === 0) {
67
+ if (left.prerelease.length === right.prerelease.length) return 0;
68
+ return left.prerelease.length === 0 ? 1 : -1;
69
+ }
70
+ const width = Math.max(left.prerelease.length, right.prerelease.length);
71
+ for (let index = 0; index < width; index += 1) {
72
+ if (left.prerelease[index] === undefined) return -1;
73
+ if (right.prerelease[index] === undefined) return 1;
74
+ const comparison = compareIdentifier(
75
+ left.prerelease[index],
76
+ right.prerelease[index],
77
+ );
78
+ if (comparison !== 0) return comparison;
79
+ }
80
+ return 0;
81
+ }
82
+
83
+ function sameProtocol(left, right) {
84
+ return (
85
+ left?.id === right?.id &&
86
+ left?.version === right?.version &&
87
+ left?.root === right?.root
88
+ );
89
+ }
90
+
91
+ function validTransition(transition, authority, candidate) {
92
+ if (!transition || typeof transition !== "object") return false;
93
+ const body = structuredClone(transition);
94
+ const transitionRoot = body.transitionRoot;
95
+ delete body.transitionRoot;
96
+ return (
97
+ exactRoot(transitionRoot) &&
98
+ adopterDeliveryGateDigest(body) === transitionRoot &&
99
+ body.fromGateRoot === authority.gateRoot &&
100
+ body.toGateRoot === candidate.gateRoot &&
101
+ body.fromProtocolRoot === authority.protocol.root &&
102
+ body.toProtocolRoot === candidate.protocol.root &&
103
+ body.fromProfileRoot === authority.profile.root &&
104
+ body.toProfileRoot === candidate.profile.root &&
105
+ exactRoot(body.compatibilityProofRoot) &&
106
+ exactRoot(body.independentReviewRoot)
107
+ );
108
+ }
109
+
110
+ function validateWarrant(warrant, candidate) {
111
+ return (
112
+ warrant &&
113
+ typeof warrant === "object" &&
114
+ warrant.outcome === "merged" &&
115
+ warrant.sourceHead === candidate.sourceCommit &&
116
+ exactRoot(warrant.sourceProofRoot) &&
117
+ exactRoot(warrant.nativeProofRoot) &&
118
+ exactRoot(warrant.integrationProofRoot)
119
+ );
120
+ }
121
+
122
+ export function qualifyBuildchainDeliveryInfrastructureBootstrap({
123
+ authority,
124
+ candidate,
125
+ gateResult,
126
+ warrant,
127
+ transitionEvidence,
128
+ } = {}) {
129
+ const issues = [];
130
+ if (!exactCut(authority)) {
131
+ issues.push(
132
+ issue("bootstrap.authority.cut", "N-1 authority cut is incomplete"),
133
+ );
134
+ }
135
+ if (!exactCut(candidate)) {
136
+ issues.push(
137
+ issue("bootstrap.candidate.cut", "candidate cut is incomplete"),
138
+ );
139
+ }
140
+ if (authority?.protected !== true || authority?.published !== true) {
141
+ issues.push(
142
+ issue(
143
+ "bootstrap.authority.release",
144
+ "N-1 authority must be both protected and publicly released",
145
+ ),
146
+ );
147
+ }
148
+ if (candidate?.authorityVersion !== authority?.version) {
149
+ issues.push(
150
+ issue(
151
+ "bootstrap.authority.stale",
152
+ "candidate must name the exact N-1 authority version",
153
+ ),
154
+ );
155
+ }
156
+ const versionOrder = compareSemver(authority?.version, candidate?.version);
157
+ if (versionOrder === null || versionOrder >= 0) {
158
+ issues.push(
159
+ issue(
160
+ "bootstrap.authority.order",
161
+ "N-1 authority version must precede the candidate version",
162
+ ),
163
+ );
164
+ }
165
+ if (
166
+ authority?.sourceCommit === candidate?.sourceCommit ||
167
+ authority?.packageRoot === candidate?.packageRoot
168
+ ) {
169
+ issues.push(
170
+ issue(
171
+ "bootstrap.self-authorization",
172
+ "candidate source or package cannot serve as its own N-1 authority",
173
+ ),
174
+ );
175
+ }
176
+
177
+ const gateValidation = validateAdopterDeliveryGateResult(gateResult);
178
+ if (!gateValidation.passed) {
179
+ issues.push(
180
+ issue(
181
+ "bootstrap.gate.failed",
182
+ "candidate must retain a passed public adopter delivery gate result",
183
+ ),
184
+ );
185
+ }
186
+ if (
187
+ gateResult?.artifact?.root !== candidate?.packageRoot ||
188
+ gateResult?.project?.adopterId !== "kungfu-systems/buildchain"
189
+ ) {
190
+ issues.push(
191
+ issue(
192
+ "bootstrap.gate.candidate",
193
+ "gate result must bind the exact Buildchain candidate package",
194
+ ),
195
+ );
196
+ }
197
+ if (!validateWarrant(warrant, candidate)) {
198
+ issues.push(
199
+ issue(
200
+ "bootstrap.warrant",
201
+ "merged Delivery Warrant evidence must bind the candidate source",
202
+ ),
203
+ );
204
+ }
205
+
206
+ const transitionRequired =
207
+ !sameProtocol(authority?.protocol, candidate?.protocol) ||
208
+ !sameProtocol(authority?.profile, candidate?.profile) ||
209
+ authority?.gateRoot !== candidate?.gateRoot;
210
+ if (
211
+ transitionRequired &&
212
+ !validTransition(transitionEvidence, authority, candidate)
213
+ ) {
214
+ issues.push(
215
+ issue(
216
+ "bootstrap.transition",
217
+ "gate, protocol, or profile changes require exact independent transition evidence",
218
+ ),
219
+ );
220
+ }
221
+
222
+ const result = {
223
+ schemaVersion: 1,
224
+ contract: BUILDCHAIN_DELIVERY_BOOTSTRAP_CONTRACT,
225
+ status: issues.length === 0 ? "passed" : "failed",
226
+ authority: structuredClone(authority ?? null),
227
+ candidate: structuredClone(candidate ?? null),
228
+ gateResultRoot: gateResult?.gateRoot ?? null,
229
+ warrant: structuredClone(warrant ?? null),
230
+ transitionRequired,
231
+ transitionEvidenceRoot: transitionEvidence?.transitionRoot ?? null,
232
+ issues,
233
+ qualifying: false,
234
+ selfCertified: false,
235
+ releaseAuthorized: false,
236
+ finalAuthority: "protected-n-minus-one-plus-exact-delivery-evidence",
237
+ };
238
+ result.bootstrapRoot = adopterDeliveryGateDigest(result);
239
+ return result;
240
+ }