@kungfu-tech/buildchain 3.0.4-alpha.2 → 3.0.4-alpha.3
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/bin/buildchain.mjs +126 -72
- package/bin/internal/trust-release-cli.mjs +15 -537
- package/bin/internal/trust-release-command-handlers.mjs +14 -0
- package/bin/internal/trust-release-inspection-handlers.mjs +175 -0
- package/bin/internal/trust-release-release-handlers.mjs +317 -0
- package/bin/internal/trust-release-verification-handlers.mjs +306 -0
- package/dist/site/buildchain-contract.json +35 -24
- package/dist/site/buildchain-site.json +22 -10
- package/dist/site/controller-registry.json +16 -3
- package/dist/site/kfd-claims.json +9 -7
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +2 -2
- package/dist/site/node-api-registry.json +7 -7
- package/dist/site/page-registry.json +9 -4
- package/dist/site/public-surface-audit.json +56 -8
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-model.json +7 -0
- package/dist/site/site-manifest.json +6 -6
- package/dist/site/workflow-registry.json +13 -5
- package/docs/MAP.md +1 -1
- package/docs/release-propagation.md +166 -8
- package/package.json +1 -1
- package/packages/core/buildchain-kfd-claims.js +1 -1
- package/packages/core/controller-evidence.js +8 -1
- package/packages/core/index.js +1 -13
- package/packages/core/paper-npm-bootstrap.js +492 -0
- package/packages/core/paper.js +271 -669
- package/packages/core/public-surface-cli.js +12 -1
- package/packages/core/release-passport.js +67 -71
- package/packages/core/release-propagation-common.js +64 -0
- package/packages/core/release-propagation-execution-profile.js +59 -0
- package/packages/core/release-propagation-release.js +196 -0
- package/packages/core/release-propagation-stage-evidence.js +364 -0
- package/packages/core/release-propagation-work-capture.js +64 -0
- package/packages/core/release-propagation-work-constants.js +34 -0
- package/packages/core/release-propagation-work-control.js +203 -0
- package/packages/core/release-propagation-work-transitions.js +145 -0
- package/packages/core/release-propagation-work.js +517 -0
- package/packages/core/release-propagation.js +34 -158
- package/scripts/aws-windows-jit-controller-core.mjs +269 -0
- package/scripts/aws-windows-jit-controller.mjs +502 -0
- package/scripts/check-internal-architecture.mjs +178 -52
- package/scripts/check-maintainability.mjs +76 -17
- package/scripts/generate-site-bundle.mjs +16 -7
- package/scripts/maintainability-metrics.mjs +24 -4
- package/scripts/release-propagation.mjs +126 -0
- package/scripts/resolve-artifact-transfer-mode.mjs +117 -0
- package/scripts/web-surface-core.mjs +46 -207
- package/scripts/web-surface-routing.mjs +286 -0
|
@@ -1,541 +1,19 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { verifyInfraContractEvidenceBundle } from "../../scripts/infra-contract-core.mjs";
|
|
5
|
-
import { verifyBuildchainLogEvents } from "../../packages/core/logging.js";
|
|
6
1
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
verifyPublicationAdmission,
|
|
23
|
-
} from "../../packages/core/publication-authority.js";
|
|
24
|
-
import {
|
|
25
|
-
createGitHubArtifactAttestationPolicy,
|
|
26
|
-
createGitHubArtifactAttestationVerificationPlan,
|
|
27
|
-
verifyGitHubArtifactAttestationEvidence,
|
|
28
|
-
} from "../../packages/core/github-artifact-attestation.js";
|
|
29
|
-
import {
|
|
30
|
-
explainArtifactPassport,
|
|
31
|
-
verifyArtifactPassport,
|
|
32
|
-
} from "../../packages/core/artifact-passport.js";
|
|
33
|
-
import {
|
|
34
|
-
projectArtifactVerificationEnvelopeToKfx,
|
|
35
|
-
verifyArtifactVerificationEnvelope,
|
|
36
|
-
} from "../../packages/core/artifact-verification-envelope.js";
|
|
37
|
-
import {
|
|
38
|
-
artifactEnvelopeOptions,
|
|
39
|
-
printJson,
|
|
40
|
-
readBooleanFlag,
|
|
41
|
-
readFlag,
|
|
42
|
-
readJsonInput,
|
|
43
|
-
readRepeatedFlag,
|
|
44
|
-
writeJsonFile,
|
|
45
|
-
} from "./cli-options.mjs";
|
|
46
|
-
|
|
47
|
-
const TRUST_RELEASE_COMMANDS = new Set([
|
|
48
|
-
"audit",
|
|
49
|
-
"collect",
|
|
50
|
-
"create",
|
|
51
|
-
"explain",
|
|
52
|
-
"inspect",
|
|
53
|
-
"project",
|
|
54
|
-
"release",
|
|
55
|
-
"transaction",
|
|
56
|
-
"verify",
|
|
57
|
-
]);
|
|
58
|
-
|
|
59
|
-
async function dispatchTrustReleaseCommand({ command, args, runScript, packageVersion }) {
|
|
60
|
-
if (command === "release") {
|
|
61
|
-
if (args[0] === "line" && args[1] === "open") {
|
|
62
|
-
const lineArgs = args.slice(2);
|
|
63
|
-
const options = {
|
|
64
|
-
cwd: readFlag(lineArgs, "cwd", process.cwd()),
|
|
65
|
-
major: readFlag(lineArgs, "major", ""),
|
|
66
|
-
minor: readFlag(lineArgs, "minor", ""),
|
|
67
|
-
sourceRef: readFlag(lineArgs, "source-ref", ""),
|
|
68
|
-
initialVersion: readFlag(lineArgs, "initial-version", ""),
|
|
69
|
-
};
|
|
70
|
-
const result = readBooleanFlag(lineArgs, "write")
|
|
71
|
-
? writeReleaseLineBootstrapVersionState({
|
|
72
|
-
...options,
|
|
73
|
-
runVersionStateLifecycle: !readBooleanFlag(lineArgs, "skip-version-state-lifecycle"),
|
|
74
|
-
generatedAt: readFlag(lineArgs, "generated-at", ""),
|
|
75
|
-
})
|
|
76
|
-
: planReleaseLineBootstrap({
|
|
77
|
-
...options,
|
|
78
|
-
requiredStatusCheck: readFlag(lineArgs, "required-status-check", "check"),
|
|
79
|
-
setDefault: !readBooleanFlag(lineArgs, "no-set-default"),
|
|
80
|
-
createAlphaPr: !readBooleanFlag(lineArgs, "no-alpha-pr"),
|
|
81
|
-
approvalCount: Number(readFlag(lineArgs, "approval-count", "1")),
|
|
82
|
-
bootstrapBranch: readFlag(lineArgs, "bootstrap-branch", ""),
|
|
83
|
-
});
|
|
84
|
-
if (readBooleanFlag(lineArgs, "json")) {
|
|
85
|
-
printJson(result);
|
|
86
|
-
} else {
|
|
87
|
-
process.stdout.write(`Buildchain release line bootstrap ${result.line}\n`);
|
|
88
|
-
process.stdout.write(`- source: ${result.source.ref}${result.source.sha ? ` (${result.source.sha})` : ""}\n`);
|
|
89
|
-
process.stdout.write(`- initial version: ${result.initialVersion}\n`);
|
|
90
|
-
process.stdout.write(`- dev: ${result.refs.dev}\n`);
|
|
91
|
-
process.stdout.write(`- alpha: ${result.refs.alpha}\n`);
|
|
92
|
-
process.stdout.write(`- release: ${result.refs.release}\n`);
|
|
93
|
-
process.stdout.write(`- version files: ${result.versionState.files.join(", ") || "none"}\n`);
|
|
94
|
-
if (result.changedFiles) {
|
|
95
|
-
process.stdout.write(`- changed files: ${result.changedFiles.join(", ") || "none"}\n`);
|
|
96
|
-
}
|
|
97
|
-
process.stdout.write(result.dryRun ? "No refs, branches, PRs, or files were modified.\n" : "Version-state files were updated in the working tree.\n");
|
|
98
|
-
}
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const explainMode = args[0] === "dry-run" || args[0] === "explain";
|
|
102
|
-
const releaseArgs = explainMode ? args.slice(1) : args;
|
|
103
|
-
if (explainMode || readBooleanFlag(args, "dry-run")) {
|
|
104
|
-
const plan = explainReleaseLineDryRun({
|
|
105
|
-
cwd: readFlag(releaseArgs, "cwd", process.cwd()),
|
|
106
|
-
targetRef: readFlag(releaseArgs, "target-ref", ""),
|
|
107
|
-
sourceRef: readFlag(releaseArgs, "source-ref", ""),
|
|
108
|
-
sha: readFlag(releaseArgs, "sha", ""),
|
|
109
|
-
tags: readFlag(releaseArgs, "tags", ""),
|
|
110
|
-
publishTransaction: readBooleanFlag(releaseArgs, "publish-transaction"),
|
|
111
|
-
publishCommand: readFlag(releaseArgs, "publish-command", ""),
|
|
112
|
-
});
|
|
113
|
-
if (readBooleanFlag(releaseArgs, "json")) {
|
|
114
|
-
printJson(plan);
|
|
115
|
-
} else {
|
|
116
|
-
process.stdout.write(formatReleaseLineDryRun(plan));
|
|
117
|
-
}
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
runScript("release-transaction.mjs", args);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (command === "transaction") {
|
|
125
|
-
const [subcommand = "inspect", ...transactionArgs] = args;
|
|
126
|
-
if (subcommand !== "inspect") {
|
|
127
|
-
throw new Error("usage: buildchain transaction inspect ...");
|
|
128
|
-
}
|
|
129
|
-
runScript("release-transaction.mjs", ["inspect", ...transactionArgs]);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (command === "create") {
|
|
134
|
-
const [subcommand = "", ...createArgs] = args;
|
|
135
|
-
const inputValue = readFlag(createArgs, "input-json", "");
|
|
136
|
-
if (!inputValue || ![
|
|
137
|
-
"publication-admission",
|
|
138
|
-
"runner-provenance",
|
|
139
|
-
"github-artifact-attestation-policy",
|
|
140
|
-
].includes(subcommand)) {
|
|
141
|
-
throw new Error("usage: buildchain create <publication-admission|runner-provenance|github-artifact-attestation-policy> --input-json <file-or-json> [--output <file>]");
|
|
142
|
-
}
|
|
143
|
-
const input = readJsonInput(inputValue, { label: "input-json" });
|
|
144
|
-
const value = subcommand === "publication-admission"
|
|
145
|
-
? createPublicationAdmission(input)
|
|
146
|
-
: subcommand === "runner-provenance"
|
|
147
|
-
? createRunnerProvenance(input)
|
|
148
|
-
: createGitHubArtifactAttestationPolicy(input);
|
|
149
|
-
const output = readFlag(createArgs, "output", "");
|
|
150
|
-
if (output) writeJsonFile(path.resolve(output), value);
|
|
151
|
-
if (!output || readBooleanFlag(createArgs, "json")) printJson(value);
|
|
152
|
-
else process.stdout.write(`${subcommand}: ${output}\n`);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (command === "collect") {
|
|
157
|
-
const [subcommand = "", ...collectArgs] = args;
|
|
158
|
-
if (subcommand !== "github-release") {
|
|
159
|
-
throw new Error("usage: buildchain collect github-release --tag <tag>");
|
|
160
|
-
}
|
|
161
|
-
const workflow = {
|
|
162
|
-
name: process.env.GITHUB_WORKFLOW || "",
|
|
163
|
-
runId: process.env.GITHUB_RUN_ID || "",
|
|
164
|
-
runAttempt: process.env.GITHUB_RUN_ATTEMPT || "",
|
|
165
|
-
url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_RUN_ID
|
|
166
|
-
? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
|
|
167
|
-
: "",
|
|
168
|
-
runnerKind: process.env.BUILDCHAIN_RUNNER_KIND || "github-hosted",
|
|
169
|
-
runnerOs: process.env.RUNNER_OS || process.platform,
|
|
170
|
-
runnerArch: process.env.RUNNER_ARCH || process.arch,
|
|
171
|
-
runnerImage: process.env.ImageOS || "",
|
|
172
|
-
};
|
|
173
|
-
const result = collectGitHubReleasePassport({
|
|
174
|
-
cwd: readFlag(collectArgs, "cwd", process.cwd()),
|
|
175
|
-
tag: readFlag(collectArgs, "tag", ""),
|
|
176
|
-
repository: readFlag(collectArgs, "repository", process.env.GITHUB_REPOSITORY || ""),
|
|
177
|
-
sourceSha: readFlag(collectArgs, "source-sha", process.env.GITHUB_SHA || ""),
|
|
178
|
-
line: readFlag(collectArgs, "line", ""),
|
|
179
|
-
outputDir: readFlag(collectArgs, "output-dir", ".buildchain/release-passport"),
|
|
180
|
-
assetsDir: readFlag(collectArgs, "assets-dir", ""),
|
|
181
|
-
assetsJson: readFlag(collectArgs, "assets-json", ""),
|
|
182
|
-
releaseJson: readFlag(collectArgs, "release-json", ""),
|
|
183
|
-
productName: readFlag(collectArgs, "product-name", "Buildchain"),
|
|
184
|
-
packageName: readFlag(collectArgs, "package-name", "@kungfu-tech/buildchain"),
|
|
185
|
-
packageVersion: readFlag(collectArgs, "package-version", packageVersion()),
|
|
186
|
-
packageSetJson: readFlag(collectArgs, "package-set-json", ""),
|
|
187
|
-
publishEvidenceJson: readFlag(collectArgs, "publish-evidence-json", ""),
|
|
188
|
-
trustedPublishingJson: readFlag(collectArgs, "trusted-publishing-json", ""),
|
|
189
|
-
transactionJson: readFlag(collectArgs, "transaction-json", ""),
|
|
190
|
-
anchorManifestJson: readFlag(collectArgs, "anchor-manifest-json", ""),
|
|
191
|
-
impactJson: readFlag(collectArgs, "impact-json", ""),
|
|
192
|
-
buildSummaryJson: readFlag(collectArgs, "build-summary-json", ""),
|
|
193
|
-
buildFactsJsons: readRepeatedFlag(collectArgs, "build-facts-json"),
|
|
194
|
-
platformManifestJsons: readRepeatedFlag(collectArgs, "platform-manifest-json"),
|
|
195
|
-
distTagEvidenceJson: readFlag(collectArgs, "dist-tag-evidence-json", ""),
|
|
196
|
-
kfd1WitnessJsons: readRepeatedFlag(collectArgs, "kfd-1-witness-json"),
|
|
197
|
-
kfd2ClaimJsons: readRepeatedFlag(collectArgs, "kfd-2-claim-json"),
|
|
198
|
-
kfd3PrebuildWitnessJsons: readRepeatedFlag(collectArgs, "kfd-3-prebuild-witness-json"),
|
|
199
|
-
kfd3ArtifactWitnessJsons: readRepeatedFlag(collectArgs, "kfd-3-artifact-witness-json"),
|
|
200
|
-
kfd3ArtifactVerifyCommand: readFlag(collectArgs, "kfd-3-artifact-verify-cmd", ""),
|
|
201
|
-
kfdSupportMatrixJson: readFlag(collectArgs, "kfd-support-matrix-json", ""),
|
|
202
|
-
kfdProductGateJsons: readRepeatedFlag(collectArgs, "kfd-product-gate-json"),
|
|
203
|
-
invariantPassportJsons: readRepeatedFlag(collectArgs, "invariant-passport-json"),
|
|
204
|
-
invariantPassportCommand: readFlag(collectArgs, "invariant-passport-cmd", ""),
|
|
205
|
-
releaseEvidenceJsons: readRepeatedFlag(collectArgs, "release-evidence-json"),
|
|
206
|
-
githubArtifactAttestationPolicyJsons: readRepeatedFlag(
|
|
207
|
-
collectArgs,
|
|
208
|
-
"github-artifact-attestation-policy-json",
|
|
209
|
-
),
|
|
210
|
-
kfdAgentHubEvidenceJson: readFlag(collectArgs, "kfd-agent-hub-evidence-json", ""),
|
|
211
|
-
basePassportJson: readFlag(collectArgs, "base-passport-json", ""),
|
|
212
|
-
requireBaseKfd: readBooleanFlag(collectArgs, "require-base-kfd"),
|
|
213
|
-
releaseJsonExtra: readFlag(collectArgs, "release-extra-json", ""),
|
|
214
|
-
publishJson: readFlag(collectArgs, "publish-json", ""),
|
|
215
|
-
workflow,
|
|
216
|
-
});
|
|
217
|
-
if (readBooleanFlag(collectArgs, "json")) {
|
|
218
|
-
printJson(result);
|
|
219
|
-
} else {
|
|
220
|
-
process.stdout.write(`release passport collected: ${path.relative(process.cwd(), result.outputDir)}\n`);
|
|
221
|
-
process.stdout.write(`artifacts: ${result.artifactEvidence.artifacts.length}\n`);
|
|
222
|
-
}
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (command === "project") {
|
|
227
|
-
const [subcommand = "", location = "", ...projectArgs] = args;
|
|
228
|
-
if (subcommand !== "kfx-admission" || !location) {
|
|
229
|
-
throw new Error("usage: buildchain project kfx-admission <file-or-json>");
|
|
230
|
-
}
|
|
231
|
-
const projection = projectArtifactVerificationEnvelopeToKfx({
|
|
232
|
-
envelope: readJsonInput(location, { label: "artifact verification envelope" }),
|
|
233
|
-
...artifactEnvelopeOptions(projectArgs),
|
|
234
|
-
});
|
|
235
|
-
if (readBooleanFlag(projectArgs, "json")) {
|
|
236
|
-
printJson(projection);
|
|
237
|
-
} else {
|
|
238
|
-
process.stdout.write(`KFX admission envelope: ${projection.envelopeRoot}\n`);
|
|
239
|
-
}
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (command === "verify") {
|
|
244
|
-
const [subcommand = "", location = "", ...verifyArgs] = args;
|
|
245
|
-
if (subcommand === "github-artifact-attestation") {
|
|
246
|
-
if (!location) {
|
|
247
|
-
throw new Error("usage: buildchain verify github-artifact-attestation <artifact> --evidence <file> --bundle <file> --platform-manifest <file> --release-passport <file>");
|
|
248
|
-
}
|
|
249
|
-
const requiredPath = (name) => {
|
|
250
|
-
const value = readFlag(verifyArgs, name, "");
|
|
251
|
-
if (!value) {
|
|
252
|
-
throw new Error(`buildchain verify github-artifact-attestation requires --${name} <file>`);
|
|
253
|
-
}
|
|
254
|
-
return path.resolve(value);
|
|
255
|
-
};
|
|
256
|
-
const evidencePath = requiredPath("evidence");
|
|
257
|
-
const bundlePath = requiredPath("bundle");
|
|
258
|
-
const platformManifestPath = requiredPath("platform-manifest");
|
|
259
|
-
const releasePassportPath = requiredPath("release-passport");
|
|
260
|
-
const evidence = readJsonInput(evidencePath, { label: "evidence" });
|
|
261
|
-
const plan = createGitHubArtifactAttestationVerificationPlan({
|
|
262
|
-
artifactPath: location,
|
|
263
|
-
bundlePath,
|
|
264
|
-
evidence,
|
|
265
|
-
});
|
|
266
|
-
const verified = spawnSync(plan.command, plan.args, {
|
|
267
|
-
cwd: process.cwd(),
|
|
268
|
-
encoding: "utf8",
|
|
269
|
-
maxBuffer: 32 * 1024 * 1024,
|
|
270
|
-
});
|
|
271
|
-
if (verified.error) throw verified.error;
|
|
272
|
-
if (verified.status !== 0) {
|
|
273
|
-
throw new Error(`gh attestation verify failed: ${(verified.stderr || verified.stdout || "unknown error").trim()}`);
|
|
274
|
-
}
|
|
275
|
-
let verificationResults;
|
|
276
|
-
try {
|
|
277
|
-
verificationResults = JSON.parse(verified.stdout);
|
|
278
|
-
} catch (error) {
|
|
279
|
-
throw new Error(`gh attestation verify returned invalid JSON: ${error.message}`);
|
|
280
|
-
}
|
|
281
|
-
const report = verifyGitHubArtifactAttestationEvidence({
|
|
282
|
-
artifactPath: path.resolve(location),
|
|
283
|
-
platformManifestPath,
|
|
284
|
-
releasePassportPath,
|
|
285
|
-
bundlePath,
|
|
286
|
-
evidence,
|
|
287
|
-
verificationResults,
|
|
288
|
-
});
|
|
289
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
290
|
-
printJson(report);
|
|
291
|
-
} else {
|
|
292
|
-
process.stdout.write(`GitHub artifact attestation: ${report.outcome}\n`);
|
|
293
|
-
for (const entry of report.issues) {
|
|
294
|
-
process.stdout.write(`- ${entry.code}: ${entry.message}\n`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
if (subcommand === "publication-admission") {
|
|
301
|
-
if (!location) {
|
|
302
|
-
throw new Error("usage: buildchain verify publication-admission <file-or-json> --registry-json <file-or-json> --runner-json <file-or-json> --control-plane-audit-json <file-or-json> --publication-evidence-json <file-or-json>");
|
|
303
|
-
}
|
|
304
|
-
const requiredInput = (name) => {
|
|
305
|
-
const value = readFlag(verifyArgs, name, "");
|
|
306
|
-
if (!value) throw new Error(`buildchain verify publication-admission requires --${name} <file-or-json>`);
|
|
307
|
-
return readJsonInput(value, { label: name });
|
|
308
|
-
};
|
|
309
|
-
const expectedInput = readFlag(verifyArgs, "expected-json", "");
|
|
310
|
-
const capability = verifyPublicationAdmission({
|
|
311
|
-
admission: readJsonInput(location, { label: "publication admission" }),
|
|
312
|
-
registry: requiredInput("registry-json"),
|
|
313
|
-
runnerProvenance: requiredInput("runner-json"),
|
|
314
|
-
controlPlaneAudit: requiredInput("control-plane-audit-json"),
|
|
315
|
-
publicationEvidence: requiredInput("publication-evidence-json"),
|
|
316
|
-
expected: expectedInput ? readJsonInput(expectedInput, { label: "expected-json" }) : {},
|
|
317
|
-
usedNonces: readRepeatedFlag(verifyArgs, "used-nonce"),
|
|
318
|
-
});
|
|
319
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
320
|
-
printJson(capability);
|
|
321
|
-
} else {
|
|
322
|
-
process.stdout.write(`publication admission: ${capability.decision}\n`);
|
|
323
|
-
process.stdout.write(`capability digest: ${capability.capabilityDigest}\n`);
|
|
324
|
-
process.stdout.write(`expires at: ${capability.expiresAt}\n`);
|
|
325
|
-
}
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
if (subcommand === "artifact") {
|
|
329
|
-
if (!location) {
|
|
330
|
-
throw new Error("usage: buildchain verify artifact <subject>");
|
|
331
|
-
}
|
|
332
|
-
const report = await verifyArtifactPassport({
|
|
333
|
-
subject: location,
|
|
334
|
-
cwd: process.cwd(),
|
|
335
|
-
passportLocation: readFlag(verifyArgs, "passport", ""),
|
|
336
|
-
locatorConfig: readFlag(verifyArgs, "locator-config", ""),
|
|
337
|
-
repository: readFlag(verifyArgs, "repository", ""),
|
|
338
|
-
tag: readFlag(verifyArgs, "tag", ""),
|
|
339
|
-
githubReleaseBaseUrl: readFlag(verifyArgs, "github-release-base-url", ""),
|
|
340
|
-
subjectDigest: readFlag(verifyArgs, "subject-digest", ""),
|
|
341
|
-
subjectKind: readFlag(verifyArgs, "subject-kind", ""),
|
|
342
|
-
npmRegistryBaseUrl: readFlag(verifyArgs, "npm-registry", ""),
|
|
343
|
-
});
|
|
344
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
345
|
-
printJson(report);
|
|
346
|
-
} else {
|
|
347
|
-
process.stdout.write(`artifact: ${report.outcome}\n`);
|
|
348
|
-
process.stdout.write(`subject: ${report.subject?.name || location}\n`);
|
|
349
|
-
process.stdout.write(`passport: ${report.passport?.location || report.discovery?.passportLocation || "unresolved"}\n`);
|
|
350
|
-
for (const entry of report.issues) {
|
|
351
|
-
process.stdout.write(`- ${entry.level}: ${entry.code}: ${entry.message}\n`);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
if (subcommand === "artifact-envelope") {
|
|
358
|
-
if (!location) {
|
|
359
|
-
throw new Error("usage: buildchain verify artifact-envelope <file-or-json>");
|
|
360
|
-
}
|
|
361
|
-
const report = verifyArtifactVerificationEnvelope({
|
|
362
|
-
envelope: readJsonInput(location, { label: "artifact verification envelope" }),
|
|
363
|
-
...artifactEnvelopeOptions(verifyArgs),
|
|
364
|
-
});
|
|
365
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
366
|
-
printJson(report);
|
|
367
|
-
} else {
|
|
368
|
-
process.stdout.write(`artifact verification envelope: ${report.outcome}\n`);
|
|
369
|
-
process.stdout.write(`root: ${report.envelopeRoot || "unresolved"}\n`);
|
|
370
|
-
for (const entry of report.issues) {
|
|
371
|
-
process.stdout.write(`- ${entry.level}: ${entry.code}: ${entry.message}\n`);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
if (subcommand === "observability-log") {
|
|
378
|
-
if (!location) {
|
|
379
|
-
throw new Error("usage: buildchain verify observability-log <jsonl>");
|
|
380
|
-
}
|
|
381
|
-
const report = verifyBuildchainLogEvents({
|
|
382
|
-
path: location,
|
|
383
|
-
minEvents: Number(readFlag(verifyArgs, "min-events", "1")),
|
|
384
|
-
allowErrors: readBooleanFlag(verifyArgs, "allow-errors"),
|
|
385
|
-
requirePhases: readRepeatedFlag(verifyArgs, "require-phase"),
|
|
386
|
-
requireComponents: readRepeatedFlag(verifyArgs, "require-component"),
|
|
387
|
-
requireEvents: readRepeatedFlag(verifyArgs, "require-event"),
|
|
388
|
-
});
|
|
389
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
390
|
-
printJson(report);
|
|
391
|
-
} else {
|
|
392
|
-
process.stdout.write(`observability log: ${report.ok ? "ok" : "failed"}\n`);
|
|
393
|
-
process.stdout.write(`events: ${report.summary.eventCount}\n`);
|
|
394
|
-
for (const entry of report.issues) {
|
|
395
|
-
process.stdout.write(`- ${entry.level}: ${entry.code}: ${entry.message}\n`);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
if (subcommand === "infra-contract-evidence-bundle") {
|
|
402
|
-
if (!location) {
|
|
403
|
-
throw new Error("usage: buildchain verify infra-contract-evidence-bundle <file>");
|
|
404
|
-
}
|
|
405
|
-
const bundle = JSON.parse(fs.readFileSync(path.resolve(location), "utf8"));
|
|
406
|
-
const report = verifyInfraContractEvidenceBundle(bundle);
|
|
407
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
408
|
-
printJson(report);
|
|
409
|
-
} else {
|
|
410
|
-
process.stdout.write(`infra contract evidence bundle: ${report.ok ? "ok" : "failed"}\n`);
|
|
411
|
-
process.stdout.write(`artifact: ${report.artifactHash || "unknown"}\n`);
|
|
412
|
-
for (const entry of report.issues) {
|
|
413
|
-
process.stdout.write(`- ${entry.level}: ${entry.code}: ${entry.message}\n`);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
417
|
-
return;
|
|
418
|
-
}
|
|
419
|
-
if (subcommand !== "release-passport" || !location) {
|
|
420
|
-
throw new Error("usage: buildchain verify release-passport <file-or-url>");
|
|
421
|
-
}
|
|
422
|
-
const report = await verifyReleasePassport({ passportLocation: location });
|
|
423
|
-
if (readBooleanFlag(verifyArgs, "json")) {
|
|
424
|
-
printJson(report);
|
|
425
|
-
} else {
|
|
426
|
-
process.stdout.write(`release passport: ${report.ok ? "ok" : "failed"}\n`);
|
|
427
|
-
process.stdout.write(`artifacts: ${report.completeness.artifactCount}\n`);
|
|
428
|
-
for (const entry of report.issues) {
|
|
429
|
-
process.stdout.write(`- ${entry.level}: ${entry.code}: ${entry.message}\n`);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (command === "audit") {
|
|
437
|
-
const [subcommand = "", ...auditArgs] = args;
|
|
438
|
-
if (subcommand === "publication-control-plane") {
|
|
439
|
-
runScript("audit-publication-control-plane.mjs", auditArgs);
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
if (subcommand === "github-governance") {
|
|
443
|
-
runScript("audit-github-governance.mjs", auditArgs);
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
throw new Error("usage: buildchain audit <publication-control-plane|github-governance> ...");
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
if (command === "explain") {
|
|
450
|
-
const [subcommand = "", ...explainArgs] = args;
|
|
451
|
-
if (subcommand === "artifact") {
|
|
452
|
-
const subject = explainArgs[0] || "";
|
|
453
|
-
if (!subject) {
|
|
454
|
-
throw new Error("usage: buildchain explain artifact <subject>");
|
|
455
|
-
}
|
|
456
|
-
const explanation = await explainArtifactPassport({
|
|
457
|
-
subject,
|
|
458
|
-
cwd: process.cwd(),
|
|
459
|
-
passportLocation: readFlag(explainArgs, "passport", ""),
|
|
460
|
-
locatorConfig: readFlag(explainArgs, "locator-config", ""),
|
|
461
|
-
repository: readFlag(explainArgs, "repository", ""),
|
|
462
|
-
tag: readFlag(explainArgs, "tag", ""),
|
|
463
|
-
githubReleaseBaseUrl: readFlag(explainArgs, "github-release-base-url", ""),
|
|
464
|
-
subjectDigest: readFlag(explainArgs, "subject-digest", ""),
|
|
465
|
-
subjectKind: readFlag(explainArgs, "subject-kind", ""),
|
|
466
|
-
npmRegistryBaseUrl: readFlag(explainArgs, "npm-registry", ""),
|
|
467
|
-
forAudience: readFlag(explainArgs, "for", "human"),
|
|
468
|
-
});
|
|
469
|
-
if (readBooleanFlag(explainArgs, "json")) {
|
|
470
|
-
printJson(explanation);
|
|
471
|
-
} else {
|
|
472
|
-
process.stdout.write(`artifact: ${explanation.subject?.name || subject}\n`);
|
|
473
|
-
process.stdout.write(`trust: ${explanation.trust}\n`);
|
|
474
|
-
process.stdout.write(`next action: ${explanation.nextAction}\n`);
|
|
475
|
-
}
|
|
476
|
-
process.exitCode = explanation.trust === "pass" ? 0 : 1;
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
if (subcommand !== "release") {
|
|
480
|
-
throw new Error("usage: buildchain explain release --passport <file-or-url>");
|
|
481
|
-
}
|
|
482
|
-
const passport = readFlag(explainArgs, "passport", "");
|
|
483
|
-
if (!passport) {
|
|
484
|
-
throw new Error("buildchain explain release requires --passport <file-or-url>");
|
|
485
|
-
}
|
|
486
|
-
const explanation = await explainReleasePassport({
|
|
487
|
-
passportLocation: passport,
|
|
488
|
-
forAudience: readFlag(explainArgs, "for", "human"),
|
|
489
|
-
});
|
|
490
|
-
if (readBooleanFlag(explainArgs, "json")) {
|
|
491
|
-
printJson(explanation);
|
|
492
|
-
} else {
|
|
493
|
-
process.stdout.write(`release: ${explanation.release?.tag || "unknown"}\n`);
|
|
494
|
-
process.stdout.write(`trust: ${explanation.trust}\n`);
|
|
495
|
-
process.stdout.write(`next action: ${explanation.nextAction}\n`);
|
|
496
|
-
}
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
if (command === "inspect") {
|
|
501
|
-
const [subcommand = "", ...inspectArgs] = args;
|
|
502
|
-
if (subcommand === "artifact") {
|
|
503
|
-
const subject = inspectArgs[0] || "";
|
|
504
|
-
if (!subject) {
|
|
505
|
-
throw new Error("usage: buildchain inspect artifact <subject>");
|
|
506
|
-
}
|
|
507
|
-
const report = await verifyArtifactPassport({
|
|
508
|
-
subject,
|
|
509
|
-
cwd: process.cwd(),
|
|
510
|
-
passportLocation: readFlag(inspectArgs, "passport", ""),
|
|
511
|
-
locatorConfig: readFlag(inspectArgs, "locator-config", ""),
|
|
512
|
-
repository: readFlag(inspectArgs, "repository", ""),
|
|
513
|
-
tag: readFlag(inspectArgs, "tag", ""),
|
|
514
|
-
githubReleaseBaseUrl: readFlag(inspectArgs, "github-release-base-url", ""),
|
|
515
|
-
subjectDigest: readFlag(inspectArgs, "subject-digest", ""),
|
|
516
|
-
subjectKind: readFlag(inspectArgs, "subject-kind", ""),
|
|
517
|
-
npmRegistryBaseUrl: readFlag(inspectArgs, "npm-registry", ""),
|
|
518
|
-
});
|
|
519
|
-
printJson(report);
|
|
520
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
if (subcommand !== "release") {
|
|
524
|
-
throw new Error("usage: buildchain inspect release --passport <file-or-url>");
|
|
525
|
-
}
|
|
526
|
-
const passport = readFlag(inspectArgs, "passport", "");
|
|
527
|
-
if (!passport) {
|
|
528
|
-
throw new Error("buildchain inspect release requires --passport <file-or-url>");
|
|
529
|
-
}
|
|
530
|
-
const explanation = await explainReleasePassport({
|
|
531
|
-
passportLocation: passport,
|
|
532
|
-
forAudience: readFlag(inspectArgs, "for", "human"),
|
|
533
|
-
});
|
|
534
|
-
printJson(explanation);
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
throw new Error(`unsupported trust or release command: ${command}`);
|
|
2
|
+
TRUST_RELEASE_COMMANDS,
|
|
3
|
+
TRUST_RELEASE_COMMAND_HANDLERS,
|
|
4
|
+
} from "./trust-release-command-handlers.mjs";
|
|
5
|
+
|
|
6
|
+
async function dispatchTrustReleaseCommand({
|
|
7
|
+
command,
|
|
8
|
+
args,
|
|
9
|
+
runScript,
|
|
10
|
+
packageVersion,
|
|
11
|
+
}) {
|
|
12
|
+
const handler = TRUST_RELEASE_COMMAND_HANDLERS[command];
|
|
13
|
+
if (!handler) {
|
|
14
|
+
throw new Error(`unsupported trust or release command: ${command}`);
|
|
15
|
+
}
|
|
16
|
+
return handler({ args, runScript, packageVersion });
|
|
539
17
|
}
|
|
540
18
|
|
|
541
19
|
export { TRUST_RELEASE_COMMANDS, dispatchTrustReleaseCommand };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { INSPECTION_COMMAND_HANDLERS } from "./trust-release-inspection-handlers.mjs";
|
|
2
|
+
import { RELEASE_COMMAND_HANDLERS } from "./trust-release-release-handlers.mjs";
|
|
3
|
+
import { handleVerifyCommand } from "./trust-release-verification-handlers.mjs";
|
|
4
|
+
|
|
5
|
+
const TRUST_RELEASE_COMMAND_HANDLERS = Object.freeze({
|
|
6
|
+
...RELEASE_COMMAND_HANDLERS,
|
|
7
|
+
verify: handleVerifyCommand,
|
|
8
|
+
...INSPECTION_COMMAND_HANDLERS,
|
|
9
|
+
});
|
|
10
|
+
const TRUST_RELEASE_COMMANDS = new Set(
|
|
11
|
+
Object.keys(TRUST_RELEASE_COMMAND_HANDLERS),
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export { TRUST_RELEASE_COMMANDS, TRUST_RELEASE_COMMAND_HANDLERS };
|