@kungfu-tech/buildchain 3.0.9-alpha.1 → 3.0.9-alpha.11

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 (105) hide show
  1. package/actions/promote-buildchain-ref/README.md +4 -0
  2. package/bin/buildchain.mjs +9 -1
  3. package/bin/internal/trust-release-release-handlers.mjs +1 -0
  4. package/contracts/dev-delivery-authority-v2.schema.json +253 -0
  5. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  6. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  7. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  8. package/contracts/next-development-request-v1.schema.json +66 -0
  9. package/contracts/next-development-transition-v1.schema.json +292 -0
  10. package/dist/site/agent-index.json +1 -0
  11. package/dist/site/artifact-schemas.json +2 -0
  12. package/dist/site/buildchain-contract.json +92 -27
  13. package/dist/site/buildchain-site.json +351 -38
  14. package/dist/site/capability-registry.json +7 -6
  15. package/dist/site/cli-registry.json +43 -3
  16. package/dist/site/controller-registry.json +6 -2
  17. package/dist/site/kfd-claims.json +223 -12
  18. package/dist/site/kfd-upstream-aggregate.json +9 -9
  19. package/dist/site/manual-registry.json +23 -7
  20. package/dist/site/node-api-registry.json +7926 -4533
  21. package/dist/site/page-registry.json +332 -27
  22. package/dist/site/public-surface-audit.json +359 -11
  23. package/dist/site/publication-registry.json +4 -4
  24. package/dist/site/release-passport-check-manifest.json +1 -0
  25. package/dist/site/release-provenance.json +14 -0
  26. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +442 -0
  27. package/dist/site/schemas/release-passport-v1.schema.json +3 -0
  28. package/dist/site/site-manifest.json +19 -11
  29. package/dist/site/workflow-registry.json +21 -10
  30. package/docs/MAP.md +5 -2
  31. package/docs/adopter-delivery-gate.md +106 -0
  32. package/docs/aws-us-elastic-runner-burst-plane.md +30 -3
  33. package/docs/cli-reference.md +202 -15
  34. package/docs/dev-alpha-candidate-patrol.md +8 -0
  35. package/docs/dev-delivery-qualification-landing-adr.md +137 -0
  36. package/docs/dev-delivery-warrant.md +149 -22
  37. package/docs/kfd-support.md +7 -2
  38. package/docs/next-development-transition.md +119 -0
  39. package/docs/node-api-reference.md +402 -204
  40. package/docs/release-governance.md +10 -7
  41. package/docs/release-passport.md +18 -2
  42. package/docs/versioning.md +4 -1
  43. package/package.json +23 -6
  44. package/packages/core/README.md +25 -0
  45. package/packages/core/adopter-delivery-gate.js +576 -0
  46. package/packages/core/adopter-delivery-json.js +66 -0
  47. package/packages/core/adopter-delivery-passport.js +259 -0
  48. package/packages/core/adopter-delivery-vectors.js +158 -0
  49. package/packages/core/adopter-delivery-vectors.json +77 -0
  50. package/packages/core/artifact-verification-envelope.js +5 -5
  51. package/packages/core/buildchain-agent-manuals.js +1 -0
  52. package/packages/core/buildchain-channel-identity.js +2 -3
  53. package/packages/core/buildchain-compatibility-proof.js +22 -0
  54. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  55. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  56. package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
  57. package/packages/core/channel-candidate.js +8 -0
  58. package/packages/core/channel-promotion-baseline.js +52 -0
  59. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  60. package/packages/core/dev-delivery-authority.js +996 -0
  61. package/packages/core/dev-delivery-native-proof.js +418 -0
  62. package/packages/core/dev-delivery-warrant-settlement.js +67 -20
  63. package/packages/core/dev-delivery-warrant.js +129 -46
  64. package/packages/core/kfd-adopter-category-driver.js +167 -0
  65. package/packages/core/kfd-adopter-manifest.js +49 -50
  66. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  67. package/packages/core/next-development-candidate-reservation.js +186 -0
  68. package/packages/core/next-development-controller.js +726 -0
  69. package/packages/core/next-development-projection.js +288 -0
  70. package/packages/core/next-development-transition.js +738 -0
  71. package/packages/core/paper-agent-entry.js +7 -4
  72. package/packages/core/paper.js +14 -7
  73. package/packages/core/published-delivery-authority.js +247 -0
  74. package/packages/core/release-passport-contract.js +10 -6
  75. package/packages/core/release-passport.js +37 -13
  76. package/scripts/aws-macos-jit-controller-core.mjs +239 -4
  77. package/scripts/aws-macos-jit-controller.mjs +198 -2
  78. package/scripts/aws-macos-jit-instance-rehydrate.mjs +260 -0
  79. package/scripts/aws-macos-jit-source-rebind.mjs +235 -14
  80. package/scripts/aws-macos-jit.mjs +12 -0
  81. package/scripts/buildchain-cli-help.mjs +10 -2
  82. package/scripts/check-internal-architecture.mjs +1 -0
  83. package/scripts/check-inventory.mjs +12 -1
  84. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  85. package/scripts/dev-delivery-authority.mjs +368 -0
  86. package/scripts/dev-delivery-native-run.mjs +235 -0
  87. package/scripts/dev-delivery-proof.mjs +64 -2
  88. package/scripts/dev-delivery-two-phase-resume.mjs +90 -0
  89. package/scripts/dev-delivery-two-phase.mjs +577 -0
  90. package/scripts/dev-delivery-warrant.mjs +48 -6
  91. package/scripts/dev-pr-delivery-warrant.mjs +19 -14
  92. package/scripts/generate-buildchain-kfd-witnesses.mjs +2 -2
  93. package/scripts/generate-channel-build-workflow.mjs +4 -0
  94. package/scripts/generate-next-development-guidance.mjs +49 -0
  95. package/scripts/generate-site-bundle.mjs +8 -3
  96. package/scripts/init-repo.mjs +135 -62
  97. package/scripts/next-development-self-dogfood-harness.mjs +409 -0
  98. package/scripts/next-development-self-dogfood.mjs +532 -0
  99. package/scripts/next-development-transition.mjs +47 -0
  100. package/scripts/release-candidate-tail-reseal.mjs +426 -0
  101. package/scripts/seal-artifact-signing-requests.mjs +7 -4
  102. package/scripts/site-capability-metadata.mjs +25 -1
  103. package/scripts/stable-candidate-qualification.mjs +7 -7
  104. package/scripts/workflow-call-contract.mjs +1 -1
  105. package/templates/native-dev-delivery.yml +86 -0
