@kungfu-tech/buildchain 2.8.15 → 2.8.16-alpha.2
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 +19 -11
- package/bin/buildchain.mjs +150 -0
- package/dist/site/buildchain-contract.json +83 -11
- package/dist/site/buildchain-site.json +121 -20
- package/dist/site/cli-registry.json +5 -0
- package/dist/site/kfd-claims.json +85 -3
- package/dist/site/manual-registry.json +18 -3
- package/dist/site/node-api-registry.json +28 -6
- package/dist/site/page-registry.json +88 -11
- package/dist/site/release-model.json +8 -0
- package/dist/site/release-provenance.json +2 -0
- package/dist/site/site-manifest.json +23 -7
- package/docs/MAP.md +8 -0
- package/docs/cli.md +40 -3
- package/docs/homebrew.md +116 -0
- package/docs/readme-badges.md +124 -0
- package/docs/web-surface-deployments.md +46 -8
- package/package.json +3 -1
- package/packages/core/README.md +12 -0
- package/packages/core/buildchain-config.js +2 -2
- package/packages/core/buildchain-contract.js +56 -0
- package/packages/core/buildchain-kfd-claims.js +37 -0
- package/packages/core/homebrew.js +414 -0
- package/packages/core/index.js +21 -0
- package/packages/core/readme-badges.js +450 -0
- package/packages/core/release-passport.js +24 -9
- package/scripts/check-inventory.mjs +69 -0
- package/scripts/generate-site-bundle.mjs +12 -0
- package/scripts/web-surface-core.mjs +177 -5
|
@@ -44,5 +44,13 @@
|
|
|
44
44
|
"release passport assets"
|
|
45
45
|
],
|
|
46
46
|
"owner": "promote-buildchain-ref"
|
|
47
|
+
},
|
|
48
|
+
"distributionIndexes": {
|
|
49
|
+
"homebrewTap": {
|
|
50
|
+
"projectType": "distribution-index",
|
|
51
|
+
"manifest": "tap-manifest.json",
|
|
52
|
+
"command": "buildchain homebrew check",
|
|
53
|
+
"sourceOfTruth": "upstream release passport and sibling evidence"
|
|
54
|
+
}
|
|
47
55
|
}
|
|
48
56
|
}
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
"./artifact-passport": "./packages/core/artifact-passport.js",
|
|
14
14
|
"./buildchain-contract": "./packages/core/buildchain-contract.js",
|
|
15
15
|
"./diagnostics": "./packages/core/diagnostics.js",
|
|
16
|
+
"./homebrew": "./packages/core/homebrew.js",
|
|
16
17
|
"./issue-reporting": "./packages/core/issue-reporting.js",
|
|
18
|
+
"./readme-badges": "./packages/core/readme-badges.js",
|
|
17
19
|
"./logging": "./packages/core/logging.js",
|
|
18
20
|
"./kfd-gate": "./packages/core/kfd-gate.js",
|
|
19
21
|
"./release-candidate": "./packages/core/release-candidate.js",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-manifest",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-07T15:32:30.986Z",
|
|
5
|
+
"publishedAt": "2026-07-07T15:32:30.986Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "d61c8a864e12e34bc6c6e2aac2e7ad60e6caebfd",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"package": {
|
|
39
39
|
"name": "@kungfu-tech/buildchain",
|
|
40
|
-
"version": "2.8.
|
|
40
|
+
"version": "2.8.16-alpha.2",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"entrypoint": "buildchain-site.json",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"path": "docs/MAP.md",
|
|
54
54
|
"plane": "use",
|
|
55
55
|
"exists": true,
|
|
56
|
-
"digest": "sha256:
|
|
56
|
+
"digest": "sha256:f4300eed89765cee0df38eb92de4d9d3adce4fbf954c735aead3bea74f05d975"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"id": "install",
|
|
@@ -79,6 +79,22 @@
|
|
|
79
79
|
"exists": true,
|
|
80
80
|
"digest": "sha256:190e3537075f37cf8a7e52bf8254606e1d9450d87c5a81dc11df8b56a7d03065"
|
|
81
81
|
},
|
|
82
|
+
{
|
|
83
|
+
"id": "readme-badges",
|
|
84
|
+
"title": "README badge blocks",
|
|
85
|
+
"path": "docs/readme-badges.md",
|
|
86
|
+
"plane": "use",
|
|
87
|
+
"exists": true,
|
|
88
|
+
"digest": "sha256:3f4a44ea7f3b70cadc78a343fe53ade74b78fa369c19630cc9b926c1e460f66f"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "homebrew",
|
|
92
|
+
"title": "Homebrew distribution indexes",
|
|
93
|
+
"path": "docs/homebrew.md",
|
|
94
|
+
"plane": "use",
|
|
95
|
+
"exists": true,
|
|
96
|
+
"digest": "sha256:2fc4e8411f35ca86d19d61c7843b9a1fa440f7afea25df13d3aa03342f09f90c"
|
|
97
|
+
},
|
|
82
98
|
{
|
|
83
99
|
"id": "binary-distribution",
|
|
84
100
|
"title": "Binary distribution contract",
|
|
@@ -149,7 +165,7 @@
|
|
|
149
165
|
"path": "docs/cli.md",
|
|
150
166
|
"plane": "use",
|
|
151
167
|
"exists": true,
|
|
152
|
-
"digest": "sha256:
|
|
168
|
+
"digest": "sha256:cfb0bf32f2b8b44bf352e79c27e34b7980e0f66e5fa10e4f202975fbb4780ad1"
|
|
153
169
|
},
|
|
154
170
|
{
|
|
155
171
|
"id": "lifecycle-protocol",
|
|
@@ -213,7 +229,7 @@
|
|
|
213
229
|
"path": "docs/web-surface-deployments.md",
|
|
214
230
|
"plane": "use",
|
|
215
231
|
"exists": true,
|
|
216
|
-
"digest": "sha256:
|
|
232
|
+
"digest": "sha256:4c7334fe2284fec3c1249124b0ff85f1242eb7a76d4b2c537c8b2cb6e0e598c1"
|
|
217
233
|
}
|
|
218
234
|
],
|
|
219
235
|
"facts": [
|
package/docs/MAP.md
CHANGED
|
@@ -25,6 +25,8 @@ manuals explain those facts and give operator examples.
|
|
|
25
25
|
| npm publish transactions, evidence, dist-tags, and recovery | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`publish-transaction.md`](publish-transaction.md) |
|
|
26
26
|
| GitHub Release passport/evidence publication | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`release-governance.md`](release-governance.md), [`release-candidate.md`](release-candidate.md) |
|
|
27
27
|
| release propagation for package/site chains | `dist/site/release-model.json` | [`release-propagation.md`](release-propagation.md) |
|
|
28
|
+
| Generated README badge blocks and badge facts | `dist/site/node-api-registry.json`, `dist/site/manual-registry.json`, `kungfu-buildchain-readme-badge-facts` | [`readme-badges.md`](readme-badges.md) |
|
|
29
|
+
| Homebrew tap distribution indexes | `dist/site/node-api-registry.json`, `dist/site/buildchain-contract.json` | [`homebrew.md`](homebrew.md) |
|
|
28
30
|
| Buildchain CLI manual | `dist/site/cli-registry.json`, `dist/site/manual-registry.json` | [`cli.md`](cli.md) |
|
|
29
31
|
| Node API / package exports | `dist/site/node-api-registry.json`, `dist/site/release-provenance.json` | [`cli.md`](cli.md#node-api-and-package-exports) |
|
|
30
32
|
|
|
@@ -59,6 +61,8 @@ replace them.
|
|
|
59
61
|
| How do I gate KFD-3 collaboration-interface releases? | [`release-passport.md`](release-passport.md#kfd-3-collaboration-interface-release-gate) + [`cli.md`](cli.md) | verify/use | stable |
|
|
60
62
|
| How do I keep `@v2` floating refs while detecting Buildchain contract drift? | [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock) | verify/use | stable |
|
|
61
63
|
| How do I propagate finalized upstream releases to downstream package/site PRs? | [`release-propagation.md`](release-propagation.md) | use | preview |
|
|
64
|
+
| How do I generate README status badges without hand-maintaining Markdown? | [`readme-badges.md`](readme-badges.md) + [`cli.md`](cli.md) | use | stable |
|
|
65
|
+
| How do I generate and verify a Homebrew tap from release passport evidence? | [`homebrew.md`](homebrew.md) + [`cli.md`](cli.md) | use/verify | stable |
|
|
62
66
|
| How do I prove a PR-stage reusable build is the artifact source promoted later? | [`release-candidate.md`](release-candidate.md) + [`reusable-build-surface.md`](reusable-build-surface.md) | verify | stable |
|
|
63
67
|
| Why are binary release assets archived by platform, and where is the single bundle? | [`binary-distribution.md`](binary-distribution.md) | verify | stable |
|
|
64
68
|
| How do I add timestamped logs inside build scripts? | [`toolkit-observability.md`](toolkit-observability.md) | use | stable |
|
|
@@ -115,6 +119,10 @@ replace them.
|
|
|
115
119
|
[`cli.md`](cli.md) and [`publish-transaction.md`](publish-transaction.md).
|
|
116
120
|
- **release chains / upstream package as source of truth / site synchronization** ->
|
|
117
121
|
[`release-propagation.md`](release-propagation.md).
|
|
122
|
+
- **README status badges / KFD badge blocks / badge facts JSON** ->
|
|
123
|
+
[`readme-badges.md`](readme-badges.md) and [`cli.md`](cli.md).
|
|
124
|
+
- **Homebrew taps / distribution indexes / Formula drift checks** ->
|
|
125
|
+
[`homebrew.md`](homebrew.md) and [`cli.md`](cli.md).
|
|
118
126
|
- **KFD-1 contract worlds / byte-for-byte release gates** ->
|
|
119
127
|
[`release-passport.md`](release-passport.md#kfd-1-contract-world-release-gate).
|
|
120
128
|
- **KFD-2 public release trust claim audit** ->
|
package/docs/cli.md
CHANGED
|
@@ -64,7 +64,9 @@ Current public import families include:
|
|
|
64
64
|
```js
|
|
65
65
|
import * as buildchain from "@kungfu-tech/buildchain";
|
|
66
66
|
import { createBuildchainLogger } from "@kungfu-tech/buildchain/logging";
|
|
67
|
+
import { checkHomebrewTap } from "@kungfu-tech/buildchain/homebrew";
|
|
67
68
|
import { verifyKfd1ReleaseGate } from "@kungfu-tech/buildchain/kfd-gate";
|
|
69
|
+
import { collectReadmeBadgeFacts } from "@kungfu-tech/buildchain/readme-badges";
|
|
68
70
|
import { verifyReleasePassport } from "@kungfu-tech/buildchain/release-passport";
|
|
69
71
|
import { createReleasePropagationPlan } from "@kungfu-tech/buildchain/release-propagation";
|
|
70
72
|
import contractWorld from "@kungfu-tech/buildchain/site/buildchain-contract.json" with { type: "json" };
|
|
@@ -90,6 +92,8 @@ Supported presets:
|
|
|
90
92
|
validation, observation, contract publication, and downstream propagation
|
|
91
93
|
planning without default mutation. Provider adapters expose built-in command
|
|
92
94
|
plans by default, and only configured `[infra.commands]` hooks can execute.
|
|
95
|
+
- `--type distribution-index` for Homebrew taps and other index repositories
|
|
96
|
+
whose files are projections of upstream release passport evidence.
|
|
93
97
|
- `--type anchored-package` for packages whose version is anchored to an
|
|
94
98
|
explicit upstream release manifest.
|
|
95
99
|
|
|
@@ -244,9 +248,42 @@ version against configured version files and the anchor manifest. The JSON
|
|
|
244
248
|
result is shaped for future `buildchain.libkungfu.dev` fact ingestion.
|
|
245
249
|
|
|
246
250
|
`buildchain release`, `buildchain web-surface`, `buildchain infra-contract`,
|
|
247
|
-
`buildchain publish-source`,
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
`buildchain publish-source`, `buildchain badges`, `buildchain homebrew`, and
|
|
252
|
+
`buildchain build-contract` route to the same implementation used by
|
|
253
|
+
Buildchain's package APIs or GitHub Actions workflows. This keeps local
|
|
254
|
+
inspection and CI behavior on the same implementation path.
|
|
255
|
+
|
|
256
|
+
Generate, check, or update the managed README badge block:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
buildchain badges readme --json
|
|
260
|
+
buildchain badges readme --check
|
|
261
|
+
buildchain badges readme --write
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The `--json` form emits the `kungfu-buildchain-readme-badge-facts` object.
|
|
265
|
+
`--check` fails closed when the README marker block is missing or stale.
|
|
266
|
+
`--write` inserts or replaces only the marked block. KFD passed badges come
|
|
267
|
+
from the repository's own verified release passport; unreleased repositories
|
|
268
|
+
downgrade to explicit local declarations such as `declared`, `aligned`, or
|
|
269
|
+
`planned`. See [`readme-badges.md`](readme-badges.md) for the marker contract
|
|
270
|
+
and `[badges]` configuration.
|
|
271
|
+
|
|
272
|
+
Generate or check Homebrew tap projections from upstream release passports:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
buildchain homebrew update-formula \
|
|
276
|
+
--package buildchain \
|
|
277
|
+
--release-passport https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json \
|
|
278
|
+
--write
|
|
279
|
+
|
|
280
|
+
buildchain homebrew check --json
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`update-formula` writes `Formula/buildchain.rb` and `tap-manifest.json` from
|
|
284
|
+
upstream release passport evidence. `check` fails closed when the Formula,
|
|
285
|
+
manifest, artifact digests, or KFD status drift from the upstream passport. See
|
|
286
|
+
[`homebrew.md`](homebrew.md) for the distribution-index project contract.
|
|
250
287
|
|
|
251
288
|
`buildchain collect github-release` creates a release passport bundle from
|
|
252
289
|
GitHub Release assets or a local asset directory:
|
package/docs/homebrew.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Homebrew Distribution Indexes
|
|
2
|
+
|
|
3
|
+
Buildchain treats a Homebrew tap as a distribution-index project: the tap
|
|
4
|
+
contains Formula or Cask files, but those files are projections of upstream
|
|
5
|
+
release passports. Version, download URLs, SHA-256 digests, KFD status, and
|
|
6
|
+
evidence links come from the upstream product release, not from hand-maintained
|
|
7
|
+
tap prose.
|
|
8
|
+
|
|
9
|
+
## Configuration
|
|
10
|
+
|
|
11
|
+
Use `project.type = "distribution-index"` for tap repositories:
|
|
12
|
+
|
|
13
|
+
```toml
|
|
14
|
+
schema = 1
|
|
15
|
+
|
|
16
|
+
[project]
|
|
17
|
+
type = "distribution-index"
|
|
18
|
+
name = "homebrew-tap"
|
|
19
|
+
|
|
20
|
+
[lifecycle.verify]
|
|
21
|
+
command = "buildchain homebrew check"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The tap manifest is the repository-owned declaration of which upstream releases
|
|
25
|
+
are indexed. Buildchain writes `tap-manifest.json` as a machine-readable
|
|
26
|
+
projection:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"schema": 1,
|
|
31
|
+
"contract": "kungfu-buildchain-homebrew-tap-manifest",
|
|
32
|
+
"kind": "homebrew-tap",
|
|
33
|
+
"entries": [
|
|
34
|
+
{
|
|
35
|
+
"type": "formula",
|
|
36
|
+
"name": "buildchain",
|
|
37
|
+
"path": "Formula/buildchain.rb",
|
|
38
|
+
"upstream": {
|
|
39
|
+
"repository": "kungfu-systems/buildchain",
|
|
40
|
+
"tag": "v2.8.15",
|
|
41
|
+
"releasePassportUrl": "https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json"
|
|
42
|
+
},
|
|
43
|
+
"version": "2.8.15",
|
|
44
|
+
"kfd": {
|
|
45
|
+
"kfd-1": "passed",
|
|
46
|
+
"kfd-2": "passed",
|
|
47
|
+
"kfd-3": "passed"
|
|
48
|
+
},
|
|
49
|
+
"artifacts": [
|
|
50
|
+
{
|
|
51
|
+
"platform": "darwin-arm64",
|
|
52
|
+
"url": "https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain-aarch64-apple-darwin.tar.gz",
|
|
53
|
+
"sha256": "..."
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## CLI
|
|
62
|
+
|
|
63
|
+
Update a formula and manifest from an upstream passport:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
buildchain homebrew update-formula \
|
|
67
|
+
--package buildchain \
|
|
68
|
+
--release-passport https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json \
|
|
69
|
+
--write
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Check that the tap still matches upstream evidence:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
buildchain homebrew check --json
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`check` fails closed when:
|
|
79
|
+
|
|
80
|
+
- the upstream release passport or its sibling evidence does not verify;
|
|
81
|
+
- `Formula/buildchain.rb` drifts from the projected version, URLs, or SHA-256
|
|
82
|
+
digests;
|
|
83
|
+
- `tap-manifest.json` drifts from the projected upstream evidence;
|
|
84
|
+
- the tap claims KFD-1, KFD-2, or KFD-3 passed without a verified upstream
|
|
85
|
+
passport section.
|
|
86
|
+
|
|
87
|
+
## Node API
|
|
88
|
+
|
|
89
|
+
Use the public `@kungfu-tech/buildchain/homebrew` export:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import {
|
|
93
|
+
collectHomebrewTapFacts,
|
|
94
|
+
renderHomebrewFormula,
|
|
95
|
+
checkHomebrewTap,
|
|
96
|
+
updateHomebrewTap,
|
|
97
|
+
} from "@kungfu-tech/buildchain/homebrew";
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The API is the single implementation source. The CLI is a thin wrapper over
|
|
101
|
+
these functions, so CI and local update commands evaluate the same facts.
|
|
102
|
+
|
|
103
|
+
## Trust Model
|
|
104
|
+
|
|
105
|
+
Formula metadata is not source of truth. A tap entry may claim `kfd-1`,
|
|
106
|
+
`kfd-2`, or `kfd-3` passed only when the upstream release passport verifies and
|
|
107
|
+
the corresponding passport section is `status = "passed"`. If verification
|
|
108
|
+
fails, Buildchain downgrades the projected KFD status to `unverified` and
|
|
109
|
+
`buildchain homebrew check` fails.
|
|
110
|
+
|
|
111
|
+
In short: KFD passed in a tap means the upstream release passport passed, not
|
|
112
|
+
that the tap author typed a passing status.
|
|
113
|
+
|
|
114
|
+
This makes Homebrew taps suitable for automated distribution-index CI: the tap
|
|
115
|
+
can move quickly while still proving that every download URL and digest is
|
|
116
|
+
bound to release passport evidence.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# README Badge Blocks
|
|
2
|
+
|
|
3
|
+
Buildchain can generate a managed README badge block from repository-owned
|
|
4
|
+
facts. The README keeps only a projection; the source facts remain in
|
|
5
|
+
`buildchain.toml`, package metadata, workflow files, and the repository's own
|
|
6
|
+
release passport.
|
|
7
|
+
|
|
8
|
+
The managed block is delimited by:
|
|
9
|
+
|
|
10
|
+
```markdown
|
|
11
|
+
<!-- buildchain:badges:start -->
|
|
12
|
+
...
|
|
13
|
+
<!-- buildchain:badges:end -->
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Buildchain owns only that block. Everything outside the markers remains normal
|
|
17
|
+
README content.
|
|
18
|
+
|
|
19
|
+
## Node API
|
|
20
|
+
|
|
21
|
+
Use the public package export:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import {
|
|
25
|
+
collectReadmeBadgeFacts,
|
|
26
|
+
renderReadmeBadgeBlock,
|
|
27
|
+
checkReadmeBadgeBlock,
|
|
28
|
+
updateReadmeBadgeBlock,
|
|
29
|
+
} from "@kungfu-tech/buildchain/readme-badges";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`collectReadmeBadgeFacts({ cwd })` returns a machine-readable object with
|
|
33
|
+
contract `kungfu-buildchain-readme-badge-facts`. It collects repository
|
|
34
|
+
identity, package name/version/license, configured platforms, configured
|
|
35
|
+
workflow status badges, release passport location and verification result, and
|
|
36
|
+
KFD badge state. When present, it also summarizes local KFD claim registry and
|
|
37
|
+
product-mechanism facts from the package-owned site bundle, so downstream
|
|
38
|
+
agents can connect README badges back to Buildchain's KFD/source-of-truth
|
|
39
|
+
surfaces.
|
|
40
|
+
|
|
41
|
+
`renderReadmeBadgeBlock(facts)` renders deterministic Markdown from that facts
|
|
42
|
+
object. `checkReadmeBadgeBlock({ readmeText, facts })` compares the current
|
|
43
|
+
README marker block against the expected block and reports missing or stale
|
|
44
|
+
drift. `updateReadmeBadgeBlock({ readmeText, facts })` inserts or replaces the
|
|
45
|
+
managed block.
|
|
46
|
+
|
|
47
|
+
The Node API is the implementation source. The CLI delegates to it.
|
|
48
|
+
|
|
49
|
+
## CLI
|
|
50
|
+
|
|
51
|
+
Generate facts as JSON:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
buildchain badges readme --json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Fail closed when the README block is missing or stale:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
buildchain badges readme --check
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Insert or replace the block:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
buildchain badges readme --write
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
All commands accept `--cwd <dir>` and `--readme <path>`. Repositories can add
|
|
70
|
+
`buildchain badges readme --check` to CI so badge drift is detected like any
|
|
71
|
+
other generated release-facing surface.
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
The optional `[badges]` table in `buildchain.toml` declares local facts that
|
|
76
|
+
cannot be inferred safely:
|
|
77
|
+
|
|
78
|
+
```toml
|
|
79
|
+
[badges]
|
|
80
|
+
release_passport = "https://github.com/example/project/releases/latest/download/buildchain.release.json"
|
|
81
|
+
kfd_1 = "declared"
|
|
82
|
+
kfd_2 = "planned"
|
|
83
|
+
kfd_3 = "aligned"
|
|
84
|
+
platforms = ["macOS", "Linux", "Windows"]
|
|
85
|
+
workflows = ["verify.yml", "build.yml"]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`release_passport` may be a local path or URL. If omitted, Buildchain tries
|
|
89
|
+
`buildchain.release.json`, then `.buildchain/release-passport/buildchain.release.json`,
|
|
90
|
+
then the repository's latest GitHub Release asset when the GitHub repository
|
|
91
|
+
can be discovered.
|
|
92
|
+
|
|
93
|
+
## KFD Badge Rules
|
|
94
|
+
|
|
95
|
+
KFD passed is evidence-backed. A repository may display `KFD-1 passed`,
|
|
96
|
+
`KFD-2 passed`, or `KFD-3 passed` only when its own release passport verifies
|
|
97
|
+
successfully and the corresponding passport section has `status: "passed"`.
|
|
98
|
+
|
|
99
|
+
When no release passport exists yet, or when the passport cannot be verified,
|
|
100
|
+
Buildchain downgrades each KFD badge to the explicit local declaration such as
|
|
101
|
+
`declared`, `aligned`, or `planned`. A local `passed` declaration is treated as
|
|
102
|
+
`declared`; unknown local states are normalized to a non-passed fallback.
|
|
103
|
+
|
|
104
|
+
Buildchain's own README may link to Buildchain's own release passport. Other
|
|
105
|
+
repositories must not claim Buildchain's KFD status as their own; their badge
|
|
106
|
+
links must point to their own release passport or evidence page.
|
|
107
|
+
|
|
108
|
+
## CI Contract
|
|
109
|
+
|
|
110
|
+
Recommended CI gate:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
buildchain badges readme --check
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The check fails when:
|
|
117
|
+
|
|
118
|
+
- the marker block is missing;
|
|
119
|
+
- generated Markdown differs from repository facts;
|
|
120
|
+
- a previously hand-written KFD passed claim is not backed by the repository's
|
|
121
|
+
verified release passport facts.
|
|
122
|
+
|
|
123
|
+
The machine-readable facts object should be used by downstream site renderers
|
|
124
|
+
or audit tools when Markdown badges are not enough.
|
|
@@ -264,12 +264,32 @@ rollback:
|
|
|
264
264
|
"alias": "sha-abcdef123456",
|
|
265
265
|
"url": "https://sha-abcdef123456.preview.libkungfu.dev",
|
|
266
266
|
"sourcePath": "/",
|
|
267
|
+
"artifactPathPrefix": "",
|
|
268
|
+
"viewerPathPrefix": "/",
|
|
269
|
+
"directoryIndex": "index.html",
|
|
270
|
+
"directoryIndexResolution": true,
|
|
267
271
|
"canonicalUrl": "https://libkungfu.dev",
|
|
268
272
|
"bucket": "libkungfu-dev-preview",
|
|
269
273
|
"distributionId": "E-PREVIEW",
|
|
270
274
|
"originPath": "",
|
|
271
275
|
"objectPrefix": "sha-abcdef123456",
|
|
272
276
|
"manifestKey": ".buildchain/deployments/sha-abcdef123456/hub.json",
|
|
277
|
+
"routing": {
|
|
278
|
+
"contract": "kungfu-buildchain-web-surface-path-prefix-rewrite",
|
|
279
|
+
"viewerPathPrefix": "/",
|
|
280
|
+
"artifactPathPrefix": "",
|
|
281
|
+
"objectPrefix": "sha-abcdef123456",
|
|
282
|
+
"directoryIndex": "index.html",
|
|
283
|
+
"directoryIndexResolution": true
|
|
284
|
+
},
|
|
285
|
+
"smokeUrls": [
|
|
286
|
+
{
|
|
287
|
+
"kind": "root",
|
|
288
|
+
"requestPath": "/",
|
|
289
|
+
"url": "https://sha-abcdef123456.preview.libkungfu.dev/",
|
|
290
|
+
"required": true
|
|
291
|
+
}
|
|
292
|
+
],
|
|
273
293
|
"noindex": true,
|
|
274
294
|
"accessControl": "none"
|
|
275
295
|
}
|
|
@@ -343,6 +363,19 @@ node scripts/web-surface.mjs \
|
|
|
343
363
|
--output .buildchain/web-surface-staging-apply.json
|
|
344
364
|
```
|
|
345
365
|
|
|
366
|
+
For multi-surface sites, each surface host is treated as a root-relative view
|
|
367
|
+
of that surface's artifact path prefix. For example, a `buildchain` surface with
|
|
368
|
+
`path = "/buildchain/"` and preview URL
|
|
369
|
+
`https://buildchain-pr-29.preview.libkungfu.dev` syncs the artifact subtree
|
|
370
|
+
`dist/buildchain/` to the preview object prefix `pr-29/buildchain`. A viewer
|
|
371
|
+
request for `https://buildchain-pr-29.preview.libkungfu.dev/docs/` therefore
|
|
372
|
+
resolves against the artifact's `dist/buildchain/docs/index.html`, not
|
|
373
|
+
`dist/docs/index.html` and not the hub surface root. The deployment manifest
|
|
374
|
+
records this as `routing.contract =
|
|
375
|
+
"kungfu-buildchain-web-surface-path-prefix-rewrite"` with
|
|
376
|
+
`viewerPathPrefix = "/"`, `artifactPathPrefix = "buildchain"`, and
|
|
377
|
+
`directoryIndexResolution = true`.
|
|
378
|
+
|
|
346
379
|
It can also execute a previously saved deploy plan. In that mode Buildchain
|
|
347
380
|
recomputes the local artifact hash before running AWS commands and fails closed
|
|
348
381
|
if the artifact no longer matches the saved plan:
|
|
@@ -414,7 +447,7 @@ The production preflight checks that:
|
|
|
414
447
|
`kfd.libkungfu.dev`;
|
|
415
448
|
- DNS resolves for every surface host.
|
|
416
449
|
|
|
417
|
-
After production apply, the workflow runs:
|
|
450
|
+
After preview, staging, and production apply, the workflow runs:
|
|
418
451
|
|
|
419
452
|
```bash
|
|
420
453
|
node scripts/web-surface.mjs \
|
|
@@ -424,13 +457,18 @@ node scripts/web-surface.mjs \
|
|
|
424
457
|
--output .buildchain/web-surface-production-health.json
|
|
425
458
|
```
|
|
426
459
|
|
|
427
|
-
The health check fetches every surface URL
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
460
|
+
The health check fetches every surface root URL and the nested smoke URLs
|
|
461
|
+
recorded in each surface binding. Nested smoke URLs are derived from the
|
|
462
|
+
artifact files under the surface path prefix, with directory index resolution
|
|
463
|
+
such as `dist/buildchain/docs/index.html` becoming `/docs/` on the buildchain
|
|
464
|
+
preview host. This fails closed when a deploy reports success but a child page
|
|
465
|
+
returns 403 or another unexpected status. Production additionally fails if a
|
|
466
|
+
response is unreachable, returns an unexpected status, or still sends
|
|
467
|
+
`x-robots-tag: noindex`. The health check also verifies that each surface
|
|
468
|
+
binding recorded a deployment manifest pointer. The production release passport
|
|
469
|
+
embeds the deploy plan, apply result, production preflight, and health check so
|
|
470
|
+
a reviewer or agent can audit why the production site changed and whether every
|
|
471
|
+
declared host and nested route was actually covered.
|
|
434
472
|
|
|
435
473
|
## Cleanup Plans
|
|
436
474
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.16-alpha.2",
|
|
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",
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
"./artifact-passport": "./packages/core/artifact-passport.js",
|
|
17
17
|
"./buildchain-contract": "./packages/core/buildchain-contract.js",
|
|
18
18
|
"./diagnostics": "./packages/core/diagnostics.js",
|
|
19
|
+
"./homebrew": "./packages/core/homebrew.js",
|
|
19
20
|
"./issue-reporting": "./packages/core/issue-reporting.js",
|
|
21
|
+
"./readme-badges": "./packages/core/readme-badges.js",
|
|
20
22
|
"./logging": "./packages/core/logging.js",
|
|
21
23
|
"./kfd-gate": "./packages/core/kfd-gate.js",
|
|
22
24
|
"./release-candidate": "./packages/core/release-candidate.js",
|
package/packages/core/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Current shared surfaces:
|
|
|
14
14
|
`@kungfu-tech/buildchain/diagnostics`;
|
|
15
15
|
- release passport creation and verification through
|
|
16
16
|
`@kungfu-tech/buildchain/release-passport`.
|
|
17
|
+
- managed README badge facts and marker blocks through
|
|
18
|
+
`@kungfu-tech/buildchain/readme-badges`.
|
|
17
19
|
|
|
18
20
|
## Toolkit Imports
|
|
19
21
|
|
|
@@ -53,3 +55,13 @@ const { collectRunnerDiagnostics } = await import("@kungfu-tech/buildchain/diagn
|
|
|
53
55
|
Web-surface validation stays in core because both local scripts and GitHub
|
|
54
56
|
Actions need the same fail-closed interpretation of project, channel, deploy,
|
|
55
57
|
retention, and staging security declarations.
|
|
58
|
+
|
|
59
|
+
README badge consumers should import the public subpath and treat Markdown as a
|
|
60
|
+
projection of the returned facts:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import { collectReadmeBadgeFacts, renderReadmeBadgeBlock } from "@kungfu-tech/buildchain/readme-badges";
|
|
64
|
+
|
|
65
|
+
const facts = await collectReadmeBadgeFacts({ cwd: process.cwd() });
|
|
66
|
+
const markdown = renderReadmeBadgeBlock(facts);
|
|
67
|
+
```
|
|
@@ -9,7 +9,7 @@ const RESERVED_LIFECYCLE_KEYS = new Set(["env", "shell"]);
|
|
|
9
9
|
const SUPPORTED_VERSION_FILE_TYPES = new Set(["json", "toml", "regex"]);
|
|
10
10
|
const SUPPORTED_VERSION_STRATEGIES = new Set(["semver", "anchored"]);
|
|
11
11
|
const SUPPORTED_VERSION_NEXT = new Set(["auto", "manual"]);
|
|
12
|
-
const SUPPORTED_PROJECT_TYPES = new Set(["package", "web-surface", "infra-contract"]);
|
|
12
|
+
const SUPPORTED_PROJECT_TYPES = new Set(["package", "web-surface", "infra-contract", "distribution-index"]);
|
|
13
13
|
const SUPPORTED_PUBLISH_MODES = new Set(["publish-final-version", "promote-existing-version"]);
|
|
14
14
|
const SUPPORTED_PUBLISH_AUTH = new Set(["trusted-publishing", "npm-token"]);
|
|
15
15
|
const SUPPORTED_PACKAGE_SET_ORDER = new Set(["as-provided", "platforms-first-main-last"]);
|
|
@@ -237,7 +237,7 @@ function normalizeProjectSection(project) {
|
|
|
237
237
|
assertPlainObject(project, "project");
|
|
238
238
|
const type = assertString(project.type, "project.type");
|
|
239
239
|
if (!SUPPORTED_PROJECT_TYPES.has(type)) {
|
|
240
|
-
throw new Error("project.type must be one of package, web-surface, or
|
|
240
|
+
throw new Error("project.type must be one of package, web-surface, infra-contract, or distribution-index");
|
|
241
241
|
}
|
|
242
242
|
const normalized = { type };
|
|
243
243
|
for (const key of ["name", "site"]) {
|
|
@@ -309,6 +309,9 @@ export function createBuildchainContractWorld({ root = process.cwd(), packageJso
|
|
|
309
309
|
optionalInputs: [
|
|
310
310
|
"validate",
|
|
311
311
|
"lifecycle",
|
|
312
|
+
"badges readme",
|
|
313
|
+
"homebrew update-formula",
|
|
314
|
+
"homebrew check",
|
|
312
315
|
"collect github-release",
|
|
313
316
|
"verify release-passport",
|
|
314
317
|
"release-propagation",
|
|
@@ -316,6 +319,59 @@ export function createBuildchainContractWorld({ root = process.cwd(), packageJso
|
|
|
316
319
|
],
|
|
317
320
|
guarantees: [
|
|
318
321
|
"CLI commands are stable within the major line unless the contract major changes",
|
|
322
|
+
"README badge block checks and writes are generated from machine-readable repository facts",
|
|
323
|
+
],
|
|
324
|
+
}),
|
|
325
|
+
surface(root, {
|
|
326
|
+
id: "homebrew-distribution-index",
|
|
327
|
+
kind: "node-api",
|
|
328
|
+
path: "packages/core/homebrew.js",
|
|
329
|
+
requiredInputs: ["upstream release passport"],
|
|
330
|
+
requiredOutputs: [
|
|
331
|
+
"kungfu-buildchain-homebrew-tap-facts",
|
|
332
|
+
"kungfu-buildchain-homebrew-tap-manifest",
|
|
333
|
+
"Formula/*.rb",
|
|
334
|
+
],
|
|
335
|
+
breakingDefaults: {
|
|
336
|
+
projectType: "distribution-index",
|
|
337
|
+
tapManifest: "tap-manifest.json",
|
|
338
|
+
kfdPassedSource: "verified upstream release passport",
|
|
339
|
+
},
|
|
340
|
+
optionalInputs: [
|
|
341
|
+
"buildchain.toml [project] type=distribution-index",
|
|
342
|
+
"Formula path",
|
|
343
|
+
"manifest path",
|
|
344
|
+
"release passport URL or local path",
|
|
345
|
+
],
|
|
346
|
+
guarantees: [
|
|
347
|
+
"Formula metadata is a deterministic projection of upstream release passport evidence",
|
|
348
|
+
"tap-manifest.json is checked against upstream version, URLs, SHA-256 digests, and KFD status",
|
|
349
|
+
"KFD passed claims fail closed unless the upstream release passport verifies the corresponding section",
|
|
350
|
+
"CLI and JavaScript callers use the same Node API implementation",
|
|
351
|
+
],
|
|
352
|
+
}),
|
|
353
|
+
surface(root, {
|
|
354
|
+
id: "readme-badge-facts",
|
|
355
|
+
kind: "node-api",
|
|
356
|
+
path: "packages/core/readme-badges.js",
|
|
357
|
+
requiredInputs: ["repository checkout"],
|
|
358
|
+
requiredOutputs: ["kungfu-buildchain-readme-badge-facts"],
|
|
359
|
+
breakingDefaults: {
|
|
360
|
+
markerStart: "<!-- buildchain:badges:start -->",
|
|
361
|
+
markerEnd: "<!-- buildchain:badges:end -->",
|
|
362
|
+
kfdPassedSource: "verified repository-owned release passport",
|
|
363
|
+
},
|
|
364
|
+
optionalInputs: [
|
|
365
|
+
"buildchain.toml [badges]",
|
|
366
|
+
"release passport URL or local path",
|
|
367
|
+
"workflow file list",
|
|
368
|
+
"platform declarations",
|
|
369
|
+
],
|
|
370
|
+
guarantees: [
|
|
371
|
+
"README badge Markdown is a deterministic projection of badge facts",
|
|
372
|
+
"KFD passed badges require the repository's own verified release passport section",
|
|
373
|
+
"unreleased repositories downgrade KFD status to explicit non-passed declarations",
|
|
374
|
+
"CLI and JavaScript callers use the same Node API implementation",
|
|
319
375
|
],
|
|
320
376
|
}),
|
|
321
377
|
surface(root, {
|