@kungfu-tech/buildchain 4.0.1-alpha.5 → 4.0.1-alpha.55

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 (159) hide show
  1. package/README.md +9 -6
  2. package/actions/release-tail/README.md +8 -0
  3. package/actions/v4-release-candidate-promote/README.md +3 -0
  4. package/architecture/agent-change-map.md +1015 -0
  5. package/architecture/ci-lane-change-budget.json +256 -0
  6. package/architecture/decisions/0004-v4-declarative-release-tail.md +47 -0
  7. package/architecture/internal-capabilities.json +220 -15
  8. package/architecture/maintainability-debt.json +3229 -0
  9. package/architecture/maintainability-policy.json +489 -132
  10. package/architecture/release-tail-contract-inventory.json +5 -2
  11. package/architecture/v3-core-mechanism-inventory.json +4 -3
  12. package/architecture/v3-v4-capability-closure.md +59 -0
  13. package/architecture/v3-v4-live-capability-inventory.json +102404 -0
  14. package/architecture/v4-adopter-delivery-parity.json +32 -5
  15. package/architecture/v4-cross-platform-adopter-qualification.json +52 -0
  16. package/architecture/v4-delivery-warrant-shadow-fixtures.json +3 -3
  17. package/architecture/v4-floating-consumer-policy.json +6 -0
  18. package/architecture/v4-publication-rehearsal-parity.json +84 -0
  19. package/architecture/v4-runtime-semantic-closure.json +710 -0
  20. package/bin/buildchain.mjs +7 -1
  21. package/bin/internal/adopter-delivery-cli.mjs +70 -0
  22. package/bin/internal/command-registry.mjs +1 -0
  23. package/bin/internal/trust-release-release-handlers.mjs +5 -0
  24. package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
  25. package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
  26. package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
  27. package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
  28. package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
  29. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
  30. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
  31. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
  32. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
  33. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
  34. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
  35. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
  36. package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
  37. package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
  38. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  39. package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
  40. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +4 -2
  41. package/contracts/v4-publication-qualification-v1.schema.json +51 -0
  42. package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  43. package/dist/site/agent-index.json +4 -0
  44. package/dist/site/artifact-schemas.json +8 -0
  45. package/dist/site/buildchain-contract.json +125 -34
  46. package/dist/site/buildchain-site.json +308 -33
  47. package/dist/site/capability-registry.json +13 -12
  48. package/dist/site/cli-registry.json +57 -2
  49. package/dist/site/controller-registry.json +41 -5
  50. package/dist/site/kfd-claims.json +438 -24
  51. package/dist/site/kfd-upstream-aggregate.json +1 -1
  52. package/dist/site/manual-registry.json +22 -7
  53. package/dist/site/node-api-registry.json +12843 -9314
  54. package/dist/site/page-registry.json +288 -21
  55. package/dist/site/public-surface-audit.json +281 -21
  56. package/dist/site/publication-authority-registry.json +66 -8
  57. package/dist/site/publication-registry.json +4 -4
  58. package/dist/site/release-provenance.json +20 -0
  59. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
  60. package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
  61. package/dist/site/schemas/v4-publication-qualification-v1.schema.json +51 -0
  62. package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  63. package/dist/site/site-manifest.json +19 -11
  64. package/dist/site/workflow-registry.json +195 -17
  65. package/docs/MAP.md +4 -2
  66. package/docs/cli-reference.md +70 -2
  67. package/docs/cli.md +8 -0
  68. package/docs/dev-delivery-warrant.md +34 -10
  69. package/docs/node-api-reference.md +524 -279
  70. package/docs/publish-transaction.md +11 -4
  71. package/docs/release-candidate.md +7 -0
  72. package/docs/release-tail-provider-plane.md +30 -0
  73. package/docs/v4-adopter-delivery.md +152 -0
  74. package/docs/v4-declarative-release-tail-migration.md +43 -0
  75. package/docs/v4-publication-rehearsal.md +130 -0
  76. package/package.json +24 -4
  77. package/packages/core/adopter-delivery-passport.js +295 -0
  78. package/packages/core/adopter-delivery-vectors.js +158 -0
  79. package/packages/core/adopter-delivery-vectors.json +77 -0
  80. package/packages/core/buildchain-agent-manuals.js +1 -0
  81. package/packages/core/buildchain-config.js +84 -0
  82. package/packages/core/buildchain-contract.js +31 -1
  83. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  84. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  85. package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
  86. package/packages/core/buildchain-publication-authority.js +2 -0
  87. package/packages/core/ci-lane-change-budget.js +247 -0
  88. package/packages/core/dev-delivery-native-proof.js +43 -27
  89. package/packages/core/dev-delivery-warrant-settlement.js +239 -3
  90. package/packages/core/dev-delivery-warrant-state.js +46 -10
  91. package/packages/core/dev-delivery-warrant.js +29 -7
  92. package/packages/core/github-governance-authority.js +5 -4
  93. package/packages/core/index.js +6 -0
  94. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  95. package/packages/core/paper-scaffold-content.js +401 -0
  96. package/packages/core/paper.js +12 -378
  97. package/packages/core/publication-control-plane-audit.js +135 -111
  98. package/packages/core/publication-rehearsal-projection.js +104 -0
  99. package/packages/core/publication-rehearsal-runtime.js +190 -0
  100. package/packages/core/published-delivery-authority.js +266 -0
  101. package/packages/core/release-candidate-recovery.js +71 -15
  102. package/packages/core/release-candidate.js +2 -2
  103. package/packages/core/release-passport.js +95 -170
  104. package/packages/core/v4-adopter-delivery-parity.js +3 -3
  105. package/packages/core/v4-adopter-delivery.js +359 -0
  106. package/packages/core/v4-cross-platform-adopter-qualification.js +343 -0
  107. package/packages/core/v4-delivery-warrant-read-candidate.js +10 -3
  108. package/packages/core/v4-floating-consumer-evidence.js +18 -4
  109. package/packages/core/v4-floating-consumer-policy.js +139 -35
  110. package/packages/core/v4-floating-consumer-release-passport.js +154 -8
  111. package/packages/core/v4-publication-qualification.js +222 -0
  112. package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
  113. package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
  114. package/packages/core/v4-publication-rehearsal.js +481 -0
  115. package/packages/core/workflow-yaml-contract.js +24 -2
  116. package/scripts/artifact-signing-controller-core.mjs +1 -1
  117. package/scripts/audit-publication-control-plane.mjs +17 -17
  118. package/scripts/buildchain-cli-help.mjs +13 -0
  119. package/scripts/check-ci-lane-change-budget.mjs +100 -0
  120. package/scripts/check-internal-architecture.mjs +23 -3
  121. package/scripts/check-inventory.mjs +24 -6
  122. package/scripts/check-maintainability.mjs +145 -4
  123. package/scripts/check-project-cut-merge-queue-admission.mjs +87 -0
  124. package/scripts/check-v3-v4-capability-inventory.mjs +574 -0
  125. package/scripts/check-v4-floating-consumer-policy-contract.mjs +30 -4
  126. package/scripts/check-v4-runtime-semantic-closure.mjs +266 -0
  127. package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
  128. package/scripts/dev-delivery-source-proof-reuse.mjs +13 -97
  129. package/scripts/dev-delivery-warrant-options.mjs +27 -11
  130. package/scripts/dev-delivery-warrant-store.mjs +10 -6
  131. package/scripts/dev-delivery-warrant.mjs +50 -6
  132. package/scripts/dev-pr-auto-merge.mjs +25 -11
  133. package/scripts/dev-pr-delivery-warrant.mjs +45 -0
  134. package/scripts/dev-pr-prequeue-guard.mjs +0 -18
  135. package/scripts/dev-qualification-patrol.mjs +9 -9
  136. package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
  137. package/scripts/generate-agent-change-map.mjs +118 -0
  138. package/scripts/generate-channel-promotion-workflow.mjs +2 -2
  139. package/scripts/generate-release-candidate-passport.mjs +177 -0
  140. package/scripts/generate-site-bundle.mjs +36 -0
  141. package/scripts/maintainability-domain-metrics.mjs +237 -0
  142. package/scripts/maintainability-governance.mjs +473 -0
  143. package/scripts/maintainability-metrics.mjs +28 -6
  144. package/scripts/project-cut-merge-queue-admission.mjs +394 -0
  145. package/scripts/promotion-channel-router.mjs +4 -4
  146. package/scripts/promotion-routing-evidence.mjs +35 -6
  147. package/scripts/release-candidate-anchor-provenance.mjs +99 -0
  148. package/scripts/release-candidate-resolver.mjs +44 -0
  149. package/scripts/release-line-policy.mjs +25 -15
  150. package/scripts/release-tail.mjs +68 -3
  151. package/scripts/resume-from-candidate-run.mjs +595 -65
  152. package/scripts/run-lifecycle-core.mjs +341 -376
  153. package/scripts/site-capability-metadata.mjs +21 -0
  154. package/scripts/stable-candidate-qualification.mjs +9 -10
  155. package/scripts/v3-v4-capability-catalog.mjs +439 -0
  156. package/scripts/v4-consumer-policy.mjs +4 -0
  157. package/scripts/v4-cross-platform-adopter-qualification.mjs +228 -0
  158. package/scripts/v4-declarative-promotion-admission.mjs +42 -0
  159. package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+
