@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
@@ -9,6 +9,7 @@ export const ARTIFACT_SIGNING_AUTHORITY_CONTRACT =
9
9
 
10
10
  const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/u;
11
11
  const SOURCE_SHA_PATTERN = /^[0-9a-f]{40}$/u;
12
+ const ENTITLEMENTS_PROFILES = new Set(["none", "jit-executable-v1"]);
12
13
  const FORBIDDEN_CREDENTIAL_KEYS =
13
14
  /(?:certificate|password|private.?key|secret|token|notary|issuer|team.?id|environment)/iu;
14
15
 
@@ -88,6 +89,64 @@ function exactSourceSha(value, label) {
88
89
  return normalized;
89
90
  }
90
91
 
92
+ function entitlementsPaths(value) {
93
+ if (value === undefined) return [];
94
+ if (!Array.isArray(value)) {
95
+ throw new Error("signing entitlements paths must be an array");
96
+ }
97
+ const paths = value.map((entry, index) => {
98
+ const normalized = nonEmptyString(
99
+ entry,
100
+ `signing entitlements paths[${index}]`,
101
+ );
102
+ const parts = normalized.split("/");
103
+ if (
104
+ normalized.startsWith("/") ||
105
+ normalized.includes("\\") ||
106
+ normalized.includes(",") ||
107
+ parts.some((part) => part === "" || part === "." || part === "..")
108
+ ) {
109
+ throw new Error(
110
+ `signing entitlements paths[${index}] must be a safe archive-relative path`,
111
+ );
112
+ }
113
+ return normalized;
114
+ });
115
+ if (new Set(paths).size !== paths.length) {
116
+ throw new Error("signing entitlements paths must not contain duplicates");
117
+ }
118
+ return paths;
119
+ }
120
+
121
+ function signingEntitlements(profileId, kind, signature) {
122
+ const profile = String(signature.entitlementsProfile || "none").trim();
123
+ const paths = entitlementsPaths(signature.entitlementsPaths);
124
+ if (!ENTITLEMENTS_PROFILES.has(profile)) {
125
+ throw new Error(
126
+ `unsupported signing entitlements profile: ${profile || "<empty>"}`,
127
+ );
128
+ }
129
+ if (
130
+ profile !== "none" &&
131
+ (profileId !== "apple-developer-id" || kind !== "archive")
132
+ ) {
133
+ throw new Error(
134
+ `signing entitlements profile ${profile} requires an Apple archive`,
135
+ );
136
+ }
137
+ if (
138
+ (profile === "none" && paths.length !== 0) ||
139
+ (profile !== "none" && paths.length === 0)
140
+ ) {
141
+ throw new Error(
142
+ "signing entitlements paths must be non-empty exactly when an entitlements profile is enabled",
143
+ );
144
+ }
145
+ return profile === "none"
146
+ ? {}
147
+ : { entitlementsProfile: profile, entitlementsPaths: paths };
148
+ }
149
+
91
150
  function assertNoCredentialMaterial(value, path = "request") {
92
151
  if (!value || typeof value !== "object") return;
93
152
  for (const [key, child] of Object.entries(value)) {
@@ -191,6 +250,7 @@ export function createArtifactSigningRequest({
191
250
  platform,
192
251
  artifactKind: kind,
193
252
  });
253
+ const entitlementIntent = signingEntitlements(profile.id, kind, signature);
194
254
  const request = {
195
255
  schemaVersion: 1,
196
256
  contract: ARTIFACT_SIGNING_REQUEST_CONTRACT,
@@ -253,6 +313,7 @@ export function createArtifactSigningRequest({
253
313
  profile: profile.id,
254
314
  provider: profile.provider,
255
315
  semantics: profile.semantics,
316
+ ...entitlementIntent,
256
317
  },
257
318
  delivery: {
258
319
  mode: nonEmptyString(
@@ -10,6 +10,7 @@ export const BUILDCHAIN_AGENT_MANUALS = Object.freeze([
10
10
  { id: "github-governance-authority", title: "GitHub governance authority", path: "docs/github-governance-authority.md", plane: "verify" },
11
11
  { id: "release-candidate", title: "Release Candidate Passport", path: "docs/release-candidate.md", plane: "verify" },
12
12
  { id: "release-train", title: "Release Train and Release Cut", path: "docs/release-train.md", plane: "verify" },
13
+ { id: "next-development-transition", title: "Next-development transition", path: "docs/next-development-transition.md", plane: "verify" },
13
14
  { id: "release-propagation", title: "Release propagation", path: "docs/release-propagation.md", plane: "use" },
14
15
  { id: "readme-badges", title: "README badge blocks", path: "docs/readme-badges.md", plane: "use" },
15
16
  { id: "homebrew", title: "Homebrew distribution indexes", path: "docs/homebrew.md", plane: "use" },
@@ -29,10 +30,12 @@ export const BUILDCHAIN_AGENT_MANUALS = Object.freeze([
29
30
  { id: "kfd-agent-hub", title: "KFD Agent Hub Builder flow", path: "docs/kfd-agent-hub.md", plane: "use" },
30
31
  { id: "lifecycle-protocol", title: "Lifecycle protocol", path: "docs/lifecycle-protocol.md", plane: "use" },
31
32
  { id: "reusable-build-surface", title: "Reusable build surface", path: "docs/reusable-build-surface.md", plane: "use" },
33
+ { id: "v4-adopter-delivery", title: "V4 public adopter delivery", path: "docs/v4-adopter-delivery.md", plane: "verify" },
32
34
  { id: "publish-transaction", title: "Publish transaction", path: "docs/publish-transaction.md", plane: "verify" },
33
35
  { id: "release-tail-contract", title: "Declarative release-tail contract", path: "docs/release-tail-contract.md", plane: "verify" },
34
36
  { id: "release-tail-provider-plane", title: "Declarative release-tail provider plane", path: "docs/release-tail-provider-plane.md", plane: "use" },
35
37
  { id: "release-governance", title: "Release governance", path: "docs/release-governance.md", plane: "why" },
38
+ { id: "v4-compatibility-facts", title: "Buildchain v4 compatibility Facts", path: "docs/v4-compatibility-facts.md", plane: "verify" },
36
39
  { id: "release-flow", title: "Release flow", path: "docs/release-flow.md", plane: "verify" },
37
40
  { id: "runtime-train-validation", title: "Runtime train validation", path: "docs/runtime-train-validation.md", plane: "verify" },
38
41
  { id: "versioning", title: "Versioning", path: "docs/versioning.md", plane: "why" },
@@ -0,0 +1,336 @@
1
+ import {
2
+ devDeliveryContentRoot as contentRoot,
3
+ devDeliveryExactRoot as exactRoot,
4
+ devDeliveryExactSha as exactSha,
5
+ devDeliveryText as text,
6
+ } from "./dev-delivery-common.js";
7
+ import {
8
+ BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA,
9
+ BUILDCHAIN_COMPATIBILITY_RELEASE_EVIDENCE_SCHEMA,
10
+ createBuildchainCompatibilityFactRegistry,
11
+ createHistoricalBuildchainCompatibilityProofs,
12
+ verifyBuildchainCompatibilityProof,
13
+ } from "./buildchain-compatibility-fact.js";
14
+ import {
15
+ KUNGFU_TEMPORAL_PATH_QUERY_SCHEMA,
16
+ verifyKungfuTemporalPath,
17
+ } from "./kungfu-temporal-fact.js";
18
+
19
+ const COMPATIBILITY_OPERATION = "accept-contract-lock";
20
+ const COMPATIBILITY_DIRECTION = "source-to-target";
21
+
22
+ function exactText(value, label) {
23
+ const normalized = text(value);
24
+ if (!normalized) throw new Error(`${label} must not be empty`);
25
+ return normalized;
26
+ }
27
+
28
+ function factInputFromProof(proof) {
29
+ return {
30
+ proofId: proof.proofId,
31
+ surfaceId: proof.source.surfaceId,
32
+ surfaceKind: proof.source.surfaceKind,
33
+ sourceBreakingDigest: proof.source.breakingDigest,
34
+ targetBreakingDigest: proof.target.breakingDigest,
35
+ scope: proof.scope,
36
+ evidence: proof.evidence,
37
+ authority: proof.authority,
38
+ cut: proof.cut,
39
+ };
40
+ }
41
+
42
+ function projectionForSurface({ proofs, factByProofRoot, surface }) {
43
+ const matching = proofs.filter(
44
+ (proof) =>
45
+ proof.target.surfaceId === surface.id &&
46
+ proof.target.surfaceKind === surface.kind &&
47
+ proof.target.breakingDigest === surface.breakingDigest &&
48
+ proof.operation === COMPATIBILITY_OPERATION,
49
+ );
50
+ const bySource = new Map();
51
+ for (const proof of matching) {
52
+ const sourceDigest = proof.source.breakingDigest;
53
+ if (bySource.has(sourceDigest))
54
+ throw new Error(
55
+ `ambiguous compatibility proof for ${surface.id} ${sourceDigest}`,
56
+ );
57
+ bySource.set(sourceDigest, proof);
58
+ }
59
+ return [...bySource.values()]
60
+ .sort((left, right) =>
61
+ left.source.breakingDigest.localeCompare(right.source.breakingDigest),
62
+ )
63
+ .map((proof) => ({
64
+ breakingDigest: proof.source.breakingDigest,
65
+ proofRoot: proof.proofRoot,
66
+ factRoot: factByProofRoot.get(proof.proofRoot)?.factRoot || "",
67
+ }));
68
+ }
69
+
70
+ export function createBuildchainCompatibilityProofRegistry({
71
+ proofs = createHistoricalBuildchainCompatibilityProofs(),
72
+ surfaces = [],
73
+ majorLine = "",
74
+ } = {}) {
75
+ const verifiedProofs = proofs
76
+ .map((proof) => {
77
+ const verification = verifyBuildchainCompatibilityProof(proof);
78
+ if (!verification.ok)
79
+ throw new Error(
80
+ `invalid compatibility proof: ${verification.reason}${verification.error ? `: ${verification.error}` : ""}`,
81
+ );
82
+ return verification.proof;
83
+ })
84
+ .sort((left, right) => left.proofRoot.localeCompare(right.proofRoot));
85
+ const factRegistry = createBuildchainCompatibilityFactRegistry({
86
+ factInputs: verifiedProofs.map(factInputFromProof),
87
+ });
88
+ const factByProofRoot = new Map(
89
+ factRegistry.facts.map((fact) => [fact.proof.proofRoot, fact]),
90
+ );
91
+ const projections = Object.fromEntries(
92
+ [...surfaces]
93
+ .sort((left, right) => left.id.localeCompare(right.id))
94
+ .map((surface) => [
95
+ surface.id,
96
+ projectionForSurface({
97
+ proofs: verifiedProofs,
98
+ factByProofRoot,
99
+ surface,
100
+ }),
101
+ ])
102
+ .filter(([, entries]) => entries.length > 0),
103
+ );
104
+ const identity = {
105
+ schema: BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA,
106
+ proofRoots: verifiedProofs.map((proof) => proof.proofRoot),
107
+ };
108
+ return {
109
+ ...identity,
110
+ proofs: verifiedProofs,
111
+ facts: factRegistry.facts,
112
+ factRegistry,
113
+ factRegistryRoot: factRegistry.registryRoot,
114
+ factCutRoot: factRegistry.currentCutRoot,
115
+ projections,
116
+ registryRoot: contentRoot(identity),
117
+ };
118
+ }
119
+
120
+ export function assertBuildchainCompatibilityProjection(contractWorld) {
121
+ if (
122
+ !Array.isArray(contractWorld?.compatibilityFacts) ||
123
+ !Array.isArray(contractWorld?.compatibilityProofs)
124
+ ) {
125
+ throw new Error(
126
+ "compatibility Facts and their proof projection are required",
127
+ );
128
+ }
129
+ const registry = createBuildchainCompatibilityProofRegistry({
130
+ proofs: contractWorld.compatibilityProofs,
131
+ surfaces: contractWorld.surfaces || [],
132
+ majorLine: contractWorld.majorLine,
133
+ });
134
+ if (contractWorld.compatibilityProofRegistryRoot !== registry.registryRoot) {
135
+ throw new Error("compatibility proof registry root mismatch");
136
+ }
137
+ if (
138
+ contractWorld.compatibilityFactRegistryRoot !== registry.factRegistryRoot
139
+ ) {
140
+ throw new Error("compatibility Fact registry root mismatch");
141
+ }
142
+ if (contractWorld.compatibilityFactCutRoot !== registry.factCutRoot) {
143
+ throw new Error("compatibility Fact Cut root mismatch");
144
+ }
145
+ if (
146
+ JSON.stringify(contractWorld.compatibilityFacts) !==
147
+ JSON.stringify(registry.facts)
148
+ ) {
149
+ throw new Error("compatibility Facts drift from the verified registry");
150
+ }
151
+ for (const surface of contractWorld.surfaces || []) {
152
+ const expected = registry.projections[surface.id] || [];
153
+ const expectedDigests = expected.map((entry) => entry.breakingDigest);
154
+ const expectedRoots = expected.map((entry) => entry.proofRoot);
155
+ const expectedFactRoots = expected.map((entry) => entry.factRoot);
156
+ const actualDigests = surface.compatibleBreakingDigests || [];
157
+ const actualRoots = surface.compatibilityProofRoots || [];
158
+ const actualFactRoots = surface.compatibilityFactRoots || [];
159
+ if (JSON.stringify(actualDigests) !== JSON.stringify(expectedDigests)) {
160
+ throw new Error(
161
+ `compatibleBreakingDigests projection mismatch for ${surface.id}`,
162
+ );
163
+ }
164
+ if (JSON.stringify(actualRoots) !== JSON.stringify(expectedRoots)) {
165
+ throw new Error(
166
+ `compatibilityProofRoots projection mismatch for ${surface.id}`,
167
+ );
168
+ }
169
+ if (JSON.stringify(actualFactRoots) !== JSON.stringify(expectedFactRoots)) {
170
+ throw new Error(
171
+ `compatibilityFactRoots projection mismatch for ${surface.id}`,
172
+ );
173
+ }
174
+ }
175
+ return {
176
+ ok: true,
177
+ reason: "exact-Fact-backed-projection",
178
+ registryRoot: registry.registryRoot,
179
+ factRegistryRoot: registry.factRegistryRoot,
180
+ factCutRoot: registry.factCutRoot,
181
+ };
182
+ }
183
+
184
+ export function verifyBuildchainCompatibilityPath({ registry, query } = {}) {
185
+ if (!registry?.temporalBundle)
186
+ throw new Error("compatibility Fact registry is required");
187
+ return verifyKungfuTemporalPath(registry.temporalBundle, query);
188
+ }
189
+
190
+ export function createBuildchainCompatibilityPathQuery({
191
+ registry,
192
+ queryId,
193
+ sourceRoot,
194
+ targetRoot,
195
+ relationPathRoots,
196
+ maxDepth = 1,
197
+ } = {}) {
198
+ if (!registry?.temporalBundle || registry.predicateRoots?.length !== 1) {
199
+ throw new Error(
200
+ "one exact compatibility Fact registry predicate is required",
201
+ );
202
+ }
203
+ const predicateRoot = registry.predicateRoots[0];
204
+ const predicate = registry.temporalBundle.predicates.find(
205
+ (entry) => entry.root === predicateRoot,
206
+ )?.record;
207
+ return {
208
+ schema: KUNGFU_TEMPORAL_PATH_QUERY_SCHEMA,
209
+ queryId: exactText(queryId, "queryId"),
210
+ operation: COMPATIBILITY_OPERATION,
211
+ predicateRoot,
212
+ sourceRoot: exactRoot(sourceRoot, "sourceRoot"),
213
+ targetRoot: exactRoot(targetRoot, "targetRoot"),
214
+ cutRoot: exactRoot(registry.currentCutRoot, "currentCutRoot"),
215
+ relationPathRoots: (relationPathRoots || []).map((entry) =>
216
+ exactRoot(entry, "relationPathRoot"),
217
+ ),
218
+ requiredAuthorityRoot: exactRoot(
219
+ predicate?.authorityRoot,
220
+ "requiredAuthorityRoot",
221
+ ),
222
+ maxDepth,
223
+ };
224
+ }
225
+
226
+ export function resolveBuildchainCompatibilityProof({
227
+ registry,
228
+ surface,
229
+ sourceBreakingDigest,
230
+ majorLine,
231
+ } = {}) {
232
+ const candidates = (registry?.proofs || []).filter(
233
+ (proof) =>
234
+ proof.source.surfaceId === surface.id &&
235
+ proof.source.surfaceKind === surface.kind &&
236
+ proof.source.breakingDigest === sourceBreakingDigest &&
237
+ proof.target.breakingDigest === surface.breakingDigest &&
238
+ proof.operation === COMPATIBILITY_OPERATION,
239
+ );
240
+ if (candidates.length === 0)
241
+ return { ok: false, reason: "compatibility-proof-missing" };
242
+ if (candidates.length > 1)
243
+ return { ok: false, reason: "ambiguous-compatibility-proof" };
244
+ const verification = verifyBuildchainCompatibilityProof(candidates[0]);
245
+ if (!verification.ok) return verification;
246
+ const projection = registry.projections?.[surface.id] || [];
247
+ if (
248
+ !projection.some(
249
+ (entry) =>
250
+ entry.breakingDigest === sourceBreakingDigest &&
251
+ entry.proofRoot === verification.proofRoot,
252
+ )
253
+ ) {
254
+ return { ok: false, reason: "compatibility-proof-projection-missing" };
255
+ }
256
+ const fact = registry.factRegistry?.facts.find(
257
+ (entry) => entry.proof.proofRoot === verification.proofRoot,
258
+ );
259
+ if (!fact) return { ok: false, reason: "compatibility-fact-missing" };
260
+ const query = createBuildchainCompatibilityPathQuery({
261
+ registry: registry.factRegistry,
262
+ queryId: `buildchain:compatibility:${surface.id}:${sourceBreakingDigest}:${surface.breakingDigest}`,
263
+ sourceRoot: fact.sourceRoot,
264
+ targetRoot: fact.targetRoot,
265
+ relationPathRoots: [fact.factRoot],
266
+ maxDepth: 1,
267
+ });
268
+ const pathReceipt = verifyBuildchainCompatibilityPath({
269
+ registry: registry.factRegistry,
270
+ query,
271
+ });
272
+ if (pathReceipt.record.status !== "accepted") {
273
+ return {
274
+ ok: false,
275
+ reason: pathReceipt.record.failureCode,
276
+ pathReceipt,
277
+ pathReceiptRoot: pathReceipt.root,
278
+ };
279
+ }
280
+ return {
281
+ ok: true,
282
+ reason: "Fact-backed-compatible-relation",
283
+ proof: verification.proof,
284
+ proofRoot: verification.proofRoot,
285
+ fact,
286
+ factRoot: fact.factRoot,
287
+ pathReceipt,
288
+ pathReceiptRoot: pathReceipt.root,
289
+ };
290
+ }
291
+
292
+ export function createBuildchainCompatibilityReleaseEvidence({
293
+ contractWorld,
294
+ release,
295
+ decisions = [],
296
+ } = {}) {
297
+ const projection = assertBuildchainCompatibilityProjection(contractWorld);
298
+ const normalizedRelease = {
299
+ sourceSha: exactSha(release?.sourceSha, "release.sourceSha"),
300
+ tag: exactText(release?.tag, "release.tag"),
301
+ channel: exactText(release?.channel, "release.channel"),
302
+ };
303
+ const rootSet = (field) =>
304
+ [...new Set(decisions.map((entry) => entry[field]).filter(Boolean))]
305
+ .map((entry) => exactRoot(entry, field))
306
+ .sort();
307
+ const compatibility = {
308
+ operation: COMPATIBILITY_OPERATION,
309
+ direction: COMPATIBILITY_DIRECTION,
310
+ authority: "Fact-registry-only",
311
+ grantsReleaseAuthority: false,
312
+ contractDigest: exactRoot(
313
+ contractWorld.contractDigest,
314
+ "contractWorld.contractDigest",
315
+ ),
316
+ compatibilityDigest: exactRoot(
317
+ contractWorld.compatibilityDigest,
318
+ "contractWorld.compatibilityDigest",
319
+ ),
320
+ factRegistryRoot: projection.factRegistryRoot,
321
+ factCutRoot: projection.factCutRoot,
322
+ proofRegistryRoot: projection.registryRoot,
323
+ usedFactRoots: rootSet("factRoot"),
324
+ usedProofRoots: rootSet("proofRoot"),
325
+ pathReceiptRoots: rootSet("pathReceiptRoot"),
326
+ };
327
+ const body = {
328
+ schemaVersion: 1,
329
+ contract: BUILDCHAIN_COMPATIBILITY_RELEASE_EVIDENCE_SCHEMA,
330
+ id: "buildchain-compatibility-facts",
331
+ kind: "compatibility-fact-lineage",
332
+ release: normalizedRelease,
333
+ compatibility,
334
+ };
335
+ return { ...body, evidenceRoot: contentRoot(body) };
336
+ }