@kungfu-tech/buildchain 2.14.16 → 2.14.17-alpha.0
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/dist/site/buildchain-contract.json +3 -3
- package/dist/site/buildchain-site.json +4 -4
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/node-api-registry.json +1 -1
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +4 -4
- package/package.json +1 -1
- package/packages/core/publication-control-plane-audit.js +46 -0
- package/scripts/assemble-binary-release-admission.mjs +15 -3
- package/scripts/audit-publication-control-plane.mjs +49 -4
- package/scripts/web-surface-core.mjs +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"product": {
|
|
5
5
|
"name": "Buildchain",
|
|
6
6
|
"package": "@kungfu-tech/buildchain",
|
|
7
|
-
"version": "2.14.
|
|
7
|
+
"version": "2.14.17-alpha.0",
|
|
8
8
|
"repository": "https://github.com/kungfu-systems/buildchain"
|
|
9
9
|
},
|
|
10
10
|
"majorLine": "v2",
|
|
@@ -604,7 +604,7 @@
|
|
|
604
604
|
"agents can discover supported Node APIs without importing internal file paths"
|
|
605
605
|
],
|
|
606
606
|
"breakingDigest": "sha256:48f925608d3e2131d90936b07dc2a30341204cae3e6e785c0f77d61ad755c945",
|
|
607
|
-
"auditDigest": "sha256:
|
|
607
|
+
"auditDigest": "sha256:8005d01fa6c771f466c77629f0589b361fc43a3a4f04b7d88bc1645d33895a51"
|
|
608
608
|
},
|
|
609
609
|
{
|
|
610
610
|
"contractVersion": 1,
|
|
@@ -2913,5 +2913,5 @@
|
|
|
2913
2913
|
}
|
|
2914
2914
|
],
|
|
2915
2915
|
"compatibilityDigest": "sha256:cdf588422ec6b460bd6f631400efa6e361a045e052c8967d6c50fadd7aa4dd90",
|
|
2916
|
-
"contractDigest": "sha256:
|
|
2916
|
+
"contractDigest": "sha256:fe7adf9ed1c1a0b14b29fef1eb72205ae29c9558806c9b35bfcc258f07d422a8"
|
|
2917
2917
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-bundle",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-22T15:29:55.552Z",
|
|
5
|
+
"publishedAt": "2026-07-22T15:29:55.552Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "a013078fdf88b5b850e48e93faf58de582130440",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"package": {
|
|
39
39
|
"name": "@kungfu-tech/buildchain",
|
|
40
|
-
"version": "2.14.
|
|
40
|
+
"version": "2.14.17-alpha.0",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"source": {
|
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
"specifier": "@kungfu-tech/buildchain/publication-control-plane-audit",
|
|
308
308
|
"export": "./publication-control-plane-audit",
|
|
309
309
|
"target": "./packages/core/publication-control-plane-audit.js",
|
|
310
|
-
"digest": "sha256:
|
|
310
|
+
"digest": "sha256:8220ad9cdf7fb9d2f361cf7b066aad039412a378350676edfdb4c1f7019cda20",
|
|
311
311
|
"summary": "Read-only publication control-plane snapshot evaluation APIs.",
|
|
312
312
|
"capabilityGroup": "release-passport-trust",
|
|
313
313
|
"audience": [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-publication-release-registry",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-22T15:29:55.552Z",
|
|
5
|
+
"publishedAt": "2026-07-22T15:29:55.552Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "a013078fdf88b5b850e48e93faf58de582130440",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"package": {
|
|
34
34
|
"name": "@kungfu-tech/buildchain",
|
|
35
|
-
"version": "2.14.
|
|
35
|
+
"version": "2.14.17-alpha.0",
|
|
36
36
|
"versionSource": "package.json#version"
|
|
37
37
|
},
|
|
38
38
|
"sourceKind": "package-site-bundle",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-manifest",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-22T15:29:55.552Z",
|
|
5
|
+
"publishedAt": "2026-07-22T15:29:55.552Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "a013078fdf88b5b850e48e93faf58de582130440",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"package": {
|
|
39
39
|
"name": "@kungfu-tech/buildchain",
|
|
40
|
-
"version": "2.14.
|
|
40
|
+
"version": "2.14.17-alpha.0",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"entrypoint": "buildchain-site.json",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.17-alpha.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
import { createPublicationControlPlaneAudit, publicationAuthorityDigest } from "./publication-authority.js";
|
|
2
2
|
|
|
3
|
+
export const BUILDCHAIN_RELEASE_RECONCILIATION_PATHS = Object.freeze([
|
|
4
|
+
".buildchain/release-impact.json",
|
|
5
|
+
"dist/site/buildchain-contract.json",
|
|
6
|
+
"dist/site/buildchain-site.json",
|
|
7
|
+
"dist/site/kfd-upstream-aggregate.json",
|
|
8
|
+
"dist/site/publication-registry.json",
|
|
9
|
+
"dist/site/site-manifest.json",
|
|
10
|
+
"package.json",
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
export function evaluateBuildchainReleaseReconciliation({
|
|
14
|
+
repository,
|
|
15
|
+
publicationVersion,
|
|
16
|
+
packageVersion,
|
|
17
|
+
message,
|
|
18
|
+
parentSha,
|
|
19
|
+
changedPaths,
|
|
20
|
+
} = {}) {
|
|
21
|
+
const normalizedPaths = Array.isArray(changedPaths) ? changedPaths.map(String) : [];
|
|
22
|
+
const allowedPaths = new Set(BUILDCHAIN_RELEASE_RECONCILIATION_PATHS);
|
|
23
|
+
return {
|
|
24
|
+
qualifying: repository === "kungfu-systems/buildchain" &&
|
|
25
|
+
/^\d+\.\d+\.\d+$/.test(String(publicationVersion || "")) &&
|
|
26
|
+
message === `chore(release): release v${publicationVersion}` &&
|
|
27
|
+
packageVersion === publicationVersion &&
|
|
28
|
+
normalizedPaths.length > 0 &&
|
|
29
|
+
normalizedPaths.every((entry) => allowedPaths.has(entry)) &&
|
|
30
|
+
/^[0-9a-f]{40}$/.test(String(parentSha || "")),
|
|
31
|
+
parentSha: String(parentSha || ""),
|
|
32
|
+
version: String(publicationVersion || ""),
|
|
33
|
+
packageVersion: String(packageVersion || ""),
|
|
34
|
+
message: String(message || ""),
|
|
35
|
+
changedPaths: normalizedPaths,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
3
39
|
function fact(id, pass, observed) {
|
|
4
40
|
return {
|
|
5
41
|
id,
|
|
@@ -77,6 +113,15 @@ export function evaluatePublicationControlPlaneSnapshot({
|
|
|
77
113
|
branchPolicy.requiredStatusCheckMatchCount === 1
|
|
78
114
|
)
|
|
79
115
|
);
|
|
116
|
+
const authorizationSha = branchPolicy.authorizationSha || branchPolicy.sourceSha;
|
|
117
|
+
const sourceAuthorizationPass = branchPolicy.sourceSha === authorizationSha || (
|
|
118
|
+
branchPolicy.releaseReconciliation?.qualifying === true &&
|
|
119
|
+
branchPolicy.releaseReconciliation.parentSha === authorizationSha &&
|
|
120
|
+
/^\d+\.\d+\.\d+$/.test(String(branchPolicy.releaseReconciliation.version || "")) &&
|
|
121
|
+
branchPolicy.releaseReconciliation.packageVersion === branchPolicy.releaseReconciliation.version &&
|
|
122
|
+
Array.isArray(branchPolicy.releaseReconciliation.changedPaths) &&
|
|
123
|
+
branchPolicy.releaseReconciliation.changedPaths.length > 0
|
|
124
|
+
);
|
|
80
125
|
const providerTransactionBranchPass = branchPolicy.ref === branch &&
|
|
81
126
|
branchPolicy.policyMode === "provider-enforced-transaction" &&
|
|
82
127
|
branchPolicy.protected === true &&
|
|
@@ -88,6 +133,7 @@ export function evaluatePublicationControlPlaneSnapshot({
|
|
|
88
133
|
/^[0-9a-f]{40}$/i.test(String(branchPolicy.requiredCheckSha || "")) &&
|
|
89
134
|
branchPolicy.requiredCheckSha === branchPolicy.pullRequestHeadSha &&
|
|
90
135
|
branchPolicy.sourceSha === branchPolicy.headSha &&
|
|
136
|
+
sourceAuthorizationPass &&
|
|
91
137
|
branchPolicy.mergedPullRequest === true &&
|
|
92
138
|
branchPolicy.baseRef === branch &&
|
|
93
139
|
branchPolicy.headRepository === repository &&
|
|
@@ -4,7 +4,10 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
validateControllerPlan,
|
|
9
|
+
validateControllerReceipt,
|
|
10
|
+
} from "../packages/core/controller-evidence.js";
|
|
8
11
|
import {
|
|
9
12
|
createPublicationAdmission,
|
|
10
13
|
createPublicationGateDecision,
|
|
@@ -102,15 +105,23 @@ function main() {
|
|
|
102
105
|
const controllerRoot = path.join(evidenceRoot, "binary-controller");
|
|
103
106
|
const manifest = readJson(oneFile(passportRoot, "buildchain-release-bundle.json"));
|
|
104
107
|
const archivePath = oneFile(passportRoot, "buildchain-release-bundle.tar.gz");
|
|
108
|
+
const controllerPlan = readJson(oneFile(controllerRoot, "plan.json"));
|
|
105
109
|
const controllerReceipt = readJson(oneFile(controllerRoot, "receipt.json"));
|
|
106
110
|
validateBundle(manifest, archivePath, { sourceSha, releaseTag });
|
|
107
111
|
|
|
108
|
-
const
|
|
112
|
+
const authorityRuntimeSha = execFileSync("git", ["-C", runtimeRoot, "rev-parse", "HEAD"], { encoding: "utf8" })
|
|
109
113
|
.trim()
|
|
110
114
|
.toLowerCase();
|
|
115
|
+
if (!/^[0-9a-f]{40}$/.test(authorityRuntimeSha)) {
|
|
116
|
+
throw new Error("publication authority runtime SHA is invalid");
|
|
117
|
+
}
|
|
118
|
+
const controllerPlanValidation = validateControllerPlan(controllerPlan);
|
|
119
|
+
if (!controllerPlanValidation.ok || !controllerPlanValidation.qualifying) {
|
|
120
|
+
throw new Error(`binary distribution controller plan did not qualify: ${controllerPlanValidation.issues.join("; ")}`);
|
|
121
|
+
}
|
|
111
122
|
const controllerValidation = validateControllerReceipt(controllerReceipt, {
|
|
123
|
+
plan: controllerPlan,
|
|
112
124
|
expectedSourceSha: sourceSha,
|
|
113
|
-
expectedRuntimeSha: runtimeSha,
|
|
114
125
|
});
|
|
115
126
|
if (!controllerValidation.ok || !controllerValidation.qualifying) {
|
|
116
127
|
throw new Error(`binary distribution controller receipt did not qualify: ${controllerValidation.issues.join("; ")}`);
|
|
@@ -118,6 +129,7 @@ function main() {
|
|
|
118
129
|
if (controllerReceipt.controller?.id !== "binary-distribution") {
|
|
119
130
|
throw new Error("binary distribution controller receipt has the wrong controller id");
|
|
120
131
|
}
|
|
132
|
+
const runtimeSha = controllerReceipt.runtime.sha;
|
|
121
133
|
|
|
122
134
|
const controlPlaneAudit = readJson(required("BUILDCHAIN_CONTROL_PLANE_AUDIT_PATH"));
|
|
123
135
|
const registry = readJson(path.join(runtimeRoot, "dist/site/publication-authority-registry.json"));
|
|
@@ -3,7 +3,10 @@ import { spawnSync } from "node:child_process";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
evaluateBuildchainReleaseReconciliation,
|
|
8
|
+
evaluatePublicationControlPlaneSnapshot,
|
|
9
|
+
} from "../packages/core/publication-control-plane-audit.js";
|
|
7
10
|
|
|
8
11
|
function flag(name, fallback = "") {
|
|
9
12
|
const index = process.argv.indexOf(`--${name}`);
|
|
@@ -199,6 +202,8 @@ function main() {
|
|
|
199
202
|
const sourceSha = flag("source-sha").toLowerCase();
|
|
200
203
|
const packageName = flag("package", "@kungfu-tech/buildchain");
|
|
201
204
|
const publisherMode = flag("publisher-mode", "npm-trusted-publisher");
|
|
205
|
+
const publicationVersion = flag("publication-version");
|
|
206
|
+
const allowReleaseReconciliation = process.argv.includes("--allow-release-reconciliation");
|
|
202
207
|
if (!repository || !branch) throw new Error("--repository and --branch are required");
|
|
203
208
|
|
|
204
209
|
const encodedWorkflow = workflowPath.split("/").map(encodeURIComponent).join("/");
|
|
@@ -260,13 +265,51 @@ function main() {
|
|
|
260
265
|
if (!/^[0-9a-f]{40}$/.test(sourceSha)) {
|
|
261
266
|
throw new Error("--source-sha is required when detailed branch policy is not readable");
|
|
262
267
|
}
|
|
263
|
-
const
|
|
264
|
-
const
|
|
268
|
+
const sourceCommit = githubJson(`repos/${repository}/commits/${sourceSha}`, "source commit");
|
|
269
|
+
const sourceParents = Array.isArray(sourceCommit.parents) ? sourceCommit.parents.map((entry) => String(entry?.sha || "").toLowerCase()) : [];
|
|
270
|
+
const sourceChangedPaths = Array.isArray(sourceCommit.files) ? sourceCommit.files.map((entry) => String(entry?.filename || "")) : [];
|
|
271
|
+
const sourceMessage = String(sourceCommit.commit?.message || "").split("\n", 1)[0];
|
|
272
|
+
let authorizationSha = sourceSha;
|
|
273
|
+
let releaseReconciliation = {
|
|
274
|
+
qualifying: false,
|
|
275
|
+
parentSha: "",
|
|
276
|
+
version: publicationVersion,
|
|
277
|
+
message: sourceMessage,
|
|
278
|
+
changedPaths: sourceChangedPaths,
|
|
279
|
+
};
|
|
280
|
+
let pullRequests = githubJson(`repos/${repository}/commits/${authorizationSha}/pulls`, "source pull-request lineage");
|
|
281
|
+
let mergedPullRequest = (Array.isArray(pullRequests) ? pullRequests : []).find((entry) =>
|
|
265
282
|
entry?.merged_at &&
|
|
266
|
-
entry.merge_commit_sha ===
|
|
283
|
+
entry.merge_commit_sha === authorizationSha &&
|
|
267
284
|
entry.base?.ref === branch &&
|
|
268
285
|
entry.head?.repo?.full_name === repository
|
|
269
286
|
);
|
|
287
|
+
if (!mergedPullRequest && allowReleaseReconciliation) {
|
|
288
|
+
const packageFile = githubJson(
|
|
289
|
+
`repos/${repository}/contents/package.json?ref=${encodeURIComponent(sourceSha)}`,
|
|
290
|
+
"release reconciliation package metadata",
|
|
291
|
+
);
|
|
292
|
+
const packageJson = JSON.parse(Buffer.from(String(packageFile.content || ""), "base64").toString("utf8"));
|
|
293
|
+
const parentSha = sourceParents.length === 1 ? sourceParents[0] : "";
|
|
294
|
+
releaseReconciliation = evaluateBuildchainReleaseReconciliation({
|
|
295
|
+
repository,
|
|
296
|
+
publicationVersion,
|
|
297
|
+
packageVersion: packageJson.version,
|
|
298
|
+
message: sourceMessage,
|
|
299
|
+
parentSha,
|
|
300
|
+
changedPaths: sourceChangedPaths,
|
|
301
|
+
});
|
|
302
|
+
if (releaseReconciliation.qualifying) {
|
|
303
|
+
authorizationSha = parentSha;
|
|
304
|
+
pullRequests = githubJson(`repos/${repository}/commits/${authorizationSha}/pulls`, "release parent pull-request lineage");
|
|
305
|
+
mergedPullRequest = (Array.isArray(pullRequests) ? pullRequests : []).find((entry) =>
|
|
306
|
+
entry?.merged_at &&
|
|
307
|
+
entry.merge_commit_sha === authorizationSha &&
|
|
308
|
+
entry.base?.ref === branch &&
|
|
309
|
+
entry.head?.repo?.full_name === repository
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
270
313
|
const reviews = mergedPullRequest
|
|
271
314
|
? githubJson(`repos/${repository}/pulls/${mergedPullRequest.number}/reviews?per_page=100`, "source pull-request reviews")
|
|
272
315
|
: [];
|
|
@@ -316,7 +359,9 @@ function main() {
|
|
|
316
359
|
requiredCheckAppId: requiredCheckSource?.app_id || 0,
|
|
317
360
|
requiredCheckSha: pullRequestHeadSha,
|
|
318
361
|
sourceSha,
|
|
362
|
+
authorizationSha,
|
|
319
363
|
headSha: String(branchState.commit?.sha || "").toLowerCase(),
|
|
364
|
+
releaseReconciliation,
|
|
320
365
|
mergedPullRequest: Boolean(mergedPullRequest),
|
|
321
366
|
pullRequestNumber: mergedPullRequest?.number || 0,
|
|
322
367
|
pullRequestHeadSha,
|
|
@@ -354,7 +354,7 @@ function publicationImmutablePolicy({ artifactRoot, binding }) {
|
|
|
354
354
|
throw new Error(`declared immutable publication prefix does not exist in artifact: ${prefix}`);
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
|
-
const preservedRoots =
|
|
357
|
+
const preservedRoots = declaredPrefixes;
|
|
358
358
|
const files = preservedRoots
|
|
359
359
|
.flatMap((root) => listFiles(surfaceRoot, root))
|
|
360
360
|
.map((filePath) => ({
|