7
+ import {
8
+ createV4CrossPlatformAdopterReport,
9
+ qualifyV4CrossPlatformAdopters,
10
+ summarizeV3V4CapabilityInventory,
11
+ } from "../packages/core/v4-cross-platform-adopter-qualification.js";
12
+
13
+ function flag(name, fallback = "") {
14
+ const index = process.argv.indexOf(`--${name}`);
15
+ return index === -1 ? fallback : process.argv[index + 1] || fallback;
16
+ }
17
+
18
+ function required(name) {
19
+ const value = flag(name);
20
+ if (!value) throw new Error(`--${name} is required`);
21
+ return value;
22
+ }
23
+
24
+ function repeated(name) {
25
+ const values = [];
26
+ for (let index = 0; index < process.argv.length; index += 1) {
27
+ if (process.argv[index] === `--${name}` && process.argv[index + 1])
28
+ values.push(process.argv[++index]);
29
+ }
30
+ return values;
31
+ }
32
+
33
+ function readJson(file) {
34
+ return JSON.parse(fs.readFileSync(file, "utf8"));
35
+ }
36
+
37
+ function writeJson(file, value) {
38
+ fs.mkdirSync(path.dirname(file), { recursive: true });
39
+ fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
40
+ }
41
+
42
+ function run(command, args, options = {}) {
43
+ const completed = spawnSync(command, args, {
44
+ encoding: "utf8",
45
+ ...options,
46
+ });
47
+ if (completed.error) throw completed.error;
48
+ return completed;
49
+ }
50
+
51
+ function expectPass(result, label) {
52
+ if (result.status !== 0)
53
+ throw new Error(
54
+ `${label} failed with ${result.status}: ${(result.stderr || "").trim()}`,
55
+ );
56
+ }
57
+
58
+ function resolveInput(consumerRoot, value) {
59
+ return path.isAbsolute(value) ? value : path.join(consumerRoot, value);
60
+ }
61
+
62
+ function runPlatform() {
63
+ const runtimeRoot = path.resolve(required("runtime-root"));
64
+ const consumerRoot = path.resolve(flag("consumer-root", process.cwd()));
65
+ const output = path.resolve(required("output"));
66
+ const workRoot = path.dirname(output);
67
+ const input = resolveInput(consumerRoot, required("input"));
68
+ const bootstrap = resolveInput(consumerRoot, required("bootstrap"));
69
+ const cli = path.join(runtimeRoot, "bin/buildchain.mjs");
70
+ const command = (subcommand, args) =>
71
+ run(process.execPath, [cli, "adopter-delivery", subcommand, ...args], {
72
+ cwd: consumerRoot,
73
+ env: process.env,
74
+ });
75
+
76
+ const inventory = readJson(
77
+ path.join(runtimeRoot, "architecture/v3-v4-live-capability-inventory.json"),
78
+ );
79
+ const inventoryEvidence = summarizeV3V4CapabilityInventory(inventory);
80
+ fs.mkdirSync(workRoot, { recursive: true });
81
+ const initialPath = path.join(workRoot, "initial-readback.json");
82
+ const retryPath = path.join(workRoot, "retry-readback.json");
83
+ const terminalPath = path.join(workRoot, "terminal-readback.json");
84
+ const tamperedPath = path.join(workRoot, "tampered-readback.json");
85
+ const bootstrapPath = path.join(workRoot, "bootstrap.json");
86
+
87
+ expectPass(
88
+ command("run", ["--input", input, "--output", initialPath]),
89
+ "initial public adopter delivery",
90
+ );
91
+ const initial = readJson(initialPath);
92
+ const tampered = structuredClone(initial);
93
+ tampered.gateResult.artifact.root = `sha256:${"f".repeat(64)}`;
94
+ writeJson(tamperedPath, tampered);
95
+ const rejected = command("verify", [
96
+ "--input",
97
+ input,
98
+ "--readback",
99
+ tamperedPath,
100
+ ]);
101
+ if (rejected.status === 0)
102
+ throw new Error("tampered public readback was not rejected");
103
+ expectPass(
104
+ command("run", ["--input", input, "--output", retryPath]),
105
+ "retry public adopter delivery",
106
+ );
107
+ const retry = readJson(retryPath);
108
+ expectPass(
109
+ command("verify", [
110
+ "--input",
111
+ input,
112
+ "--readback",
113
+ retryPath,
114
+ "--output",
115
+ terminalPath,
116
+ ]),
117
+ "terminal public adopter delivery readback",
118
+ );
119
+ const terminal = readJson(terminalPath);
120
+ expectPass(
121
+ command("bootstrap", ["--input", bootstrap, "--output", bootstrapPath]),
122
+ "public N-1 bootstrap",
123
+ );
124
+ const bootstrapEvidence = readJson(bootstrapPath);
125
+ const neutralDriver = run(
126
+ process.execPath,
127
+ [
128
+ "--test",
129
+ path.join(
130
+ runtimeRoot,
131
+ "tests/non-kfd-specification-driver-clean-room.test.mjs",
132
+ ),
133
+ ],
134
+ { cwd: runtimeRoot, env: process.env },
135
+ );
136
+ expectPass(neutralDriver, "independent protocol-neutral driver");
137
+
138
+ const report = createV4CrossPlatformAdopterReport({
139
+ platform: required("platform"),
140
+ consumer: required("consumer"),
141
+ sourceBinding: {
142
+ runtimeSha: required("runtime-sha"),
143
+ consumerSha: required("consumer-sha"),
144
+ inventoryRoot: inventoryEvidence.inventoryRoot,
145
+ sourceCuts: inventoryEvidence.sourceCuts,
146
+ },
147
+ capabilityMatrix: {
148
+ capabilityCount: inventoryEvidence.summary.capabilityCount,
149
+ categoryCounts: inventoryEvidence.summary.categoryCounts,
150
+ dispositionCounts: inventoryEvidence.summary.dispositionCounts,
151
+ categories: inventoryEvidence.categories,
152
+ },
153
+ execution: {
154
+ initialRun: {
155
+ status: "passed",
156
+ readbackRoot: initial.deliveryRoot,
157
+ },
158
+ tamperFailure: {
159
+ status: "failed-as-required",
160
+ exitCode: rejected.status ?? 1,
161
+ },
162
+ retryRun: {
163
+ status: "passed",
164
+ readbackRoot: retry.deliveryRoot,
165
+ },
166
+ terminalVerify: {
167
+ status: "passed",
168
+ readbackRoot: terminal.deliveryRoot,
169
+ },
170
+ bootstrap: {
171
+ status: "passed",
172
+ resultRoot: bootstrapEvidence.resultRoot,
173
+ },
174
+ neutralDriver: {
175
+ id: "ledger-specification-driver",
176
+ status: "passed",
177
+ kfdDependencyPresent: false,
178
+ },
179
+ },
180
+ authority: {
181
+ productionWrites: false,
182
+ providerEffects: false,
183
+ releaseEffects: false,
184
+ stablePublication: false,
185
+ },
186
+ });
187
+ writeJson(output, report);
188
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
189
+ }
190
+
191
+ function collectReports(root) {
192
+ const reports = [];
193
+ const visit = (directory) => {
194
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
195
+ const target = path.join(directory, entry.name);
196
+ if (entry.isDirectory()) visit(target);
197
+ else if (entry.isFile() && entry.name.endsWith(".json")) {
198
+ const candidate = readJson(target);
199
+ if (
200
+ candidate?.contract ===
201
+ "kungfu-buildchain-v4-cross-platform-adopter-report/v1"
202
+ )
203
+ reports.push(candidate);
204
+ }
205
+ }
206
+ };
207
+ visit(root);
208
+ return reports;
209
+ }
210
+
211
+ function aggregate() {
212
+ const reportsRoot = path.resolve(required("reports-root"));
213
+ const qualification = qualifyV4CrossPlatformAdopters({
214
+ reports: collectReports(reportsRoot),
215
+ consumers: repeated("consumer"),
216
+ });
217
+ const output = flag("output");
218
+ if (output) writeJson(path.resolve(output), qualification);
219
+ process.stdout.write(`${JSON.stringify(qualification, null, 2)}\n`);
220
+ }
221
+
222
+ const mode = process.argv[2] || "";
223
+ if (mode === "run") runPlatform();
224
+ else if (mode === "aggregate") aggregate();
225
+ else
226
+ throw new Error(
227
+ "usage: v4-cross-platform-adopter-qualification.mjs <run|aggregate> ...",
228
+ );
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ import { pathToFileURL } from "node:url";
3
+
4
+ import { assertV4DeclarativePromotionInputs } from "../packages/core/v4-publication-qualification.js";
5
+
6
+ export function admitV4DeclarativePromotion({
7
+ inputs,
8
+ runtimeRef,
9
+ declarative,
10
+ }) {
11
+ if (!/^v4(?:$|[-./])/u.test(String(runtimeRef || ""))) {
12
+ return Object.freeze({ mode: "legacy", admitted: true });
13
+ }
14
+ if (declarative !== true) {
15
+ const error = new Error(
16
+ "Buildchain v4 release-candidate-promote requires declarative-release-tail=true",
17
+ );
18
+ error.code = "v4-declarative-release-tail-required";
19
+ throw error;
20
+ }
21
+ assertV4DeclarativePromotionInputs(inputs);
22
+ return Object.freeze({ mode: "v4-declarative", admitted: true });
23
+ }
24
+
25
+ if (
26
+ process.argv[1] &&
27
+ import.meta.url === pathToFileURL(process.argv[1]).href
28
+ ) {
29
+ try {
30
+ const result = admitV4DeclarativePromotion({
31
+ inputs: JSON.parse(process.env.BUILDCHAIN_PROMOTION_INPUTS_JSON || "{}"),
32
+ runtimeRef: process.env.BUILDCHAIN_RUNTIME_REF,
33
+ declarative: process.env.BUILDCHAIN_DECLARATIVE_RELEASE_TAIL === "true",
34
+ });
35
+ process.stdout.write(`${JSON.stringify(result)}\n`);
36
+ } catch (error) {
37
+ process.stderr.write(
38
+ `v4-declarative-promotion-admission: ${error.code || "rejected"}: ${error.message}\n`,
39
+ );
40
+ process.exitCode = 1;
41
+ }
42
+ }
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+
3
+ import crypto from "node:crypto";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ import {
9
+ createV4PublicationRehearsalCapsule,
10
+ executeV4PublicationRehearsal,
11
+ } from "../packages/core/v4-publication-rehearsal.js";
12
+
13
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
14
+ const fixtureRoot = path.join(
15
+ root,
16
+ "contracts/fixtures/v4-publication-rehearsal-v1",
17
+ );
18
+ const candidateRoot = path.join(fixtureRoot, "candidate");
19
+
20
+ function digest(bytes) {
21
+ return `sha256:${crypto.createHash("sha256").update(bytes).digest("hex")}`;
22
+ }
23
+
24
+ function candidateFiles() {
25
+ const roles = {
26
+ "artifacts/product.bin": "installable-product",
27
+ "config/buildchain.toml": "buildchain-config",
28
+ "documents/release-activation.json": "release-activation-document",
29
+ "documents/signed-channel.json": "signed-channel-document",
30
+ "evidence/qualification.json": "qualification-evidence",
31
+ "manifests/candidate.json": "candidate-manifest",
32
+ "manifests/release-passport.json": "release-passport",
33
+ };
34
+ return Object.keys(roles)
35
+ .map((relative) => {
36
+ const bytes = fs.readFileSync(path.join(candidateRoot, relative));
37
+ return {
38
+ role: roles[relative],
39
+ path: relative,
40
+ size: bytes.length,
41
+ root: digest(bytes),
42
+ };
43
+ })
44
+ .sort((left, right) =>
45
+ Buffer.from(left.path).compare(Buffer.from(right.path)),
46
+ );
47
+ }
48
+
49
+ async function generated() {
50
+ const declaration = JSON.parse(
51
+ fs.readFileSync(
52
+ path.join(
53
+ root,
54
+ "contracts/fixtures/release-tail-capabilities-v1/kungfu-alpha.json",
55
+ ),
56
+ "utf8",
57
+ ),
58
+ );
59
+ const files = candidateFiles();
60
+ const binding = (relative) => ({
61
+ path: relative,
62
+ root: files.find((entry) => entry.path === relative).root,
63
+ });
64
+ const capsule = createV4PublicationRehearsalCapsule({
65
+ source: {
66
+ repository: "kungfu-systems/buildchain",
67
+ revision: "bc12cd0ff18a7e1d918777ea093c169349952d34",
68
+ },
69
+ declaration,
70
+ manifest: binding("manifests/candidate.json"),
71
+ config: binding("config/buildchain.toml"),
72
+ providerBindings: {
73
+ schema: "kungfu.buildchain.release-tail.provider-bindings/v1",
74
+ artifacts: {
75
+ "installable-product": {
76
+ path: "artifacts/product.bin",
77
+ name: "product.bin",
78
+ },
79
+ "release-passport": {
80
+ path: "manifests/release-passport.json",
81
+ name: "release-passport.json",
82
+ },
83
+ },
84
+ documents: {
85
+ "release.activate": {
86
+ path: "documents/release-activation.json",
87
+ method: "PUT",
88
+ },
89
+ "signed-channel.commit": {
90
+ path: "documents/signed-channel.json",
91
+ method: "PUT",
92
+ },
93
+ },
94
+ evidence: {
95
+ inputs: ["evidence/qualification.json"],
96
+ output: "generated/released-evidence.json",
97
+ },
98
+ },
99
+ files,
100
+ });
101
+ const vectors = [];
102
+ for (const platform of ["linux", "macos", "windows"]) {
103
+ const result = await executeV4PublicationRehearsal({
104
+ capsule,
105
+ candidateRoot,
106
+ mode: "simulate",
107
+ });
108
+ vectors.push({
109
+ platform,
110
+ capsuleRoot: result.evidence.capsuleRoot,
111
+ transactionRoot: result.evidence.transactionRoot,
112
+ stateRoot: result.evidence.stateRoot,
113
+ evidenceRoot: result.evidence.evidenceRoot,
114
+ });
115
+ }
116
+ return {
117
+ capsule,
118
+ vectors: {
119
+ schema: "buildchain-v4-publication-rehearsal-offline-vectors/v1",
120
+ vectors,
121
+ vectorRoot: digest(JSON.stringify(vectors)),
122
+ },
123
+ };
124
+ }
125
+
126
+ const { capsule, vectors } = await generated();
127
+ const outputs = new Map([
128
+ [path.join(fixtureRoot, "capsule.json"), capsule],
129
+ [path.join(fixtureRoot, "offline-vectors.json"), vectors],
130
+ ]);
131
+ const check = process.argv.includes("--check");
132
+ for (const [file, value] of outputs) {
133
+ const bytes = `${JSON.stringify(value, null, 2)}\n`;
134
+ if (check) {
135
+ if (!fs.existsSync(file) || fs.readFileSync(file, "utf8") !== bytes)
136
+ throw new Error(`${path.relative(root, file)} is stale`);
137
+ } else {
138
+ fs.mkdirSync(path.dirname(file), { recursive: true });
139
+ fs.writeFileSync(file, bytes);
140
+ }
141
+ }
142
+ process.stdout.write(
143
+ `${JSON.stringify({ capsuleRoot: capsule.capsuleRoot, vectorRoot: vectors.vectorRoot })}\n`,
144
+ );