@@ -13,6 +13,7 @@ import {
13
13
  workCheck,
14
14
  } from "./paper-repository.js";
15
15
  import { mergePublicationRehearsalAgentInstructions } from "./publication-rehearsal-projection.js";
16
+ import { mergeNextDevelopmentAgentInstructions } from "./next-development-projection.js";
16
17
 
17
18
  export const PAPER_AGENT_ENTRY_CONTRACT = "kungfu-buildchain-paper-agent-entry";
18
19
  export const PAPER_AGENT_ENTRY_SCHEMA_VERSION = 1;
@@ -168,10 +169,12 @@ export function paperAgentEntryFiles({
168
169
  [PAPER_PATHS.agentEntry, jsonText(entry)],
169
170
  [
170
171
  PAPER_PATHS.agentInstructions,
171
- mergePublicationRehearsalAgentInstructions(
172
- mergePaperAgentEntryInstructions(currentAgents, {
173
- developmentRef: resolvedDevelopmentRef,
174
- }),
172
+ mergeNextDevelopmentAgentInstructions(
173
+ mergePublicationRehearsalAgentInstructions(
174
+ mergePaperAgentEntryInstructions(currentAgents, {
175
+ developmentRef: resolvedDevelopmentRef,
176
+ }),
177
+ ),
175
178
  ),
176
179
  ],
177
180
  ]);
@@ -51,6 +51,11 @@ import {
51
51
  projectPublicationRehearsalToml,
52
52
  publicationRehearsalWorkflow,
53
53
  } from "./publication-rehearsal-projection.js";
54
+ import {
55
+ appendNextDevelopmentToml,
56
+ nextDevelopmentWorkflowHeader,
57
+ projectNextDevelopmentToml,
58
+ } from "./next-development-projection.js";
54
59
 
55
60
  export { PAPER_PATHS, resolvePaperRepository } from "./paper-repository.js";
56
61
  export {
@@ -356,7 +361,7 @@ immutable_base_url = ${tomlString(joinUrl(siteBaseUrl, "archive").replace(/\/$/,
356
361
  registry_path = ".buildchain/publication/publication-registry.json"
357
362
  `
358
363
  : "";
359
- return appendPublicationRehearsalToml(`schema = 1
364
+ return appendNextDevelopmentToml(appendPublicationRehearsalToml(`schema = 1
360
365
 
361
366
  [project]
362
367
  type = "publication-artifact"
@@ -390,14 +395,14 @@ command = "make pdf"
390
395
 
391
396
  [lifecycle.verify]
392
397
  command = "make check"
393
- `);
398
+ `));
394
399
  }
395
400
 
396
401
  function scaffoldBuildWorkflow(
397
402
  buildchainSha,
398
403
  { artifactName = "paper-publication" } = {},
399
404
  ) {
400
- return `name: Build
405
+ return `${nextDevelopmentWorkflowHeader()}name: Build
401
406
 
402
407
  on:
403
408
  workflow_dispatch:
@@ -425,7 +430,7 @@ jobs:
425
430
  }
426
431
 
427
432
  function scaffoldVerifyWorkflow(buildchainSha) {
428
- return `name: Verify
433
+ return `${nextDevelopmentWorkflowHeader()}name: Verify
429
434
 
430
435
  on:
431
436
  pull_request:
@@ -456,7 +461,7 @@ function scaffoldReleaseWorkflow(
456
461
  const passportInput = releasePassportProductName
457
462
  ? ` release-passport-product-name: ${JSON.stringify(releasePassportProductName)}\n`
458
463
  : "";
459
- return `name: Paper Release
464
+ return `${nextDevelopmentWorkflowHeader()}name: Paper Release
460
465
 
461
466
  on:
462
467
  workflow_dispatch:
@@ -1017,8 +1022,10 @@ function migrationFiles({
1017
1022
  const files = new Map([
1018
1023
  [
1019
1024
  PAPER_PATHS.config,
1020
- projectPublicationRehearsalToml(
1021
- fs.readFileSync(path.resolve(cwd, PAPER_PATHS.config), "utf8"),
1025
+ projectNextDevelopmentToml(
1026
+ projectPublicationRehearsalToml(
1027
+ fs.readFileSync(path.resolve(cwd, PAPER_PATHS.config), "utf8"),
1028
+ ),
1022
1029
  ),
1023
1030
  ],
1024
1031
  [PAPER_PATHS.contractLock, contractLockText],
@@ -0,0 +1,247 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createReadStream } from "node:fs";
3
+ import { mkdir, mkdtemp, readFile, realpath, rm } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import path from "node:path";
6
+ import { promisify } from "node:util";
7
+ import { pathToFileURL } from "node:url";
8
+ import { execFile } from "node:child_process";
9
+
10
+ import { adopterDeliveryGateDigest } from "./adopter-delivery-gate.js";
11
+
12
+ export const PUBLISHED_DELIVERY_AUTHORITY_CONTRACT =
13
+ "kungfu-buildchain-published-delivery-authority/v1";
14
+
15
+ const execFileAsync = promisify(execFile);
16
+ const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
17
+ const PACKAGES = [
18
+ {
19
+ key: "buildchain",
20
+ name: "@kungfu-tech/buildchain",
21
+ packageRoot: "archive",
22
+ modules: {
23
+ adopterDeliveryGate: "packages/core/adopter-delivery-gate.js",
24
+ bootstrap: "packages/core/buildchain-delivery-bootstrap.js",
25
+ infrastructure: "packages/core/buildchain-delivery-infrastructure.js",
26
+ kfdCategoryDriver: "packages/core/kfd-adopter-category-driver.js",
27
+ },
28
+ },
29
+ {
30
+ key: "kfd",
31
+ name: "@kungfu-tech/kfd",
32
+ packageRoot: "profiles/adopter-conformance/adopters/kfd/manifest.json",
33
+ modules: {},
34
+ },
35
+ ];
36
+
37
+ async function sha256File(file) {
38
+ const hash = createHash("sha256");
39
+ for await (const chunk of createReadStream(file)) hash.update(chunk);
40
+ return `sha256:${hash.digest("hex")}`;
41
+ }
42
+
43
+ function exactDeclaration(value, expectedName, label) {
44
+ if (
45
+ value?.name !== expectedName ||
46
+ typeof value.version !== "string" ||
47
+ value.version.length === 0 ||
48
+ typeof value.archivePath !== "string" ||
49
+ value.archivePath.length === 0 ||
50
+ !ROOT_PATTERN.test(value.archiveRoot ?? "") ||
51
+ !ROOT_PATTERN.test(value.artifactRoot ?? "")
52
+ ) {
53
+ throw new TypeError(`${label} package declaration is incomplete`);
54
+ }
55
+ return structuredClone(value);
56
+ }
57
+
58
+ function safeArchiveEntries(listing, verboseListing, label) {
59
+ const entries = listing.split("\n").filter(Boolean);
60
+ const types = verboseListing.split("\n").filter(Boolean);
61
+ if (entries.length === 0 || entries.length !== types.length) {
62
+ throw new Error(`${label} archive listing is incomplete`);
63
+ }
64
+ for (let index = 0; index < entries.length; index += 1) {
65
+ const entry = entries[index];
66
+ const parts = entry.split("/");
67
+ if (
68
+ parts[0] !== "package" ||
69
+ parts.some((part, partIndex) =>
70
+ partIndex === parts.length - 1 && part === ""
71
+ ? false
72
+ : part === "" || part === "." || part === "..",
73
+ )
74
+ ) {
75
+ throw new Error(`${label} archive contains an unsafe path`);
76
+ }
77
+ if (!["-", "d"].includes(types[index][0])) {
78
+ throw new Error(`${label} archive contains a non-file entry`);
79
+ }
80
+ }
81
+ }
82
+
83
+ async function extractPackage(declaration, destination, definition, label) {
84
+ const observedRoot = await sha256File(declaration.archivePath);
85
+ if (observedRoot !== declaration.archiveRoot) {
86
+ throw new Error(`${label} archive bytes do not match archiveRoot`);
87
+ }
88
+ const [{ stdout: listing }, { stdout: verboseListing }] = await Promise.all([
89
+ execFileAsync("tar", ["-tzf", declaration.archivePath], {
90
+ maxBuffer: 16 * 1024 * 1024,
91
+ }),
92
+ execFileAsync("tar", ["-tvzf", declaration.archivePath], {
93
+ maxBuffer: 16 * 1024 * 1024,
94
+ }),
95
+ ]);
96
+ safeArchiveEntries(listing, verboseListing, label);
97
+ await mkdir(destination, { recursive: true });
98
+ await execFileAsync(
99
+ "tar",
100
+ [
101
+ "-xzf",
102
+ declaration.archivePath,
103
+ "--strip-components",
104
+ "1",
105
+ "-C",
106
+ destination,
107
+ ],
108
+ { maxBuffer: 16 * 1024 * 1024 },
109
+ );
110
+ const packageJsonPath = path.join(destination, "package.json");
111
+ const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
112
+ if (
113
+ packageJson.name !== declaration.name ||
114
+ packageJson.version !== declaration.version
115
+ ) {
116
+ throw new Error(`${label} extracted package identity does not match`);
117
+ }
118
+ if (definition.packageRoot === "archive") {
119
+ if (declaration.artifactRoot !== declaration.archiveRoot) {
120
+ throw new Error(`${label} package artifactRoot must match archiveRoot`);
121
+ }
122
+ } else {
123
+ const packageManifest = JSON.parse(
124
+ await readFile(path.join(destination, definition.packageRoot), "utf8"),
125
+ );
126
+ const packageCut = packageManifest?.kfdCut?.package;
127
+ if (
128
+ packageCut?.name !== declaration.name ||
129
+ packageCut?.version !== declaration.version ||
130
+ packageCut?.artifactRoot !== declaration.artifactRoot
131
+ ) {
132
+ throw new Error(`${label} semantic package identity does not match`);
133
+ }
134
+ }
135
+ const destinationRoot = await realpath(destination);
136
+ if (!destinationRoot.endsWith(path.join(...declaration.name.split("/")))) {
137
+ throw new Error(`${label} extraction escaped its package coordinate`);
138
+ }
139
+ return {
140
+ name: declaration.name,
141
+ version: declaration.version,
142
+ archiveRoot: declaration.archiveRoot,
143
+ artifactRoot: declaration.artifactRoot,
144
+ };
145
+ }
146
+
147
+ async function importAuthorityRuntime(buildchainRoot) {
148
+ const definition = PACKAGES[0];
149
+ const imported = {};
150
+ for (const [key, relativePath] of Object.entries(definition.modules)) {
151
+ imported[key] = await import(
152
+ pathToFileURL(path.join(buildchainRoot, relativePath)).href
153
+ );
154
+ }
155
+ const runtime = {
156
+ createAdopterDeliveryGate:
157
+ imported.adopterDeliveryGate.createAdopterDeliveryGate,
158
+ createPackageArtifactProfile:
159
+ imported.adopterDeliveryGate.createPackageArtifactProfile,
160
+ qualifyBuildchainDeliveryInfrastructureBootstrap:
161
+ imported.bootstrap.qualifyBuildchainDeliveryInfrastructureBootstrap,
162
+ createBuildchainDeliveryInfrastructureInstanceManifest:
163
+ imported.infrastructure
164
+ .createBuildchainDeliveryInfrastructureInstanceManifest,
165
+ verifyBuildchainDeliveryInfrastructureInstance:
166
+ imported.infrastructure.verifyBuildchainDeliveryInfrastructureInstance,
167
+ createKfdAdopterCategoryProtocolDriver:
168
+ imported.kfdCategoryDriver.createKfdAdopterCategoryProtocolDriver,
169
+ };
170
+ for (const [name, implementation] of Object.entries(runtime)) {
171
+ if (typeof implementation !== "function") {
172
+ throw new Error(`published Buildchain authority is missing ${name}`);
173
+ }
174
+ }
175
+ return runtime;
176
+ }
177
+
178
+ export async function loadPublishedBuildchainDeliveryAuthority({
179
+ buildchain,
180
+ kfd,
181
+ } = {}) {
182
+ const declarations = {
183
+ buildchain: exactDeclaration(
184
+ buildchain,
185
+ "@kungfu-tech/buildchain",
186
+ "Buildchain authority",
187
+ ),
188
+ kfd: exactDeclaration(kfd, "@kungfu-tech/kfd", "KFD authority"),
189
+ };
190
+ const temporaryRoot = await mkdtemp(
191
+ path.join(tmpdir(), "buildchain-published-delivery-authority-"),
192
+ );
193
+ let retained = false;
194
+ try {
195
+ const identities = {};
196
+ for (const definition of PACKAGES) {
197
+ identities[definition.key] = await extractPackage(
198
+ declarations[definition.key],
199
+ path.join(temporaryRoot, "node_modules", ...definition.name.split("/")),
200
+ definition,
201
+ `${definition.key} authority`,
202
+ );
203
+ }
204
+ const authorityRuntime = await importAuthorityRuntime(
205
+ path.join(temporaryRoot, "node_modules", ...PACKAGES[0].name.split("/")),
206
+ );
207
+ const authority = {
208
+ schemaVersion: 1,
209
+ contract: PUBLISHED_DELIVERY_AUTHORITY_CONTRACT,
210
+ packages: identities,
211
+ moduleCoordinates: structuredClone(PACKAGES[0].modules),
212
+ qualifying: false,
213
+ selfCertified: false,
214
+ releaseAuthorized: false,
215
+ finalAuthority:
216
+ "caller-bound-public-npm-archive-bytes-and-package-identity",
217
+ };
218
+ authority.authorityRoot = adopterDeliveryGateDigest(authority);
219
+ retained = true;
220
+ return {
221
+ ...authority,
222
+ authorityRuntime,
223
+ temporaryRoot,
224
+ async dispose() {
225
+ await rm(temporaryRoot, { recursive: true, force: true });
226
+ },
227
+ };
228
+ } finally {
229
+ if (!retained) await rm(temporaryRoot, { recursive: true, force: true });
230
+ }
231
+ }
232
+
233
+ export async function withPublishedBuildchainDeliveryAuthority(
234
+ declarations,
235
+ operation,
236
+ ) {
237
+ if (typeof operation !== "function") {
238
+ throw new TypeError("published authority operation must be a function");
239
+ }
240
+ const authority =
241
+ await loadPublishedBuildchainDeliveryAuthority(declarations);
242
+ try {
243
+ return await operation(authority);
244
+ } finally {
245
+ await authority.dispose();
246
+ }
247
+ }
@@ -10,6 +10,7 @@ import {
10
10
  installedKfdPackageArtifactRoot,
11
11
  validateKfdAdopterReleaseBinding,
12
12
  } from "./artifact-verification-envelope.js";
13
+ import { normalizeAdopterDeliveryPassportBinding } from "./adopter-delivery-passport.js";
13
14
 
14
15
  export const RELEASE_PASSPORT_CONTRACT = "kungfu-buildchain-release-passport";
15
16
  export const RELEASE_CHECK_REPORT_CONTRACT = "kungfu-buildchain-release-check-report";
@@ -110,6 +111,7 @@ export const RELEASE_PASSPORT_SCHEMA = {
110
111
  "kfd-1": OBJECT,
111
112
  "kfd-2": OBJECT,
112
113
  "kfd-3": OBJECT,
114
+ adopterDelivery: OBJECT,
113
115
  kfdAdopter: OBJECT,
114
116
  kfdSupport: OBJECT,
115
117
  },
@@ -134,6 +136,7 @@ const BUILDCHAIN_AGGREGATION_FIELDS = [
134
136
  "platformArtifactManifests",
135
137
  "distTagPromotion",
136
138
  "controllerReceipts",
139
+ "adopterDelivery",
137
140
  "kfdAdopter",
138
141
  "kfdSupport",
139
142
  "githubArtifactAttestations",
@@ -356,7 +359,7 @@ export function defaultReleaseLlmsText({ tag = "", passportPath = "buildchain.re
356
359
  ].join("\n");
357
360
  }
358
361
 
359
- export function buildReleaseArtifactEvidence({ normalizedAssets = [], repository = "", tag = "", sourceSha = "", workflow = {}, kfdAdopter } = {}) {
362
+ export function buildReleaseArtifactEvidence({ normalizedAssets = [], repository = "", tag = "", sourceSha = "", workflow = {}, adopterDelivery, kfdAdopter } = {}) {
360
363
  return {
361
364
  schemaVersion: 1,
362
365
  contract: "kungfu-buildchain-artifact-evidence",
@@ -381,6 +384,7 @@ export function buildReleaseArtifactEvidence({ normalizedAssets = [], repository
381
384
  sha256: asset.sha256, url: asset.url, githubAssetId: asset.githubAssetId,
382
385
  attestation: passportOptional(asset.attestation || ""),
383
386
  })),
387
+ ...(adopterDelivery ? { adopterDelivery: normalizeAdopterDeliveryPassportBinding(adopterDelivery) } : {}),
384
388
  ...(kfdAdopter ? { kfdAdopter: structuredClone(kfdAdopter) } : {}),
385
389
  };
386
390
  }
@@ -405,7 +409,7 @@ export function prepareReleasePassportKfdSections({ kfd1, kfd2Claims, kfd3, kfdA
405
409
  };
406
410
  }
407
411
 
408
- export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, sourceSha = "", checkedAt } = {}) {
412
+ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", sourceSha = "", checkedAt } = {}) {
409
413
  if (!manifest) {
410
414
  if (comparisonMatrix || gateResults.length > 0) {
411
415
  throw new Error("KFD support and product-gate inputs require --kfd-adopter-manifest-json; --kfd-support-matrix-json is comparison-only");
@@ -414,7 +418,7 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
414
418
  }
415
419
  const manifestGate = createKfdAdopterManifestGate({
416
420
  manifest, packageArtifactRoot: installedKfdPackageArtifactRoot(), gateResults,
417
- expectedSourceSha: sourceSha, checkedAt,
421
+ authorityPath: "kfd-adopter-manifest.json", expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha, checkedAt,
418
422
  });
419
423
  const legacyProjection = createKfdLegacySupportMatrixProjection({ manifest, manifestGate });
420
424
  if (comparisonMatrix) {
@@ -425,18 +429,18 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
425
429
  }
426
430
  return {
427
431
  manifest, manifestGate, legacyProjection,
428
- binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedSourceSha: sourceSha }),
432
+ binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha }),
429
433
  };
430
434
  }
431
435
 
432
- export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedSourceSha = "" } = {}) {
436
+ export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", expectedSourceSha = "" } = {}) {
433
437
  if (!binding) {
434
438
  return passportLegacyProjection
435
439
  ? [{ code: "kfdSupport.authority", message: "legacy KFD support projection requires the standard adopter manifest binding" }]
436
440
  : [];
437
441
  }
438
442
  const issues = validateKfdAdopterReleaseBinding(binding, {
439
- manifest, manifestGate, legacyProjection, expectedSourceSha,
443
+ manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha,
440
444
  }).issues.map((entry) => ({ code: `kfdAdopter.${entry.path || entry.code}`, message: entry.message, details: entry }));
441
445
  if (!artifactBinding || passportStableJson(artifactBinding) !== passportStableJson(binding)) {
442
446
  issues.push({ code: "kfdAdopter.artifactEvidence", message: "release passport and artifact evidence must bind the same exact KFD adopter closure" });
@@ -33,6 +33,10 @@ import { normalizeControllerReceiptReferences } from "./controller-evidence.js";
33
33
  import {
34
34
  normalizeGitHubArtifactAttestationPolicy,
35
35
  } from "./github-artifact-attestation.js";
36
+ import {
37
+ normalizeAdopterDeliveryPassportBinding,
38
+ validateAdopterDeliveryReleaseEvidence,
39
+ } from "./adopter-delivery-passport.js";
36
40
 
37
41
  export { RELEASE_CHECK_REPORT_CONTRACT, RELEASE_PASSPORT_CONTRACT };
38
42
  export const ARTIFACT_EVIDENCE_CONTRACT = "kungfu-buildchain-artifact-evidence";
@@ -1160,9 +1164,9 @@ function normalizePromotionRouting(value = undefined) {
1160
1164
  return JSON.parse(JSON.stringify(value));
1161
1165
  }
1162
1166
 
1163
- export function createArtifactEvidence({ assets = [], repository = "", tag = "", sourceSha = "", workflow = {}, kfdAdopter = undefined } = {}) {
1167
+ export function createArtifactEvidence({ assets = [], repository = "", tag = "", sourceSha = "", workflow = {}, adopterDelivery = undefined, kfdAdopter = undefined } = {}) {
1164
1168
  const normalizedAssets = assets.map((asset, index) => normalizeAsset(asset, index));
1165
- return buildReleaseArtifactEvidence({ normalizedAssets, repository, tag, sourceSha, workflow, kfdAdopter });
1169
+ return buildReleaseArtifactEvidence({ normalizedAssets, repository, tag, sourceSha, workflow, adopterDelivery, kfdAdopter });
1166
1170
  }
1167
1171
 
1168
1172
  function firstTruthy(...values) {
@@ -1187,11 +1191,13 @@ function acceptedControllerSourceShas(input) {
1187
1191
  : [];
1188
1192
  }
1189
1193
 
1190
- function prepareReleaseKfdAdopterArtifacts({ kfdAdopter, assets, repository, tag, sourceSha, workflow }) {
1191
- const normalized = kfdAdopter ? structuredClone(kfdAdopter) : undefined;
1194
+ function prepareReleaseAdopterArtifacts({ adopterDelivery, kfdAdopter, assets, repository, tag, sourceSha, workflow }) {
1195
+ const normalizedAdopterDelivery = normalizeAdopterDeliveryPassportBinding(adopterDelivery);
1196
+ const normalizedKfdAdopter = kfdAdopter ? structuredClone(kfdAdopter) : undefined;
1192
1197
  return {
1193
- normalized,
1194
- artifactEvidence: createArtifactEvidence({ assets, repository, tag, sourceSha, workflow, kfdAdopter: normalized }),
1198
+ normalizedAdopterDelivery,
1199
+ normalizedKfdAdopter,
1200
+ artifactEvidence: createArtifactEvidence({ assets, repository, tag, sourceSha, workflow, adopterDelivery: normalizedAdopterDelivery, kfdAdopter: normalizedKfdAdopter }),
1195
1201
  };
1196
1202
  }
1197
1203
 
@@ -1229,6 +1235,7 @@ export function createReleasePassport({
1229
1235
  kfd1 = undefined,
1230
1236
  kfd2Claims = [],
1231
1237
  kfd3 = undefined,
1238
+ adopterDelivery = undefined,
1232
1239
  kfdAdopter = undefined,
1233
1240
  kfdAdopterManifestEvidencePath = "",
1234
1241
  kfdAdopterGateEvidencePath = "",
@@ -1244,8 +1251,8 @@ export function createReleasePassport({
1244
1251
  checkedAt = "",
1245
1252
  } = {}) {
1246
1253
  const normalizedTag = nonEmptyString(tag, "tag");
1247
- const { normalized: normalizedKfdAdopter, artifactEvidence } = prepareReleaseKfdAdopterArtifacts({
1248
- kfdAdopter, assets, repository, tag: normalizedTag, sourceSha, workflow,
1254
+ const { normalizedAdopterDelivery, normalizedKfdAdopter, artifactEvidence } = prepareReleaseAdopterArtifacts({
1255
+ adopterDelivery, kfdAdopter, assets, repository, tag: normalizedTag, sourceSha, workflow,
1249
1256
  });
1250
1257
  const normalizedPublishEvidence = normalizePublishEvidence(publishEvidence);
1251
1258
  const normalizedPackageSet = normalizePackageSet(packageSet, { packageName, packageVersion, publish });
@@ -1405,6 +1412,7 @@ export function createReleasePassport({
1405
1412
  ["buildFacts", normalizedBuildFacts],
1406
1413
  ["platformArtifactManifests", normalizedPlatformArtifactManifests],
1407
1414
  ["distTagPromotion", normalizedDistTagPromotionEvidence],
1415
+ ["adopterDelivery", normalizedAdopterDelivery],
1408
1416
  ...kfdParts.sectionEntries,
1409
1417
  ["kfdAgentHub", normalizedKfdAgentHub],
1410
1418
  ["invariantPassports", invariantPassports],
@@ -1465,7 +1473,7 @@ export function createReleasePassport({
1465
1473
  };
1466
1474
  }
1467
1475
 
1468
- function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, sourceSha, checkedAt }) {
1476
+ function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, repository, sourceSha, checkedAt }) {
1469
1477
  const manifestMeta = parseJsonInputWithMeta(manifestJson, undefined, { cwd, label: "kfdAdopterManifestJson" });
1470
1478
  const supportMatrixMeta = parseJsonInputWithMeta(supportMatrixJson, undefined, { cwd, label: "kfdSupportMatrixJson" });
1471
1479
  const productGateMetas = (productGateJsons || [])
@@ -1476,7 +1484,7 @@ function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson,
1476
1484
  manifest: manifestMeta.value,
1477
1485
  gateResults: productGateMetas.map((meta) => meta.value),
1478
1486
  comparisonMatrix: supportMatrixMeta.value,
1479
- sourceSha,
1487
+ expectedAdopterId: repository || "kungfu-systems/buildchain", expectedSourceRepository: repository, sourceSha,
1480
1488
  checkedAt,
1481
1489
  });
1482
1490
  }
@@ -1525,7 +1533,7 @@ export function collectGitHubReleasePassport({
1525
1533
  kfd2ClaimJsons = [],
1526
1534
  kfd3PrebuildWitnessJsons = [],
1527
1535
  kfd3ArtifactWitnessJsons = [],
1528
- kfd3ArtifactVerifyCommand = "",
1536
+ kfd3ArtifactVerifyCommand = "", adopterDeliveryJson = "",
1529
1537
  kfdAdopterManifestJson = "",
1530
1538
  kfdSupportMatrixJson = "",
1531
1539
  kfdProductGateJsons = [],
@@ -1586,6 +1594,11 @@ export function collectGitHubReleasePassport({
1586
1594
  cwd,
1587
1595
  label: "KFD-3 artifact verify command",
1588
1596
  });
1597
+ const adopterDelivery = parseJsonInput(
1598
+ adopterDeliveryJson,
1599
+ undefined,
1600
+ { cwd, label: "adopterDeliveryJson" },
1601
+ );
1589
1602
  const basePassportMeta = parseJsonInputWithMeta(basePassportJson, undefined, { cwd, label: "basePassportJson" });
1590
1603
  const invariantPassportMetas = (invariantPassportJsons || [])
1591
1604
  .filter(Boolean)
@@ -1662,7 +1675,7 @@ export function collectGitHubReleasePassport({
1662
1675
  const productMechanism = defaultProductMechanism({ repository, productName });
1663
1676
  const kfdAdopterEvidence = collectKfdAdopterReleaseInputs({
1664
1677
  cwd, manifestJson: kfdAdopterManifestJson, supportMatrixJson: kfdSupportMatrixJson,
1665
- productGateJsons: kfdProductGateJsons, sourceSha, checkedAt: resolvedCheckedAt,
1678
+ productGateJsons: kfdProductGateJsons, repository, sourceSha, checkedAt: resolvedCheckedAt,
1666
1679
  });
1667
1680
  const {
1668
1681
  manifest: kfdAdopterManifest,
@@ -1676,6 +1689,7 @@ export function collectGitHubReleasePassport({
1676
1689
  tag: resolvedTag,
1677
1690
  sourceSha,
1678
1691
  workflow,
1692
+ adopterDelivery,
1679
1693
  kfdAdopter,
1680
1694
  });
1681
1695
  const bundledPublishEvidencePath = publishEvidenceMeta.value ? "evidence.json" : "";
@@ -1742,6 +1756,7 @@ export function collectGitHubReleasePassport({
1742
1756
  kfd1,
1743
1757
  kfd2Claims: kfd2ClaimMetas.map((meta) => meta.value),
1744
1758
  kfd3,
1759
+ adopterDelivery,
1745
1760
  kfdAdopter,
1746
1761
  kfdAdopterManifestEvidencePath: kfdAdopter ? "kfd-adopter-manifest.json" : "",
1747
1762
  kfdAdopterGateEvidencePath: kfdAdopter ? "kfd-adopter-manifest-gate.json" : "",
@@ -2094,6 +2109,13 @@ function validateReleaseEvidenceContracts({
2094
2109
  validateContract(agentIndex, AGENT_INDEX_CONTRACT, "agentIndex", issues);
2095
2110
  validateContract(productMechanism, PRODUCT_MECHANISM_CONTRACT, "productMechanism", issues);
2096
2111
  validateKfdAgentHubReleaseEvidence(passport?.kfdAgentHub, kfdAgentHubEvidence, issues);
2112
+ for (const entry of validateAdopterDeliveryReleaseEvidence({
2113
+ binding: passport?.adopterDelivery,
2114
+ artifactBinding: artifactEvidence?.adopterDelivery,
2115
+ expectedProjectRepository: optionalString(passport?.product?.repository),
2116
+ })) {
2117
+ issues.push(issue("error", entry.code, entry.message, entry.details));
2118
+ }
2097
2119
  for (const entry of validateKfdAdopterReleaseEvidence({
2098
2120
  binding: passport?.kfdAdopter,
2099
2121
  artifactBinding: artifactEvidence?.kfdAdopter,
@@ -2101,7 +2123,8 @@ function validateReleaseEvidenceContracts({
2101
2123
  manifestGate: kfdAdopterManifestGate,
2102
2124
  legacyProjection: kfdSupportEvidence,
2103
2125
  passportLegacyProjection: passport?.kfdSupport,
2104
- expectedSourceSha: optionalString(passport?.release?.sourceSha),
2126
+ expectedAdopterId: optionalString(passport?.product?.repository) || "kungfu-systems/buildchain",
2127
+ expectedSourceRepository: optionalString(passport?.product?.repository), expectedSourceSha: optionalString(passport?.release?.sourceSha),
2105
2128
  })) {
2106
2129
  issues.push(issue("error", entry.code, entry.message, entry.details));
2107
2130
  }
@@ -2650,6 +2673,7 @@ function buildReleaseCheckReport({
2650
2673
  ? passport.platformArtifactManifests.length
2651
2674
  : 0,
2652
2675
  distTagPromotionEvidencePresent: Boolean(passport?.distTagPromotion),
2676
+ adopterDeliveryPresent: Boolean(passport?.adopterDelivery),
2653
2677
  impactPresent: Boolean(impact),
2654
2678
  agentIndexPresent: Boolean(agentIndex),
2655
2679
  productMechanismPresent: Boolean(productMechanism),