@kungfu-tech/buildchain 2.12.7-alpha.21 → 2.12.7-alpha.3

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.
Files changed (33) hide show
  1. package/actions/promote-buildchain-ref/README.md +1 -5
  2. package/dist/site/buildchain-contract.json +23 -48
  3. package/dist/site/buildchain-site.json +16 -16
  4. package/dist/site/capability-registry.json +1 -1
  5. package/dist/site/controller-registry.json +3 -23
  6. package/dist/site/kfd-claims.json +9 -63
  7. package/dist/site/kfd-upstream-aggregate.json +1 -1
  8. package/dist/site/manual-registry.json +2 -2
  9. package/dist/site/node-api-registry.json +6 -6
  10. package/dist/site/page-registry.json +10 -10
  11. package/dist/site/public-surface-audit.json +9 -72
  12. package/dist/site/publication-authority-registry.json +1 -25
  13. package/dist/site/publication-registry.json +4 -4
  14. package/dist/site/site-manifest.json +6 -6
  15. package/dist/site/workflow-registry.json +6 -72
  16. package/docs/publication-artifacts.md +20 -30
  17. package/docs/publication-authority.md +9 -21
  18. package/docs/release-candidate.md +0 -19
  19. package/docs/shifu-gate-profiles.md +0 -6
  20. package/package.json +1 -1
  21. package/packages/core/buildchain-publication-authority.js +0 -1
  22. package/packages/core/controller-evidence.js +1 -1
  23. package/packages/core/index.js +0 -7
  24. package/packages/core/publication-authority.js +2 -41
  25. package/packages/core/publication-control-plane-audit.js +1 -3
  26. package/scripts/assemble-self-publication-admission.mjs +9 -19
  27. package/scripts/audit-publication-control-plane.mjs +2 -5
  28. package/scripts/check-inventory.mjs +0 -3
  29. package/scripts/locked-source-checkout.mjs +2 -22
  30. package/scripts/workflow-friction-report.mjs +2 -13
  31. package/packages/core/publication-artifact-candidate.js +0 -128
  32. package/scripts/assemble-publication-artifact-admission.mjs +0 -190
  33. package/scripts/publication-artifact-candidate.mjs +0 -122
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-publication-release-registry",
4
- "generatedAt": "2026-07-15T12:26:57.218Z",
5
- "publishedAt": "2026-07-15T12:26:57.218Z",
4
+ "generatedAt": "2026-07-14T16:58:46.295Z",
5
+ "publishedAt": "2026-07-14T16:58:46.295Z",
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": "97973413b7ba208df42a3ead28d2b80067a3ecc8",
22
+ "sourceRevision": "a80e367748620f3c1cb16a08d81c854131ed6d89",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "package": {
34
34
  "name": "@kungfu-tech/buildchain",
35
- "version": "2.12.7-alpha.21",
35
+ "version": "2.12.7-alpha.3",
36
36
  "versionSource": "package.json#version"
37
37
  },
38
38
  "sourceKind": "package-site-bundle",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-manifest",
4
- "generatedAt": "2026-07-15T12:26:57.218Z",
5
- "publishedAt": "2026-07-15T12:26:57.218Z",
4
+ "generatedAt": "2026-07-14T16:58:46.295Z",
5
+ "publishedAt": "2026-07-14T16:58:46.295Z",
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": "97973413b7ba208df42a3ead28d2b80067a3ecc8",
22
+ "sourceRevision": "a80e367748620f3c1cb16a08d81c854131ed6d89",
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.12.7-alpha.21",
40
+ "version": "2.12.7-alpha.3",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "entrypoint": "buildchain-site.json",
@@ -85,7 +85,7 @@
85
85
  "path": "docs/publication-authority.md",
86
86
  "plane": "verify",
87
87
  "exists": true,
88
- "digest": "sha256:05bc22c7e5885e591bc121fc43f588e5d49ccf0a8de6a642811c1d0d03dcee1e"
88
+ "digest": "sha256:fc08e6657a1b586b6b8b5618ca4f49dfaa85955687f5bba8e2e69e7513fe6c71"
89
89
  },
90
90
  {
91
91
  "id": "release-candidate",
@@ -93,7 +93,7 @@
93
93
  "path": "docs/release-candidate.md",
94
94
  "plane": "verify",
95
95
  "exists": true,
96
- "digest": "sha256:6a20c6e3e483327d5ccbe70271f7fb4752731bd0523eeddb96f27b2b6ebf1cf8"
96
+ "digest": "sha256:841d6f3281ba6dfe80527e4f149807bdbd05d41f9e94afe1c446fcd6d29e307c"
97
97
  },
