@kungfu-tech/buildchain 4.0.0 → 4.0.1-alpha.2

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 (69) hide show
  1. package/AGENTS.md +13 -5
  2. package/actions/promote-buildchain-ref/README.md +11 -6
  3. package/architecture/internal-capabilities.json +11 -2
  4. package/architecture/maintainability-policy.json +149 -17
  5. package/architecture/v4-floating-consumer-policy.json +75 -0
  6. package/architecture/v4-floating-consumer-policy.md +32 -0
  7. package/architecture/v4-runtime-ref-resume-authority.json +64 -0
  8. package/architecture/v4-stage-capsule-qualification.json +2 -2
  9. package/bin/internal/trust-release-release-handlers.mjs +5 -0
  10. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +53 -0
  11. package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
  12. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +105 -0
  13. package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
  14. package/dist/site/buildchain-contract.json +101 -31
  15. package/dist/site/buildchain-site.json +73 -27
  16. package/dist/site/capability-registry.json +3 -3
  17. package/dist/site/controller-registry.json +62 -6
  18. package/dist/site/kfd-claims.json +68 -13
  19. package/dist/site/kfd-upstream-aggregate.json +1 -1
  20. package/dist/site/manual-registry.json +6 -6
  21. package/dist/site/node-api-registry.json +799 -127
  22. package/dist/site/page-registry.json +63 -17
  23. package/dist/site/public-surface-audit.json +49 -17
  24. package/dist/site/publication-registry.json +4 -4
  25. package/dist/site/release-provenance.json +2 -0
  26. package/dist/site/site-manifest.json +10 -10
  27. package/dist/site/workflow-registry.json +46 -18
  28. package/docs/MAP.md +2 -0
  29. package/docs/dev-delivery-warrant.md +19 -1
  30. package/docs/lifecycle-protocol.md +41 -0
  31. package/docs/node-api-reference.md +207 -134
  32. package/docs/reusable-build-surface.md +41 -0
  33. package/docs/runtime-train-validation.md +10 -0
  34. package/docs/v4-runtime-ref-resume-authority.md +69 -0
  35. package/docs/versioning.md +1 -0
  36. package/package.json +6 -4
  37. package/packages/core/artifact-signing.js +61 -0
  38. package/packages/core/buildchain-config.js +66 -1
  39. package/packages/core/dev-delivery-proof.js +37 -3
  40. package/packages/core/dev-delivery-warrant.js +3 -3
  41. package/packages/core/index.js +2 -0
  42. package/packages/core/publication-authority.js +5 -5
  43. package/packages/core/release-candidate.js +79 -19
  44. package/packages/core/release-passport.js +239 -33
  45. package/packages/core/v4-floating-consumer-evidence.js +324 -0
  46. package/packages/core/v4-floating-consumer-policy.js +446 -0
  47. package/packages/core/v4-floating-consumer-release-passport.js +126 -0
  48. package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
  49. package/packages/core/v4-runtime-selector-persistence.js +228 -0
  50. package/packages/core/workflow-yaml-contract.js +48 -0
  51. package/scripts/audit-publication-control-plane.mjs +31 -31
  52. package/scripts/check-inventory.mjs +1 -1
  53. package/scripts/check-v4-floating-consumer-policy-contract.mjs +198 -0
  54. package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
  55. package/scripts/dev-delivery-source-proof-reuse.mjs +631 -0
  56. package/scripts/dev-pr-auto-merge.mjs +37 -48
  57. package/scripts/dev-pr-delivery-warrant.mjs +205 -2
  58. package/scripts/dev-pr-prequeue-guard.mjs +399 -0
  59. package/scripts/ensure-github-release.mjs +3 -3
  60. package/scripts/generate-channel-build-workflow.mjs +3 -0
  61. package/scripts/generate-channel-promotion-workflow.mjs +112 -12
  62. package/scripts/generate-release-candidate-passport.mjs +41 -33
  63. package/scripts/init-repo.mjs +5 -1
  64. package/scripts/inspect-artifact-signing-requests.mjs +6 -0
  65. package/scripts/npm-publish-transaction.mjs +101 -89
  66. package/scripts/resume-from-candidate-run.mjs +11 -14
  67. package/scripts/seal-artifact-signing-requests.mjs +6 -0
  68. package/scripts/site-capability-metadata.mjs +2 -0
  69. package/scripts/v4-consumer-policy.mjs +231 -0
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import {
6
+ certifyV4FloatingConsumerPolicyReceipt,
7
+ resolveV4FloatingConsumerPolicyAuthority,
8
+ scanV4FloatingConsumerPolicy,
9
+ v4ConsumerPolicyScannerRoot,
10
+ } from "../packages/core/v4-floating-consumer-policy.js";
11
+ import { writeGitHubOutputs } from "./build-contract-core.mjs";
12
+ const RUNTIME_ROOT = path.resolve(import.meta.dirname, "..");
13
+ function parseArgs(argv) {
14
+ const options = {};
15
+ for (let index = 0; index < argv.length; index += 1) {
16
+ const arg = argv[index];
17
+ if (!arg.startsWith("--") || !argv[index + 1])
18
+ throw new Error(`invalid argument: ${arg}`);
19
+ options[
20
+ arg
21
+ .slice(2)
22
+ .replace(/-([a-z])/gu, (_, character) => character.toUpperCase())
23
+ ] = argv[index + 1];
24
+ index += 1;
25
+ }
26
+ return options;
27
+ }
28
+
29
+ function env(name, fallback = "") {
30
+ return process.env[name] || fallback;
31
+ }
32
+ function readJson(file) {
33
+ return JSON.parse(fs.readFileSync(file, "utf8"));
34
+ }
35
+ function writeJson(file, value) {
36
+ fs.mkdirSync(path.dirname(file), { recursive: true });
37
+ fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
38
+ }
39
+ export { v4ConsumerPolicyScannerRoot };
40
+ export function scanCommand(options = {}) {
41
+ const root = path.resolve(
42
+ options.root || env("BUILDCHAIN_CONSUMER_ROOT", process.cwd()),
43
+ );
44
+ const output = path.resolve(
45
+ root,
46
+ options.output ||
47
+ env(
48
+ "BUILDCHAIN_V4_POLICY_RECEIPT_PATH",
49
+ ".buildchain/evidence/v4-consumer-policy-receipt.json",
50
+ ),
51
+ );
52
+ const policy = readJson(
53
+ path.join(RUNTIME_ROOT, "architecture/v4-floating-consumer-policy.json"),
54
+ );
55
+ const result = scanV4FloatingConsumerPolicy({
56
+ root,
57
+ repository: options.repository || env("GITHUB_REPOSITORY"),
58
+ sourceSha: options.sourceSha || env("GITHUB_SHA"),
59
+ invokedWorkflow:
60
+ options.invokedWorkflow || env("BUILDCHAIN_INVOKED_WORKFLOW"),
61
+ invocationSourcePath:
62
+ options.invocationSourcePath ||
63
+ env("BUILDCHAIN_INVOCATION_SOURCE_PATH", env("GITHUB_WORKFLOW_REF")),
64
+ expectedInvocationChannel:
65
+ options.expectedInvocationChannel ||
66
+ env("BUILDCHAIN_EXPECTED_INVOCATION_CHANNEL"),
67
+ resolvedWorkflowSha:
68
+ options.resolvedWorkflowSha || env("BUILDCHAIN_WORKFLOW_SHA"),
69
+ resolvedRuntimeSha:
70
+ options.resolvedRuntimeSha ||
71
+ env("BUILDCHAIN_RUNTIME_SHA", env("BUILDCHAIN_WORKFLOW_SHA")),
72
+ stableLockPath:
73
+ options.stableLock ||
74
+ env(
75
+ "BUILDCHAIN_STABLE_CONTRACT_LOCK_PATH",
76
+ ".buildchain/contract-lock.json",
77
+ ),
78
+ alphaLockPath:
79
+ options.alphaLock ||
80
+ env(
81
+ "BUILDCHAIN_ALPHA_CONTRACT_LOCK_PATH",
82
+ ".buildchain/alpha-contract-lock.json",
83
+ ),
84
+ policy,
85
+ scannerRoot: v4ConsumerPolicyScannerRoot(),
86
+ });
87
+ writeJson(output, result);
88
+ writeGitHubOutputs({
89
+ "v4-consumer-policy-status": result.ok ? "passed" : "failed",
90
+ "v4-consumer-policy-receipt-path": output,
91
+ "v4-consumer-policy-receipt-root": result.receiptRoot,
92
+ "v4-consumer-policy-receipt-json": JSON.stringify(result.receipt),
93
+ "v4-consumer-policy-channel": result.receipt.invocation.channel,
94
+ "v4-consumer-policy-selector": result.receipt.invocation.visibleSelector,
95
+ "v4-consumer-policy-scanner-root": result.receipt.policy.scannerRoot,
96
+ });
97
+ return result;
98
+ }
99
+
100
+ export function certifyCommand(options = {}) {
101
+ const inputValue = options.input || env("BUILDCHAIN_V4_POLICY_RECEIPT_PATH");
102
+ if (!inputValue) throw new Error("certify requires --input");
103
+ const document = readJson(path.resolve(inputValue));
104
+ const evidence = document.consumerPolicy || document;
105
+ const receipt = evidence.receipt || evidence;
106
+ const receiptRoot =
107
+ options.receiptRoot ||
108
+ evidence.receiptRoot ||
109
+ document.receiptRoot ||
110
+ env("BUILDCHAIN_V4_POLICY_RECEIPT_ROOT");
111
+ const callerRoot = path.resolve(
112
+ options.callerRoot || env("BUILDCHAIN_EXPECTED_CALLER_ROOT", process.cwd()),
113
+ );
114
+ const stableLockPath =
115
+ options.stableLock ||
116
+ env(
117
+ "BUILDCHAIN_STABLE_CONTRACT_LOCK_PATH",
118
+ ".buildchain/contract-lock.json",
119
+ );
120
+ const alphaLockPath =
121
+ options.alphaLock ||
122
+ env(
123
+ "BUILDCHAIN_ALPHA_CONTRACT_LOCK_PATH",
124
+ ".buildchain/alpha-contract-lock.json",
125
+ );
126
+ const repository =
127
+ options.repository || env("BUILDCHAIN_EXPECTED_CALLER_REPOSITORY");
128
+ const sourceSha =
129
+ options.sourceSha || env("BUILDCHAIN_EXPECTED_CALLER_SOURCE_SHA");
130
+ const invokedWorkflow =
131
+ options.invokedWorkflow ||
132
+ env("BUILDCHAIN_EXPECTED_INVOKED_WORKFLOW") ||
133
+ receipt?.invocation?.workflow;
134
+ const resolvedRuntimeSha =
135
+ options.resolvedRuntimeSha || env("BUILDCHAIN_EXPECTED_RUNTIME_SHA");
136
+ const authority = resolveV4FloatingConsumerPolicyAuthority({
137
+ runtimeRoot: RUNTIME_ROOT,
138
+ callerRoot,
139
+ stableLockPath,
140
+ alphaLockPath,
141
+ });
142
+ const selectedLock =
143
+ receipt?.invocation?.visibleSelector === "v4-alpha"
144
+ ? readJson(path.join(callerRoot, alphaLockPath))
145
+ : readJson(path.join(callerRoot, stableLockPath));
146
+ const authorityScan = scanV4FloatingConsumerPolicy({
147
+ root: callerRoot,
148
+ repository,
149
+ sourceSha,
150
+ invokedWorkflow,
151
+ invocationSourcePath: receipt?.invocation?.sourcePath,
152
+ expectedInvocationChannel: receipt?.invocation?.channel,
153
+ resolvedWorkflowSha: selectedLock.buildchain?.resolvedSha,
154
+ resolvedRuntimeSha,
155
+ stableLockPath,
156
+ alphaLockPath,
157
+ policy: authority.policy,
158
+ scannerRoot: authority.scannerRoot,
159
+ });
160
+ const certificationAuthority = {
161
+ receiptRoot: authorityScan.receiptRoot,
162
+ policyRoot: authority.policyRoot,
163
+ scannerRoot: authority.scannerRoot,
164
+ contractLocks: authority.contractLocks,
165
+ };
166
+ const result = certifyV4FloatingConsumerPolicyReceipt({
167
+ receipt,
168
+ receiptRoot,
169
+ expectedReceiptRoot: authorityScan.receiptRoot,
170
+ repository,
171
+ sourceSha,
172
+ invokedWorkflow,
173
+ resolvedRuntimeSha,
174
+ policyRoot: authority.policyRoot,
175
+ scannerRoot: authority.scannerRoot,
176
+ stableLockRoot: authority.contractLocks.stable.root,
177
+ alphaLockRoot: authority.contractLocks.alpha.root,
178
+ stableLockPath,
179
+ alphaLockPath,
180
+ authority: certificationAuthority,
181
+ });
182
+ const output = path.resolve(
183
+ options.output ||
184
+ env(
185
+ "BUILDCHAIN_V4_POLICY_CERTIFICATION_PATH",
186
+ ".buildchain/evidence/v4-consumer-policy-certification.json",
187
+ ),
188
+ );
189
+ const documentWithAuthority = {
190
+ ...result,
191
+ authority: certificationAuthority,
192
+ };
193
+ writeJson(output, documentWithAuthority);
194
+ writeGitHubOutputs({
195
+ "v4-consumer-policy-certification-status": result.ok
196
+ ? "certified"
197
+ : "rejected",
198
+ "v4-consumer-policy-certification-path": output,
199
+ "v4-consumer-policy-certification-root": result.certificationRoot,
200
+ });
201
+ return documentWithAuthority;
202
+ }
203
+
204
+ function main(argv = process.argv.slice(2)) {
205
+ const command = argv.shift();
206
+ const options = parseArgs(argv);
207
+ const result =
208
+ command === "scan"
209
+ ? scanCommand(options)
210
+ : command === "certify"
211
+ ? certifyCommand(options)
212
+ : (() => {
213
+ throw new Error(
214
+ "usage: v4-consumer-policy.mjs <scan|certify> [--option value]",
215
+ );
216
+ })();
217
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
218
+ if (!result.ok) process.exitCode = 1;
219
+ }
220
+
221
+ if (
222
+ process.argv[1] &&
223
+ import.meta.url === pathToFileURL(process.argv[1]).href
224
+ ) {
225
+ try {
226
+ main();
227
+ } catch (error) {
228
+ console.error(`v4 consumer policy: ${error.message}`);
229
+ process.exitCode = 1;
230
+ }
231
+ }