@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.
- package/AGENTS.md +13 -5
- package/actions/promote-buildchain-ref/README.md +11 -6
- package/architecture/internal-capabilities.json +11 -2
- package/architecture/maintainability-policy.json +149 -17
- package/architecture/v4-floating-consumer-policy.json +75 -0
- package/architecture/v4-floating-consumer-policy.md +32 -0
- package/architecture/v4-runtime-ref-resume-authority.json +64 -0
- package/architecture/v4-stage-capsule-qualification.json +2 -2
- package/bin/internal/trust-release-release-handlers.mjs +5 -0
- package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +53 -0
- package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
- package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +105 -0
- package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
- package/dist/site/buildchain-contract.json +101 -31
- package/dist/site/buildchain-site.json +73 -27
- package/dist/site/capability-registry.json +3 -3
- package/dist/site/controller-registry.json +62 -6
- package/dist/site/kfd-claims.json +68 -13
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +6 -6
- package/dist/site/node-api-registry.json +799 -127
- package/dist/site/page-registry.json +63 -17
- package/dist/site/public-surface-audit.json +49 -17
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +2 -0
- package/dist/site/site-manifest.json +10 -10
- package/dist/site/workflow-registry.json +46 -18
- package/docs/MAP.md +2 -0
- package/docs/dev-delivery-warrant.md +19 -1
- package/docs/lifecycle-protocol.md +41 -0
- package/docs/node-api-reference.md +207 -134
- package/docs/reusable-build-surface.md +41 -0
- package/docs/runtime-train-validation.md +10 -0
- package/docs/v4-runtime-ref-resume-authority.md +69 -0
- package/docs/versioning.md +1 -0
- package/package.json +6 -4
- package/packages/core/artifact-signing.js +61 -0
- package/packages/core/buildchain-config.js +66 -1
- package/packages/core/dev-delivery-proof.js +37 -3
- package/packages/core/dev-delivery-warrant.js +3 -3
- package/packages/core/index.js +2 -0
- package/packages/core/publication-authority.js +5 -5
- package/packages/core/release-candidate.js +79 -19
- package/packages/core/release-passport.js +239 -33
- package/packages/core/v4-floating-consumer-evidence.js +324 -0
- package/packages/core/v4-floating-consumer-policy.js +446 -0
- package/packages/core/v4-floating-consumer-release-passport.js +126 -0
- package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
- package/packages/core/v4-runtime-selector-persistence.js +228 -0
- package/packages/core/workflow-yaml-contract.js +48 -0
- package/scripts/audit-publication-control-plane.mjs +31 -31
- package/scripts/check-inventory.mjs +1 -1
- package/scripts/check-v4-floating-consumer-policy-contract.mjs +198 -0
- package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
- package/scripts/dev-delivery-source-proof-reuse.mjs +631 -0
- package/scripts/dev-pr-auto-merge.mjs +37 -48
- package/scripts/dev-pr-delivery-warrant.mjs +205 -2
- package/scripts/dev-pr-prequeue-guard.mjs +399 -0
- package/scripts/ensure-github-release.mjs +3 -3
- package/scripts/generate-channel-build-workflow.mjs +3 -0
- package/scripts/generate-channel-promotion-workflow.mjs +112 -12
- package/scripts/generate-release-candidate-passport.mjs +41 -33
- package/scripts/init-repo.mjs +5 -1
- package/scripts/inspect-artifact-signing-requests.mjs +6 -0
- package/scripts/npm-publish-transaction.mjs +101 -89
- package/scripts/resume-from-candidate-run.mjs +11 -14
- package/scripts/seal-artifact-signing-requests.mjs +6 -0
- package/scripts/site-capability-metadata.mjs +2 -0
- package/scripts/v4-consumer-policy.mjs +231 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const V4_FLOATING_CONSUMER_POLICY =
|
|
4
|
+
"kungfu-buildchain-v4-floating-consumer-policy/v1";
|
|
5
|
+
export const V4_FLOATING_CONSUMER_RECEIPT =
|
|
6
|
+
"kungfu-buildchain-v4-floating-consumer-policy-receipt/v1";
|
|
7
|
+
export const V4_FLOATING_CONSUMER_CERTIFICATION =
|
|
8
|
+
"kungfu-buildchain-v4-floating-consumer-certification/v1";
|
|
9
|
+
|
|
10
|
+
const SHA256_ROOT = /^sha256:[0-9a-f]{64}$/u;
|
|
11
|
+
|
|
12
|
+
function stableJson(value) {
|
|
13
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
14
|
+
if (value && typeof value === "object") {
|
|
15
|
+
return `{${Object.keys(value)
|
|
16
|
+
.sort()
|
|
17
|
+
.map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`)
|
|
18
|
+
.join(",")}}`;
|
|
19
|
+
}
|
|
20
|
+
return JSON.stringify(value);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function documentRoot(value) {
|
|
24
|
+
return `sha256:${crypto
|
|
25
|
+
.createHash("sha256")
|
|
26
|
+
.update(stableJson(value))
|
|
27
|
+
.digest("hex")}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function normalizeWorkflowPath(value) {
|
|
31
|
+
const text = String(value || "").replace(/^\/+/, "");
|
|
32
|
+
return text.startsWith(".github/workflows/")
|
|
33
|
+
? text
|
|
34
|
+
: `.github/workflows/${text}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function checker(failures) {
|
|
38
|
+
return (condition, code, message) => {
|
|
39
|
+
if (!condition) failures.push({ code, message });
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function verifyIdentity(value, expected, check, label) {
|
|
44
|
+
if (expected.repository)
|
|
45
|
+
check(
|
|
46
|
+
value?.caller?.repository === expected.repository,
|
|
47
|
+
"caller-repository-mismatch",
|
|
48
|
+
`${label} caller repository mismatch`,
|
|
49
|
+
);
|
|
50
|
+
if (expected.sourceSha)
|
|
51
|
+
check(
|
|
52
|
+
value?.caller?.sourceSha === expected.sourceSha.toLowerCase(),
|
|
53
|
+
"caller-source-mismatch",
|
|
54
|
+
`${label} caller source mismatch`,
|
|
55
|
+
);
|
|
56
|
+
if (expected.invokedWorkflow)
|
|
57
|
+
check(
|
|
58
|
+
value?.invocation?.workflow ===
|
|
59
|
+
normalizeWorkflowPath(expected.invokedWorkflow),
|
|
60
|
+
"invoked-workflow-mismatch",
|
|
61
|
+
`${label} workflow mismatch`,
|
|
62
|
+
);
|
|
63
|
+
if (expected.resolvedRuntimeSha)
|
|
64
|
+
check(
|
|
65
|
+
value?.invocation?.resolvedRuntimeSha ===
|
|
66
|
+
expected.resolvedRuntimeSha.toLowerCase(),
|
|
67
|
+
"runtime-sha-mismatch",
|
|
68
|
+
`${label} runtime SHA mismatch`,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function verifyAuthorityFields(value, expected, check, label) {
|
|
73
|
+
for (const [field, actual, code, message] of [
|
|
74
|
+
["policyRoot", value?.policy?.root, "policy-root-mismatch", "policy root"],
|
|
75
|
+
[
|
|
76
|
+
"scannerRoot",
|
|
77
|
+
value?.policy?.scannerRoot,
|
|
78
|
+
"scanner-root-mismatch",
|
|
79
|
+
"scanner root",
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
"stableLockRoot",
|
|
83
|
+
value?.contractLocks?.stable?.root,
|
|
84
|
+
"stable-lock-root-mismatch",
|
|
85
|
+
"stable lock root",
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
"alphaLockRoot",
|
|
89
|
+
value?.contractLocks?.alpha?.root,
|
|
90
|
+
"alpha-lock-root-mismatch",
|
|
91
|
+
"alpha lock root",
|
|
92
|
+
],
|
|
93
|
+
[
|
|
94
|
+
"stableLockPath",
|
|
95
|
+
value?.contractLocks?.stable?.path,
|
|
96
|
+
"stable-lock-path-mismatch",
|
|
97
|
+
"stable lock path",
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
"alphaLockPath",
|
|
101
|
+
value?.contractLocks?.alpha?.path,
|
|
102
|
+
"alpha-lock-path-mismatch",
|
|
103
|
+
"alpha lock path",
|
|
104
|
+
],
|
|
105
|
+
]) {
|
|
106
|
+
if (expected[field])
|
|
107
|
+
check(actual === expected[field], code, `${label} ${message} mismatch`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function verifyFloatingSelector(value, check, label) {
|
|
112
|
+
check(
|
|
113
|
+
value?.invocation?.selectorClass === "floating",
|
|
114
|
+
"selector-class-invalid",
|
|
115
|
+
`${label} must bind a floating selector`,
|
|
116
|
+
);
|
|
117
|
+
check(
|
|
118
|
+
["v4", "v4-alpha"].includes(value?.invocation?.visibleSelector),
|
|
119
|
+
"selector-invalid",
|
|
120
|
+
`${label} selector must be v4 or v4-alpha`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function v4FloatingConsumerDocumentRoot(value) {
|
|
125
|
+
return documentRoot(value);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function verifyV4FloatingConsumerPolicyReceipt(options = {}) {
|
|
129
|
+
const { receipt, receiptRoot = "", expectedReceiptRoot = "" } = options;
|
|
130
|
+
const failures = [];
|
|
131
|
+
const check = checker(failures);
|
|
132
|
+
check(
|
|
133
|
+
receipt?.schema === V4_FLOATING_CONSUMER_RECEIPT,
|
|
134
|
+
"receipt-contract-invalid",
|
|
135
|
+
`receipt must use ${V4_FLOATING_CONSUMER_RECEIPT}`,
|
|
136
|
+
);
|
|
137
|
+
check(
|
|
138
|
+
receipt?.status === "passed",
|
|
139
|
+
"receipt-not-passed",
|
|
140
|
+
"policy receipt status must be passed",
|
|
141
|
+
);
|
|
142
|
+
check(
|
|
143
|
+
Array.isArray(receipt?.failures) && receipt.failures.length === 0,
|
|
144
|
+
"receipt-retains-failures",
|
|
145
|
+
"passed receipt must not retain failures",
|
|
146
|
+
);
|
|
147
|
+
const computedRoot = receipt ? documentRoot(receipt) : "";
|
|
148
|
+
check(
|
|
149
|
+
SHA256_ROOT.test(String(receiptRoot || "")),
|
|
150
|
+
"receipt-root-invalid",
|
|
151
|
+
"policy receipt root must be a sha256 root",
|
|
152
|
+
);
|
|
153
|
+
check(
|
|
154
|
+
receiptRoot === computedRoot,
|
|
155
|
+
"receipt-root-mismatch",
|
|
156
|
+
"policy receipt root does not match its content",
|
|
157
|
+
);
|
|
158
|
+
if (expectedReceiptRoot)
|
|
159
|
+
check(
|
|
160
|
+
computedRoot === expectedReceiptRoot,
|
|
161
|
+
"receipt-authority-root-mismatch",
|
|
162
|
+
"policy receipt does not match the independently reconstructed receipt",
|
|
163
|
+
);
|
|
164
|
+
verifyIdentity(receipt, options, check, "policy receipt");
|
|
165
|
+
verifyAuthorityFields(receipt, options, check, "policy receipt");
|
|
166
|
+
verifyFloatingSelector(receipt, check, "policy receipt");
|
|
167
|
+
return { ok: failures.length === 0, failures, receiptRoot: computedRoot };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function defaultAuthority(options, receiptRoot) {
|
|
171
|
+
return {
|
|
172
|
+
receiptRoot: options.expectedReceiptRoot || receiptRoot,
|
|
173
|
+
policyRoot: options.policyRoot || "",
|
|
174
|
+
scannerRoot: options.scannerRoot || "",
|
|
175
|
+
contractLocks: {
|
|
176
|
+
stable: {
|
|
177
|
+
path: options.stableLockPath || "",
|
|
178
|
+
root: options.stableLockRoot || "",
|
|
179
|
+
},
|
|
180
|
+
alpha: {
|
|
181
|
+
path: options.alphaLockPath || "",
|
|
182
|
+
root: options.alphaLockRoot || "",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function certifyV4FloatingConsumerPolicyReceipt(options = {}) {
|
|
189
|
+
const verification = verifyV4FloatingConsumerPolicyReceipt(options);
|
|
190
|
+
const certification = {
|
|
191
|
+
schema: V4_FLOATING_CONSUMER_CERTIFICATION,
|
|
192
|
+
status: verification.ok ? "certified" : "rejected",
|
|
193
|
+
receiptRoot: verification.receiptRoot,
|
|
194
|
+
caller: options.receipt?.caller || {},
|
|
195
|
+
invocation: options.receipt?.invocation || {},
|
|
196
|
+
policy: options.receipt?.policy || {},
|
|
197
|
+
contractLocks: options.receipt?.contractLocks || {},
|
|
198
|
+
authority:
|
|
199
|
+
options.authority || defaultAuthority(options, verification.receiptRoot),
|
|
200
|
+
failures: verification.failures,
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
ok: verification.ok,
|
|
204
|
+
verification,
|
|
205
|
+
certification,
|
|
206
|
+
certificationRoot: documentRoot(certification),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function verifyCertificationAuthority(certification, expected, check) {
|
|
211
|
+
const authority = certification?.authority;
|
|
212
|
+
for (const [value, code, message] of [
|
|
213
|
+
[
|
|
214
|
+
certification?.policy?.root,
|
|
215
|
+
"policy-root-invalid",
|
|
216
|
+
"certified policy root",
|
|
217
|
+
],
|
|
218
|
+
[
|
|
219
|
+
certification?.policy?.scannerRoot,
|
|
220
|
+
"scanner-root-invalid",
|
|
221
|
+
"certified scanner root",
|
|
222
|
+
],
|
|
223
|
+
[
|
|
224
|
+
certification?.contractLocks?.stable?.root,
|
|
225
|
+
"stable-lock-root-invalid",
|
|
226
|
+
"certified stable lock root",
|
|
227
|
+
],
|
|
228
|
+
[
|
|
229
|
+
certification?.contractLocks?.alpha?.root,
|
|
230
|
+
"alpha-lock-root-invalid",
|
|
231
|
+
"certified alpha lock root",
|
|
232
|
+
],
|
|
233
|
+
]) {
|
|
234
|
+
check(
|
|
235
|
+
SHA256_ROOT.test(String(value || "")),
|
|
236
|
+
code,
|
|
237
|
+
`${message} must be a sha256 root`,
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
check(
|
|
241
|
+
authority?.receiptRoot === certification?.receiptRoot,
|
|
242
|
+
"certification-authority-receipt-mismatch",
|
|
243
|
+
"certification authority must bind the certified receipt root",
|
|
244
|
+
);
|
|
245
|
+
check(
|
|
246
|
+
authority?.policyRoot === certification?.policy?.root,
|
|
247
|
+
"certification-authority-policy-mismatch",
|
|
248
|
+
"certification authority must bind the certified policy root",
|
|
249
|
+
);
|
|
250
|
+
check(
|
|
251
|
+
authority?.scannerRoot === certification?.policy?.scannerRoot,
|
|
252
|
+
"certification-authority-scanner-mismatch",
|
|
253
|
+
"certification authority must bind the certified scanner root",
|
|
254
|
+
);
|
|
255
|
+
for (const channel of ["stable", "alpha"]) {
|
|
256
|
+
check(
|
|
257
|
+
authority?.contractLocks?.[channel]?.path ===
|
|
258
|
+
certification?.contractLocks?.[channel]?.path &&
|
|
259
|
+
authority?.contractLocks?.[channel]?.root ===
|
|
260
|
+
certification?.contractLocks?.[channel]?.root,
|
|
261
|
+
`certification-authority-${channel}-lock-mismatch`,
|
|
262
|
+
`certification authority must bind the certified ${channel} lock`,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
if (expected.expectedReceiptRoot)
|
|
266
|
+
check(
|
|
267
|
+
certification?.receiptRoot === expected.expectedReceiptRoot,
|
|
268
|
+
"receipt-authority-root-mismatch",
|
|
269
|
+
"certification receipt root does not match external authority",
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function verifyV4FloatingConsumerPolicyCertification(options = {}) {
|
|
274
|
+
const { certification, certificationRoot = "" } = options;
|
|
275
|
+
const failures = [];
|
|
276
|
+
const check = checker(failures);
|
|
277
|
+
check(
|
|
278
|
+
certification?.schema === V4_FLOATING_CONSUMER_CERTIFICATION,
|
|
279
|
+
"certification-contract-invalid",
|
|
280
|
+
`certification must use ${V4_FLOATING_CONSUMER_CERTIFICATION}`,
|
|
281
|
+
);
|
|
282
|
+
check(
|
|
283
|
+
certification?.status === "certified",
|
|
284
|
+
"certification-not-certified",
|
|
285
|
+
"certification status must be certified",
|
|
286
|
+
);
|
|
287
|
+
check(
|
|
288
|
+
Array.isArray(certification?.failures) &&
|
|
289
|
+
certification.failures.length === 0,
|
|
290
|
+
"certification-retains-failures",
|
|
291
|
+
"certified evidence must not retain failures",
|
|
292
|
+
);
|
|
293
|
+
const computedRoot = certification ? documentRoot(certification) : "";
|
|
294
|
+
check(
|
|
295
|
+
SHA256_ROOT.test(String(certificationRoot || "")),
|
|
296
|
+
"certification-root-invalid",
|
|
297
|
+
"certification root must be a sha256 root",
|
|
298
|
+
);
|
|
299
|
+
check(
|
|
300
|
+
certificationRoot === computedRoot,
|
|
301
|
+
"certification-root-mismatch",
|
|
302
|
+
"certification root does not match its content",
|
|
303
|
+
);
|
|
304
|
+
if (options.expectedCertificationRoot)
|
|
305
|
+
check(
|
|
306
|
+
certificationRoot === options.expectedCertificationRoot,
|
|
307
|
+
"certification-authority-root-mismatch",
|
|
308
|
+
"certification root does not match the workflow-certified root",
|
|
309
|
+
);
|
|
310
|
+
check(
|
|
311
|
+
SHA256_ROOT.test(String(certification?.receiptRoot || "")),
|
|
312
|
+
"receipt-root-invalid",
|
|
313
|
+
"certification must bind a receipt root",
|
|
314
|
+
);
|
|
315
|
+
verifyIdentity(certification, options, check, "certification");
|
|
316
|
+
verifyAuthorityFields(certification, options, check, "certification");
|
|
317
|
+
verifyCertificationAuthority(certification, options, check);
|
|
318
|
+
verifyFloatingSelector(certification, check, "certification");
|
|
319
|
+
return {
|
|
320
|
+
ok: failures.length === 0,
|
|
321
|
+
failures,
|
|
322
|
+
certificationRoot: computedRoot,
|
|
323
|
+
};
|
|
324
|
+
}
|