@kungfu-tech/buildchain 3.0.9-alpha.1 → 3.0.9-alpha.11
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/actions/promote-buildchain-ref/README.md +4 -0
- package/bin/buildchain.mjs +9 -1
- package/bin/internal/trust-release-release-handlers.mjs +1 -0
- package/contracts/dev-delivery-authority-v2.schema.json +253 -0
- package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
- package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
- package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
- package/contracts/next-development-request-v1.schema.json +66 -0
- package/contracts/next-development-transition-v1.schema.json +292 -0
- package/dist/site/agent-index.json +1 -0
- package/dist/site/artifact-schemas.json +2 -0
- package/dist/site/buildchain-contract.json +92 -27
- package/dist/site/buildchain-site.json +351 -38
- package/dist/site/capability-registry.json +7 -6
- package/dist/site/cli-registry.json +43 -3
- package/dist/site/controller-registry.json +6 -2
- package/dist/site/kfd-claims.json +223 -12
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +23 -7
- package/dist/site/node-api-registry.json +7926 -4533
- package/dist/site/page-registry.json +332 -27
- package/dist/site/public-surface-audit.json +359 -11
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-passport-check-manifest.json +1 -0
- package/dist/site/release-provenance.json +14 -0
- package/dist/site/schemas/dev-delivery-authority-v2.schema.json +442 -0
- package/dist/site/schemas/release-passport-v1.schema.json +3 -0
- package/dist/site/site-manifest.json +19 -11
- package/dist/site/workflow-registry.json +21 -10
- package/docs/MAP.md +5 -2
- package/docs/adopter-delivery-gate.md +106 -0
- package/docs/aws-us-elastic-runner-burst-plane.md +30 -3
- package/docs/cli-reference.md +202 -15
- package/docs/dev-alpha-candidate-patrol.md +8 -0
- package/docs/dev-delivery-qualification-landing-adr.md +137 -0
- package/docs/dev-delivery-warrant.md +149 -22
- package/docs/kfd-support.md +7 -2
- package/docs/next-development-transition.md +119 -0
- package/docs/node-api-reference.md +402 -204
- package/docs/release-governance.md +10 -7
- package/docs/release-passport.md +18 -2
- package/docs/versioning.md +4 -1
- package/package.json +23 -6
- package/packages/core/README.md +25 -0
- package/packages/core/adopter-delivery-gate.js +576 -0
- package/packages/core/adopter-delivery-json.js +66 -0
- package/packages/core/adopter-delivery-passport.js +259 -0
- package/packages/core/adopter-delivery-vectors.js +158 -0
- package/packages/core/adopter-delivery-vectors.json +77 -0
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/buildchain-agent-manuals.js +1 -0
- package/packages/core/buildchain-channel-identity.js +2 -3
- package/packages/core/buildchain-compatibility-proof.js +22 -0
- package/packages/core/buildchain-delivery-bootstrap.js +240 -0
- package/packages/core/buildchain-delivery-infrastructure.js +164 -0
- package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
- package/packages/core/channel-candidate.js +8 -0
- package/packages/core/channel-promotion-baseline.js +52 -0
- package/packages/core/dev-alpha-candidate-selection.js +10 -2
- package/packages/core/dev-delivery-authority.js +996 -0
- package/packages/core/dev-delivery-native-proof.js +418 -0
- package/packages/core/dev-delivery-warrant-settlement.js +67 -20
- package/packages/core/dev-delivery-warrant.js +129 -46
- package/packages/core/kfd-adopter-category-driver.js +167 -0
- package/packages/core/kfd-adopter-manifest.js +49 -50
- package/packages/core/legacy-kfd-adopter-driver.js +167 -0
- package/packages/core/next-development-candidate-reservation.js +186 -0
- package/packages/core/next-development-controller.js +726 -0
- package/packages/core/next-development-projection.js +288 -0
- package/packages/core/next-development-transition.js +738 -0
- package/packages/core/paper-agent-entry.js +7 -4
- package/packages/core/paper.js +14 -7
- package/packages/core/published-delivery-authority.js +247 -0
- package/packages/core/release-passport-contract.js +10 -6
- package/packages/core/release-passport.js +37 -13
- package/scripts/aws-macos-jit-controller-core.mjs +239 -4
- package/scripts/aws-macos-jit-controller.mjs +198 -2
- package/scripts/aws-macos-jit-instance-rehydrate.mjs +260 -0
- package/scripts/aws-macos-jit-source-rebind.mjs +235 -14
- package/scripts/aws-macos-jit.mjs +12 -0
- package/scripts/buildchain-cli-help.mjs +10 -2
- package/scripts/check-internal-architecture.mjs +1 -0
- package/scripts/check-inventory.mjs +12 -1
- package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
- package/scripts/dev-delivery-authority.mjs +368 -0
- package/scripts/dev-delivery-native-run.mjs +235 -0
- package/scripts/dev-delivery-proof.mjs +64 -2
- package/scripts/dev-delivery-two-phase-resume.mjs +90 -0
- package/scripts/dev-delivery-two-phase.mjs +577 -0
- package/scripts/dev-delivery-warrant.mjs +48 -6
- package/scripts/dev-pr-delivery-warrant.mjs +19 -14
- package/scripts/generate-buildchain-kfd-witnesses.mjs +2 -2
- package/scripts/generate-channel-build-workflow.mjs +4 -0
- package/scripts/generate-next-development-guidance.mjs +49 -0
- package/scripts/generate-site-bundle.mjs +8 -3
- package/scripts/init-repo.mjs +135 -62
- package/scripts/next-development-self-dogfood-harness.mjs +409 -0
- package/scripts/next-development-self-dogfood.mjs +532 -0
- package/scripts/next-development-transition.mjs +47 -0
- package/scripts/release-candidate-tail-reseal.mjs +426 -0
- package/scripts/seal-artifact-signing-requests.mjs +7 -4
- package/scripts/site-capability-metadata.mjs +25 -1
- package/scripts/stable-candidate-qualification.mjs +7 -7
- package/scripts/workflow-call-contract.mjs +1 -1
- package/templates/native-dev-delivery.yml +86 -0
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
workCheck,
|
|
14
14
|
} from "./paper-repository.js";
|
|
15
15
|
import { mergePublicationRehearsalAgentInstructions } from "./publication-rehearsal-projection.js";
|
|
16
|
+
import { mergeNextDevelopmentAgentInstructions } from "./next-development-projection.js";
|
|
16
17
|
|
|
17
18
|
export const PAPER_AGENT_ENTRY_CONTRACT = "kungfu-buildchain-paper-agent-entry";
|
|
18
19
|
export const PAPER_AGENT_ENTRY_SCHEMA_VERSION = 1;
|
|
@@ -168,10 +169,12 @@ export function paperAgentEntryFiles({
|
|
|
168
169
|
[PAPER_PATHS.agentEntry, jsonText(entry)],
|
|
169
170
|
[
|
|
170
171
|
PAPER_PATHS.agentInstructions,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
mergeNextDevelopmentAgentInstructions(
|
|
173
|
+
mergePublicationRehearsalAgentInstructions(
|
|
174
|
+
mergePaperAgentEntryInstructions(currentAgents, {
|
|
175
|
+
developmentRef: resolvedDevelopmentRef,
|
|
176
|
+
}),
|
|
177
|
+
),
|
|
175
178
|
),
|
|
176
179
|
],
|
|
177
180
|
]);
|
package/packages/core/paper.js
CHANGED
|
@@ -51,6 +51,11 @@ import {
|
|
|
51
51
|
projectPublicationRehearsalToml,
|
|
52
52
|
publicationRehearsalWorkflow,
|
|
53
53
|
} from "./publication-rehearsal-projection.js";
|
|
54
|
+
import {
|
|
55
|
+
appendNextDevelopmentToml,
|
|
56
|
+
nextDevelopmentWorkflowHeader,
|
|
57
|
+
projectNextDevelopmentToml,
|
|
58
|
+
} from "./next-development-projection.js";
|
|
54
59
|
|
|
55
60
|
export { PAPER_PATHS, resolvePaperRepository } from "./paper-repository.js";
|
|
56
61
|
export {
|
|
@@ -356,7 +361,7 @@ immutable_base_url = ${tomlString(joinUrl(siteBaseUrl, "archive").replace(/\/$/,
|
|
|
356
361
|
registry_path = ".buildchain/publication/publication-registry.json"
|
|
357
362
|
`
|
|
358
363
|
: "";
|
|
359
|
-
return appendPublicationRehearsalToml(`schema = 1
|
|
364
|
+
return appendNextDevelopmentToml(appendPublicationRehearsalToml(`schema = 1
|
|
360
365
|
|
|
361
366
|
[project]
|
|
362
367
|
type = "publication-artifact"
|
|
@@ -390,14 +395,14 @@ command = "make pdf"
|
|
|
390
395
|
|
|
391
396
|
[lifecycle.verify]
|
|
392
397
|
command = "make check"
|
|
393
|
-
`);
|
|
398
|
+
`));
|
|
394
399
|
}
|
|
395
400
|
|
|
396
401
|
function scaffoldBuildWorkflow(
|
|
397
402
|
buildchainSha,
|
|
398
403
|
{ artifactName = "paper-publication" } = {},
|
|
399
404
|
) {
|
|
400
|
-
return
|
|
405
|
+
return `${nextDevelopmentWorkflowHeader()}name: Build
|
|
401
406
|
|
|
402
407
|
on:
|
|
403
408
|
workflow_dispatch:
|
|
@@ -425,7 +430,7 @@ jobs:
|
|
|
425
430
|
}
|
|
426
431
|
|
|
427
432
|
function scaffoldVerifyWorkflow(buildchainSha) {
|
|
428
|
-
return
|
|
433
|
+
return `${nextDevelopmentWorkflowHeader()}name: Verify
|
|
429
434
|
|
|
430
435
|
on:
|
|
431
436
|
pull_request:
|
|
@@ -456,7 +461,7 @@ function scaffoldReleaseWorkflow(
|
|
|
456
461
|
const passportInput = releasePassportProductName
|
|
457
462
|
? ` release-passport-product-name: ${JSON.stringify(releasePassportProductName)}\n`
|
|
458
463
|
: "";
|
|
459
|
-
return
|
|
464
|
+
return `${nextDevelopmentWorkflowHeader()}name: Paper Release
|
|
460
465
|
|
|
461
466
|
on:
|
|
462
467
|
workflow_dispatch:
|
|
@@ -1017,8 +1022,10 @@ function migrationFiles({
|
|
|
1017
1022
|
const files = new Map([
|
|
1018
1023
|
[
|
|
1019
1024
|
PAPER_PATHS.config,
|
|
1020
|
-
|
|
1021
|
-
|
|
1025
|
+
projectNextDevelopmentToml(
|
|
1026
|
+
projectPublicationRehearsalToml(
|
|
1027
|
+
fs.readFileSync(path.resolve(cwd, PAPER_PATHS.config), "utf8"),
|
|
1028
|
+
),
|
|
1022
1029
|
),
|
|
1023
1030
|
],
|
|
1024
1031
|
[PAPER_PATHS.contractLock, contractLockText],
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { mkdir, mkdtemp, readFile, realpath, rm } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
import { execFile } from "node:child_process";
|
|
9
|
+
|
|
10
|
+
import { adopterDeliveryGateDigest } from "./adopter-delivery-gate.js";
|
|
11
|
+
|
|
12
|
+
export const PUBLISHED_DELIVERY_AUTHORITY_CONTRACT =
|
|
13
|
+
"kungfu-buildchain-published-delivery-authority/v1";
|
|
14
|
+
|
|
15
|
+
const execFileAsync = promisify(execFile);
|
|
16
|
+
const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
17
|
+
const PACKAGES = [
|
|
18
|
+
{
|
|
19
|
+
key: "buildchain",
|
|
20
|
+
name: "@kungfu-tech/buildchain",
|
|
21
|
+
packageRoot: "archive",
|
|
22
|
+
modules: {
|
|
23
|
+
adopterDeliveryGate: "packages/core/adopter-delivery-gate.js",
|
|
24
|
+
bootstrap: "packages/core/buildchain-delivery-bootstrap.js",
|
|
25
|
+
infrastructure: "packages/core/buildchain-delivery-infrastructure.js",
|
|
26
|
+
kfdCategoryDriver: "packages/core/kfd-adopter-category-driver.js",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
key: "kfd",
|
|
31
|
+
name: "@kungfu-tech/kfd",
|
|
32
|
+
packageRoot: "profiles/adopter-conformance/adopters/kfd/manifest.json",
|
|
33
|
+
modules: {},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
async function sha256File(file) {
|
|
38
|
+
const hash = createHash("sha256");
|
|
39
|
+
for await (const chunk of createReadStream(file)) hash.update(chunk);
|
|
40
|
+
return `sha256:${hash.digest("hex")}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function exactDeclaration(value, expectedName, label) {
|
|
44
|
+
if (
|
|
45
|
+
value?.name !== expectedName ||
|
|
46
|
+
typeof value.version !== "string" ||
|
|
47
|
+
value.version.length === 0 ||
|
|
48
|
+
typeof value.archivePath !== "string" ||
|
|
49
|
+
value.archivePath.length === 0 ||
|
|
50
|
+
!ROOT_PATTERN.test(value.archiveRoot ?? "") ||
|
|
51
|
+
!ROOT_PATTERN.test(value.artifactRoot ?? "")
|
|
52
|
+
) {
|
|
53
|
+
throw new TypeError(`${label} package declaration is incomplete`);
|
|
54
|
+
}
|
|
55
|
+
return structuredClone(value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function safeArchiveEntries(listing, verboseListing, label) {
|
|
59
|
+
const entries = listing.split("\n").filter(Boolean);
|
|
60
|
+
const types = verboseListing.split("\n").filter(Boolean);
|
|
61
|
+
if (entries.length === 0 || entries.length !== types.length) {
|
|
62
|
+
throw new Error(`${label} archive listing is incomplete`);
|
|
63
|
+
}
|
|
64
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
65
|
+
const entry = entries[index];
|
|
66
|
+
const parts = entry.split("/");
|
|
67
|
+
if (
|
|
68
|
+
parts[0] !== "package" ||
|
|
69
|
+
parts.some((part, partIndex) =>
|
|
70
|
+
partIndex === parts.length - 1 && part === ""
|
|
71
|
+
? false
|
|
72
|
+
: part === "" || part === "." || part === "..",
|
|
73
|
+
)
|
|
74
|
+
) {
|
|
75
|
+
throw new Error(`${label} archive contains an unsafe path`);
|
|
76
|
+
}
|
|
77
|
+
if (!["-", "d"].includes(types[index][0])) {
|
|
78
|
+
throw new Error(`${label} archive contains a non-file entry`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function extractPackage(declaration, destination, definition, label) {
|
|
84
|
+
const observedRoot = await sha256File(declaration.archivePath);
|
|
85
|
+
if (observedRoot !== declaration.archiveRoot) {
|
|
86
|
+
throw new Error(`${label} archive bytes do not match archiveRoot`);
|
|
87
|
+
}
|
|
88
|
+
const [{ stdout: listing }, { stdout: verboseListing }] = await Promise.all([
|
|
89
|
+
execFileAsync("tar", ["-tzf", declaration.archivePath], {
|
|
90
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
91
|
+
}),
|
|
92
|
+
execFileAsync("tar", ["-tvzf", declaration.archivePath], {
|
|
93
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
94
|
+
}),
|
|
95
|
+
]);
|
|
96
|
+
safeArchiveEntries(listing, verboseListing, label);
|
|
97
|
+
await mkdir(destination, { recursive: true });
|
|
98
|
+
await execFileAsync(
|
|
99
|
+
"tar",
|
|
100
|
+
[
|
|
101
|
+
"-xzf",
|
|
102
|
+
declaration.archivePath,
|
|
103
|
+
"--strip-components",
|
|
104
|
+
"1",
|
|
105
|
+
"-C",
|
|
106
|
+
destination,
|
|
107
|
+
],
|
|
108
|
+
{ maxBuffer: 16 * 1024 * 1024 },
|
|
109
|
+
);
|
|
110
|
+
const packageJsonPath = path.join(destination, "package.json");
|
|
111
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
112
|
+
if (
|
|
113
|
+
packageJson.name !== declaration.name ||
|
|
114
|
+
packageJson.version !== declaration.version
|
|
115
|
+
) {
|
|
116
|
+
throw new Error(`${label} extracted package identity does not match`);
|
|
117
|
+
}
|
|
118
|
+
if (definition.packageRoot === "archive") {
|
|
119
|
+
if (declaration.artifactRoot !== declaration.archiveRoot) {
|
|
120
|
+
throw new Error(`${label} package artifactRoot must match archiveRoot`);
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
const packageManifest = JSON.parse(
|
|
124
|
+
await readFile(path.join(destination, definition.packageRoot), "utf8"),
|
|
125
|
+
);
|
|
126
|
+
const packageCut = packageManifest?.kfdCut?.package;
|
|
127
|
+
if (
|
|
128
|
+
packageCut?.name !== declaration.name ||
|
|
129
|
+
packageCut?.version !== declaration.version ||
|
|
130
|
+
packageCut?.artifactRoot !== declaration.artifactRoot
|
|
131
|
+
) {
|
|
132
|
+
throw new Error(`${label} semantic package identity does not match`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const destinationRoot = await realpath(destination);
|
|
136
|
+
if (!destinationRoot.endsWith(path.join(...declaration.name.split("/")))) {
|
|
137
|
+
throw new Error(`${label} extraction escaped its package coordinate`);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
name: declaration.name,
|
|
141
|
+
version: declaration.version,
|
|
142
|
+
archiveRoot: declaration.archiveRoot,
|
|
143
|
+
artifactRoot: declaration.artifactRoot,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function importAuthorityRuntime(buildchainRoot) {
|
|
148
|
+
const definition = PACKAGES[0];
|
|
149
|
+
const imported = {};
|
|
150
|
+
for (const [key, relativePath] of Object.entries(definition.modules)) {
|
|
151
|
+
imported[key] = await import(
|
|
152
|
+
pathToFileURL(path.join(buildchainRoot, relativePath)).href
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
const runtime = {
|
|
156
|
+
createAdopterDeliveryGate:
|
|
157
|
+
imported.adopterDeliveryGate.createAdopterDeliveryGate,
|
|
158
|
+
createPackageArtifactProfile:
|
|
159
|
+
imported.adopterDeliveryGate.createPackageArtifactProfile,
|
|
160
|
+
qualifyBuildchainDeliveryInfrastructureBootstrap:
|
|
161
|
+
imported.bootstrap.qualifyBuildchainDeliveryInfrastructureBootstrap,
|
|
162
|
+
createBuildchainDeliveryInfrastructureInstanceManifest:
|
|
163
|
+
imported.infrastructure
|
|
164
|
+
.createBuildchainDeliveryInfrastructureInstanceManifest,
|
|
165
|
+
verifyBuildchainDeliveryInfrastructureInstance:
|
|
166
|
+
imported.infrastructure.verifyBuildchainDeliveryInfrastructureInstance,
|
|
167
|
+
createKfdAdopterCategoryProtocolDriver:
|
|
168
|
+
imported.kfdCategoryDriver.createKfdAdopterCategoryProtocolDriver,
|
|
169
|
+
};
|
|
170
|
+
for (const [name, implementation] of Object.entries(runtime)) {
|
|
171
|
+
if (typeof implementation !== "function") {
|
|
172
|
+
throw new Error(`published Buildchain authority is missing ${name}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return runtime;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function loadPublishedBuildchainDeliveryAuthority({
|
|
179
|
+
buildchain,
|
|
180
|
+
kfd,
|
|
181
|
+
} = {}) {
|
|
182
|
+
const declarations = {
|
|
183
|
+
buildchain: exactDeclaration(
|
|
184
|
+
buildchain,
|
|
185
|
+
"@kungfu-tech/buildchain",
|
|
186
|
+
"Buildchain authority",
|
|
187
|
+
),
|
|
188
|
+
kfd: exactDeclaration(kfd, "@kungfu-tech/kfd", "KFD authority"),
|
|
189
|
+
};
|
|
190
|
+
const temporaryRoot = await mkdtemp(
|
|
191
|
+
path.join(tmpdir(), "buildchain-published-delivery-authority-"),
|
|
192
|
+
);
|
|
193
|
+
let retained = false;
|
|
194
|
+
try {
|
|
195
|
+
const identities = {};
|
|
196
|
+
for (const definition of PACKAGES) {
|
|
197
|
+
identities[definition.key] = await extractPackage(
|
|
198
|
+
declarations[definition.key],
|
|
199
|
+
path.join(temporaryRoot, "node_modules", ...definition.name.split("/")),
|
|
200
|
+
definition,
|
|
201
|
+
`${definition.key} authority`,
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
const authorityRuntime = await importAuthorityRuntime(
|
|
205
|
+
path.join(temporaryRoot, "node_modules", ...PACKAGES[0].name.split("/")),
|
|
206
|
+
);
|
|
207
|
+
const authority = {
|
|
208
|
+
schemaVersion: 1,
|
|
209
|
+
contract: PUBLISHED_DELIVERY_AUTHORITY_CONTRACT,
|
|
210
|
+
packages: identities,
|
|
211
|
+
moduleCoordinates: structuredClone(PACKAGES[0].modules),
|
|
212
|
+
qualifying: false,
|
|
213
|
+
selfCertified: false,
|
|
214
|
+
releaseAuthorized: false,
|
|
215
|
+
finalAuthority:
|
|
216
|
+
"caller-bound-public-npm-archive-bytes-and-package-identity",
|
|
217
|
+
};
|
|
218
|
+
authority.authorityRoot = adopterDeliveryGateDigest(authority);
|
|
219
|
+
retained = true;
|
|
220
|
+
return {
|
|
221
|
+
...authority,
|
|
222
|
+
authorityRuntime,
|
|
223
|
+
temporaryRoot,
|
|
224
|
+
async dispose() {
|
|
225
|
+
await rm(temporaryRoot, { recursive: true, force: true });
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
} finally {
|
|
229
|
+
if (!retained) await rm(temporaryRoot, { recursive: true, force: true });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export async function withPublishedBuildchainDeliveryAuthority(
|
|
234
|
+
declarations,
|
|
235
|
+
operation,
|
|
236
|
+
) {
|
|
237
|
+
if (typeof operation !== "function") {
|
|
238
|
+
throw new TypeError("published authority operation must be a function");
|
|
239
|
+
}
|
|
240
|
+
const authority =
|
|
241
|
+
await loadPublishedBuildchainDeliveryAuthority(declarations);
|
|
242
|
+
try {
|
|
243
|
+
return await operation(authority);
|
|
244
|
+
} finally {
|
|
245
|
+
await authority.dispose();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
installedKfdPackageArtifactRoot,
|
|
11
11
|
validateKfdAdopterReleaseBinding,
|
|
12
12
|
} from "./artifact-verification-envelope.js";
|
|
13
|
+
import { normalizeAdopterDeliveryPassportBinding } from "./adopter-delivery-passport.js";
|
|
13
14
|
|
|
14
15
|
export const RELEASE_PASSPORT_CONTRACT = "kungfu-buildchain-release-passport";
|
|
15
16
|
export const RELEASE_CHECK_REPORT_CONTRACT = "kungfu-buildchain-release-check-report";
|
|
@@ -110,6 +111,7 @@ export const RELEASE_PASSPORT_SCHEMA = {
|
|
|
110
111
|
"kfd-1": OBJECT,
|
|
111
112
|
"kfd-2": OBJECT,
|
|
112
113
|
"kfd-3": OBJECT,
|
|
114
|
+
adopterDelivery: OBJECT,
|
|
113
115
|
kfdAdopter: OBJECT,
|
|
114
116
|
kfdSupport: OBJECT,
|
|
115
117
|
},
|
|
@@ -134,6 +136,7 @@ const BUILDCHAIN_AGGREGATION_FIELDS = [
|
|
|
134
136
|
"platformArtifactManifests",
|
|
135
137
|
"distTagPromotion",
|
|
136
138
|
"controllerReceipts",
|
|
139
|
+
"adopterDelivery",
|
|
137
140
|
"kfdAdopter",
|
|
138
141
|
"kfdSupport",
|
|
139
142
|
"githubArtifactAttestations",
|
|
@@ -356,7 +359,7 @@ export function defaultReleaseLlmsText({ tag = "", passportPath = "buildchain.re
|
|
|
356
359
|
].join("\n");
|
|
357
360
|
}
|
|
358
361
|
|
|
359
|
-
export function buildReleaseArtifactEvidence({ normalizedAssets = [], repository = "", tag = "", sourceSha = "", workflow = {}, kfdAdopter } = {}) {
|
|
362
|
+
export function buildReleaseArtifactEvidence({ normalizedAssets = [], repository = "", tag = "", sourceSha = "", workflow = {}, adopterDelivery, kfdAdopter } = {}) {
|
|
360
363
|
return {
|
|
361
364
|
schemaVersion: 1,
|
|
362
365
|
contract: "kungfu-buildchain-artifact-evidence",
|
|
@@ -381,6 +384,7 @@ export function buildReleaseArtifactEvidence({ normalizedAssets = [], repository
|
|
|
381
384
|
sha256: asset.sha256, url: asset.url, githubAssetId: asset.githubAssetId,
|
|
382
385
|
attestation: passportOptional(asset.attestation || ""),
|
|
383
386
|
})),
|
|
387
|
+
...(adopterDelivery ? { adopterDelivery: normalizeAdopterDeliveryPassportBinding(adopterDelivery) } : {}),
|
|
384
388
|
...(kfdAdopter ? { kfdAdopter: structuredClone(kfdAdopter) } : {}),
|
|
385
389
|
};
|
|
386
390
|
}
|
|
@@ -405,7 +409,7 @@ export function prepareReleasePassportKfdSections({ kfd1, kfd2Claims, kfd3, kfdA
|
|
|
405
409
|
};
|
|
406
410
|
}
|
|
407
411
|
|
|
408
|
-
export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, sourceSha = "", checkedAt } = {}) {
|
|
412
|
+
export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", sourceSha = "", checkedAt } = {}) {
|
|
409
413
|
if (!manifest) {
|
|
410
414
|
if (comparisonMatrix || gateResults.length > 0) {
|
|
411
415
|
throw new Error("KFD support and product-gate inputs require --kfd-adopter-manifest-json; --kfd-support-matrix-json is comparison-only");
|
|
@@ -414,7 +418,7 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
|
|
|
414
418
|
}
|
|
415
419
|
const manifestGate = createKfdAdopterManifestGate({
|
|
416
420
|
manifest, packageArtifactRoot: installedKfdPackageArtifactRoot(), gateResults,
|
|
417
|
-
expectedSourceSha: sourceSha, checkedAt,
|
|
421
|
+
authorityPath: "kfd-adopter-manifest.json", expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha, checkedAt,
|
|
418
422
|
});
|
|
419
423
|
const legacyProjection = createKfdLegacySupportMatrixProjection({ manifest, manifestGate });
|
|
420
424
|
if (comparisonMatrix) {
|
|
@@ -425,18 +429,18 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
|
|
|
425
429
|
}
|
|
426
430
|
return {
|
|
427
431
|
manifest, manifestGate, legacyProjection,
|
|
428
|
-
binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedSourceSha: sourceSha }),
|
|
432
|
+
binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha }),
|
|
429
433
|
};
|
|
430
434
|
}
|
|
431
435
|
|
|
432
|
-
export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedSourceSha = "" } = {}) {
|
|
436
|
+
export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", expectedSourceSha = "" } = {}) {
|
|
433
437
|
if (!binding) {
|
|
434
438
|
return passportLegacyProjection
|
|
435
439
|
? [{ code: "kfdSupport.authority", message: "legacy KFD support projection requires the standard adopter manifest binding" }]
|
|
436
440
|
: [];
|
|
437
441
|
}
|
|
438
442
|
const issues = validateKfdAdopterReleaseBinding(binding, {
|
|
439
|
-
manifest, manifestGate, legacyProjection, expectedSourceSha,
|
|
443
|
+
manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha,
|
|
440
444
|
}).issues.map((entry) => ({ code: `kfdAdopter.${entry.path || entry.code}`, message: entry.message, details: entry }));
|
|
441
445
|
if (!artifactBinding || passportStableJson(artifactBinding) !== passportStableJson(binding)) {
|
|
442
446
|
issues.push({ code: "kfdAdopter.artifactEvidence", message: "release passport and artifact evidence must bind the same exact KFD adopter closure" });
|
|
@@ -33,6 +33,10 @@ import { normalizeControllerReceiptReferences } from "./controller-evidence.js";
|
|
|
33
33
|
import {
|
|
34
34
|
normalizeGitHubArtifactAttestationPolicy,
|
|
35
35
|
} from "./github-artifact-attestation.js";
|
|
36
|
+
import {
|
|
37
|
+
normalizeAdopterDeliveryPassportBinding,
|
|
38
|
+
validateAdopterDeliveryReleaseEvidence,
|
|
39
|
+
} from "./adopter-delivery-passport.js";
|
|
36
40
|
|
|
37
41
|
export { RELEASE_CHECK_REPORT_CONTRACT, RELEASE_PASSPORT_CONTRACT };
|
|
38
42
|
export const ARTIFACT_EVIDENCE_CONTRACT = "kungfu-buildchain-artifact-evidence";
|
|
@@ -1160,9 +1164,9 @@ function normalizePromotionRouting(value = undefined) {
|
|
|
1160
1164
|
return JSON.parse(JSON.stringify(value));
|
|
1161
1165
|
}
|
|
1162
1166
|
|
|
1163
|
-
export function createArtifactEvidence({ assets = [], repository = "", tag = "", sourceSha = "", workflow = {}, kfdAdopter = undefined } = {}) {
|
|
1167
|
+
export function createArtifactEvidence({ assets = [], repository = "", tag = "", sourceSha = "", workflow = {}, adopterDelivery = undefined, kfdAdopter = undefined } = {}) {
|
|
1164
1168
|
const normalizedAssets = assets.map((asset, index) => normalizeAsset(asset, index));
|
|
1165
|
-
return buildReleaseArtifactEvidence({ normalizedAssets, repository, tag, sourceSha, workflow, kfdAdopter });
|
|
1169
|
+
return buildReleaseArtifactEvidence({ normalizedAssets, repository, tag, sourceSha, workflow, adopterDelivery, kfdAdopter });
|
|
1166
1170
|
}
|
|
1167
1171
|
|
|
1168
1172
|
function firstTruthy(...values) {
|
|
@@ -1187,11 +1191,13 @@ function acceptedControllerSourceShas(input) {
|
|
|
1187
1191
|
: [];
|
|
1188
1192
|
}
|
|
1189
1193
|
|
|
1190
|
-
function
|
|
1191
|
-
const
|
|
1194
|
+
function prepareReleaseAdopterArtifacts({ adopterDelivery, kfdAdopter, assets, repository, tag, sourceSha, workflow }) {
|
|
1195
|
+
const normalizedAdopterDelivery = normalizeAdopterDeliveryPassportBinding(adopterDelivery);
|
|
1196
|
+
const normalizedKfdAdopter = kfdAdopter ? structuredClone(kfdAdopter) : undefined;
|
|
1192
1197
|
return {
|
|
1193
|
-
|
|
1194
|
-
|
|
1198
|
+
normalizedAdopterDelivery,
|
|
1199
|
+
normalizedKfdAdopter,
|
|
1200
|
+
artifactEvidence: createArtifactEvidence({ assets, repository, tag, sourceSha, workflow, adopterDelivery: normalizedAdopterDelivery, kfdAdopter: normalizedKfdAdopter }),
|
|
1195
1201
|
};
|
|
1196
1202
|
}
|
|
1197
1203
|
|
|
@@ -1229,6 +1235,7 @@ export function createReleasePassport({
|
|
|
1229
1235
|
kfd1 = undefined,
|
|
1230
1236
|
kfd2Claims = [],
|
|
1231
1237
|
kfd3 = undefined,
|
|
1238
|
+
adopterDelivery = undefined,
|
|
1232
1239
|
kfdAdopter = undefined,
|
|
1233
1240
|
kfdAdopterManifestEvidencePath = "",
|
|
1234
1241
|
kfdAdopterGateEvidencePath = "",
|
|
@@ -1244,8 +1251,8 @@ export function createReleasePassport({
|
|
|
1244
1251
|
checkedAt = "",
|
|
1245
1252
|
} = {}) {
|
|
1246
1253
|
const normalizedTag = nonEmptyString(tag, "tag");
|
|
1247
|
-
const {
|
|
1248
|
-
kfdAdopter, assets, repository, tag: normalizedTag, sourceSha, workflow,
|
|
1254
|
+
const { normalizedAdopterDelivery, normalizedKfdAdopter, artifactEvidence } = prepareReleaseAdopterArtifacts({
|
|
1255
|
+
adopterDelivery, kfdAdopter, assets, repository, tag: normalizedTag, sourceSha, workflow,
|
|
1249
1256
|
});
|
|
1250
1257
|
const normalizedPublishEvidence = normalizePublishEvidence(publishEvidence);
|
|
1251
1258
|
const normalizedPackageSet = normalizePackageSet(packageSet, { packageName, packageVersion, publish });
|
|
@@ -1405,6 +1412,7 @@ export function createReleasePassport({
|
|
|
1405
1412
|
["buildFacts", normalizedBuildFacts],
|
|
1406
1413
|
["platformArtifactManifests", normalizedPlatformArtifactManifests],
|
|
1407
1414
|
["distTagPromotion", normalizedDistTagPromotionEvidence],
|
|
1415
|
+
["adopterDelivery", normalizedAdopterDelivery],
|
|
1408
1416
|
...kfdParts.sectionEntries,
|
|
1409
1417
|
["kfdAgentHub", normalizedKfdAgentHub],
|
|
1410
1418
|
["invariantPassports", invariantPassports],
|
|
@@ -1465,7 +1473,7 @@ export function createReleasePassport({
|
|
|
1465
1473
|
};
|
|
1466
1474
|
}
|
|
1467
1475
|
|
|
1468
|
-
function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, sourceSha, checkedAt }) {
|
|
1476
|
+
function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, repository, sourceSha, checkedAt }) {
|
|
1469
1477
|
const manifestMeta = parseJsonInputWithMeta(manifestJson, undefined, { cwd, label: "kfdAdopterManifestJson" });
|
|
1470
1478
|
const supportMatrixMeta = parseJsonInputWithMeta(supportMatrixJson, undefined, { cwd, label: "kfdSupportMatrixJson" });
|
|
1471
1479
|
const productGateMetas = (productGateJsons || [])
|
|
@@ -1476,7 +1484,7 @@ function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson,
|
|
|
1476
1484
|
manifest: manifestMeta.value,
|
|
1477
1485
|
gateResults: productGateMetas.map((meta) => meta.value),
|
|
1478
1486
|
comparisonMatrix: supportMatrixMeta.value,
|
|
1479
|
-
sourceSha,
|
|
1487
|
+
expectedAdopterId: repository || "kungfu-systems/buildchain", expectedSourceRepository: repository, sourceSha,
|
|
1480
1488
|
checkedAt,
|
|
1481
1489
|
});
|
|
1482
1490
|
}
|
|
@@ -1525,7 +1533,7 @@ export function collectGitHubReleasePassport({
|
|
|
1525
1533
|
kfd2ClaimJsons = [],
|
|
1526
1534
|
kfd3PrebuildWitnessJsons = [],
|
|
1527
1535
|
kfd3ArtifactWitnessJsons = [],
|
|
1528
|
-
kfd3ArtifactVerifyCommand = "",
|
|
1536
|
+
kfd3ArtifactVerifyCommand = "", adopterDeliveryJson = "",
|
|
1529
1537
|
kfdAdopterManifestJson = "",
|
|
1530
1538
|
kfdSupportMatrixJson = "",
|
|
1531
1539
|
kfdProductGateJsons = [],
|
|
@@ -1586,6 +1594,11 @@ export function collectGitHubReleasePassport({
|
|
|
1586
1594
|
cwd,
|
|
1587
1595
|
label: "KFD-3 artifact verify command",
|
|
1588
1596
|
});
|
|
1597
|
+
const adopterDelivery = parseJsonInput(
|
|
1598
|
+
adopterDeliveryJson,
|
|
1599
|
+
undefined,
|
|
1600
|
+
{ cwd, label: "adopterDeliveryJson" },
|
|
1601
|
+
);
|
|
1589
1602
|
const basePassportMeta = parseJsonInputWithMeta(basePassportJson, undefined, { cwd, label: "basePassportJson" });
|
|
1590
1603
|
const invariantPassportMetas = (invariantPassportJsons || [])
|
|
1591
1604
|
.filter(Boolean)
|
|
@@ -1662,7 +1675,7 @@ export function collectGitHubReleasePassport({
|
|
|
1662
1675
|
const productMechanism = defaultProductMechanism({ repository, productName });
|
|
1663
1676
|
const kfdAdopterEvidence = collectKfdAdopterReleaseInputs({
|
|
1664
1677
|
cwd, manifestJson: kfdAdopterManifestJson, supportMatrixJson: kfdSupportMatrixJson,
|
|
1665
|
-
productGateJsons: kfdProductGateJsons, sourceSha, checkedAt: resolvedCheckedAt,
|
|
1678
|
+
productGateJsons: kfdProductGateJsons, repository, sourceSha, checkedAt: resolvedCheckedAt,
|
|
1666
1679
|
});
|
|
1667
1680
|
const {
|
|
1668
1681
|
manifest: kfdAdopterManifest,
|
|
@@ -1676,6 +1689,7 @@ export function collectGitHubReleasePassport({
|
|
|
1676
1689
|
tag: resolvedTag,
|
|
1677
1690
|
sourceSha,
|
|
1678
1691
|
workflow,
|
|
1692
|
+
adopterDelivery,
|
|
1679
1693
|
kfdAdopter,
|
|
1680
1694
|
});
|
|
1681
1695
|
const bundledPublishEvidencePath = publishEvidenceMeta.value ? "evidence.json" : "";
|
|
@@ -1742,6 +1756,7 @@ export function collectGitHubReleasePassport({
|
|
|
1742
1756
|
kfd1,
|
|
1743
1757
|
kfd2Claims: kfd2ClaimMetas.map((meta) => meta.value),
|
|
1744
1758
|
kfd3,
|
|
1759
|
+
adopterDelivery,
|
|
1745
1760
|
kfdAdopter,
|
|
1746
1761
|
kfdAdopterManifestEvidencePath: kfdAdopter ? "kfd-adopter-manifest.json" : "",
|
|
1747
1762
|
kfdAdopterGateEvidencePath: kfdAdopter ? "kfd-adopter-manifest-gate.json" : "",
|
|
@@ -2094,6 +2109,13 @@ function validateReleaseEvidenceContracts({
|
|
|
2094
2109
|
validateContract(agentIndex, AGENT_INDEX_CONTRACT, "agentIndex", issues);
|
|
2095
2110
|
validateContract(productMechanism, PRODUCT_MECHANISM_CONTRACT, "productMechanism", issues);
|
|
2096
2111
|
validateKfdAgentHubReleaseEvidence(passport?.kfdAgentHub, kfdAgentHubEvidence, issues);
|
|
2112
|
+
for (const entry of validateAdopterDeliveryReleaseEvidence({
|
|
2113
|
+
binding: passport?.adopterDelivery,
|
|
2114
|
+
artifactBinding: artifactEvidence?.adopterDelivery,
|
|
2115
|
+
expectedProjectRepository: optionalString(passport?.product?.repository),
|
|
2116
|
+
})) {
|
|
2117
|
+
issues.push(issue("error", entry.code, entry.message, entry.details));
|
|
2118
|
+
}
|
|
2097
2119
|
for (const entry of validateKfdAdopterReleaseEvidence({
|
|
2098
2120
|
binding: passport?.kfdAdopter,
|
|
2099
2121
|
artifactBinding: artifactEvidence?.kfdAdopter,
|
|
@@ -2101,7 +2123,8 @@ function validateReleaseEvidenceContracts({
|
|
|
2101
2123
|
manifestGate: kfdAdopterManifestGate,
|
|
2102
2124
|
legacyProjection: kfdSupportEvidence,
|
|
2103
2125
|
passportLegacyProjection: passport?.kfdSupport,
|
|
2104
|
-
|
|
2126
|
+
expectedAdopterId: optionalString(passport?.product?.repository) || "kungfu-systems/buildchain",
|
|
2127
|
+
expectedSourceRepository: optionalString(passport?.product?.repository), expectedSourceSha: optionalString(passport?.release?.sourceSha),
|
|
2105
2128
|
})) {
|
|
2106
2129
|
issues.push(issue("error", entry.code, entry.message, entry.details));
|
|
2107
2130
|
}
|
|
@@ -2650,6 +2673,7 @@ function buildReleaseCheckReport({
|
|
|
2650
2673
|
? passport.platformArtifactManifests.length
|
|
2651
2674
|
: 0,
|
|
2652
2675
|
distTagPromotionEvidencePresent: Boolean(passport?.distTagPromotion),
|
|
2676
|
+
adopterDeliveryPresent: Boolean(passport?.adopterDelivery),
|
|
2653
2677
|
impactPresent: Boolean(impact),
|
|
2654
2678
|
agentIndexPresent: Boolean(agentIndex),
|
|
2655
2679
|
productMechanismPresent: Boolean(productMechanism),
|