@kungfu-tech/buildchain 2.10.4 → 2.10.5
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/README.md +16 -1
- package/bin/buildchain.mjs +299 -16
- package/dist/site/buildchain-contract.json +7 -7
- package/dist/site/buildchain-site.json +42 -37
- package/dist/site/capability-registry.json +2 -2
- package/dist/site/cli-registry.json +164 -8
- package/dist/site/kfd-claims.json +190 -19
- package/dist/site/manual-registry.json +10 -10
- package/dist/site/node-api-registry.json +24 -11
- package/dist/site/page-registry.json +27 -22
- package/dist/site/public-surface-audit.json +334 -126
- package/dist/site/release-provenance.json +2 -1
- package/dist/site/site-manifest.json +14 -14
- package/dist/site/workflow-registry.json +4 -1
- package/docs/MAP.md +2 -2
- package/docs/cli.md +48 -14
- package/docs/install.md +1 -1
- package/docs/kfd-support.md +80 -21
- package/docs/lifecycle-protocol.md +7 -2
- package/docs/publish-transaction.md +1 -1
- package/docs/readme-badges.md +2 -2
- package/docs/release-passport.md +1 -1
- package/docs/reusable-build-surface.md +7 -7
- package/docs/web-surface-deployments.md +33 -4
- package/package.json +3 -2
- package/packages/core/buildchain-config.js +10 -5
- package/packages/core/buildchain-layout.js +157 -0
- package/packages/core/index.js +34 -0
- package/packages/core/kfd.js +273 -0
- package/packages/core/kfd3-surface-register.js +25 -17
- package/packages/core/public-surface-audit.js +14 -7
- package/scripts/buildchain-contract-lock.mjs +6 -2
- package/scripts/check-inventory.mjs +5 -4
- package/scripts/generate-site-bundle.mjs +20 -3
- package/scripts/init-repo.mjs +2 -1
- package/scripts/web-surface-production-release-pr.mjs +209 -36
- package/scripts/web-surface-release-pr-review.mjs +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"./diagnostics": "./packages/core/diagnostics.js",
|
|
21
21
|
"./homebrew": "./packages/core/homebrew.js",
|
|
22
22
|
"./issue-reporting": "./packages/core/issue-reporting.js",
|
|
23
|
-
"./kfd
|
|
23
|
+
"./kfd": "./packages/core/kfd.js",
|
|
24
|
+
"./buildchain-layout": "./packages/core/buildchain-layout.js",
|
|
24
25
|
"./release-line-bootstrap": "./packages/core/release-line-bootstrap.js",
|
|
25
26
|
"./readme-badges": "./packages/core/readme-badges.js",
|
|
26
27
|
"./public-surface-audit": "./packages/core/public-surface-audit.js",
|
|
@@ -3,8 +3,12 @@ import fs from "node:fs";
|
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { parse, stringify } from "smol-toml";
|
|
6
|
+
import {
|
|
7
|
+
BUILDCHAIN_CONFIG_PATH,
|
|
8
|
+
resolveBuildchainConfigPath,
|
|
9
|
+
} from "./buildchain-layout.js";
|
|
6
10
|
|
|
7
|
-
const CONFIG_FILE =
|
|
11
|
+
const CONFIG_FILE = BUILDCHAIN_CONFIG_PATH;
|
|
8
12
|
const RESERVED_LIFECYCLE_KEYS = new Set(["env", "shell"]);
|
|
9
13
|
const SUPPORTED_VERSION_FILE_TYPES = new Set(["json", "toml", "regex"]);
|
|
10
14
|
const SUPPORTED_VERSION_STRATEGIES = new Set(["semver", "anchored"]);
|
|
@@ -97,7 +101,8 @@ function setByDottedKey(target, key, value) {
|
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
export function loadBuildchainConfig(cwd = process.cwd()) {
|
|
100
|
-
const
|
|
104
|
+
const configPath = resolveBuildchainConfigPath(cwd);
|
|
105
|
+
const filePath = path.join(cwd, configPath);
|
|
101
106
|
if (!fs.existsSync(filePath)) {
|
|
102
107
|
return undefined;
|
|
103
108
|
}
|
|
@@ -106,13 +111,13 @@ export function loadBuildchainConfig(cwd = process.cwd()) {
|
|
|
106
111
|
try {
|
|
107
112
|
config = parse(source);
|
|
108
113
|
} catch (error) {
|
|
109
|
-
throw new Error(`${
|
|
114
|
+
throw new Error(`${configPath} parse failed: ${error.message}`);
|
|
110
115
|
}
|
|
111
116
|
if (config.schema !== 1) {
|
|
112
|
-
throw new Error(`${
|
|
117
|
+
throw new Error(`${configPath} schema must be 1`);
|
|
113
118
|
}
|
|
114
119
|
return {
|
|
115
|
-
path:
|
|
120
|
+
path: configPath,
|
|
116
121
|
filePath,
|
|
117
122
|
config: normalizeBuildchainConfig(config),
|
|
118
123
|
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
export const BUILDCHAIN_DIR = ".buildchain";
|
|
5
|
+
export const BUILDCHAIN_CONFIG_PATH = ".buildchain/buildchain.toml";
|
|
6
|
+
export const LEGACY_BUILDCHAIN_CONFIG_PATH = "buildchain.toml";
|
|
7
|
+
export const BUILDCHAIN_CONTRACT_LOCK_PATH = ".buildchain/contract-lock.json";
|
|
8
|
+
export const LEGACY_BUILDCHAIN_CONTRACT_LOCK_PATH = "buildchain.contract-lock.json";
|
|
9
|
+
export const BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH = ".buildchain/kfd/kfd-3-surfaces.json";
|
|
10
|
+
export const LEGACY_BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH = "buildchain.kfd3.json";
|
|
11
|
+
export const BUILDCHAIN_RELEASE_PASSPORT_PATH = ".buildchain/release-passport/buildchain.release.json";
|
|
12
|
+
export const LEGACY_BUILDCHAIN_RELEASE_PASSPORT_PATH = "buildchain.release.json";
|
|
13
|
+
|
|
14
|
+
export const BUILDCHAIN_GENERATED_DIRS = Object.freeze([
|
|
15
|
+
".buildchain/artifacts",
|
|
16
|
+
".buildchain/diagnostics",
|
|
17
|
+
".buildchain/logs",
|
|
18
|
+
".buildchain/tmp",
|
|
19
|
+
".buildchain/runtime",
|
|
20
|
+
".buildchain/release-state",
|
|
21
|
+
".buildchain/release-evidence",
|
|
22
|
+
".buildchain/downloaded-manifests",
|
|
23
|
+
".buildchain/downloaded-diagnostics",
|
|
24
|
+
".buildchain/downloaded-relay-manifests",
|
|
25
|
+
".buildchain/relayed-artifacts",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export function toPosixPath(value) {
|
|
29
|
+
return String(value || "").split(path.sep).join("/");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function repoPath(cwd, relativePath) {
|
|
33
|
+
return path.join(cwd, relativePath);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function firstExistingRepoPath(cwd, candidates = []) {
|
|
37
|
+
for (const candidate of candidates) {
|
|
38
|
+
if (fs.existsSync(repoPath(cwd, candidate))) {
|
|
39
|
+
return candidate;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return candidates[0] || "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function resolveBuildchainConfigPath(cwd = process.cwd()) {
|
|
46
|
+
return firstExistingRepoPath(cwd, [
|
|
47
|
+
BUILDCHAIN_CONFIG_PATH,
|
|
48
|
+
LEGACY_BUILDCHAIN_CONFIG_PATH,
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function resolveBuildchainContractLockPath(cwd = process.cwd()) {
|
|
53
|
+
return firstExistingRepoPath(cwd, [
|
|
54
|
+
BUILDCHAIN_CONTRACT_LOCK_PATH,
|
|
55
|
+
LEGACY_BUILDCHAIN_CONTRACT_LOCK_PATH,
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function resolveKfd3SurfaceRegistryPath(cwd = process.cwd()) {
|
|
60
|
+
return firstExistingRepoPath(cwd, [
|
|
61
|
+
BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH,
|
|
62
|
+
LEGACY_BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH,
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function resolveReleasePassportPath(cwd = process.cwd()) {
|
|
67
|
+
return firstExistingRepoPath(cwd, [
|
|
68
|
+
BUILDCHAIN_RELEASE_PASSPORT_PATH,
|
|
69
|
+
LEGACY_BUILDCHAIN_RELEASE_PASSPORT_PATH,
|
|
70
|
+
]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function discoverBuildchainRepoFiles(cwd = process.cwd()) {
|
|
74
|
+
const files = [
|
|
75
|
+
{
|
|
76
|
+
kind: "config",
|
|
77
|
+
canonical: BUILDCHAIN_CONFIG_PATH,
|
|
78
|
+
legacy: LEGACY_BUILDCHAIN_CONFIG_PATH,
|
|
79
|
+
tracked: true,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
kind: "contract-lock",
|
|
83
|
+
canonical: BUILDCHAIN_CONTRACT_LOCK_PATH,
|
|
84
|
+
legacy: LEGACY_BUILDCHAIN_CONTRACT_LOCK_PATH,
|
|
85
|
+
tracked: true,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
kind: "kfd-3-surface-registry",
|
|
89
|
+
canonical: BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH,
|
|
90
|
+
legacy: LEGACY_BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH,
|
|
91
|
+
tracked: true,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
kind: "release-passport",
|
|
95
|
+
canonical: BUILDCHAIN_RELEASE_PASSPORT_PATH,
|
|
96
|
+
legacy: LEGACY_BUILDCHAIN_RELEASE_PASSPORT_PATH,
|
|
97
|
+
tracked: false,
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
return files.map((entry) => {
|
|
101
|
+
const canonicalExists = fs.existsSync(repoPath(cwd, entry.canonical));
|
|
102
|
+
const legacyExists = fs.existsSync(repoPath(cwd, entry.legacy));
|
|
103
|
+
return {
|
|
104
|
+
...entry,
|
|
105
|
+
canonicalExists,
|
|
106
|
+
legacyExists,
|
|
107
|
+
activePath: canonicalExists ? entry.canonical : legacyExists ? entry.legacy : entry.canonical,
|
|
108
|
+
migrationNeeded: !canonicalExists && legacyExists,
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function planBuildchainLayoutMigration({ cwd = process.cwd() } = {}) {
|
|
114
|
+
const entries = discoverBuildchainRepoFiles(cwd);
|
|
115
|
+
const moves = entries
|
|
116
|
+
.filter((entry) => entry.migrationNeeded)
|
|
117
|
+
.map((entry) => ({
|
|
118
|
+
kind: entry.kind,
|
|
119
|
+
from: entry.legacy,
|
|
120
|
+
to: entry.canonical,
|
|
121
|
+
tracked: entry.tracked,
|
|
122
|
+
}));
|
|
123
|
+
return {
|
|
124
|
+
schemaVersion: 1,
|
|
125
|
+
contract: "kungfu-buildchain-repository-layout-migration",
|
|
126
|
+
cwd: path.resolve(cwd),
|
|
127
|
+
canonicalRoot: BUILDCHAIN_DIR,
|
|
128
|
+
status: moves.length > 0 ? "migration-needed" : "current",
|
|
129
|
+
files: entries,
|
|
130
|
+
generatedDirs: BUILDCHAIN_GENERATED_DIRS,
|
|
131
|
+
moves,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function migrateBuildchainLayout({ cwd = process.cwd(), write = false, force = false } = {}) {
|
|
136
|
+
const plan = planBuildchainLayoutMigration({ cwd });
|
|
137
|
+
const applied = [];
|
|
138
|
+
if (write) {
|
|
139
|
+
for (const move of plan.moves) {
|
|
140
|
+
const from = repoPath(cwd, move.from);
|
|
141
|
+
const to = repoPath(cwd, move.to);
|
|
142
|
+
if (fs.existsSync(to) && !force) {
|
|
143
|
+
throw new Error(`${move.to} already exists; pass --force to overwrite`);
|
|
144
|
+
}
|
|
145
|
+
fs.mkdirSync(path.dirname(to), { recursive: true });
|
|
146
|
+
fs.renameSync(from, to);
|
|
147
|
+
applied.push(move);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
...plan,
|
|
152
|
+
write,
|
|
153
|
+
force,
|
|
154
|
+
status: write && applied.length === plan.moves.length ? "applied" : plan.status,
|
|
155
|
+
applied,
|
|
156
|
+
};
|
|
157
|
+
}
|
package/packages/core/index.js
CHANGED
|
@@ -257,6 +257,40 @@ export {
|
|
|
257
257
|
updateHomebrewTap,
|
|
258
258
|
} from "./homebrew.js";
|
|
259
259
|
|
|
260
|
+
export {
|
|
261
|
+
BUILDCHAIN_CONFIG_PATH,
|
|
262
|
+
BUILDCHAIN_CONTRACT_LOCK_PATH,
|
|
263
|
+
BUILDCHAIN_DIR,
|
|
264
|
+
BUILDCHAIN_GENERATED_DIRS,
|
|
265
|
+
BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH,
|
|
266
|
+
BUILDCHAIN_RELEASE_PASSPORT_PATH,
|
|
267
|
+
LEGACY_BUILDCHAIN_CONFIG_PATH,
|
|
268
|
+
LEGACY_BUILDCHAIN_CONTRACT_LOCK_PATH,
|
|
269
|
+
LEGACY_BUILDCHAIN_KFD3_SURFACE_REGISTRY_PATH,
|
|
270
|
+
LEGACY_BUILDCHAIN_RELEASE_PASSPORT_PATH,
|
|
271
|
+
discoverBuildchainRepoFiles,
|
|
272
|
+
migrateBuildchainLayout,
|
|
273
|
+
planBuildchainLayoutMigration,
|
|
274
|
+
resolveBuildchainConfigPath,
|
|
275
|
+
resolveBuildchainContractLockPath,
|
|
276
|
+
resolveKfd3SurfaceRegistryPath,
|
|
277
|
+
resolveReleasePassportPath,
|
|
278
|
+
} from "./buildchain-layout.js";
|
|
279
|
+
export {
|
|
280
|
+
buildchainKfdClaims,
|
|
281
|
+
collectKfdStatus,
|
|
282
|
+
discoverKfdStandards,
|
|
283
|
+
layout,
|
|
284
|
+
kfd1,
|
|
285
|
+
kfd2,
|
|
286
|
+
kfd3,
|
|
287
|
+
kfd4,
|
|
288
|
+
listKfdSchemas,
|
|
289
|
+
normalizeKfdStandardId,
|
|
290
|
+
readKfdSchema,
|
|
291
|
+
schemas,
|
|
292
|
+
} from "./kfd.js";
|
|
293
|
+
|
|
260
294
|
export {
|
|
261
295
|
KFD3_CAPABILITY_QUERY_CONTRACT,
|
|
262
296
|
KFD3_DEFAULT_REGISTRY_PATH,
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
createBuildchainKfd1Witness,
|
|
7
|
+
createBuildchainKfd2Claims,
|
|
8
|
+
createBuildchainKfd3ArtifactWitness,
|
|
9
|
+
createBuildchainKfd3PrebuildWitness,
|
|
10
|
+
createBuildchainKfdClaimRegistry,
|
|
11
|
+
createBuildchainKfdSurfaceRegistry,
|
|
12
|
+
createBuildchainPublicClaimDefinitions,
|
|
13
|
+
} from "./buildchain-kfd-claims.js";
|
|
14
|
+
import {
|
|
15
|
+
migrateBuildchainLayout,
|
|
16
|
+
planBuildchainLayoutMigration,
|
|
17
|
+
resolveBuildchainConfigPath,
|
|
18
|
+
resolveBuildchainContractLockPath,
|
|
19
|
+
resolveKfd3SurfaceRegistryPath,
|
|
20
|
+
resolveReleasePassportPath,
|
|
21
|
+
} from "./buildchain-layout.js";
|
|
22
|
+
import {
|
|
23
|
+
createKfd1ReleaseGateEvidence,
|
|
24
|
+
createKfd3CollaborationInterfaceReleaseGateEvidence,
|
|
25
|
+
normalizeKfd1ContractWorldWitness,
|
|
26
|
+
normalizeKfd3CollaborationInterfaceArtifactWitness,
|
|
27
|
+
normalizeKfd3CollaborationInterfacePrebuildWitness,
|
|
28
|
+
resolveKfd1Metadata,
|
|
29
|
+
resolveKfd2Metadata,
|
|
30
|
+
resolveKfd3Metadata,
|
|
31
|
+
validateKfd1ReleaseGateEvidence,
|
|
32
|
+
validateKfd2TrustTaxonomyEntry,
|
|
33
|
+
validateKfd3CollaborationInterfaceReleaseGateEvidence,
|
|
34
|
+
} from "./kfd-gate.js";
|
|
35
|
+
import {
|
|
36
|
+
auditKfd3Surfaces,
|
|
37
|
+
createKfd3SurfaceWitness,
|
|
38
|
+
detectKfd3Surfaces,
|
|
39
|
+
queryKfd3Capabilities,
|
|
40
|
+
readKfd3SurfaceRegistry,
|
|
41
|
+
registerKfd3Surfaces,
|
|
42
|
+
writeKfd3SurfaceRegistry,
|
|
43
|
+
} from "./kfd3-surface-register.js";
|
|
44
|
+
|
|
45
|
+
const require = createRequire(import.meta.url);
|
|
46
|
+
|
|
47
|
+
function readJsonPackageExport(exportPath) {
|
|
48
|
+
return JSON.parse(fs.readFileSync(require.resolve(exportPath), "utf8"));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function readJsonFile(filePath) {
|
|
52
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readJsonInput(value, { cwd = process.cwd(), label = "json" } = {}) {
|
|
56
|
+
const input = String(value || "").trim();
|
|
57
|
+
if (!input) {
|
|
58
|
+
throw new Error(`${label} is required`);
|
|
59
|
+
}
|
|
60
|
+
const filePath = path.isAbsolute(input) ? input : path.join(cwd, input);
|
|
61
|
+
if (fs.existsSync(filePath)) {
|
|
62
|
+
return readJsonFile(filePath);
|
|
63
|
+
}
|
|
64
|
+
return JSON.parse(input);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function readJsonInputs(values = [], { cwd = process.cwd(), label = "json" } = {}) {
|
|
68
|
+
return values.map((value, index) => readJsonInput(value, { cwd, label: `${label}[${index}]` }));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function normalizeKfdStandardId(value) {
|
|
72
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
73
|
+
const match = raw.match(/^(?:kfd[-\s]?)?([1-9][0-9]*)$/);
|
|
74
|
+
if (!match) {
|
|
75
|
+
throw new Error(`unsupported KFD standard: ${value}`);
|
|
76
|
+
}
|
|
77
|
+
return `kfd-${match[1]}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function discoverKfdStandards() {
|
|
81
|
+
const packageJson = readJsonPackageExport("@kungfu-tech/kfd/package.json");
|
|
82
|
+
const standards = readJsonPackageExport("@kungfu-tech/kfd/standards.json");
|
|
83
|
+
return {
|
|
84
|
+
schemaVersion: 1,
|
|
85
|
+
contract: "kungfu-buildchain-kfd-standard-discovery",
|
|
86
|
+
package: {
|
|
87
|
+
name: packageJson.name,
|
|
88
|
+
version: packageJson.version,
|
|
89
|
+
repository: packageJson.repository?.url || "",
|
|
90
|
+
},
|
|
91
|
+
metadataSchema: standards.metadataSchema || {},
|
|
92
|
+
source: standards.source || {},
|
|
93
|
+
standards: Object.entries(standards.standards || {})
|
|
94
|
+
.map(([key, value]) => ({
|
|
95
|
+
key: value?.key || key,
|
|
96
|
+
id: value?.id || value?.label || key,
|
|
97
|
+
label: value?.label || value?.id || key,
|
|
98
|
+
title: value?.title || "",
|
|
99
|
+
status: value?.status || "",
|
|
100
|
+
revision: value?.revision || 0,
|
|
101
|
+
schemaIds: { ...(value?.schemaIds || {}) },
|
|
102
|
+
schemaPaths: { ...(value?.schemaPaths || {}) },
|
|
103
|
+
}))
|
|
104
|
+
.sort((a, b) => a.key.localeCompare(b.key)),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function listKfdSchemas({ standard = "" } = {}) {
|
|
109
|
+
const discovery = discoverKfdStandards();
|
|
110
|
+
const selectedStandard = standard ? normalizeKfdStandardId(standard) : "";
|
|
111
|
+
const schemas = [];
|
|
112
|
+
for (const entry of discovery.standards) {
|
|
113
|
+
if (selectedStandard && normalizeKfdStandardId(entry.key) !== selectedStandard) continue;
|
|
114
|
+
const names = [...new Set([
|
|
115
|
+
...Object.keys(entry.schemaIds || {}),
|
|
116
|
+
...Object.keys(entry.schemaPaths || {}),
|
|
117
|
+
])].sort();
|
|
118
|
+
for (const name of names) {
|
|
119
|
+
schemas.push({
|
|
120
|
+
standard: entry.key,
|
|
121
|
+
name,
|
|
122
|
+
schemaId: entry.schemaIds?.[name] || "",
|
|
123
|
+
schemaPath: entry.schemaPaths?.[name] || "",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
schemaVersion: 1,
|
|
129
|
+
contract: "kungfu-buildchain-kfd-schema-list",
|
|
130
|
+
package: discovery.package,
|
|
131
|
+
standard: selectedStandard || "",
|
|
132
|
+
schemas,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function readKfdSchema({ standard, schema = "" } = {}) {
|
|
137
|
+
const selectedStandard = normalizeKfdStandardId(standard);
|
|
138
|
+
const schemaList = listKfdSchemas({ standard: selectedStandard }).schemas;
|
|
139
|
+
const selectedSchema = schema
|
|
140
|
+
? schemaList.find((entry) => entry.name === schema || entry.schemaId === schema || entry.schemaPath === schema)
|
|
141
|
+
: schemaList[0];
|
|
142
|
+
if (!selectedSchema?.schemaPath) {
|
|
143
|
+
throw new Error(`KFD schema not found for ${selectedStandard}${schema ? `:${schema}` : ""}`);
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
schemaVersion: 1,
|
|
147
|
+
contract: "kungfu-buildchain-kfd-schema",
|
|
148
|
+
standard: selectedStandard,
|
|
149
|
+
name: selectedSchema.name,
|
|
150
|
+
schemaId: selectedSchema.schemaId,
|
|
151
|
+
schemaPath: selectedSchema.schemaPath,
|
|
152
|
+
schema: readJsonPackageExport(`@kungfu-tech/kfd/${selectedSchema.schemaPath}`),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export const schemas = Object.freeze({
|
|
157
|
+
discover: discoverKfdStandards,
|
|
158
|
+
list: listKfdSchemas,
|
|
159
|
+
read: readKfdSchema,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
export const kfd1 = Object.freeze({
|
|
163
|
+
resolveMetadata: resolveKfd1Metadata,
|
|
164
|
+
normalizeContractWorldWitness: normalizeKfd1ContractWorldWitness,
|
|
165
|
+
createReleaseGateEvidence: createKfd1ReleaseGateEvidence,
|
|
166
|
+
validateReleaseGateEvidence: validateKfd1ReleaseGateEvidence,
|
|
167
|
+
createBuildchainWitness: createBuildchainKfd1Witness,
|
|
168
|
+
createGate: ({ cwd = process.cwd(), witnessJsons = [], artifactRoot = "", artifacts = [] } = {}) => createKfd1ReleaseGateEvidence({
|
|
169
|
+
cwd,
|
|
170
|
+
artifactRoot,
|
|
171
|
+
artifacts,
|
|
172
|
+
witnesses: readJsonInputs(witnessJsons, { cwd, label: "kfd-1 witness" }),
|
|
173
|
+
}),
|
|
174
|
+
validateGate: (section) => validateKfd1ReleaseGateEvidence(section),
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
export const kfd2 = Object.freeze({
|
|
178
|
+
resolveMetadata: resolveKfd2Metadata,
|
|
179
|
+
validateTrustTaxonomyEntry: validateKfd2TrustTaxonomyEntry,
|
|
180
|
+
createBuildchainClaims: createBuildchainKfd2Claims,
|
|
181
|
+
createBuildchainPublicClaimDefinitions,
|
|
182
|
+
validateTaxonomyEntries: ({ entries = [], kind = "residualRisk" } = {}) => entries.map((entry, index) => validateKfd2TrustTaxonomyEntry(entry, {
|
|
183
|
+
kind,
|
|
184
|
+
label: `${kind}[${index}]`,
|
|
185
|
+
})),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
export const kfd3 = Object.freeze({
|
|
189
|
+
resolveMetadata: resolveKfd3Metadata,
|
|
190
|
+
normalizePrebuildWitness: normalizeKfd3CollaborationInterfacePrebuildWitness,
|
|
191
|
+
normalizeArtifactWitness: normalizeKfd3CollaborationInterfaceArtifactWitness,
|
|
192
|
+
createReleaseGateEvidence: createKfd3CollaborationInterfaceReleaseGateEvidence,
|
|
193
|
+
validateReleaseGateEvidence: validateKfd3CollaborationInterfaceReleaseGateEvidence,
|
|
194
|
+
detectSurfaces: detectKfd3Surfaces,
|
|
195
|
+
registerSurfaces: registerKfd3Surfaces,
|
|
196
|
+
auditSurfaces: auditKfd3Surfaces,
|
|
197
|
+
createSurfaceWitness: createKfd3SurfaceWitness,
|
|
198
|
+
queryCapabilities: queryKfd3Capabilities,
|
|
199
|
+
readSurfaceRegistry: readKfd3SurfaceRegistry,
|
|
200
|
+
writeSurfaceRegistry: writeKfd3SurfaceRegistry,
|
|
201
|
+
createBuildchainPrebuildWitness: createBuildchainKfd3PrebuildWitness,
|
|
202
|
+
createBuildchainArtifactWitness: createBuildchainKfd3ArtifactWitness,
|
|
203
|
+
createBuildchainSurfaceRegistry: createBuildchainKfdSurfaceRegistry,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
export const kfd4 = Object.freeze({
|
|
207
|
+
schemas: {
|
|
208
|
+
list: (options = {}) => listKfdSchemas({ ...options, standard: "kfd-4" }),
|
|
209
|
+
read: (options = {}) => readKfdSchema({ ...options, standard: "kfd-4" }),
|
|
210
|
+
},
|
|
211
|
+
status: "schema-only",
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
export const buildchainKfdClaims = Object.freeze({
|
|
215
|
+
createClaimRegistry: createBuildchainKfdClaimRegistry,
|
|
216
|
+
createSurfaceRegistry: createBuildchainKfdSurfaceRegistry,
|
|
217
|
+
createPublicClaimDefinitions: createBuildchainPublicClaimDefinitions,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export function collectKfdStatus({ cwd = process.cwd() } = {}) {
|
|
221
|
+
const resolvedCwd = path.resolve(cwd);
|
|
222
|
+
const schemas = listKfdSchemas();
|
|
223
|
+
const layout = planBuildchainLayoutMigration({ cwd: resolvedCwd });
|
|
224
|
+
const paths = {
|
|
225
|
+
config: resolveBuildchainConfigPath(resolvedCwd),
|
|
226
|
+
contractLock: resolveBuildchainContractLockPath(resolvedCwd),
|
|
227
|
+
kfd3SurfaceRegistry: resolveKfd3SurfaceRegistryPath(resolvedCwd),
|
|
228
|
+
releasePassport: resolveReleasePassportPath(resolvedCwd),
|
|
229
|
+
};
|
|
230
|
+
const pathStatus = Object.fromEntries(Object.entries(paths).map(([key, relPath]) => [
|
|
231
|
+
key,
|
|
232
|
+
{
|
|
233
|
+
path: relPath,
|
|
234
|
+
exists: fs.existsSync(path.join(resolvedCwd, relPath)),
|
|
235
|
+
},
|
|
236
|
+
]));
|
|
237
|
+
return {
|
|
238
|
+
schemaVersion: 1,
|
|
239
|
+
contract: "kungfu-buildchain-kfd-status",
|
|
240
|
+
cwd: resolvedCwd,
|
|
241
|
+
layout: {
|
|
242
|
+
status: layout.status,
|
|
243
|
+
canonicalRoot: layout.canonicalRoot,
|
|
244
|
+
migrationNeeded: layout.moves.length > 0,
|
|
245
|
+
moves: layout.moves,
|
|
246
|
+
},
|
|
247
|
+
standards: schemas.schemas.reduce((acc, entry) => {
|
|
248
|
+
acc[entry.standard] ||= [];
|
|
249
|
+
acc[entry.standard].push({
|
|
250
|
+
name: entry.name,
|
|
251
|
+
schemaId: entry.schemaId,
|
|
252
|
+
schemaPath: entry.schemaPath,
|
|
253
|
+
});
|
|
254
|
+
return acc;
|
|
255
|
+
}, {}),
|
|
256
|
+
support: {
|
|
257
|
+
"kfd-1": ["schema", "witness", "gate", "verify"],
|
|
258
|
+
"kfd-2": ["schema", "taxonomy", "claims"],
|
|
259
|
+
"kfd-3": ["schema", "detect", "register", "audit", "witness", "query"],
|
|
260
|
+
"kfd-4": ["schema"],
|
|
261
|
+
},
|
|
262
|
+
paths: pathStatus,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export const layout = Object.freeze({
|
|
267
|
+
plan: planBuildchainLayoutMigration,
|
|
268
|
+
migrate: migrateBuildchainLayout,
|
|
269
|
+
resolveConfigPath: resolveBuildchainConfigPath,
|
|
270
|
+
resolveContractLockPath: resolveBuildchainContractLockPath,
|
|
271
|
+
resolveKfd3SurfaceRegistryPath,
|
|
272
|
+
resolveReleasePassportPath,
|
|
273
|
+
});
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { resolveKfd3SurfaceRegistryPath } from "./buildchain-layout.js";
|
|
4
5
|
|
|
5
6
|
export const KFD3_SURFACE_REGISTRY_CONTRACT = "kungfu-buildchain-kfd-3-surface-registry";
|
|
6
7
|
export const KFD3_SURFACE_DETECTION_CONTRACT = "kungfu-buildchain-kfd-3-surface-detection";
|
|
7
8
|
export const KFD3_SURFACE_AUDIT_CONTRACT = "kungfu-buildchain-kfd-3-surface-audit";
|
|
8
9
|
export const KFD3_CAPABILITY_QUERY_CONTRACT = "kungfu-buildchain-kfd-3-capability-query";
|
|
9
|
-
export const KFD3_DEFAULT_REGISTRY_PATH = "buildchain.
|
|
10
|
+
export const KFD3_DEFAULT_REGISTRY_PATH = ".buildchain/kfd/kfd-3-surfaces.json";
|
|
10
11
|
|
|
11
12
|
const KIND_ALIASES = Object.freeze({
|
|
12
13
|
"node-api": "node-api",
|
|
@@ -343,15 +344,20 @@ export function detectKfd3Surfaces({ cwd = process.cwd(), kinds = [], artifactPa
|
|
|
343
344
|
};
|
|
344
345
|
}
|
|
345
346
|
|
|
346
|
-
|
|
347
|
-
|
|
347
|
+
function resolveRegistryPath(cwd, registryPath) {
|
|
348
|
+
return registryPath || resolveKfd3SurfaceRegistryPath(cwd);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function readKfd3SurfaceRegistry({ cwd = process.cwd(), registryPath = "" } = {}) {
|
|
352
|
+
const effectiveRegistryPath = resolveRegistryPath(cwd, registryPath);
|
|
353
|
+
const filePath = path.resolve(cwd, effectiveRegistryPath);
|
|
348
354
|
const registry = readJsonFile(filePath, null);
|
|
349
355
|
if (!registry) {
|
|
350
356
|
return {
|
|
351
357
|
schemaVersion: 1,
|
|
352
358
|
contract: KFD3_SURFACE_REGISTRY_CONTRACT,
|
|
353
359
|
product: {},
|
|
354
|
-
registryPath,
|
|
360
|
+
registryPath: effectiveRegistryPath,
|
|
355
361
|
surfaces: [],
|
|
356
362
|
};
|
|
357
363
|
}
|
|
@@ -359,24 +365,25 @@ export function readKfd3SurfaceRegistry({ cwd = process.cwd(), registryPath = KF
|
|
|
359
365
|
schemaVersion: registry.schemaVersion || 1,
|
|
360
366
|
contract: registry.contract || KFD3_SURFACE_REGISTRY_CONTRACT,
|
|
361
367
|
product: registry.product || {},
|
|
362
|
-
registryPath,
|
|
368
|
+
registryPath: registry.registryPath || effectiveRegistryPath,
|
|
363
369
|
surfaces: Array.isArray(registry.surfaces) ? registry.surfaces : [],
|
|
364
370
|
policy: registry.policy || {},
|
|
365
371
|
};
|
|
366
372
|
}
|
|
367
373
|
|
|
368
|
-
export function writeKfd3SurfaceRegistry({ cwd = process.cwd(), registryPath =
|
|
374
|
+
export function writeKfd3SurfaceRegistry({ cwd = process.cwd(), registryPath = "", registry }) {
|
|
375
|
+
const effectiveRegistryPath = resolveRegistryPath(cwd, registryPath);
|
|
369
376
|
const next = {
|
|
370
377
|
schemaVersion: 1,
|
|
371
378
|
contract: KFD3_SURFACE_REGISTRY_CONTRACT,
|
|
372
379
|
product: registry.product || {},
|
|
373
|
-
registryPath,
|
|
380
|
+
registryPath: effectiveRegistryPath,
|
|
374
381
|
surfaces: uniqueSurfaces(registry.surfaces || []).map((entry) => ({
|
|
375
382
|
...entry,
|
|
376
383
|
state: entry.state || "declared",
|
|
377
384
|
declaration: entry.declaration || {
|
|
378
385
|
owner: "product",
|
|
379
|
-
source: "buildchain kfd
|
|
386
|
+
source: "buildchain kfd 3 register",
|
|
380
387
|
},
|
|
381
388
|
})),
|
|
382
389
|
policy: registry.policy || {
|
|
@@ -384,13 +391,13 @@ export function writeKfd3SurfaceRegistry({ cwd = process.cwd(), registryPath = K
|
|
|
384
391
|
declaredButMissing: "fail",
|
|
385
392
|
},
|
|
386
393
|
};
|
|
387
|
-
writeJsonFile(path.resolve(cwd,
|
|
394
|
+
writeJsonFile(path.resolve(cwd, effectiveRegistryPath), next);
|
|
388
395
|
return next;
|
|
389
396
|
}
|
|
390
397
|
|
|
391
398
|
export function registerKfd3Surfaces({
|
|
392
399
|
cwd = process.cwd(),
|
|
393
|
-
registryPath =
|
|
400
|
+
registryPath = "",
|
|
394
401
|
kinds = [],
|
|
395
402
|
artifactPath = "",
|
|
396
403
|
product = {},
|
|
@@ -435,7 +442,7 @@ export function registerKfd3Surfaces({
|
|
|
435
442
|
|
|
436
443
|
export function auditKfd3Surfaces({
|
|
437
444
|
cwd = process.cwd(),
|
|
438
|
-
registryPath =
|
|
445
|
+
registryPath = "",
|
|
439
446
|
kinds = [],
|
|
440
447
|
artifactPath = "",
|
|
441
448
|
} = {}) {
|
|
@@ -490,7 +497,7 @@ export function auditKfd3Surfaces({
|
|
|
490
497
|
|
|
491
498
|
export function createKfd3SurfaceWitness({
|
|
492
499
|
cwd = process.cwd(),
|
|
493
|
-
registryPath =
|
|
500
|
+
registryPath = "",
|
|
494
501
|
kind = "prebuild",
|
|
495
502
|
sourceSha = "",
|
|
496
503
|
artifactPath = "",
|
|
@@ -613,7 +620,7 @@ function capabilitiesFromRegistry({ registry, audit, passport = null }) {
|
|
|
613
620
|
export async function queryKfd3Capabilities({
|
|
614
621
|
cwd = process.cwd(),
|
|
615
622
|
product = "",
|
|
616
|
-
registryPath =
|
|
623
|
+
registryPath = "",
|
|
617
624
|
passportLocation = "",
|
|
618
625
|
artifactPath = "",
|
|
619
626
|
} = {}) {
|
|
@@ -649,15 +656,16 @@ export async function queryKfd3Capabilities({
|
|
|
649
656
|
};
|
|
650
657
|
}
|
|
651
658
|
|
|
652
|
-
const
|
|
653
|
-
const
|
|
654
|
-
const
|
|
659
|
+
const effectiveRegistryPath = resolveRegistryPath(cwd, registryPath);
|
|
660
|
+
const registry = readKfd3SurfaceRegistry({ cwd, registryPath: effectiveRegistryPath });
|
|
661
|
+
const hasRegistry = fs.existsSync(path.resolve(cwd, effectiveRegistryPath));
|
|
662
|
+
const audit = hasRegistry ? auditKfd3Surfaces({ cwd, registryPath: effectiveRegistryPath, artifactPath }) : null;
|
|
655
663
|
if (hasRegistry) {
|
|
656
664
|
return {
|
|
657
665
|
schemaVersion: 1,
|
|
658
666
|
contract: KFD3_CAPABILITY_QUERY_CONTRACT,
|
|
659
667
|
product: product || registry.product?.name || registry.product?.id || "local-product",
|
|
660
|
-
source: { type: "surface-registry", path:
|
|
668
|
+
source: { type: "surface-registry", path: effectiveRegistryPath },
|
|
661
669
|
status: audit.status,
|
|
662
670
|
summary: audit.summary,
|
|
663
671
|
capabilities: capabilitiesFromRegistry({ registry, audit }),
|