@kungfu-tech/kfd 1.0.0-alpha.14 → 1.0.0-alpha.15
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/.buildchain/kfd-1/contract-world.witness.json +16 -16
- package/.buildchain/kfd-2/public-release-trust.claim.json +14 -14
- package/.buildchain/kfd-3/collaboration-interface.artifact.json +21 -21
- package/.buildchain/kfd-3/collaboration-interface.prebuild.json +7 -7
- package/README.md +8 -0
- package/kfd.release.json +1 -1
- package/package.json +4 -1
- package/release-impact.json +9 -3
- package/scripts/check.mjs +647 -0
- package/scripts/npm-publish-transaction.mjs +220 -0
- package/scripts/update-kfd-1-witness.mjs +24 -0
- package/scripts/update-kfd-2-claim.mjs +82 -0
- package/scripts/update-kfd-3-witness.mjs +227 -0
- package/scripts/update-site-bundle.mjs +293 -0
- package/site/kfd-site.json +109 -2
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
|
|
7
|
+
const EXACT_TAG_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
8
|
+
|
|
9
|
+
function readArg(argv, name, fallback = "") {
|
|
10
|
+
const index = argv.indexOf(`--${name}`);
|
|
11
|
+
return index === -1 ? fallback : argv[index + 1] || "";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function hasFlag(argv, name) {
|
|
15
|
+
return argv.includes(`--${name}`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function readEnv(name, fallback = "") {
|
|
19
|
+
return process.env[name] || fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function runNpm({ cwd, args, allowFailure = false }) {
|
|
23
|
+
const result = spawnSync("npm", args, { cwd, env: process.env, encoding: "utf8" });
|
|
24
|
+
if (result.error) throw result.error;
|
|
25
|
+
if (!allowFailure && result.status !== 0) {
|
|
26
|
+
throw new Error(`npm ${args.join(" ")} failed\n${result.stdout || ""}${result.stderr || ""}`.trim());
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function readPackageJson(cwd) {
|
|
32
|
+
const filePath = path.join(cwd, "package.json");
|
|
33
|
+
if (!fs.existsSync(filePath)) throw new Error(`package.json not found: ${filePath}`);
|
|
34
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function parsePackResult(stdout) {
|
|
38
|
+
const parsed = JSON.parse(stdout);
|
|
39
|
+
const pack = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
40
|
+
if (!pack?.name || !pack?.version) throw new Error("npm pack did not return package name and version");
|
|
41
|
+
return {
|
|
42
|
+
name: pack.name,
|
|
43
|
+
version: pack.version,
|
|
44
|
+
filename: pack.filename || "",
|
|
45
|
+
integrity: pack.integrity || "",
|
|
46
|
+
shasum: pack.shasum || "",
|
|
47
|
+
entryCount: pack.entryCount || pack.files?.length || 0,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function artifactDigest(pack) {
|
|
52
|
+
if (pack.integrity) return pack.integrity;
|
|
53
|
+
if (pack.shasum) return `sha1:${pack.shasum}`;
|
|
54
|
+
throw new Error("npm pack did not return integrity or shasum");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function parseNpmView(stdout) {
|
|
58
|
+
const raw = String(stdout || "").trim();
|
|
59
|
+
if (!raw) return undefined;
|
|
60
|
+
const parsed = JSON.parse(raw);
|
|
61
|
+
const dist = parsed?.dist || parsed;
|
|
62
|
+
return {
|
|
63
|
+
integrity: dist?.integrity || parsed?.["dist.integrity"] || "",
|
|
64
|
+
shasum: dist?.shasum || parsed?.["dist.shasum"] || "",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function publishedDigest({ cwd, name, version, registry }) {
|
|
69
|
+
const result = runNpm({
|
|
70
|
+
cwd,
|
|
71
|
+
args: ["view", `${name}@${version}`, "dist.integrity", "dist.shasum", "--json", `--registry=${registry}`],
|
|
72
|
+
allowFailure: true,
|
|
73
|
+
});
|
|
74
|
+
if (result.status !== 0) {
|
|
75
|
+
const output = `${result.stdout || ""}\n${result.stderr || ""}`;
|
|
76
|
+
if (/\bE404\b|404 Not Found|is not in this registry/i.test(output)) return undefined;
|
|
77
|
+
throw new Error(`npm view ${name}@${version} failed\n${output}`.trim());
|
|
78
|
+
}
|
|
79
|
+
const view = parseNpmView(result.stdout);
|
|
80
|
+
return view?.integrity || (view?.shasum ? `sha1:${view.shasum}` : "");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function assertPackageVersion({ pkg, expectedVersion }) {
|
|
84
|
+
if (pkg.private === true) throw new Error("package.json private must be false before npm publish");
|
|
85
|
+
if (!pkg.name || typeof pkg.name !== "string") throw new Error("package.json name must be a non-empty string");
|
|
86
|
+
if (!pkg.version || typeof pkg.version !== "string") throw new Error("package.json version must be a non-empty string");
|
|
87
|
+
if (expectedVersion && pkg.version !== expectedVersion) {
|
|
88
|
+
throw new Error(`package.json version must match Buildchain version: package=${pkg.version} buildchain=${expectedVersion}`);
|
|
89
|
+
}
|
|
90
|
+
const exactTag = `v${pkg.version}`;
|
|
91
|
+
if (!EXACT_TAG_PATTERN.test(exactTag)) throw new Error(`unsupported release tag for npm publish: ${exactTag}`);
|
|
92
|
+
return exactTag;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function writeEvidence({ cwd, evidencePath, evidence }) {
|
|
96
|
+
const resolved = path.resolve(cwd, evidencePath);
|
|
97
|
+
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
98
|
+
fs.writeFileSync(resolved, `${JSON.stringify(evidence, null, 2)}\n`);
|
|
99
|
+
return resolved;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function writeGitHubOutputs(outputs) {
|
|
103
|
+
const outputPath = process.env.GITHUB_OUTPUT;
|
|
104
|
+
if (!outputPath) return;
|
|
105
|
+
fs.appendFileSync(outputPath, `${Object.entries(outputs)
|
|
106
|
+
.map(([key, value]) => `${key}=${String(value).replace(/\r?\n/g, " ")}`)
|
|
107
|
+
.join("\n")}\n`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function npmPublishTransaction({
|
|
111
|
+
cwd = process.cwd(),
|
|
112
|
+
registry = "https://registry.npmjs.org/",
|
|
113
|
+
dryRunPublish = false,
|
|
114
|
+
access = "public",
|
|
115
|
+
skipRegistryLookup = false,
|
|
116
|
+
} = {}) {
|
|
117
|
+
const resolvedCwd = path.resolve(cwd);
|
|
118
|
+
const pkg = readPackageJson(resolvedCwd);
|
|
119
|
+
const expectedVersion = readEnv("BUILDCHAIN_VERSION");
|
|
120
|
+
const exactTag = assertPackageVersion({ pkg, expectedVersion });
|
|
121
|
+
const distTag = readEnv("BUILDCHAIN_NPM_DIST_TAG", pkg.version.includes("-") ? "alpha" : "latest");
|
|
122
|
+
const pack = parsePackResult(runNpm({
|
|
123
|
+
cwd: resolvedCwd,
|
|
124
|
+
args: ["pack", "--dry-run", "--json", `--registry=${registry}`],
|
|
125
|
+
}).stdout);
|
|
126
|
+
const digest = artifactDigest(pack);
|
|
127
|
+
const existingDigest = skipRegistryLookup ? undefined : publishedDigest({
|
|
128
|
+
cwd: resolvedCwd,
|
|
129
|
+
name: pkg.name,
|
|
130
|
+
version: pkg.version,
|
|
131
|
+
registry,
|
|
132
|
+
});
|
|
133
|
+
let publishAction = "already-published";
|
|
134
|
+
if (existingDigest) {
|
|
135
|
+
if (existingDigest !== digest) throw new Error(`artifact digest mismatch: npm:${pkg.name}@${pkg.version}`);
|
|
136
|
+
} else if (dryRunPublish) {
|
|
137
|
+
publishAction = "dry-run";
|
|
138
|
+
} else {
|
|
139
|
+
runNpm({
|
|
140
|
+
cwd: resolvedCwd,
|
|
141
|
+
args: ["publish", "--access", access, "--tag", distTag, `--registry=${registry}`],
|
|
142
|
+
});
|
|
143
|
+
publishAction = "published";
|
|
144
|
+
const registryDigest = skipRegistryLookup ? undefined : publishedDigest({
|
|
145
|
+
cwd: resolvedCwd,
|
|
146
|
+
name: pkg.name,
|
|
147
|
+
version: pkg.version,
|
|
148
|
+
registry,
|
|
149
|
+
});
|
|
150
|
+
if (registryDigest && registryDigest !== digest) {
|
|
151
|
+
throw new Error(`artifact digest mismatch: npm:${pkg.name}@${pkg.version}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const evidencePath = readEnv("BUILDCHAIN_PUBLISH_EVIDENCE");
|
|
155
|
+
if (!evidencePath) throw new Error("BUILDCHAIN_PUBLISH_EVIDENCE is required");
|
|
156
|
+
const evidence = {
|
|
157
|
+
schema: 1,
|
|
158
|
+
version: expectedVersion || pkg.version,
|
|
159
|
+
channel: readEnv("BUILDCHAIN_CHANNEL"),
|
|
160
|
+
source_sha: readEnv("BUILDCHAIN_SOURCE_SHA"),
|
|
161
|
+
release_sha: readEnv("BUILDCHAIN_RELEASE_SHA"),
|
|
162
|
+
target_ref: readEnv("BUILDCHAIN_TARGET_REF"),
|
|
163
|
+
release_material_sha: readEnv("BUILDCHAIN_RELEASE_MATERIAL_SHA", readEnv("BUILDCHAIN_RELEASE_SHA")),
|
|
164
|
+
publish_tooling_sha: readEnv("BUILDCHAIN_PUBLISH_TOOLING_SHA", readEnv("BUILDCHAIN_RELEASE_SHA")),
|
|
165
|
+
artifacts: [{
|
|
166
|
+
group: "node",
|
|
167
|
+
kind: "npm",
|
|
168
|
+
name: pkg.name,
|
|
169
|
+
ref: pkg.version,
|
|
170
|
+
digest,
|
|
171
|
+
}],
|
|
172
|
+
};
|
|
173
|
+
const resolvedEvidencePath = writeEvidence({ cwd: resolvedCwd, evidencePath, evidence });
|
|
174
|
+
writeGitHubOutputs({
|
|
175
|
+
version: pkg.version,
|
|
176
|
+
"exact-tag": exactTag,
|
|
177
|
+
"dist-tag": distTag,
|
|
178
|
+
"artifact-digest": digest,
|
|
179
|
+
"publish-action": publishAction,
|
|
180
|
+
"publish-evidence": resolvedEvidencePath,
|
|
181
|
+
});
|
|
182
|
+
return {
|
|
183
|
+
schemaVersion: 1,
|
|
184
|
+
package: { name: pkg.name, version: pkg.version },
|
|
185
|
+
exactTag,
|
|
186
|
+
distTag,
|
|
187
|
+
registry,
|
|
188
|
+
publishAction,
|
|
189
|
+
pack,
|
|
190
|
+
evidencePath: resolvedEvidencePath,
|
|
191
|
+
evidence,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function usage() {
|
|
196
|
+
return `Usage:
|
|
197
|
+
node scripts/npm-publish-transaction.mjs [--cwd <dir>] [--registry <url>]
|
|
198
|
+
[--dry-run-publish] [--skip-registry-lookup]
|
|
199
|
+
`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
203
|
+
try {
|
|
204
|
+
const argv = process.argv.slice(2);
|
|
205
|
+
if (hasFlag(argv, "help") || argv.includes("-h")) {
|
|
206
|
+
process.stdout.write(usage());
|
|
207
|
+
process.exit(0);
|
|
208
|
+
}
|
|
209
|
+
const result = npmPublishTransaction({
|
|
210
|
+
cwd: readArg(argv, "cwd", process.cwd()),
|
|
211
|
+
registry: readArg(argv, "registry", "https://registry.npmjs.org/"),
|
|
212
|
+
dryRunPublish: hasFlag(argv, "dry-run-publish"),
|
|
213
|
+
skipRegistryLookup: hasFlag(argv, "skip-registry-lookup"),
|
|
214
|
+
});
|
|
215
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.error(`npm-publish-transaction: ${error.message}`);
|
|
218
|
+
process.exitCode = 1;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
|
|
4
|
+
const outputPath = ".buildchain/kfd-1/contract-world.witness.json";
|
|
5
|
+
|
|
6
|
+
const readJson = (filePath) => JSON.parse(readFileSync(filePath, "utf8"));
|
|
7
|
+
const sha256File = (filePath) => crypto.createHash("sha256").update(readFileSync(filePath)).digest("hex");
|
|
8
|
+
|
|
9
|
+
const witness = readJson(outputPath);
|
|
10
|
+
const standardsSha = sha256File("standards.json");
|
|
11
|
+
const registrySha = sha256File("registry.json");
|
|
12
|
+
|
|
13
|
+
witness.contractWorld.digest = `sha256:${standardsSha}`;
|
|
14
|
+
witness.canonicalPolicy.sha256 = standardsSha;
|
|
15
|
+
witness.registry.sha256 = registrySha;
|
|
16
|
+
|
|
17
|
+
for (const surface of witness.surfaces ?? []) {
|
|
18
|
+
if (!surface.sourcePath || !surface.artifactPath) continue;
|
|
19
|
+
surface.sourceSha256 = sha256File(surface.sourcePath);
|
|
20
|
+
surface.expectedSha256 = sha256File(surface.artifactPath);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
writeFileSync(outputPath, `${JSON.stringify(witness, null, 2)}\n`);
|
|
24
|
+
console.log(`updated ${outputPath}`);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
const outputPath = ".buildchain/kfd-2/public-release-trust.claim.json";
|
|
6
|
+
|
|
7
|
+
const readJson = (filePath) => JSON.parse(readFileSync(filePath, "utf8"));
|
|
8
|
+
const sha256File = (filePath) => crypto.createHash("sha256").update(readFileSync(filePath)).digest("hex");
|
|
9
|
+
const pointer = (filePath, extra = {}) => ({
|
|
10
|
+
path: filePath,
|
|
11
|
+
sha256: sha256File(filePath),
|
|
12
|
+
...extra,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const packageJson = readJson("package.json");
|
|
16
|
+
const releaseAnchor = readJson("kfd.release.json");
|
|
17
|
+
|
|
18
|
+
const sourceBindings = [
|
|
19
|
+
pointer("package.json", { id: "package-version-and-exports" }),
|
|
20
|
+
pointer("kfd.release.json", { id: "anchored-release-version" }),
|
|
21
|
+
pointer("registry.json", { id: "decision-registry" }),
|
|
22
|
+
pointer("standards.json", { id: "standards-metadata" }),
|
|
23
|
+
pointer("release-impact.json", { id: "release-impact-ledger" }),
|
|
24
|
+
pointer("buildchain.toml", { id: "buildchain-release-contract" }),
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const machineEvidence = [
|
|
28
|
+
pointer("scripts/check.mjs", { id: "self-verification-command" }),
|
|
29
|
+
pointer(".github/workflows/build.yml", { id: "buildchain-build-workflow" }),
|
|
30
|
+
pointer(".github/workflows/buildchain-ref-promotion.yml", { id: "buildchain-promotion-workflow" }),
|
|
31
|
+
pointer("schemas/kfd-2/trust-taxonomy.schema.json", { id: "kfd-2-trust-taxonomy-schema" }),
|
|
32
|
+
pointer("schemas/kfd-2/release-claims.schema.json", { id: "kfd-2-release-claims-schema" }),
|
|
33
|
+
pointer("schemas/kfd-2/release-trust-passport.schema.json", { id: "kfd-2-release-trust-passport-schema" }),
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const hashes = Object.fromEntries(
|
|
37
|
+
[...sourceBindings, ...machineEvidence].map((entry) => [entry.id, entry.sha256]),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const claim = {
|
|
41
|
+
id: "kfd-public-release-trust",
|
|
42
|
+
public: true,
|
|
43
|
+
claim:
|
|
44
|
+
"The KFD npm release is backed by declared source facts, machine-readable evidence, artifact coordinates, verification, audit boundary, responsibility, and explicit residual-risk state.",
|
|
45
|
+
sourceBindings,
|
|
46
|
+
machineEvidence,
|
|
47
|
+
hashes,
|
|
48
|
+
artifacts: [
|
|
49
|
+
{
|
|
50
|
+
name: packageJson.name,
|
|
51
|
+
version: packageJson.version,
|
|
52
|
+
path: "package.json",
|
|
53
|
+
sha256: sha256File("package.json"),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "kfd-release-anchor",
|
|
57
|
+
version: releaseAnchor.npmVersion,
|
|
58
|
+
path: "kfd.release.json",
|
|
59
|
+
sha256: sha256File("kfd.release.json"),
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
verification: {
|
|
63
|
+
result: "passed",
|
|
64
|
+
command: "node scripts/check.mjs",
|
|
65
|
+
},
|
|
66
|
+
auditBoundary: {
|
|
67
|
+
scope: "KFD public npm package release facts, package exports, release governance files, and Buildchain release-passport inputs",
|
|
68
|
+
enumerability: "closed-world",
|
|
69
|
+
},
|
|
70
|
+
responsibility: {
|
|
71
|
+
owner: "KFD maintainers",
|
|
72
|
+
sourceOwner: "KFD maintainers",
|
|
73
|
+
verificationOwner: "KFD package self-verification",
|
|
74
|
+
releaseDecisionOwner: "KFD maintainers",
|
|
75
|
+
releasePassportProofOwner: "Buildchain",
|
|
76
|
+
},
|
|
77
|
+
residualRisk: [],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
81
|
+
writeFileSync(outputPath, `${JSON.stringify(claim, null, 2)}\n`);
|
|
82
|
+
console.log(`updated ${outputPath}`);
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
const interfacePath = ".buildchain/kfd-3/collaboration-interface.json";
|
|
6
|
+
const prebuildPath = ".buildchain/kfd-3/collaboration-interface.prebuild.json";
|
|
7
|
+
const artifactPath = ".buildchain/kfd-3/collaboration-interface.artifact.json";
|
|
8
|
+
|
|
9
|
+
const readJson = (filePath) => JSON.parse(readFileSync(filePath, "utf8"));
|
|
10
|
+
const sha256File = (filePath) => crypto.createHash("sha256").update(readFileSync(filePath)).digest("hex");
|
|
11
|
+
const hashablePath = (filePath) => filePath.split("#", 1)[0];
|
|
12
|
+
const pointer = (filePath, description = undefined) => ({
|
|
13
|
+
path: filePath,
|
|
14
|
+
sha256: sha256File(hashablePath(filePath)),
|
|
15
|
+
...(description ? { description } : {}),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const writeJson = (filePath, value) => {
|
|
19
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
20
|
+
writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const packageJson = readJson("package.json");
|
|
24
|
+
const registry = readJson("registry.json");
|
|
25
|
+
const standards = readJson("standards.json");
|
|
26
|
+
const collaborationInterface = readJson(interfacePath);
|
|
27
|
+
const interfaceSha = sha256File(interfacePath);
|
|
28
|
+
const interfaceDigest = `sha256:${interfaceSha}`;
|
|
29
|
+
|
|
30
|
+
const decisionDocs = registry.entries.map((entry) => ({
|
|
31
|
+
id: `decision:${entry.slug}`,
|
|
32
|
+
sourcePath: entry.path,
|
|
33
|
+
sha256: sha256File(entry.path),
|
|
34
|
+
}));
|
|
35
|
+
const schemaSurfaces = [
|
|
36
|
+
"schemas/kfd-standards.schema.json",
|
|
37
|
+
"schemas/kfd-1/contract-world.schema.json",
|
|
38
|
+
"schemas/kfd-1/witness.schema.json",
|
|
39
|
+
"schemas/kfd-2/trust-taxonomy.schema.json",
|
|
40
|
+
"schemas/kfd-2/release-claims.schema.json",
|
|
41
|
+
"schemas/kfd-2/release-trust-passport.schema.json",
|
|
42
|
+
"schemas/kfd-3/collaboration-interface.schema.json",
|
|
43
|
+
"schemas/kfd-3/witness.schema.json",
|
|
44
|
+
].map((filePath) => ({
|
|
45
|
+
id: `schema:${filePath.replace(/^schemas\//, "").replace(/\.schema\.json$/, "").replace(/\//g, ":")}`,
|
|
46
|
+
sourcePath: filePath,
|
|
47
|
+
sha256: sha256File(filePath),
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
const groupedSurfaces = {
|
|
51
|
+
docs: [
|
|
52
|
+
{ id: "doc:readme", sourcePath: "README.md", sha256: sha256File("README.md") },
|
|
53
|
+
{ id: "doc:trademarks", sourcePath: "TRADEMARKS.md", sha256: sha256File("TRADEMARKS.md") },
|
|
54
|
+
{ id: "doc:docs-map", sourcePath: "docs/MAP.md", sha256: sha256File("docs/MAP.md") },
|
|
55
|
+
{ id: "doc:kfd-2-release-trust", sourcePath: "docs/kfd-2-release-trust.md", sha256: sha256File("docs/kfd-2-release-trust.md") },
|
|
56
|
+
{ id: "doc:kfd-3-collaboration-interface", sourcePath: "docs/kfd-3-collaboration-interface.md", sha256: sha256File("docs/kfd-3-collaboration-interface.md") },
|
|
57
|
+
...decisionDocs,
|
|
58
|
+
],
|
|
59
|
+
schemas: schemaSurfaces,
|
|
60
|
+
standardsMetadata: [
|
|
61
|
+
{ id: "metadata:registry", sourcePath: "registry.json", sha256: sha256File("registry.json") },
|
|
62
|
+
{ id: "metadata:standards", sourcePath: "standards.json", sha256: sha256File("standards.json") },
|
|
63
|
+
{ id: "metadata:release-impact", sourcePath: "release-impact.json", sha256: sha256File("release-impact.json") },
|
|
64
|
+
{ id: "metadata:release-anchor", sourcePath: "kfd.release.json", sha256: sha256File("kfd.release.json") },
|
|
65
|
+
{ id: "metadata:kfd-2-public-release-trust-claim", sourcePath: ".buildchain/kfd-2/public-release-trust.claim.json", sha256: sha256File(".buildchain/kfd-2/public-release-trust.claim.json") },
|
|
66
|
+
],
|
|
67
|
+
packageExports: [
|
|
68
|
+
{ id: "export:package-json", sourcePath: "package.json#exports", sha256: sha256File("package.json") },
|
|
69
|
+
{ id: "export:npm-files", sourcePath: "package.json#files", sha256: sha256File("package.json") },
|
|
70
|
+
],
|
|
71
|
+
siteConsumptionContracts: [
|
|
72
|
+
{ id: "site:kfd-site-bundle", sourcePath: "site/kfd-site.json", sha256: sha256File("site/kfd-site.json") },
|
|
73
|
+
{ id: "site:release-propagation", sourcePath: "buildchain.release-propagation.json", sha256: sha256File("buildchain.release-propagation.json") },
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const explicitSurfaces = collaborationInterface.surfaces.map((surface) => ({
|
|
78
|
+
id: surface.id,
|
|
79
|
+
name: surface.id,
|
|
80
|
+
kind: surface.kind,
|
|
81
|
+
participantProfile: Array.isArray(surface.participants) ? surface.participants.join(",") : "",
|
|
82
|
+
availability: surface.maturity || "shipped",
|
|
83
|
+
visibility: "public",
|
|
84
|
+
participantFacing: true,
|
|
85
|
+
public: true,
|
|
86
|
+
sourcePath: surface.discoverability?.path || "",
|
|
87
|
+
}));
|
|
88
|
+
|
|
89
|
+
const declaredSurfaceIds = new Set(explicitSurfaces.map((surface) => surface.id));
|
|
90
|
+
for (const entrypoint of collaborationInterface.minimalEntrypoints) {
|
|
91
|
+
if (declaredSurfaceIds.has(entrypoint.id)) continue;
|
|
92
|
+
explicitSurfaces.push({
|
|
93
|
+
id: entrypoint.id,
|
|
94
|
+
name: entrypoint.id,
|
|
95
|
+
kind: "entrypoint",
|
|
96
|
+
participantProfile: Array.isArray(entrypoint.participants) ? entrypoint.participants.join(",") : "",
|
|
97
|
+
availability: "shipped",
|
|
98
|
+
visibility: "public",
|
|
99
|
+
participantFacing: true,
|
|
100
|
+
public: true,
|
|
101
|
+
sourcePath: entrypoint.surface,
|
|
102
|
+
});
|
|
103
|
+
declaredSurfaceIds.add(entrypoint.id);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const participantProfiles = collaborationInterface.participants.map((entry) => entry.id);
|
|
107
|
+
const responsibility = {
|
|
108
|
+
registryFactsOwner: "KFD maintainers",
|
|
109
|
+
artifactVerificationOwner: "KFD package self-verification",
|
|
110
|
+
releasePassportProofOwner: "Buildchain",
|
|
111
|
+
};
|
|
112
|
+
const residualRisk = [
|
|
113
|
+
{
|
|
114
|
+
id: "human-language-interpretation",
|
|
115
|
+
definedBy: "https://kfd.libkungfu.dev/schemas/kfd-2/trust-taxonomy.schema.json#/$defs/residualRisk",
|
|
116
|
+
riskType: "natural-language-semantic-risk",
|
|
117
|
+
trustImpact: "downgrade-warning",
|
|
118
|
+
machineProvability: "not-exhaustively-enumerable",
|
|
119
|
+
agentAction: "semantic-review-required",
|
|
120
|
+
reason: "Natural-language standard interpretation is inspectable and reviewable but not exhaustively enumerable from package bytes.",
|
|
121
|
+
owner: "KFD maintainers",
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
const prebuild = {
|
|
126
|
+
schemaVersion: 1,
|
|
127
|
+
contract: "kungfu-buildchain-kfd-3-collaboration-interface-prebuild-witness",
|
|
128
|
+
id: "kfd-repository",
|
|
129
|
+
standard: "kfd-3",
|
|
130
|
+
supportLevel: "release",
|
|
131
|
+
source: {
|
|
132
|
+
repo: "kungfu-systems/kfd",
|
|
133
|
+
},
|
|
134
|
+
sourceRegistry: {
|
|
135
|
+
id: "kfd-collaboration-interface",
|
|
136
|
+
path: interfacePath,
|
|
137
|
+
sha256: interfaceSha,
|
|
138
|
+
},
|
|
139
|
+
collaborationInterfaceDigest: interfaceDigest,
|
|
140
|
+
collaborationInterface,
|
|
141
|
+
participantProfiles,
|
|
142
|
+
surfaces: explicitSurfaces,
|
|
143
|
+
...groupedSurfaces,
|
|
144
|
+
auditBoundary: {
|
|
145
|
+
mode: "closed-world",
|
|
146
|
+
scope: "KFD participant-facing public collaboration/control surfaces shipped in the repository and npm package",
|
|
147
|
+
reachableSurfaceMode: "declared-boundary",
|
|
148
|
+
unclassifiedPolicy: "fail",
|
|
149
|
+
nonExhaustivelyEnumerableSurfaces: residualRisk,
|
|
150
|
+
},
|
|
151
|
+
residualRisk,
|
|
152
|
+
responsibility,
|
|
153
|
+
expectedArtifactVerification: {
|
|
154
|
+
command: "node scripts/check.mjs",
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const artifact = {
|
|
159
|
+
schemaVersion: 1,
|
|
160
|
+
contract: "kfd-3-witness",
|
|
161
|
+
id: "kfd-repository",
|
|
162
|
+
standard: "kfd-3",
|
|
163
|
+
collaborationInterface: {
|
|
164
|
+
schemaId: standards.standards["kfd-3"].schemaIds.collaborationInterface,
|
|
165
|
+
digest: interfaceDigest,
|
|
166
|
+
},
|
|
167
|
+
sourceRegistry: {
|
|
168
|
+
id: "kfd-collaboration-interface",
|
|
169
|
+
path: interfacePath,
|
|
170
|
+
sha256: interfaceSha,
|
|
171
|
+
},
|
|
172
|
+
artifact: {
|
|
173
|
+
name: packageJson.name,
|
|
174
|
+
path: "npm:@kungfu-tech/kfd",
|
|
175
|
+
digest: interfaceDigest,
|
|
176
|
+
},
|
|
177
|
+
surfaces: explicitSurfaces,
|
|
178
|
+
...groupedSurfaces,
|
|
179
|
+
evidence: {
|
|
180
|
+
minimalEntrypoints: collaborationInterface.minimalEntrypoints.map((entry) => pointer(entry.surface, entry.purpose)),
|
|
181
|
+
discoverability: [
|
|
182
|
+
pointer("README.md", "Human and agent entrypoint"),
|
|
183
|
+
pointer("TRADEMARKS.md", "Official status, trademark, and authority boundary"),
|
|
184
|
+
pointer("docs/MAP.md", "Documentation routing entrypoint"),
|
|
185
|
+
pointer("registry.json", "Machine-readable decision index"),
|
|
186
|
+
pointer("standards.json", "Machine-readable standards metadata"),
|
|
187
|
+
pointer(".buildchain/kfd-2/public-release-trust.claim.json", "KFD-2 public release trust claim"),
|
|
188
|
+
pointer("package.json", "Package export map"),
|
|
189
|
+
pointer("site/kfd-site.json", "Site content projection"),
|
|
190
|
+
],
|
|
191
|
+
transparentConstraints: [
|
|
192
|
+
pointer("CONTRIBUTING.md", "Append-only decision and contribution constraints"),
|
|
193
|
+
pointer("TRADEMARKS.md", "Trademark and official-status constraints"),
|
|
194
|
+
pointer("scripts/check.mjs", "Repository self-verification gate"),
|
|
195
|
+
pointer("site/kfd-site.json", "Site rendering boundary"),
|
|
196
|
+
],
|
|
197
|
+
choicePaths: [
|
|
198
|
+
pointer("README.md", "Human reading path"),
|
|
199
|
+
pointer("registry.json", "Agent registry path"),
|
|
200
|
+
pointer("standards.json", "Agent standards metadata path"),
|
|
201
|
+
pointer(".buildchain/kfd-2/public-release-trust.claim.json", "Agent release trust claim path"),
|
|
202
|
+
pointer("package.json", "Package consumption path"),
|
|
203
|
+
],
|
|
204
|
+
manuals: [
|
|
205
|
+
pointer("docs/MAP.md"),
|
|
206
|
+
pointer("TRADEMARKS.md"),
|
|
207
|
+
pointer("docs/kfd-3-collaboration-interface.md"),
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
closure: {
|
|
211
|
+
classificationMode: "closed-world",
|
|
212
|
+
reachableEntrypoints: collaborationInterface.minimalEntrypoints.map((entry) => entry.id),
|
|
213
|
+
classifiedEntrypoints: collaborationInterface.minimalEntrypoints.map((entry) => entry.id),
|
|
214
|
+
unclassifiedEntrypoints: [],
|
|
215
|
+
},
|
|
216
|
+
verifier: {
|
|
217
|
+
name: "kfd self-verification",
|
|
218
|
+
command: "node scripts/check.mjs",
|
|
219
|
+
},
|
|
220
|
+
residualRisk,
|
|
221
|
+
result: "pass",
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
writeJson(prebuildPath, prebuild);
|
|
225
|
+
writeJson(artifactPath, artifact);
|
|
226
|
+
console.log(`updated ${prebuildPath}`);
|
|
227
|
+
console.log(`updated ${artifactPath}`);
|