98
98
  {
99
99
  "id": "release-propagation",
@@ -215,19 +215,14 @@
215
215
  "reusable": true,
216
216
  "inputs": [
217
217
  "admission-json",
218
- "authority-workflow-path",
219
218
  "auto-admission",
220
- "auto-admission-kind",
221
- "auto-no-gate",
222
219
  "buildchain-ref",
223
220
  "buildchain-repository",
224
221
  "control-plane-audit-json",
225
222
  "dry-run",
226
- "evidence-controller-artifact",
227
223
  "evidence-manifest-pattern",
228
224
  "evidence-passport-artifact",
229
225
  "evidence-payload-pattern",
230
- "evidence-publication-artifact",
231
226
  "evidence-repository",
232
227
  "evidence-run-id",
233
228
  "evidence-summary-artifact",
@@ -236,15 +231,13 @@
236
231
  "package-name",
237
232
  "product",
238
233
  "publication-target",
239
- "publication-version",
240
234
  "publisher-workflow-path",
241
- "required-status-check",
242
235
  "runner-provenance-json",
243
236
  "source-sha",
244
237
  "target-ref",
245
238
  "used-nonces-json"
246
239
  ],
247
- "inputCount": 29,
240
+ "inputCount": 22,
248
241
  "secrets": [],
249
242
  "secretCount": 0,
250
243
  "outputs": [
@@ -1031,54 +1024,6 @@
1031
1024
  "capabilityGroup": "api-cli-reference",
1032
1025
  "status": "active"
1033
1026
  },
1034
- {
1035
- "id": "paper-release-sealed",
1036
- "path": ".github/workflows/paper-release-sealed.yml",
1037
- "reusable": true,
1038
- "inputs": [
1039
- "artifact-name",
1040
- "artifact-paths",
1041
- "artifact-retention-days",
1042
- "branch-protection-bypass-apps",
1043
- "branch-protection-bypass-teams",
1044
- "branch-protection-bypass-users",
1045
- "buildchain-contract-lock-path",
1046
- "buildchain-ref",
1047
- "buildchain-repository",
1048
- "dry-run",
1049
- "github-release",
1050
- "github-release-notes",
1051
- "github-release-title",
1052
- "package-name",
1053
- "publish-dist-tag",
1054
- "publisher-workflow-path",
1055
- "release-passport-impact-json",
1056
- "release-passport-output-dir",
1057
- "release-passport-product-name",
1058
- "required-status-check",
1059
- "target-ref",
1060
- "target-sha",
1061
- "toolchain-type",
1062
- "verify-command",
1063
- "working-directory"
1064
- ],
1065
- "inputCount": 25,
1066
- "secrets": [
1067
- "BUILDCHAIN_PROMOTION_TOKEN"
1068
- ],
1069
- "secretCount": 1,
1070
- "outputs": [
1071
- "github-release-url",
1072
- "package-name",
1073
- "package-version",
1074
- "public-release-tag",
1075
- "release-passport-path"
1076
- ],
1077
- "outputCount": 5,
1078
- "surface": "repository-workflow",
1079
- "capabilityGroup": "api-cli-reference",
1080
- "status": "active"
1081
- },
1082
1027
  {
1083
1028
  "id": "paper-release",
1084
1029
  "path": ".github/workflows/paper-release.yml",
@@ -1248,11 +1193,7 @@
1248
1193
  "buildchain-ref",
1249
1194
  "buildchain-repository",
1250
1195
  "node-version",
1251
- "package-name",
1252
- "prepare-paper-package",
1253
- "publish-dist-tag",
1254
1196
  "setup-node",
1255
- "target-ref",
1256
1197
  "toolchain-command",
1257
1198
  "toolchain-digest",
1258
1199
  "toolchain-image",
@@ -1260,7 +1201,7 @@
1260
1201
  "verify-command",
1261
1202
  "working-directory"
1262
1203
  ],
1263
- "inputCount": 21,
1204
+ "inputCount": 17,
1264
1205
  "secrets": [],
1265
1206
  "secretCount": 0,
1266
1207
  "outputs": [
@@ -1271,17 +1212,13 @@
1271
1212
  "controller-receipt-digest",
1272
1213
  "controller-receipt-json",
1273
1214
  "controller-receipt-status",
1274
- "package-name",
1275
- "package-version",
1276
1215
  "publication-artifact-name",
1277
1216
  "publication-manifest-json",
1278
1217
  "publication-manifest-path",
1279
1218
  "publication-passport-path",
1280
- "publication-registry-path",
1281
- "publish-dist-tag",
1282
- "runtime-sha"
1219
+ "publication-registry-path"
1283
1220
  ],
1284
- "outputCount": 16,
1221
+ "outputCount": 12,
1285
1222
  "surface": "repository-workflow",
1286
1223
  "capabilityGroup": "reusable-build",
1287
1224
  "status": "active"
@@ -1310,7 +1247,6 @@
1310
1247
  "package-manager",
1311
1248
  "publication-admission-json",
1312
1249
  "publication-auto-admission",
1313
- "publication-auto-no-gate",
1314
1250
  "publication-control-plane-audit-json",
1315
1251
  "publication-expected-json",
1316
1252
  "publication-gate-aggregate-json",
@@ -1348,7 +1284,7 @@
1348
1284
  "target-sha",
1349
1285
  "trusted-publishing"
1350
1286
  ],
