@kungfu-tech/buildchain 4.0.1-alpha.5 → 4.0.1-alpha.6
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/release-tail/README.md +8 -0
- package/architecture/internal-capabilities.json +65 -5
- package/architecture/maintainability-policy.json +22 -16
- package/architecture/release-tail-contract-inventory.json +5 -2
- package/architecture/v4-adopter-delivery-parity.json +32 -5
- package/architecture/v4-publication-rehearsal-parity.json +84 -0
- package/bin/buildchain.mjs +7 -1
- package/bin/internal/adopter-delivery-cli.mjs +70 -0
- package/bin/internal/command-registry.mjs +1 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
- package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
- package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
- package/dist/site/agent-index.json +3 -0
- package/dist/site/artifact-schemas.json +6 -0
- package/dist/site/buildchain-contract.json +14 -14
- package/dist/site/buildchain-site.json +219 -22
- package/dist/site/capability-registry.json +10 -9
- package/dist/site/cli-registry.json +53 -1
- package/dist/site/kfd-claims.json +253 -14
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +20 -5
- package/dist/site/node-api-registry.json +11501 -9312
- package/dist/site/page-registry.json +202 -13
- package/dist/site/public-surface-audit.json +195 -11
- package/dist/site/publication-authority-registry.json +17 -4
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +14 -0
- package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
- package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
- package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
- package/dist/site/site-manifest.json +17 -9
- package/dist/site/workflow-registry.json +89 -8
- package/docs/MAP.md +3 -1
- package/docs/cli-reference.md +68 -0
- package/docs/cli.md +8 -0
- package/docs/node-api-reference.md +198 -51
- package/docs/release-tail-provider-plane.md +30 -0
- package/docs/v4-adopter-delivery.md +133 -0
- package/docs/v4-publication-rehearsal.md +130 -0
- package/package.json +17 -3
- 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/buildchain-agent-manuals.js +1 -0
- package/packages/core/buildchain-config.js +84 -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/legacy-kfd-adopter-driver.js +167 -0
- package/packages/core/published-delivery-authority.js +266 -0
- package/packages/core/release-passport.js +26 -8
- package/packages/core/v4-adopter-delivery-parity.js +3 -3
- package/packages/core/v4-adopter-delivery.js +359 -0
- package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
- package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
- package/packages/core/v4-publication-rehearsal.js +481 -0
- package/scripts/buildchain-cli-help.mjs +10 -0
- package/scripts/check-inventory.mjs +3 -3
- package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
- package/scripts/dev-delivery-source-proof-reuse.mjs +13 -97
- package/scripts/generate-release-candidate-passport.mjs +152 -0
- package/scripts/generate-site-bundle.mjs +30 -0
- package/scripts/release-tail.mjs +51 -3
- package/scripts/resume-from-candidate-run.mjs +545 -15
- package/scripts/site-capability-metadata.mjs +16 -0
- package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ADOPTER_PROTOCOL_DRIVER_INTERFACE,
|
|
3
|
+
adopterDeliveryGateDigest,
|
|
4
|
+
defineAdopterProtocolDriver,
|
|
5
|
+
} from "./adopter-delivery-gate.js";
|
|
6
|
+
import {
|
|
7
|
+
KFD_LEGACY_SUPPORT_MATRIX_CONTRACT,
|
|
8
|
+
validateKfdAdopterManifestGate,
|
|
9
|
+
validateKfdLegacySupportMatrixProjection,
|
|
10
|
+
} from "./kfd-adopter-manifest.js";
|
|
11
|
+
|
|
12
|
+
export const LEGACY_KFD_ADOPTER_PROTOCOL_ID =
|
|
13
|
+
"buildchain.kfd-adopter/legacy-support-matrix";
|
|
14
|
+
export const LEGACY_KFD_ADOPTER_PROTOCOL_VERSION = "1.0.0";
|
|
15
|
+
export const LEGACY_KFD_ADOPTER_DRIVER_REPORT_CONTRACT =
|
|
16
|
+
"kungfu-buildchain-legacy-kfd-adopter-driver-report";
|
|
17
|
+
|
|
18
|
+
function issue(code, path, message) {
|
|
19
|
+
return { code, path, message };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function normalizedIssues(entries) {
|
|
23
|
+
return (entries ?? []).map(({ code, path, message }) => ({
|
|
24
|
+
code,
|
|
25
|
+
path: path ? `/${path.replaceAll(".", "/")}` : "/declaration",
|
|
26
|
+
message,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sameJson(left, right) {
|
|
31
|
+
try {
|
|
32
|
+
return adopterDeliveryGateDigest(left) === adopterDeliveryGateDigest(right);
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function bindingIssues(request, manifest) {
|
|
39
|
+
const issues = [];
|
|
40
|
+
if (
|
|
41
|
+
request.project.instanceId !== manifest?.manifestId ||
|
|
42
|
+
request.project.adopterId !== manifest?.adopter?.id
|
|
43
|
+
) {
|
|
44
|
+
issues.push(
|
|
45
|
+
issue(
|
|
46
|
+
"delivery-legacy-project-binding-mismatch",
|
|
47
|
+
"/project",
|
|
48
|
+
"Delivery project identity must match the standard adopter manifest.",
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (!sameJson(request.artifact, manifest?.adopter?.artifact)) {
|
|
53
|
+
issues.push(
|
|
54
|
+
issue(
|
|
55
|
+
"delivery-legacy-artifact-binding-mismatch",
|
|
56
|
+
"/artifact",
|
|
57
|
+
"Delivery artifact must match the standard adopter manifest artifact.",
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return issues;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function invalidContextResult(issues) {
|
|
65
|
+
const report = {
|
|
66
|
+
schemaVersion: 1,
|
|
67
|
+
contract: LEGACY_KFD_ADOPTER_DRIVER_REPORT_CONTRACT,
|
|
68
|
+
valid: false,
|
|
69
|
+
qualifying: false,
|
|
70
|
+
selfCertified: false,
|
|
71
|
+
independentlyCertified: false,
|
|
72
|
+
manifestRoot: null,
|
|
73
|
+
manifestGateRoot: null,
|
|
74
|
+
legacyProjectionRoot: null,
|
|
75
|
+
legacyProjection: null,
|
|
76
|
+
adapterIssues: issues,
|
|
77
|
+
nonClaims: [
|
|
78
|
+
"The legacy support matrix is a one-way projection, not declaration authority.",
|
|
79
|
+
"Buildchain carries the existing standard manifest decision and does not certify KFD adoption.",
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
valid: false,
|
|
84
|
+
report,
|
|
85
|
+
reportRoot: adopterDeliveryGateDigest(report),
|
|
86
|
+
issues,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function createLegacyKfdAdopterProtocolDriver() {
|
|
91
|
+
return defineAdopterProtocolDriver({
|
|
92
|
+
interface: ADOPTER_PROTOCOL_DRIVER_INTERFACE,
|
|
93
|
+
id: LEGACY_KFD_ADOPTER_PROTOCOL_ID,
|
|
94
|
+
version: LEGACY_KFD_ADOPTER_PROTOCOL_VERSION,
|
|
95
|
+
verify({ request, context }) {
|
|
96
|
+
const manifest = context?.adopterManifest;
|
|
97
|
+
const manifestGate = context?.adopterManifestGate;
|
|
98
|
+
if (!manifest || !manifestGate) {
|
|
99
|
+
return invalidContextResult([
|
|
100
|
+
issue(
|
|
101
|
+
"delivery-legacy-verification-context-invalid",
|
|
102
|
+
"/protocol",
|
|
103
|
+
"The exact standard adopter manifest and manifest gate are required.",
|
|
104
|
+
),
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const source = manifest?.adopter?.artifact?.coordinate?.match(
|
|
109
|
+
/^([^@\s]+)@([0-9a-f]{40})$/,
|
|
110
|
+
);
|
|
111
|
+
const gateValidation = validateKfdAdopterManifestGate(manifestGate, {
|
|
112
|
+
expectedAdopterId: manifest?.adopter?.id,
|
|
113
|
+
expectedSourceRepository: source?.[1] ?? "",
|
|
114
|
+
expectedSourceSha: source?.[2] ?? "",
|
|
115
|
+
checkedAt: manifestGate?.checkedAt,
|
|
116
|
+
});
|
|
117
|
+
const projectionValidation = validateKfdLegacySupportMatrixProjection(
|
|
118
|
+
request.declaration,
|
|
119
|
+
{ manifest, manifestGate },
|
|
120
|
+
);
|
|
121
|
+
const adapterIssues = [
|
|
122
|
+
...bindingIssues(request, manifest),
|
|
123
|
+
...normalizedIssues(gateValidation.issues),
|
|
124
|
+
...normalizedIssues(projectionValidation.issues),
|
|
125
|
+
];
|
|
126
|
+
if (
|
|
127
|
+
request.declaration?.contract !== KFD_LEGACY_SUPPORT_MATRIX_CONTRACT
|
|
128
|
+
) {
|
|
129
|
+
adapterIssues.push(
|
|
130
|
+
issue(
|
|
131
|
+
"delivery-legacy-contract-invalid",
|
|
132
|
+
"/declaration/contract",
|
|
133
|
+
`Legacy declaration must use ${KFD_LEGACY_SUPPORT_MATRIX_CONTRACT}.`,
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const valid =
|
|
139
|
+
gateValidation.valid &&
|
|
140
|
+
projectionValidation.valid &&
|
|
141
|
+
adapterIssues.length === 0;
|
|
142
|
+
const report = {
|
|
143
|
+
schemaVersion: 1,
|
|
144
|
+
contract: LEGACY_KFD_ADOPTER_DRIVER_REPORT_CONTRACT,
|
|
145
|
+
valid,
|
|
146
|
+
qualifying: false,
|
|
147
|
+
selfCertified: false,
|
|
148
|
+
independentlyCertified: false,
|
|
149
|
+
manifestRoot: manifestGate?.authority?.manifestRoot ?? null,
|
|
150
|
+
manifestGateRoot: manifestGate?.gateRoot ?? null,
|
|
151
|
+
legacyProjectionRoot: adopterDeliveryGateDigest(request.declaration),
|
|
152
|
+
legacyProjection: structuredClone(request.declaration),
|
|
153
|
+
adapterIssues,
|
|
154
|
+
nonClaims: [
|
|
155
|
+
"The legacy support matrix is a one-way projection, not declaration authority.",
|
|
156
|
+
"Buildchain carries the existing standard manifest decision and does not certify KFD adoption.",
|
|
157
|
+
],
|
|
158
|
+
};
|
|
159
|
+
return {
|
|
160
|
+
valid,
|
|
161
|
+
report,
|
|
162
|
+
reportRoot: adopterDeliveryGateDigest(report),
|
|
163
|
+
issues: adapterIssues,
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import {
|
|
4
|
+
copyFile,
|
|
5
|
+
mkdir,
|
|
6
|
+
mkdtemp,
|
|
7
|
+
readFile,
|
|
8
|
+
realpath,
|
|
9
|
+
rm,
|
|
10
|
+
} from "node:fs/promises";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { promisify } from "node:util";
|
|
14
|
+
import { pathToFileURL } from "node:url";
|
|
15
|
+
import { execFile } from "node:child_process";
|
|
16
|
+
|
|
17
|
+
import { adopterDeliveryGateDigest } from "./adopter-delivery-gate.js";
|
|
18
|
+
|
|
19
|
+
export const PUBLISHED_DELIVERY_AUTHORITY_CONTRACT =
|
|
20
|
+
"kungfu-buildchain-published-delivery-authority/v1";
|
|
21
|
+
|
|
22
|
+
const execFileAsync = promisify(execFile);
|
|
23
|
+
const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
24
|
+
const PACKAGES = [
|
|
25
|
+
{
|
|
26
|
+
key: "buildchain",
|
|
27
|
+
name: "@kungfu-tech/buildchain",
|
|
28
|
+
packageRoot: "archive",
|
|
29
|
+
modules: {
|
|
30
|
+
adopterDeliveryGate: "packages/core/adopter-delivery-gate.js",
|
|
31
|
+
bootstrap: "packages/core/buildchain-delivery-bootstrap.js",
|
|
32
|
+
infrastructure: "packages/core/buildchain-delivery-infrastructure.js",
|
|
33
|
+
kfdCategoryDriver: "packages/core/kfd-adopter-category-driver.js",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: "kfd",
|
|
38
|
+
name: "@kungfu-tech/kfd",
|
|
39
|
+
packageRoot: "profiles/adopter-conformance/adopters/kfd/manifest.json",
|
|
40
|
+
modules: {},
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
async function sha256File(file) {
|
|
45
|
+
const hash = createHash("sha256");
|
|
46
|
+
for await (const chunk of createReadStream(file)) hash.update(chunk);
|
|
47
|
+
return `sha256:${hash.digest("hex")}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function exactDeclaration(value, expectedName, label) {
|
|
51
|
+
if (
|
|
52
|
+
value?.name !== expectedName ||
|
|
53
|
+
typeof value.version !== "string" ||
|
|
54
|
+
value.version.length === 0 ||
|
|
55
|
+
typeof value.archivePath !== "string" ||
|
|
56
|
+
value.archivePath.length === 0 ||
|
|
57
|
+
!ROOT_PATTERN.test(value.archiveRoot ?? "") ||
|
|
58
|
+
!ROOT_PATTERN.test(value.artifactRoot ?? "")
|
|
59
|
+
) {
|
|
60
|
+
throw new TypeError(`${label} package declaration is incomplete`);
|
|
61
|
+
}
|
|
62
|
+
return structuredClone(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function safeArchiveEntries(listing, verboseListing, label) {
|
|
66
|
+
const entries = listing.split("\n").filter(Boolean);
|
|
67
|
+
const types = verboseListing.split("\n").filter(Boolean);
|
|
68
|
+
if (entries.length === 0 || entries.length !== types.length) {
|
|
69
|
+
throw new Error(`${label} archive listing is incomplete`);
|
|
70
|
+
}
|
|
71
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
72
|
+
const entry = entries[index];
|
|
73
|
+
const parts = entry.split("/");
|
|
74
|
+
if (
|
|
75
|
+
parts[0] !== "package" ||
|
|
76
|
+
parts.some((part, partIndex) =>
|
|
77
|
+
partIndex === parts.length - 1 && part === ""
|
|
78
|
+
? false
|
|
79
|
+
: part === "" || part === "." || part === "..",
|
|
80
|
+
)
|
|
81
|
+
) {
|
|
82
|
+
throw new Error(`${label} archive contains an unsafe path`);
|
|
83
|
+
}
|
|
84
|
+
if (!["-", "d"].includes(types[index][0])) {
|
|
85
|
+
throw new Error(`${label} archive contains a non-file entry`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function extractPackage(declaration, destination, definition, label) {
|
|
91
|
+
const archivePath = path.resolve(declaration.archivePath);
|
|
92
|
+
const observedRoot = await sha256File(archivePath);
|
|
93
|
+
if (observedRoot !== declaration.archiveRoot) {
|
|
94
|
+
throw new Error(`${label} archive bytes do not match archiveRoot`);
|
|
95
|
+
}
|
|
96
|
+
await mkdir(destination, { recursive: true });
|
|
97
|
+
const stagedArchiveName = `.buildchain-${definition.key}-authority.tgz`;
|
|
98
|
+
const stagedArchivePath = path.join(
|
|
99
|
+
path.dirname(destination),
|
|
100
|
+
stagedArchiveName,
|
|
101
|
+
);
|
|
102
|
+
const stagedArchiveFile = `../${stagedArchiveName}`;
|
|
103
|
+
await copyFile(archivePath, stagedArchivePath);
|
|
104
|
+
try {
|
|
105
|
+
if ((await sha256File(stagedArchivePath)) !== declaration.archiveRoot) {
|
|
106
|
+
throw new Error(`${label} staged archive bytes do not match archiveRoot`);
|
|
107
|
+
}
|
|
108
|
+
const [{ stdout: listing }, { stdout: verboseListing }] = await Promise.all(
|
|
109
|
+
[
|
|
110
|
+
execFileAsync("tar", ["-tzf", stagedArchiveFile], {
|
|
111
|
+
cwd: destination,
|
|
112
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
113
|
+
}),
|
|
114
|
+
execFileAsync("tar", ["-tvzf", stagedArchiveFile], {
|
|
115
|
+
cwd: destination,
|
|
116
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
117
|
+
}),
|
|
118
|
+
],
|
|
119
|
+
);
|
|
120
|
+
safeArchiveEntries(listing, verboseListing, label);
|
|
121
|
+
await execFileAsync(
|
|
122
|
+
"tar",
|
|
123
|
+
["-xzf", stagedArchiveFile, "--strip-components", "1"],
|
|
124
|
+
{ cwd: destination, maxBuffer: 16 * 1024 * 1024 },
|
|
125
|
+
);
|
|
126
|
+
} finally {
|
|
127
|
+
await rm(stagedArchivePath, { force: true });
|
|
128
|
+
}
|
|
129
|
+
const packageJsonPath = path.join(destination, "package.json");
|
|
130
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
131
|
+
if (
|
|
132
|
+
packageJson.name !== declaration.name ||
|
|
133
|
+
packageJson.version !== declaration.version
|
|
134
|
+
) {
|
|
135
|
+
throw new Error(`${label} extracted package identity does not match`);
|
|
136
|
+
}
|
|
137
|
+
if (definition.packageRoot === "archive") {
|
|
138
|
+
if (declaration.artifactRoot !== declaration.archiveRoot) {
|
|
139
|
+
throw new Error(`${label} package artifactRoot must match archiveRoot`);
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
const packageManifest = JSON.parse(
|
|
143
|
+
await readFile(path.join(destination, definition.packageRoot), "utf8"),
|
|
144
|
+
);
|
|
145
|
+
const packageCut = packageManifest?.kfdCut?.package;
|
|
146
|
+
if (
|
|
147
|
+
packageCut?.name !== declaration.name ||
|
|
148
|
+
packageCut?.version !== declaration.version ||
|
|
149
|
+
packageCut?.artifactRoot !== declaration.artifactRoot
|
|
150
|
+
) {
|
|
151
|
+
throw new Error(`${label} semantic package identity does not match`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const destinationRoot = await realpath(destination);
|
|
155
|
+
if (!destinationRoot.endsWith(path.join(...declaration.name.split("/")))) {
|
|
156
|
+
throw new Error(`${label} extraction escaped its package coordinate`);
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
name: declaration.name,
|
|
160
|
+
version: declaration.version,
|
|
161
|
+
archiveRoot: declaration.archiveRoot,
|
|
162
|
+
artifactRoot: declaration.artifactRoot,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function importAuthorityRuntime(buildchainRoot) {
|
|
167
|
+
const definition = PACKAGES[0];
|
|
168
|
+
const imported = {};
|
|
169
|
+
for (const [key, relativePath] of Object.entries(definition.modules)) {
|
|
170
|
+
imported[key] = await import(
|
|
171
|
+
pathToFileURL(path.join(buildchainRoot, relativePath)).href
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const runtime = {
|
|
175
|
+
createAdopterDeliveryGate:
|
|
176
|
+
imported.adopterDeliveryGate.createAdopterDeliveryGate,
|
|
177
|
+
createPackageArtifactProfile:
|
|
178
|
+
imported.adopterDeliveryGate.createPackageArtifactProfile,
|
|
179
|
+
qualifyBuildchainDeliveryInfrastructureBootstrap:
|
|
180
|
+
imported.bootstrap.qualifyBuildchainDeliveryInfrastructureBootstrap,
|
|
181
|
+
createBuildchainDeliveryInfrastructureInstanceManifest:
|
|
182
|
+
imported.infrastructure
|
|
183
|
+
.createBuildchainDeliveryInfrastructureInstanceManifest,
|
|
184
|
+
verifyBuildchainDeliveryInfrastructureInstance:
|
|
185
|
+
imported.infrastructure.verifyBuildchainDeliveryInfrastructureInstance,
|
|
186
|
+
createKfdAdopterCategoryProtocolDriver:
|
|
187
|
+
imported.kfdCategoryDriver.createKfdAdopterCategoryProtocolDriver,
|
|
188
|
+
};
|
|
189
|
+
for (const [name, implementation] of Object.entries(runtime)) {
|
|
190
|
+
if (typeof implementation !== "function") {
|
|
191
|
+
throw new Error(`published Buildchain authority is missing ${name}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return runtime;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export async function loadPublishedBuildchainDeliveryAuthority({
|
|
198
|
+
buildchain,
|
|
199
|
+
kfd,
|
|
200
|
+
} = {}) {
|
|
201
|
+
const declarations = {
|
|
202
|
+
buildchain: exactDeclaration(
|
|
203
|
+
buildchain,
|
|
204
|
+
"@kungfu-tech/buildchain",
|
|
205
|
+
"Buildchain authority",
|
|
206
|
+
),
|
|
207
|
+
kfd: exactDeclaration(kfd, "@kungfu-tech/kfd", "KFD authority"),
|
|
208
|
+
};
|
|
209
|
+
const temporaryRoot = await mkdtemp(
|
|
210
|
+
path.join(tmpdir(), "buildchain-published-delivery-authority-"),
|
|
211
|
+
);
|
|
212
|
+
let retained = false;
|
|
213
|
+
try {
|
|
214
|
+
const identities = {};
|
|
215
|
+
for (const definition of PACKAGES) {
|
|
216
|
+
identities[definition.key] = await extractPackage(
|
|
217
|
+
declarations[definition.key],
|
|
218
|
+
path.join(temporaryRoot, "node_modules", ...definition.name.split("/")),
|
|
219
|
+
definition,
|
|
220
|
+
`${definition.key} authority`,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const authorityRuntime = await importAuthorityRuntime(
|
|
224
|
+
path.join(temporaryRoot, "node_modules", ...PACKAGES[0].name.split("/")),
|
|
225
|
+
);
|
|
226
|
+
const authority = {
|
|
227
|
+
schemaVersion: 1,
|
|
228
|
+
contract: PUBLISHED_DELIVERY_AUTHORITY_CONTRACT,
|
|
229
|
+
packages: identities,
|
|
230
|
+
moduleCoordinates: structuredClone(PACKAGES[0].modules),
|
|
231
|
+
qualifying: false,
|
|
232
|
+
selfCertified: false,
|
|
233
|
+
releaseAuthorized: false,
|
|
234
|
+
finalAuthority:
|
|
235
|
+
"caller-bound-public-npm-archive-bytes-and-package-identity",
|
|
236
|
+
};
|
|
237
|
+
authority.authorityRoot = adopterDeliveryGateDigest(authority);
|
|
238
|
+
retained = true;
|
|
239
|
+
return {
|
|
240
|
+
...authority,
|
|
241
|
+
authorityRuntime,
|
|
242
|
+
temporaryRoot,
|
|
243
|
+
async dispose() {
|
|
244
|
+
await rm(temporaryRoot, { recursive: true, force: true });
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
} finally {
|
|
248
|
+
if (!retained) await rm(temporaryRoot, { recursive: true, force: true });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export async function withPublishedBuildchainDeliveryAuthority(
|
|
253
|
+
declarations,
|
|
254
|
+
operation,
|
|
255
|
+
) {
|
|
256
|
+
if (typeof operation !== "function") {
|
|
257
|
+
throw new TypeError("published authority operation must be a function");
|
|
258
|
+
}
|
|
259
|
+
const authority =
|
|
260
|
+
await loadPublishedBuildchainDeliveryAuthority(declarations);
|
|
261
|
+
try {
|
|
262
|
+
return await operation(authority);
|
|
263
|
+
} finally {
|
|
264
|
+
await authority.dispose();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -439,11 +439,17 @@ function mergeAuthoritativePassportBase(passport, basePassport = undefined, { re
|
|
|
439
439
|
kfd3: basePassport.evidence?.kfd3 || passport.evidence?.kfd3 || "",
|
|
440
440
|
},
|
|
441
441
|
};
|
|
442
|
-
for (const key of [
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
442
|
+
for (const key of [
|
|
443
|
+
"versionImpact",
|
|
444
|
+
"surfaceImpacts",
|
|
445
|
+
"promotionRouting",
|
|
446
|
+
"v4ConsumerPolicy",
|
|
447
|
+
"v4RuntimeResume",
|
|
448
|
+
"transaction",
|
|
449
|
+
"trustedPublishing",
|
|
450
|
+
"distTagPromotion",
|
|
451
|
+
])
|
|
452
|
+
if (basePassport[key] !== undefined) merged[key] = basePassport[key];
|
|
447
453
|
if (basePassport.controllerReceipts !== undefined) {
|
|
448
454
|
merged.controllerReceipts = basePassport.controllerReceipts;
|
|
449
455
|
}
|
|
@@ -1162,6 +1168,18 @@ function normalizeV4RuntimeResumeEvidence(value, expected = {}) {
|
|
|
1162
1168
|
};
|
|
1163
1169
|
}
|
|
1164
1170
|
|
|
1171
|
+
function v4RuntimeResumeSourceSha(release, fallback = "") {
|
|
1172
|
+
const builtSourceSha = releaseField(
|
|
1173
|
+
release || {},
|
|
1174
|
+
"builtSourceSha",
|
|
1175
|
+
"built_source_sha",
|
|
1176
|
+
);
|
|
1177
|
+
return release?.treeEquivalent === true && builtSourceSha
|
|
1178
|
+
? builtSourceSha
|
|
1179
|
+
: fallback;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
|
|
1165
1183
|
function prepareBuildEvidence({
|
|
1166
1184
|
buildSummary,
|
|
1167
1185
|
buildFacts,
|
|
@@ -1317,7 +1335,7 @@ export function createReleasePassport(options = {}) {
|
|
|
1317
1335
|
const { promotion, buildEvidence } = preparePromotionBuild(options);
|
|
1318
1336
|
const normalizedV4RuntimeResume = normalizeV4RuntimeResumeEvidence(v4RuntimeResumeEvidence, {
|
|
1319
1337
|
repository,
|
|
1320
|
-
sourceSha,
|
|
1338
|
+
sourceSha: v4RuntimeResumeSourceSha(release, sourceSha),
|
|
1321
1339
|
resumeRuntimeSha: promotion.routing?.runtime?.resolvedSha || "",
|
|
1322
1340
|
consumerPolicyReceiptRoot: promotion.consumerPolicy?.certification?.receiptRoot || "",
|
|
1323
1341
|
});
|
|
@@ -2302,7 +2320,7 @@ function validateV4RuntimeResumePassportSection({ passport, issues }) {
|
|
|
2302
2320
|
receipt: evidence.authorization,
|
|
2303
2321
|
receiptRoot: evidence.authorizationRoot,
|
|
2304
2322
|
repository: passport?.product?.repository || "",
|
|
2305
|
-
sourceSha: passport?.release?.sourceSha || "",
|
|
2323
|
+
sourceSha: v4RuntimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
|
|
2306
2324
|
runtimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
2307
2325
|
consumerPolicyReceiptRoot,
|
|
2308
2326
|
});
|
|
@@ -2313,7 +2331,7 @@ function validateV4RuntimeResumePassportSection({ passport, issues }) {
|
|
|
2313
2331
|
lineage: evidence.lineage,
|
|
2314
2332
|
lineageRoot: evidence.lineageRoot,
|
|
2315
2333
|
repository: passport?.product?.repository || "",
|
|
2316
|
-
sourceSha: passport?.release?.sourceSha || "",
|
|
2334
|
+
sourceSha: v4RuntimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
|
|
2317
2335
|
resumeRuntimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
2318
2336
|
consumerPolicyReceiptRoot,
|
|
2319
2337
|
});
|
|
@@ -31,10 +31,10 @@ const root = path.resolve(
|
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
export const V4_ADOPTER_DELIVERY_PARITY_SOURCE = Object.freeze({
|
|
34
|
-
v3Commit: "
|
|
34
|
+
v3Commit: "6b96bdad8d9f8ccf9275f27d9370a226a9c78465",
|
|
35
35
|
vectorSuiteRoot:
|
|
36
|
-
"sha256:
|
|
37
|
-
kfdPackage: "@kungfu-tech/kfd@1.0.0-alpha.
|
|
36
|
+
"sha256:c978707556406ffda4ef4192032332c01c2da1cebb6ad8c4f0edfc65d5cef0c7",
|
|
37
|
+
kfdPackage: "@kungfu-tech/kfd@1.0.0-alpha.65",
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
function clone(value) {
|