@kungfu-tech/buildchain 3.0.3-alpha.0 → 3.0.3-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 +1 -1
- package/CONTRIBUTING.md +1 -1
- package/README.md +32 -1
- package/actions/promote-buildchain-ref/README.md +90 -19
- package/actions/report-buildchain-issue/README.md +19 -1
- package/actions/run-lifecycle/README.md +5 -0
- package/actions/validate-config/README.md +19 -1
- package/bin/buildchain.mjs +41 -241
- package/bin/internal/command-registry.mjs +82 -0
- package/bin/internal/trust-release-cli.mjs +1 -0
- package/contracts/auditable-demo-media-profiles-v1.json +116 -1
- package/contracts/buildchain-v2-residuals-v1.json +0 -45
- package/contracts/evidence/auditable-demo-responsive-web-delivery-v1.json +143 -0
- package/contracts/evidence/auditable-demo-web-delivery-v1.json +7 -3
- package/contracts/fixtures/auditable-demo-responsive-web-delivery-v1/complete-transcript.txt +2 -0
- package/contracts/fixtures/auditable-demo-responsive-web-delivery-v1/public-projection.json +16 -0
- package/contracts/fixtures/auditable-demo-responsive-web-delivery-v1/scene.json +12 -0
- package/dist/site/buildchain-contract.json +161 -42
- package/dist/site/buildchain-site.json +180 -84
- package/dist/site/capability-registry.json +6 -6
- package/dist/site/cli-registry.json +932 -98
- package/dist/site/controller-registry.json +97 -5
- package/dist/site/kfd-claims.json +316 -23
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +20 -20
- package/dist/site/node-api-registry.json +371 -56
- package/dist/site/page-registry.json +155 -59
- package/dist/site/public-surface-audit.json +286 -24
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +3 -0
- package/dist/site/site-manifest.json +24 -24
- package/dist/site/workflow-registry.json +570 -79
- package/docs/MAP.md +22 -4
- package/docs/auditable-demo.md +35 -12
- package/docs/aws-us-elastic-runner-burst-plane.md +381 -0
- package/docs/cli.md +143 -12
- package/docs/consumer-issue-reporting.md +19 -1
- package/docs/github-governance-authority.md +2 -2
- package/docs/lifecycle-protocol.md +20 -2
- package/docs/migration-inventory.md +24 -5
- package/docs/ownership.md +19 -1
- package/docs/publication-artifacts.md +185 -18
- package/docs/publication-authority.md +4 -4
- package/docs/publish-transaction.md +78 -31
- package/docs/release-candidate.md +24 -0
- package/docs/release-flow.md +50 -32
- package/docs/release-governance.md +31 -31
- package/docs/release-passport.md +4 -0
- package/docs/release-propagation.md +57 -12
- package/docs/reusable-build-surface.md +95 -27
- package/docs/runtime-train-validation.md +20 -2
- package/docs/stable-candidate-patrol.md +6 -6
- package/docs/toolkit-observability.md +22 -0
- package/docs/versioning.md +6 -4
- package/docs/web-surface-deployments.md +62 -0
- package/package.json +7 -5
- package/packages/core/README.md +61 -4
- package/packages/core/buildchain-contract.js +8 -4
- package/packages/core/cache-evidence.js +1 -0
- package/packages/core/diagnostics.js +105 -30
- package/packages/core/github-governance-authority.js +10 -25
- package/packages/core/index.js +40 -0
- package/packages/core/paper-fleet.js +260 -0
- package/packages/core/paper-repository.js +210 -0
- package/packages/core/paper-work.js +365 -0
- package/packages/core/paper.js +3180 -0
- package/packages/core/public-surface-audit.js +26 -75
- package/packages/core/public-surface-cli.js +117 -0
- package/packages/core/publication-artifact.js +1 -6
- package/packages/core/publication-authority.js +1 -0
- package/packages/core/publication-reproducibility.js +947 -0
- package/packages/core/publication-sealed-bundle.js +190 -0
- package/packages/core/publish-transaction.js +147 -17
- package/packages/core/release-candidate.js +234 -0
- package/packages/core/release-passport.js +483 -201
- package/packages/core/release-propagation.js +175 -1
- package/scripts/auditable-demo.mjs +119 -5
- package/scripts/aws-codebuild-toolchain.mjs +285 -0
- package/scripts/aws-macos-jit-core.mjs +378 -0
- package/scripts/aws-macos-jit.mjs +123 -0
- package/scripts/aws-runner-burst-core.mjs +248 -0
- package/scripts/aws-runner-burst.mjs +79 -0
- package/scripts/aws-windows-jit-core.mjs +374 -0
- package/scripts/aws-windows-jit.mjs +121 -0
- package/scripts/build-contract-core.mjs +69 -6
- package/scripts/build-standalone-binary.mjs +23 -0
- package/scripts/buildchain-cli-help.mjs +256 -0
- package/scripts/buildchain-contract-lock.mjs +1 -1
- package/scripts/check-internal-architecture.mjs +69 -2
- package/scripts/check-inventory.mjs +69 -2
- package/scripts/check-javascript-syntax.mjs +31 -0
- package/scripts/check-maintainability.mjs +371 -0
- package/scripts/compiler-cache-evidence.mjs +221 -0
- package/scripts/dev-alpha-candidate-patrol.mjs +268 -43
- package/scripts/finalize-native-artifact-signing-result.mjs +75 -4
- package/scripts/generate-channel-promotion-workflow.mjs +3 -12
- package/scripts/generate-release-candidate-passport.mjs +4 -0
- package/scripts/generate-site-bundle.mjs +68 -188
- package/scripts/import-artifact-signing-results.mjs +64 -5
- package/scripts/inspect-artifact-signing-requests.mjs +7 -0
- package/scripts/maintainability-metrics.mjs +339 -0
- package/scripts/npm-publish-transaction.mjs +57 -6
- package/scripts/paper-work-fleet-cli.mjs +563 -0
- package/scripts/paper.mjs +631 -0
- package/scripts/promotion-channel-router.mjs +16 -4
- package/scripts/publication-reproducibility.mjs +62 -0
- package/scripts/release-propagation.mjs +39 -0
- package/scripts/resolve-build-contract.mjs +6 -0
- package/scripts/route-offline-runners.mjs +236 -0
- package/scripts/run-lifecycle-core.mjs +62 -1
- package/scripts/runtime-ref-core.mjs +23 -2
- package/scripts/seal-artifact-signing-requests.mjs +13 -6
- package/scripts/site-capability-metadata.mjs +202 -0
- package/scripts/stable-candidate-qualification.mjs +42 -0
- package/scripts/web-surface-core.mjs +272 -86
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
commandId,
|
|
6
|
+
enumerateCliCommandsFromBin,
|
|
7
|
+
} from "./public-surface-cli.js";
|
|
8
|
+
|
|
9
|
+
export { enumerateCliCommandsFromBin } from "./public-surface-cli.js";
|
|
4
10
|
|
|
5
11
|
export const BUILDCHAIN_PUBLIC_SURFACE_AUDIT_CONTRACT = "kungfu-buildchain-public-surface-reverse-audit";
|
|
6
12
|
|
|
@@ -40,79 +46,6 @@ function listDirectories(root, dir) {
|
|
|
40
46
|
.sort();
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
function commandId(first = "", second = "", third = "") {
|
|
44
|
-
const head = String(first || "").trim();
|
|
45
|
-
const sub = String(second || "").trim();
|
|
46
|
-
const leaf = String(third || "").trim();
|
|
47
|
-
const normalizedLeaf = leaf === "..." ? "" : leaf;
|
|
48
|
-
if (!head) return "";
|
|
49
|
-
if (["-h", "--help", "help"].includes(head)) return "help";
|
|
50
|
-
if (["-v", "--version", "version"].includes(head)) return "version";
|
|
51
|
-
if (head === "release" && ["--dry-run", "dry-run", "explain"].includes(sub)) return "release-dry-run";
|
|
52
|
-
if (head === "release" && sub === "line") return "release-line-open";
|
|
53
|
-
if (head === "release") return "release-transaction";
|
|
54
|
-
if (head === "transaction") return "transaction-inspect";
|
|
55
|
-
if (head === "collect" && sub) return `collect-${sub}`;
|
|
56
|
-
if (head === "verify" && sub) return `verify-${sub}`;
|
|
57
|
-
if (head === "explain" && sub) return `explain-${sub}`;
|
|
58
|
-
if (head === "inspect" && sub) return `inspect-${sub}`;
|
|
59
|
-
if (head === "npm" && sub) return `npm-${sub}`;
|
|
60
|
-
if (head === "lifecycle" && sub) return "lifecycle";
|
|
61
|
-
if (head === "log" && sub) return "logging";
|
|
62
|
-
if (head === "diagnostics" && sub) return `diagnostics-${sub}`;
|
|
63
|
-
if (head === "facts" && sub) return "build-facts";
|
|
64
|
-
if (head === "kfd") {
|
|
65
|
-
if (!sub || sub === "...") return "kfd";
|
|
66
|
-
if (sub === "schema") return normalizedLeaf ? `kfd-schema-${normalizedLeaf}` : "kfd-schema";
|
|
67
|
-
if (sub === "upstream") return normalizedLeaf ? `kfd-upstream-${normalizedLeaf}` : "kfd-upstream";
|
|
68
|
-
if (/^[1-9][0-9]*$/.test(sub)) return normalizedLeaf ? `kfd-${sub}-${normalizedLeaf}` : `kfd-${sub}`;
|
|
69
|
-
return `kfd-${sub}`;
|
|
70
|
-
}
|
|
71
|
-
if (head === "sample" && sub) return `sample-${sub}`;
|
|
72
|
-
if (head === "badges" && sub) return `badges-${sub}`;
|
|
73
|
-
if (head === "homebrew" && sub) return `homebrew-${sub}`;
|
|
74
|
-
if (head === "release-propagation") return "release-propagation";
|
|
75
|
-
if (head === "publish-source") return "publish-source";
|
|
76
|
-
if (head === "publication-artifact" && sub) return `publication-artifact-${sub}`;
|
|
77
|
-
if (head === "publication-artifact") return "publication-artifact";
|
|
78
|
-
if (head === "publication" && sub) return `publication-artifact-${sub}`;
|
|
79
|
-
if (head === "publication") return "publication-artifact";
|
|
80
|
-
if (head === "build-contract") return "build-contract";
|
|
81
|
-
if (head === "infra-contract") return "infra-contract";
|
|
82
|
-
if (head === "web-surface") return "web-surface";
|
|
83
|
-
return head;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function enumerateCliCommandsFromBin({ root = process.cwd(), binPath = "bin/buildchain.mjs" } = {}) {
|
|
87
|
-
const source = readText(root, binPath);
|
|
88
|
-
const dispatchSource = [
|
|
89
|
-
source,
|
|
90
|
-
...listFiles(root, "bin/internal", (name) => name.endsWith(".mjs"))
|
|
91
|
-
.map((relPath) => readText(root, relPath)),
|
|
92
|
-
].join("\n");
|
|
93
|
-
const usageMatch = source.match(/return `Usage:\n([\s\S]*?)`;\n}/);
|
|
94
|
-
const usage = usageMatch?.[1] || "";
|
|
95
|
-
const usageCommands = [];
|
|
96
|
-
for (const line of usage.split(/\r?\n/)) {
|
|
97
|
-
const match = line.trim().match(/^buildchain\s+([^\s]+)(?:\s+([^\s]+))?(?:\s+([^\s]+))?/);
|
|
98
|
-
if (!match) continue;
|
|
99
|
-
usageCommands.push({
|
|
100
|
-
id: commandId(match[1], match[2], match[3]),
|
|
101
|
-
usage: line.trim().replace(/\s+/g, " "),
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
const dispatchCommands = [...dispatchSource.matchAll(/if\s*\(\s*command\s*===\s*"([^"]+)"/g)]
|
|
105
|
-
.map((match) => commandId(match[1]));
|
|
106
|
-
return uniqueSorted([
|
|
107
|
-
...usageCommands.map((entry) => entry.id),
|
|
108
|
-
...dispatchCommands,
|
|
109
|
-
]).map((id) => ({
|
|
110
|
-
id,
|
|
111
|
-
source: "bin/buildchain.mjs",
|
|
112
|
-
usage: usageCommands.find((entry) => entry.id === id)?.usage || `buildchain ${id}`,
|
|
113
|
-
}));
|
|
114
|
-
}
|
|
115
|
-
|
|
116
49
|
function parseYamlWorkflowCall(text) {
|
|
117
50
|
const lines = text.split(/\r?\n/);
|
|
118
51
|
const result = { reusable: false, inputs: [], secrets: [], outputs: [] };
|
|
@@ -330,8 +263,26 @@ export function collectPublicSurfaceReverseAudit({
|
|
|
330
263
|
mode: "closed-world-enumerable",
|
|
331
264
|
scope: "Buildchain CLI usage/dispatch, reusable workflow inputs, action inputs, site pages, and documentation command references",
|
|
332
265
|
residualRisk: [
|
|
333
|
-
|
|
334
|
-
|
|
266
|
+
{
|
|
267
|
+
id: "public-surface-helper-command-enumeration",
|
|
268
|
+
definedBy: "https://kfd.libkungfu.dev/schemas/kfd-2/trust-taxonomy.schema.json#/$defs/residualRisk",
|
|
269
|
+
riskType: "natural-language-semantic-risk",
|
|
270
|
+
trustImpact: "downgrade-warning",
|
|
271
|
+
machineProvability: "not-machine-verifiable",
|
|
272
|
+
agentAction: "semantic-review-required",
|
|
273
|
+
owner: "Buildchain maintainers",
|
|
274
|
+
reason: "Shell commands delegated through helper scripts are counted only when exposed through bin/buildchain.mjs usage or documentation.",
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: "public-surface-yaml-enumeration",
|
|
278
|
+
definedBy: "https://kfd.libkungfu.dev/schemas/kfd-2/trust-taxonomy.schema.json#/$defs/residualRisk",
|
|
279
|
+
riskType: "natural-language-semantic-risk",
|
|
280
|
+
trustImpact: "downgrade-warning",
|
|
281
|
+
machineProvability: "not-machine-verifiable",
|
|
282
|
+
agentAction: "semantic-review-required",
|
|
283
|
+
owner: "Buildchain maintainers",
|
|
284
|
+
reason: "YAML enumeration covers first-class action and workflow inputs, not arbitrary step environment variables.",
|
|
285
|
+
},
|
|
335
286
|
],
|
|
336
287
|
},
|
|
337
288
|
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
function readText(root, relPath) {
|
|
5
|
+
return fs.readFileSync(path.join(root, relPath), "utf8");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function listFiles(root, dir, predicate = () => true) {
|
|
9
|
+
const base = path.join(root, dir);
|
|
10
|
+
if (!fs.existsSync(base)) return [];
|
|
11
|
+
return fs
|
|
12
|
+
.readdirSync(base, { withFileTypes: true })
|
|
13
|
+
.filter((entry) => entry.isFile() && predicate(entry.name))
|
|
14
|
+
.map((entry) => `${dir}/${entry.name}`)
|
|
15
|
+
.sort();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function uniqueSorted(values) {
|
|
19
|
+
return [...new Set(values.filter(Boolean))].sort();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function releaseCommandId(sub) {
|
|
23
|
+
if (["--dry-run", "dry-run", "explain"].includes(sub))
|
|
24
|
+
return "release-dry-run";
|
|
25
|
+
if (sub === "line") return "release-line-open";
|
|
26
|
+
return "release-transaction";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function kfdCommandId(sub, leaf) {
|
|
30
|
+
if (!sub || sub === "...") return "kfd";
|
|
31
|
+
if (["schema", "upstream"].includes(sub) || /^[1-9][0-9]*$/.test(sub)) {
|
|
32
|
+
return leaf ? `kfd-${sub}-${leaf}` : `kfd-${sub}`;
|
|
33
|
+
}
|
|
34
|
+
return `kfd-${sub}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function paperCommandId(sub, leaf) {
|
|
38
|
+
if (sub === "bootstrap" && leaf === "npm") return "paper-bootstrap-npm";
|
|
39
|
+
if (["work", "fleet"].includes(sub) && leaf) return `paper-${sub}-${leaf}`;
|
|
40
|
+
return sub ? `paper-${sub}` : "paper";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function commandId(first = "", second = "", third = "") {
|
|
44
|
+
const head = String(first || "").trim();
|
|
45
|
+
const sub = String(second || "").trim();
|
|
46
|
+
const leaf =
|
|
47
|
+
String(third || "").trim() === "..." ? "" : String(third || "").trim();
|
|
48
|
+
const paired = new Set([
|
|
49
|
+
"collect",
|
|
50
|
+
"verify",
|
|
51
|
+
"explain",
|
|
52
|
+
"inspect",
|
|
53
|
+
"npm",
|
|
54
|
+
"diagnostics",
|
|
55
|
+
"sample",
|
|
56
|
+
"badges",
|
|
57
|
+
"homebrew",
|
|
58
|
+
]);
|
|
59
|
+
if (!head) return "";
|
|
60
|
+
if (["-h", "--help", "help"].includes(head)) return "help";
|
|
61
|
+
if (["-v", "--version", "version"].includes(head)) return "version";
|
|
62
|
+
if (head === "release") return releaseCommandId(sub);
|
|
63
|
+
if (head === "transaction") return "transaction-inspect";
|
|
64
|
+
if (paired.has(head) && sub) return `${head}-${sub}`;
|
|
65
|
+
if (head === "lifecycle" && sub) return "lifecycle";
|
|
66
|
+
if (head === "log" && sub) return "logging";
|
|
67
|
+
if (head === "facts" && sub) return "build-facts";
|
|
68
|
+
if (head === "kfd") return kfdCommandId(sub, leaf);
|
|
69
|
+
if (["release-propagation", "publish-source"].includes(head)) return head;
|
|
70
|
+
if (["publication-artifact", "publication"].includes(head)) {
|
|
71
|
+
return sub ? `publication-artifact-${sub}` : "publication-artifact";
|
|
72
|
+
}
|
|
73
|
+
if (head === "paper") return paperCommandId(sub, leaf);
|
|
74
|
+
return head;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function usageCommands(source) {
|
|
78
|
+
const usageMatch = source.match(/`Usage:\n([\s\S]*?)`;/);
|
|
79
|
+
const rows = [];
|
|
80
|
+
for (const line of (usageMatch?.[1] || "").split(/\r?\n/)) {
|
|
81
|
+
const match = line
|
|
82
|
+
.trim()
|
|
83
|
+
.match(/^buildchain\s+([^\s]+)(?:\s+([^\s]+))?(?:\s+([^\s]+))?/);
|
|
84
|
+
if (!match) continue;
|
|
85
|
+
rows.push({
|
|
86
|
+
id: commandId(match[1], match[2], match[3]),
|
|
87
|
+
usage: line.trim().replace(/\s+/g, " "),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return rows;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function enumerateCliCommandsFromBin({
|
|
94
|
+
root = process.cwd(),
|
|
95
|
+
binPath = "bin/buildchain.mjs",
|
|
96
|
+
} = {}) {
|
|
97
|
+
const binSource = readText(root, binPath);
|
|
98
|
+
const helpSource = readText(root, "scripts/buildchain-cli-help.mjs");
|
|
99
|
+
const dispatchSource = [
|
|
100
|
+
binSource,
|
|
101
|
+
...listFiles(root, "bin/internal", (name) => name.endsWith(".mjs")).map(
|
|
102
|
+
(relPath) => readText(root, relPath),
|
|
103
|
+
),
|
|
104
|
+
].join("\n");
|
|
105
|
+
const usage = usageCommands(helpSource);
|
|
106
|
+
const dispatch = [
|
|
107
|
+
...dispatchSource.matchAll(/if\s*\(\s*command\s*===\s*"([^"]+)"/g),
|
|
108
|
+
].map((match) => commandId(match[1]));
|
|
109
|
+
return uniqueSorted([...usage.map((entry) => entry.id), ...dispatch]).map(
|
|
110
|
+
(id) => ({
|
|
111
|
+
id,
|
|
112
|
+
source: "bin/buildchain.mjs",
|
|
113
|
+
usage:
|
|
114
|
+
usage.find((entry) => entry.id === id)?.usage || `buildchain ${id}`,
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
@@ -253,7 +253,7 @@ export function createPublicationSourceBundle({
|
|
|
253
253
|
} = {}) {
|
|
254
254
|
const outputPath = path.resolve(cwd, output);
|
|
255
255
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
256
|
-
const paths = sourcePaths.length > 0 ? sourcePaths : ["."];
|
|
256
|
+
const paths = [...(sourcePaths.length > 0 ? sourcePaths : ["."])].sort();
|
|
257
257
|
execFileSync("git", [
|
|
258
258
|
"archive",
|
|
259
259
|
"--format=tar.gz",
|
|
@@ -501,11 +501,6 @@ function mergePublicationRegistryVersions({ registries = [], publicationId }) {
|
|
|
501
501
|
if (registry.publication?.id !== publicationId) {
|
|
502
502
|
throw new Error(`publication archive registry id mismatch: expected ${publicationId}, got ${registry.publication?.id || "(missing)"}`);
|
|
503
503
|
}
|
|
504
|
-
if (registry.historyPolicy === "cumulative-authenticated-hydration") {
|
|
505
|
-
const declaredVersions = new Set(registry.versions.map((record) => String(record?.version || "")));
|
|
506
|
-
const missingVersions = [...versions.keys()].filter((version) => !declaredVersions.has(version));
|
|
507
|
-
if (missingVersions.length > 0) throw new Error(`cumulative publication archive registry dropped accepted versions: ${missingVersions.join(", ")}`);
|
|
508
|
-
}
|
|
509
504
|
for (const record of registry.versions) {
|
|
510
505
|
const version = String(record?.version || "").trim();
|
|
511
506
|
if (!version) throw new Error("publication archive registry record is missing version");
|
|
@@ -649,6 +649,7 @@ function validatePublicationEvidence(publicationEvidence, admission) {
|
|
|
649
649
|
platformMatrix: passport.platformMatrix,
|
|
650
650
|
buildchain: passport.buildchain,
|
|
651
651
|
...(passport.gateProfileEvidence ? { gateProfileEvidence: passport.gateProfileEvidence } : {}),
|
|
652
|
+
...(passport.familyEvidence ? { familyEvidence: passport.familyEvidence } : {}),
|
|
652
653
|
...(passport.controllerReceipts ? { controllerReceipts: passport.controllerReceipts } : {}),
|
|
653
654
|
});
|
|
654
655
|
if (normalizeDigest(passport.candidateHash, "releaseCandidatePassport.candidateHash") !== candidateHash) {
|