1351
- "inputCount": 56,
1287
+ "inputCount": 55,
1352
1288
  "secrets": [
1353
1289
  "BUILDCHAIN_ISSUE_APP_ID",
1354
1290
  "BUILDCHAIN_ISSUE_APP_PRIVATE_KEY",
@@ -1551,11 +1487,9 @@
1551
1487
  "branch-protection-bypass-teams",
1552
1488
  "branch-protection-bypass-users",
1553
1489
  "dry-run",
1554
- "expected-publication-version",
1555
1490
  "generated-ref-update-token",
1556
1491
  "generated-status-check-token",
1557
1492
  "github-release",
1558
- "github-release-artifact-paths",
1559
1493
  "github-release-notes",
1560
1494
  "github-release-title",
1561
1495
  "promote-only-release-candidate",
@@ -1601,7 +1535,7 @@
1601
1535
  "transaction-state-path",
1602
1536
  "verification-command"
1603
1537
  ],
1604
- "inputCount": 54,
1538
+ "inputCount": 52,
1605
1539
  "capabilityGroup": "release-passport-trust",
1606
1540
  "status": "active"
1607
1541
  },
@@ -182,42 +182,40 @@ on:
182
182
 
183
183
  jobs:
184
184
  paper-release:
185
- uses: kungfu-systems/buildchain/.github/workflows/paper-release-sealed.yml@v2
185
+ uses: kungfu-systems/buildchain/.github/workflows/paper-release.yml@v2
186
186
  permissions:
187
- actions: read
188
187
  checks: write
189
188
  contents: write
190
189
  id-token: write
191
190
  issues: write
192
191
  with:
193
192
  buildchain-ref: ${{ inputs.buildchain-ref || '' }}
194
- publisher-workflow-path: .github/workflows/paper-release.yml
193
+ publication-admission-json: ${{ needs.authority.outputs.admission-json }}
194
+ publication-runner-provenance-json: ${{ needs.authority.outputs.runner-provenance-json }}
195
+ publication-control-plane-audit-json: ${{ needs.authority.outputs.control-plane-audit-json }}
196
+ publication-expected-json: ${{ needs.authority.outputs.expected-json }}
195
197
  toolchain-type: config
196
198
  verify-command: make check
197
- artifact-paths: _build/paper-name.pdf
198
199
  buildchain-contract-lock-path: .buildchain/contract-lock.json
199
- secrets:
200
- BUILDCHAIN_PROMOTION_TOKEN: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}
201
200
  ```
202
201
 
203
- The sealed preset does not use a long-lived token for npm publication. It may
204
- accept an optional `BUILDCHAIN_PROMOTION_TOKEN` only for machine-generated
205
- version-state updates on protected channel branches; npm publication remains
206
- bound to GitHub OIDC trusted publishing. The preset builds and packages the
207
- paper in a read-only job, then a credential-free authority job downloads that
208
- exact candidate, audits the external control plane, and seals a capability over
209
- the source tree, Buildchain runtime, controller receipt, PDF, and npm package
210
- bytes. Only the final job receives write and OIDC permissions; it downloads the
211
- admitted candidate, recomputes the capability binding, and publishes without
212
- executing consumer build commands. npm binds the OIDC identity to the consumer
213
- workflow named by `publisher-workflow-path`.
202
+ The publication job does not accept a long-lived promotion token. The caller
203
+ must first produce a fresh sealed admission, runner provenance, external
204
+ control-plane audit, and exact expected bindings. The credential-free verifier
205
+ job checks those receipts; only then can the publication job use its short-lived
206
+ `github.token` and caller-bound OIDC trusted publisher identity. npm binds that
207
+ identity to the consumer workflow filename; an npm Environment restriction is
208
+ optional and must be represented explicitly when configured. The workflow fails
209
+ before the publication build when the target branch protection cannot be read.
214
210
 
215
211
  The preset:
216
212
 
217
- - resolves the floating Buildchain runtime once and binds the exact SHA into the
218
- publication candidate and authority capability;
213
+ - resolves the same floating Buildchain runtime and contract lock as the build
214
+ workflow;
215
+ - verifies that the declared promotion authority can read the protected target
216
+ channel before starting the publication build;
219
217
  - builds the PDF through the declared pinned LaTeX Docker toolchain or custom
220
- command in a read-only job;
218
+ command;
221
219
  - verifies the paper repository;
222
220
  - writes the publication manifest, publication passport, optional archive
223
221
  registry, and source bundle;
@@ -228,22 +226,14 @@ The preset:
228
226
  - creates a `publish-gate/<alpha|release>/.../<version>` source lock for the
229
227
  channel commit and requires `promote-buildchain-ref` to verify that lock
230
228
  before any publish side effect;
231
- - verifies the complete candidate again after authority and publishes the
232
- package through npm Trusted Publishing without rebuilding it;
229
+ - publishes the package through npm Trusted Publishing;
233
230
  - writes Buildchain release/passport evidence; and
234
- - creates or updates the exact-version GitHub Release by default, uploading
235
- every file declared by `publication.primary_artifact` and
236
- `publication.artifact_paths` alongside the release evidence.
231
+ - creates or updates the exact-version GitHub Release by default.
237
232
 
238
233
  Consumers can opt out of the GitHub Release with `github-release: false`, but
239
234
  the default is on so downstream release propagation can observe
240
235
  `release.published` without hand-written `gh release` steps.
241
236
 
242
- Declared publication artifacts are resolved from the generated publication
243
- manifest rather than repeated in consumer workflow YAML. Publication fails
244
- before upload if a declared artifact is missing or if its basename would
245
- collide with another GitHub Release asset.
246
-
247
237
  For npm Trusted Publishing, register the consumer workflow file that calls this
248
238
  preset, for example `.github/workflows/paper-release.yml`, against the declared
249
239
  package in npm. The trusted publisher is the consumer repository and workflow
@@ -8,11 +8,11 @@ confidence: high
8
8
  sensitivity: public
9
9
  evidence_grade: B
10
10
  review_state: unreviewed
11
- last_reviewed: 2026-07-15
11
+ last_reviewed: 2026-07-14
12
12
  ai_provenance:
13
13
  model_family: GPT-5
14
14
  product: Codex
15
- generated_at: 2026-07-15
15
+ generated_at: 2026-07-14
16
16
  limits: Live provider configuration must be re-audited; no credential values are represented.
17
17
  ---
18
18
 
@@ -109,29 +109,17 @@ artifacts. The denial explicitly records that npm Trusted Publishing and OIDC
109
109
  were not evaluated, so downstream diagnostics cannot misclassify an admission
110
110
  assembly failure as an npm authentication failure.
111
111
 
112
- An explicitly opted-in managed `workflow_run` promotion lane may assemble those
113
- inputs from evidence owned by its caller repository. It downloads the exact prior RC passport,
112
+ Buildchain's own `workflow_run` promotion lane may assemble those inputs only
113
+ for `kungfu-systems/buildchain`. It downloads the exact prior RC passport,
114
114
  summary, referenced controller receipt, manifests, and product payloads; proves
115
115
  the admitted channel commit has the same Git tree as the RC; performs the live
116
116
  read-only control-plane audit; records the GitHub-hosted job as ephemeral runner
117
- provenance; and consumes either a caller-supplied Gate aggregate or an explicit
118
- caller no-Gate decision. The
117
+ provenance; and creates an explicit Buildchain-owned no-Gate decision. The
119
118
  independent verifier then recomputes every receipt and payload digest exactly as
120
- it does for externally supplied admission. Automatic assembly keeps Buildchain
121
- as the canonical authority repository, requires evidence to belong to the
122
- caller, binds a repository-local publisher workflow, and rejects unknown refs,
123
- non-exact source SHAs, package/target mismatches, or an undeclared Gate policy.
124
- Manual apply and consumers that do not opt in still require their own explicit
125
- admission inputs.
126
-
127
- Before authority verification, the reusable promotion controller runs the same
128
- release transaction selector in read-only mode. That plan supplies one exact
129
- publication version and tag to the admission verifier, the publish-gate source
130
- lock, and the real promotion action. The verifier rejects a capability for a
131
- different version, and the promotion action rechecks the planned version before
132
- any publish transaction side effect. Release-candidate fixture versions are
133
- artifact evidence only; they never name Buildchain's own source-lock or
134
- publication capability.
119
+ it does for externally supplied admission. The self-assembly mode rejects other
120
+ repositories, unknown refs, non-exact source SHAs, and any caller other than
121
+ `.github/workflows/buildchain-ref-promotion.yml`. Manual apply and external
122
+ consumer workflows still require their own explicit admission inputs.
135
123
 
136
124
  Evidence publication is a separate authority class and never grants product
137
125
  publication.
@@ -116,22 +116,3 @@ KFD-1 source/artifact contract surfaces, audits KFD-2 public release claims, and
116
116
  compares KFD-3 declared shipped public surfaces with artifact-exposed public
117
117
  surfaces. The release passport records the results under `kfd-1`, `kfd-2`, and
118
118
  the KFD-provided `kfd-3` section.
119
-
120
- Managed consumers may also ask the promotion wrapper to assemble sealed
121
- publication evidence from the exact release candidate instead of producing
122
- short-lived admission JSON in repository-specific workflow code:
123
-
124
- ```yaml
125
- publication-auto-admission: true
126
- publication-auto-no-gate: true
127
- publication-publisher-workflow-path: .github/workflows/buildchain-ref-promotion.yml
128
- publication-product: Example Product
129
- publication-target: npm:@example/product
130
- publication-package-name: "@example/product"
131
- ```
132
-
133
- `publication-auto-no-gate` is an explicit consumer decision, not a default. A
134
- consumer with a Shifu Gate registry supplies `publication-gate-aggregate-json`
135
- instead. Buildchain still requires caller-owned RC evidence, an exact authority
136
- runtime and source SHA, a repository-local publisher workflow, matching npm
137
- target/package identity, and a qualifying control-plane audit.
@@ -78,12 +78,6 @@ Every matrix job checks out the exact source SHA planned by Buildchain, invokes
78
78
  then invokes `shifu gate receipt validate`. Buildchain uploads the original
79
79
  receipt and validation result even when the run fails.
80
80
 
81
- Before invoking the project-owned command, the workflow adds the runner
82
- account's `~/.local/bin` directory to `PATH` on Windows, Linux, and macOS. This
83
- keeps user-scoped tools such as `uv` available to strict Shifu cache profiles
84
- without assuming an administrator-managed system installation. The consumer or
85
- runner owner remains responsible for provisioning the declared tools.
86
-
87
81
  The fixed `Gate profile / aggregate` job fails closed for missing receipts,
88
82
  invalid or stale Shifu validation, dirty or mismatched source SHA, registry or
89
83
  plan drift, missing required results, required failures/skips, or gate action
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "2.12.7-alpha.21",
3
+ "version": "2.12.7-alpha.3",
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",
@@ -27,7 +27,6 @@ const DESCRIPTORS = Object.freeze([
27
27
  [".github/workflows/buildchain-stable-candidate-patrol.yml", "governance-write"],
28
28
  [".github/workflows/dev-pr-auto-merge.yml", "governance-write"],
29
29
  [".github/workflows/npm-publish.yml", "dry-run-only"],
30
- [".github/workflows/paper-release-sealed.yml", "product-publication", true, ["npm-publish", "github-release"], "trusted-publishing", "none", "fixed", "caller-bound"],
31
30
  [".github/workflows/paper-release.yml", "product-publication", true, ["npm-publish", "github-release"], "trusted-publishing", "none", "fixed", "caller-bound"],
32
31
  [".github/workflows/patrol-daily.yml", "governance-write"],
33
32
  [".github/workflows/patrol-monthly.yml", "governance-write"],
@@ -303,7 +303,7 @@ function normalizeEvidence(entries = []) {
303
303
  function receiptStatus(plan, stages) {
304
304
  if (stages.some((stage) => stage.status === "failed")) return "failed";
305
305
  if (stages.length > 0 && stages.every((stage) => stage.status === "skipped")) return "skipped";
306
- if (stages.some((stage) => stage.status === "cancelled" || (stage.required && stage.status === "missing"))) return "partial";
306
+ if (stages.some((stage) => stage.status === "cancelled" || stage.status === "missing")) return "partial";
307
307
  const required = new Set(plan.expected.stages.filter((stage) => stage.required).map((stage) => stage.id));
308
308
  if (stages.filter((stage) => required.has(stage.id)).every((stage) => stage.status === "passed")) return "passed";
309
309
  return "partial";
@@ -153,13 +153,6 @@ export {
153
153
  verifyPublicationAdmission,
154
154
  } from "./publication-authority.js";
155
155
 
156
- export {
157
- PUBLICATION_ARTIFACT_CANDIDATE_CONTRACT,
158
- createPublicationArtifactCandidate,
159
- publicationArtifactCandidateDigest,
160
- resolvePublicationCandidateFile,
161
- } from "./publication-artifact-candidate.js";
162
-
163
156
  export {
164
157
  buildchainPublicationAuthorityDescriptors,
165
158
  createBuildchainPublicationAuthorityRegistry,
@@ -1,7 +1,6 @@
1
1
  import crypto from "node:crypto";
2
2
 
3
3
  import { validateControllerReceipt } from "./controller-evidence.js";
4
- import { createPublicationArtifactCandidate } from "./publication-artifact-candidate.js";
5
4
  import { sha256Json, validateReleaseCandidatePassport } from "./release-candidate.js";
6
5
 
7
6
  export const PUBLICATION_AUTHORITY_REGISTRY_CONTRACT =
@@ -382,7 +381,6 @@ export function createPublicationArtifactManifestSet({
382
381
  }
383
382
 
384
383
  function validateGateAggregate(gateAggregate, { admission, passport }) {
385
- const passportSourceSha = passport.source?.headSha || passport.source?.sha;
386
384
  if (gateAggregate?.contract === "buildchain.shifu-gate-aggregate/v1") {
387
385
  const { digest, ...payload } = gateAggregate;
388
386
  const actualDigest = sha256Json(payload);
@@ -392,7 +390,7 @@ function validateGateAggregate(gateAggregate, { admission, passport }) {
392
390
  if (gateAggregate.status !== "pass" || gateAggregate.qualifying !== true) {
393
391
  throw new Error("gate aggregate is not qualifying");
394
392
  }
395
- if (![admission.sourceSha, passportSourceSha].includes(gateAggregate.sourceSha)) {
393
+ if (![admission.sourceSha, passport.source?.headSha].includes(gateAggregate.sourceSha)) {
396
394
  throw new Error("gate aggregate source SHA mismatch");
397
395
  }
398
396
  normalizeDigest(gateAggregate.registry?.digest, "gateAggregate.registry.digest");
@@ -410,7 +408,7 @@ function validateGateAggregate(gateAggregate, { admission, passport }) {
410
408
  if (gateAggregate.required !== false) {
411
409
  throw new Error("a required Gate policy must supply a qualifying Shifu Gate aggregate");
412
410
  }
413
- if (![admission.sourceSha, passportSourceSha].includes(gateAggregate.sourceSha)) {
411
+ if (![admission.sourceSha, passport.source?.headSha].includes(gateAggregate.sourceSha)) {
414
412
  throw new Error("publication Gate decision source SHA mismatch");
415
413
  }
416
414
  const normalizedPolicy = {
@@ -430,43 +428,6 @@ function validatePublicationEvidence(publicationEvidence, admission) {
430
428
  if (!publicationEvidence || typeof publicationEvidence !== "object" || Array.isArray(publicationEvidence)) {
431
429
  throw new Error("independent publication evidence is required");
432
430
  }
433
- if (publicationEvidence.publicationArtifactCandidate) {
434
- const candidate = createPublicationArtifactCandidate(publicationEvidence.publicationArtifactCandidate);
435
- const passport = publicationEvidence.publicationArtifactCandidate.passport;
436
- const controllerReceipt = publicationEvidence.publicationArtifactCandidate.controllerReceipt;
437
- const controllerReceiptDigest = normalizeDigest(controllerReceipt.digest, "controllerReceipt.digest");
438
- if (controllerReceiptDigest !== normalizeDigest(admission.controllerReceiptDigest, "admission.controllerReceiptDigest")) {
439
- throw new Error("controller receipt evidence binding mismatch");
440
- }
441
- const contractDigest = normalizeDigest(controllerReceipt.runtime?.contractDigest, "controllerReceipt.runtime.contractDigest");
442
- if (contractDigest !== normalizeDigest(admission.contractDigest, "admission.contractDigest")) {
443
- throw new Error("runtime contract evidence binding mismatch");
444
- }
445
- const gate = validateGateAggregate(publicationEvidence.gateAggregate, { admission, passport });
446
- if (gate.gateAggregateDigest !== normalizeDigest(admission.gateAggregateDigest, "admission.gateAggregateDigest")) {
447
- throw new Error("Gate aggregate evidence binding mismatch");
448
- }
449
- if (gate.policyDigest !== normalizeDigest(admission.policyDigest, "admission.policyDigest")) {
450
- throw new Error("Gate policy evidence binding mismatch");
451
- }
452
- if (candidate.candidateDigest !== normalizeDigest(admission.artifactDigest, "admission.artifactDigest")) {
453
- throw new Error("publication artifact candidate evidence binding mismatch");
454
- }
455
- return {
456
- sourceTreeSha: candidate.sourceTreeSha,
457
- controllerReceiptDigest,
458
- contractDigest,
459
- gateAggregateDigest: gate.gateAggregateDigest,
460
- policyDigest: gate.policyDigest,
461
- artifactDigest: candidate.candidateDigest,
462
- evidenceDigest: publicationAuthorityDigest({
463
- sourceTreeSha: candidate.sourceTreeSha,
464
- controllerReceiptDigest,
465
- gateAggregateDigest: gate.gateAggregateDigest,
466
- artifactDigest: candidate.candidateDigest,
467
- }),
468
- };
469
- }
470
431
  const passport = publicationEvidence.releaseCandidatePassport;
471
432
  const buildSummary = publicationEvidence.buildSummary;
472
433
  const passportValidation = validateReleaseCandidatePassport({
@@ -16,7 +16,6 @@ export function evaluatePublicationControlPlaneSnapshot({
16
16
  branch,
17
17
  packageName,
18
18
  publisherMode = "npm-trusted-publisher",
19
- requiredStatusCheck = "check",
20
19
  snapshot,
21
20
  observedAt,
22
21
  expiresAt,
@@ -73,8 +72,7 @@ export function evaluatePublicationControlPlaneSnapshot({
73
72
  branchPolicy.protected === true &&
74
73
  branchPolicy.enforcementLevel === "everyone" &&
75
74
  Array.isArray(branchPolicy.requiredStatusChecks) &&
76
- branchPolicy.requiredStatusCheck === requiredStatusCheck &&
77
- branchPolicy.requiredStatusChecks.includes(requiredStatusCheck) &&
75
+ branchPolicy.requiredStatusChecks.includes("check") &&
78
76
  branchPolicy.requiredCheckPassed === true &&
79
77
  branchPolicy.sourceSha === branchPolicy.headSha &&
80
78
  branchPolicy.mergedPullRequest === true &&
@@ -115,22 +115,13 @@ async function main() {
115
115
  manifests,
116
116
  payloads: manifests.map((manifest) => payloadFor(manifest, path.join(evidenceRoot, "payloads"))),
117
117
  });
118
- const suppliedGateAggregate = String(process.env.BUILDCHAIN_GATE_AGGREGATE_JSON || "").trim();
119
- let gateAggregate;
120
- if (suppliedGateAggregate) {
121
- gateAggregate = JSON.parse(suppliedGateAggregate);
122
- } else {
123
- if (process.env.BUILDCHAIN_ALLOW_NO_GATE !== "true") {
124
- throw new Error("managed release-candidate admission requires a Gate aggregate or explicit no-Gate decision");
125
- }
126
- gateAggregate = createPublicationGateDecision({
127
- sourceSha,
128
- profile: process.env.BUILDCHAIN_GATE_PROFILE || "managed-release-candidate-no-gate",
129
- required: false,
130
- rationale: process.env.BUILDCHAIN_GATE_RATIONALE || "The consumer explicitly declared no Shifu Gate registry for this publication transaction.",
131
- policy: { scope: "managed-release-candidate", repository },
132
- });
133
- }
118
+ const gateAggregate = createPublicationGateDecision({
119
+ sourceSha,
120
+ profile: process.env.BUILDCHAIN_GATE_PROFILE || "buildchain-self-publication",
121
+ required: false,
122
+ rationale: process.env.BUILDCHAIN_GATE_RATIONALE || "Buildchain self-publication has no consumer-owned Shifu Gate registry.",
123
+ policy: { scope: "buildchain-self-publication", repository },
124
+ });
134
125
  const runnerProvenance = createRunnerProvenance({
135
126
  runnerClass: "ephemeral",
136
127
  os: required("RUNNER_OS"),
@@ -146,7 +137,6 @@ async function main() {
146
137
  isolation: "github-hosted-single-job",
147
138
  });
148
139
  const packageJson = JSON.parse(fs.readFileSync(path.join(runtimeRoot, "package.json"), "utf8"));
149
- const publicationVersion = required("BUILDCHAIN_PUBLICATION_VERSION");
150
140
  const issuedAt = new Date();
151
141
  const admission = createPublicationAdmission({
152
142
  registryDigest: registry.registryDigest,
@@ -164,7 +154,7 @@ async function main() {
164
154
  environment: process.env.BUILDCHAIN_PUBLICATION_ENVIRONMENT || "none",
165
155
  product: process.env.BUILDCHAIN_PUBLICATION_PRODUCT || "Buildchain",
166
156
  target: process.env.BUILDCHAIN_PUBLICATION_TARGET || `npm:${packageJson.name}`,
167
- version: publicationVersion,
157
+ version: process.env.BUILDCHAIN_PUBLICATION_VERSION || packageJson.version,
168
158
  channel: required("BUILDCHAIN_PUBLICATION_CHANNEL"),
169
159
  artifactDigest: artifactSet.manifestSetDigest,
170
160
  nonce: `${required("GITHUB_RUN_ID")}:${required("GITHUB_RUN_ATTEMPT")}:${sourceSha}`,
@@ -187,6 +177,6 @@ async function main() {
187
177
  }
188
178
 
189
179
  main().catch((error) => {
190
- console.error(`assemble release-candidate admission: ${error.message}`);
180
+ console.error(`assemble self publication admission: ${error.message}`);
191
181
  process.exitCode = 1;
192
182
  });
@@ -191,7 +191,6 @@ function main() {
191
191
  const workflowPath = flag("workflow", ".github/workflows/release-candidate-promote.yml");
192
192
  const workflowRef = flag("workflow-ref");
193
193
  const publisherWorkflowPath = flag("publisher-workflow", workflowPath);
194
- const requiredStatusCheck = flag("required-status-check", "check");
195
194
  const jobId = flag("job", "promote");
196
195
  const environment = flag("environment", "none");
197
196
  const providerEnvironment = environment === "none" ? "" : environment;
@@ -281,16 +280,15 @@ function main() {
281
280
  const checkRuns = githubJson(`repos/${repository}/commits/${sourceSha}/check-runs?per_page=100`, "source check runs");
282
281
  const requiredStatusCheckPolicy = branchState.protection?.required_status_checks || {};
283
282
  const requiredStatusChecks = requiredStatusCheckPolicy.contexts || [];
284
- const requiredCheckSource = (requiredStatusCheckPolicy.checks || []).find((entry) => entry.context === requiredStatusCheck);
283
+ const requiredCheckSource = (requiredStatusCheckPolicy.checks || []).find((entry) => entry.context === "check");
285
284
  branchPolicy = {
286
285
  ref: branch,
287
286
  policyMode: "provider-enforced-transaction",
288
287
  protected: branchState.protected === true,
289
288
  enforcementLevel: branchState.protection?.required_status_checks?.enforcement_level || "",
290
289
  requiredStatusChecks,
291
- requiredStatusCheck,
292
290
  requiredCheckPassed: (checkRuns.check_runs || []).some((entry) =>
293
- entry.name === requiredStatusCheck &&
291
+ entry.name === "check" &&
294
292
  entry.conclusion === "success" &&
295
293
  (!requiredCheckSource?.app_id || entry.app?.id === requiredCheckSource.app_id)
296
294
  ),
@@ -352,7 +350,6 @@ function main() {
352
350
  branch,
353
351
  packageName,
354
352
  publisherMode,
355
- requiredStatusCheck,
356
353
  observedAt: observedAt.toISOString(),
357
354
  expiresAt: expiresAt.toISOString(),
358
355
  snapshot: {