@kungfu-tech/buildchain 2.12.7-alpha.18 → 2.12.7-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.
Files changed (31) 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 +13 -13
  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 +8 -60
  7. package/dist/site/kfd-upstream-aggregate.json +1 -1
  8. package/dist/site/manual-registry.json +1 -1
  9. package/dist/site/node-api-registry.json +6 -6
  10. package/dist/site/page-registry.json +8 -8
  11. package/dist/site/public-surface-audit.json +9 -71
  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 +5 -5
  15. package/dist/site/workflow-registry.json +6 -71
  16. package/docs/publication-artifacts.md +20 -30
  17. package/docs/publication-authority.md +2 -11
  18. package/docs/shifu-gate-profiles.md +0 -6
  19. package/package.json +1 -1
  20. package/packages/core/buildchain-publication-authority.js +0 -1
  21. package/packages/core/controller-evidence.js +1 -1
  22. package/packages/core/index.js +0 -7
  23. package/packages/core/publication-authority.js +2 -41
  24. package/packages/core/publication-control-plane-audit.js +1 -3
  25. package/scripts/assemble-self-publication-admission.mjs +1 -2
  26. package/scripts/audit-publication-control-plane.mjs +2 -5
  27. package/scripts/check-inventory.mjs +0 -3
  28. package/scripts/workflow-friction-report.mjs +2 -13
  29. package/packages/core/publication-artifact-candidate.js +0 -128
  30. package/scripts/assemble-publication-artifact-admission.mjs +0 -190
  31. 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-15T10:03:44.581Z",
5
- "publishedAt": "2026-07-15T10:03:44.581Z",
4
+ "generatedAt": "2026-07-14T16:40:36.563Z",
5
+ "publishedAt": "2026-07-14T16:40:36.563Z",
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": "1115b3787d74a3781f04f66b69ec7ed83c540b5e",
22
+ "sourceRevision": "31f70f81cbdd542d9473651cf13cd6e8eb33cd74",
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.18",
35
+ "version": "2.12.7-alpha.2",
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-15T10:03:44.581Z",
5
- "publishedAt": "2026-07-15T10:03:44.581Z",
4
+ "generatedAt": "2026-07-14T16:40:36.563Z",
5
+ "publishedAt": "2026-07-14T16:40:36.563Z",
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": "1115b3787d74a3781f04f66b69ec7ed83c540b5e",
22
+ "sourceRevision": "31f70f81cbdd542d9473651cf13cd6e8eb33cd74",
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.18",
40
+ "version": "2.12.7-alpha.2",
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:06ba05f9d8a2685a0896334b6013a97c45b7d71163cf6898e5a6274baf7f0296"
88
+ "digest": "sha256:fc08e6657a1b586b6b8b5618ca4f49dfaa85955687f5bba8e2e69e7513fe6c71"
89
89
  },
90
90
  {
91
91
  "id": "release-candidate",
@@ -215,18 +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
219
  "buildchain-ref",
222
220
  "buildchain-repository",
223
221
  "control-plane-audit-json",
224
222
  "dry-run",
225
- "evidence-controller-artifact",
226
223
  "evidence-manifest-pattern",
227
224
  "evidence-passport-artifact",
228
225
  "evidence-payload-pattern",
229
- "evidence-publication-artifact",
230
226
  "evidence-repository",
231
227
  "evidence-run-id",
232
228
  "evidence-summary-artifact",
@@ -235,15 +231,13 @@
235
231
  "package-name",
236
232
  "product",
237
233
  "publication-target",
238
- "publication-version",
239
234
  "publisher-workflow-path",
240
- "required-status-check",
241
235
  "runner-provenance-json",
242
236
  "source-sha",
243
237
  "target-ref",
244
238
  "used-nonces-json"
245
239
  ],
246
- "inputCount": 28,
240
+ "inputCount": 22,
247
241
  "secrets": [],
248
242
  "secretCount": 0,
249
243
  "outputs": [
@@ -1030,54 +1024,6 @@
1030
1024
  "capabilityGroup": "api-cli-reference",
1031
1025
  "status": "active"
1032
1026
  },
1033
- {
1034
- "id": "paper-release-sealed",
1035
- "path": ".github/workflows/paper-release-sealed.yml",
1036
- "reusable": true,
1037
- "inputs": [
1038
- "artifact-name",
1039
- "artifact-paths",
1040
- "artifact-retention-days",
1041
- "branch-protection-bypass-apps",
1042
- "branch-protection-bypass-teams",
1043
- "branch-protection-bypass-users",
1044
- "buildchain-contract-lock-path",
1045
- "buildchain-ref",
1046
- "buildchain-repository",
1047
- "dry-run",
1048
- "github-release",
1049
- "github-release-notes",
1050
- "github-release-title",
1051
- "package-name",
1052
- "publish-dist-tag",
1053
- "publisher-workflow-path",
1054
- "release-passport-impact-json",
1055
- "release-passport-output-dir",
1056
- "release-passport-product-name",
1057
- "required-status-check",
1058
- "target-ref",
1059
- "target-sha",
1060
- "toolchain-type",
1061
- "verify-command",
1062
- "working-directory"
1063
- ],
1064
- "inputCount": 25,
1065
- "secrets": [
1066
- "BUILDCHAIN_PROMOTION_TOKEN"
1067
- ],
1068
- "secretCount": 1,
1069
- "outputs": [
1070
- "github-release-url",
1071
- "package-name",
1072
- "package-version",
1073
- "public-release-tag",
1074
- "release-passport-path"
1075
- ],
1076
- "outputCount": 5,
1077
- "surface": "repository-workflow",
1078
- "capabilityGroup": "api-cli-reference",
1079
- "status": "active"
1080
- },
1081
1027
  {
1082
1028
  "id": "paper-release",
1083
1029
  "path": ".github/workflows/paper-release.yml",
@@ -1247,11 +1193,7 @@
1247
1193
  "buildchain-ref",
1248
1194
  "buildchain-repository",
1249
1195
  "node-version",
1250
- "package-name",
1251
- "prepare-paper-package",
1252
- "publish-dist-tag",
1253
1196
  "setup-node",
1254
- "target-ref",
1255
1197
  "toolchain-command",
1256
1198
  "toolchain-digest",
1257
1199
  "toolchain-image",
@@ -1259,7 +1201,7 @@
1259
1201
  "verify-command",
1260
1202
  "working-directory"
1261
1203
  ],
1262
- "inputCount": 21,
1204
+ "inputCount": 17,
1263
1205
  "secrets": [],
1264
1206
  "secretCount": 0,
1265
1207
  "outputs": [
@@ -1270,17 +1212,13 @@
1270
1212
  "controller-receipt-digest",
1271
1213
  "controller-receipt-json",
1272
1214
  "controller-receipt-status",
1273
- "package-name",
1274
- "package-version",
1275
1215
  "publication-artifact-name",
1276
1216
  "publication-manifest-json",
1277
1217
  "publication-manifest-path",
1278
1218
  "publication-passport-path",
1279
- "publication-registry-path",
1280
- "publish-dist-tag",
1281
- "runtime-sha"
1219
+ "publication-registry-path"
1282
1220
  ],
1283
- "outputCount": 16,
1221
+ "outputCount": 12,
1284
1222
  "surface": "repository-workflow",
1285
1223
  "capabilityGroup": "reusable-build",
1286
1224
  "status": "active"
@@ -1351,12 +1289,11 @@
1351
1289
  "BUILDCHAIN_ISSUE_APP_ID",
1352
1290
  "BUILDCHAIN_ISSUE_APP_PRIVATE_KEY",
1353
1291
  "BUILDCHAIN_ISSUE_TOKEN",
1354
- "BUILDCHAIN_PROMOTION_TOKEN",
1355
1292
  "buildchain-issue-app-id",
1356
1293
  "buildchain-issue-app-private-key",
1357
1294
  "buildchain-issue-token"
1358
1295
  ],
1359
- "secretCount": 7,
1296
+ "secretCount": 6,
1360
1297
  "outputs": [
1361
1298
  "built-source-sha",
1362
1299
  "controller-plan-artifact",
@@ -1549,11 +1486,9 @@
1549
1486
  "branch-protection-bypass-teams",
1550
1487
  "branch-protection-bypass-users",
1551
1488
  "dry-run",
1552
- "expected-publication-version",
1553
1489
  "generated-ref-update-token",
1554
1490
  "generated-status-check-token",
1555
1491
  "github-release",
1556
- "github-release-artifact-paths",
1557
1492
  "github-release-notes",
1558
1493
  "github-release-title",
1559
1494
  "promote-only-release-candidate",
@@ -1599,7 +1534,7 @@
1599
1534
  "transaction-state-path",
1600
1535
  "verification-command"
1601
1536
  ],
1602
- "inputCount": 54,
1537
+ "inputCount": 52,
1603
1538
  "capabilityGroup": "release-passport-trust",
1604
1539
  "status": "active"
1605
1540
  },
@@ -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
 
@@ -121,15 +121,6 @@ repositories, unknown refs, non-exact source SHAs, and any caller other than
121
121
  `.github/workflows/buildchain-ref-promotion.yml`. Manual apply and external
122
122
  consumer workflows still require their own explicit admission inputs.
123
123
 
124
- Before authority verification, the reusable promotion controller runs the same
125
- release transaction selector in read-only mode. That plan supplies one exact
126
- publication version and tag to the admission verifier, the publish-gate source
127
- lock, and the real promotion action. The verifier rejects a capability for a
128
- different version, and the promotion action rechecks the planned version before
129
- any publish transaction side effect. Release-candidate fixture versions are
130
- artifact evidence only; they never name Buildchain's own source-lock or
131
- publication capability.
132
-
133
124
  Evidence publication is a separate authority class and never grants product
134
125
  publication.
135
126
 
@@ -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.18",
3
+ "version": "2.12.7-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",
@@ -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 &&
@@ -137,7 +137,6 @@ async function main() {
137
137
  isolation: "github-hosted-single-job",
138
138
  });
139
139
  const packageJson = JSON.parse(fs.readFileSync(path.join(runtimeRoot, "package.json"), "utf8"));
140
- const publicationVersion = required("BUILDCHAIN_PUBLICATION_VERSION");
141
140
  const issuedAt = new Date();
142
141
  const admission = createPublicationAdmission({
143
142
  registryDigest: registry.registryDigest,
@@ -155,7 +154,7 @@ async function main() {
155
154
  environment: process.env.BUILDCHAIN_PUBLICATION_ENVIRONMENT || "none",
156
155
  product: process.env.BUILDCHAIN_PUBLICATION_PRODUCT || "Buildchain",
157
156
  target: process.env.BUILDCHAIN_PUBLICATION_TARGET || `npm:${packageJson.name}`,
158
- version: publicationVersion,
157
+ version: process.env.BUILDCHAIN_PUBLICATION_VERSION || packageJson.version,
159
158
  channel: required("BUILDCHAIN_PUBLICATION_CHANNEL"),
160
159
  artifactDigest: artifactSet.manifestSetDigest,
161
160
  nonce: `${required("GITHUB_RUN_ID")}:${required("GITHUB_RUN_ATTEMPT")}:${sourceSha}`,
@@ -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: {
@@ -840,9 +840,6 @@ for (const requiredSnippet of [
840
840
  "publish-source-ref: ${{ steps.publish-gate.outputs.ref }}",
841
841
  "publish-source-sha: ${{ steps.publish-gate.outputs.sha }}",
842
842
  "publish-source-locked: ${{ steps.publish-gate.outputs.locked }}",
843
- "expected-publication-version: ${{ needs.publication-plan.outputs.version }}",
844
- "publication-version: ${{ needs.publication-plan.outputs.version }}",
845
- "name: Plan exact publication version",
846
843
  "DRY_RUN: ${{ inputs.dry-run }}",
847
844
  "if (dryRun) {",
848
845
  "Enforce Buildchain stable release canary gate",
@@ -202,8 +202,6 @@ export async function classifyWorkflowFriction({
202
202
  buildWorkflowName = DEFAULT_BUILD_WORKFLOW_NAME,
203
203
  releaseCandidateOutcome = env("BUILDCHAIN_RC_RESOLVE_OUTCOME"),
204
204
  releaseCandidateDiagnosis = env("BUILDCHAIN_RC_DIAGNOSIS"),
205
- promotionOutcome = env("BUILDCHAIN_PROMOTION_OUTCOME"),
206
- promotionDiagnosis = env("BUILDCHAIN_PROMOTION_DIAGNOSIS"),
207
205
  runUrl = env("BUILDCHAIN_WORKFLOW_RUN_URL"),
208
206
  outputDir = ".buildchain/workflow-friction",
209
207
  fetchImpl = globalThis.fetch,
@@ -258,23 +256,14 @@ export async function classifyWorkflowFriction({
258
256
  if (releaseCandidateOutcome === "failure") {
259
257
  diagnosisParts.push("Promotion reached the post-Verify workflow before required PR-stage RC evidence could be resolved.");
260
258
  }
261
- if (releaseCandidateOutcome === "failure" && releaseCandidateDiagnosis) {
259
+ if (releaseCandidateDiagnosis) {
262
260
  diagnosisParts.push(releaseCandidateDiagnosis);
263
261
  }
264
- if (promotionOutcome === "failure") {
265
- diagnosisParts.push(
266
- promotionDiagnosis
267
- ? `Promotion failed: ${promotionDiagnosis}`
268
- : "Promotion failed after PR-stage release-candidate evidence resolved successfully.",
269
- );
270
- }
271
262
  diagnosisParts.push(...workflowRunDiagnostics);
272
263
  const diagnosis = diagnosisParts.join(" ") || "Buildchain ref promotion failed after Verify succeeded; inspect the classified evidence and keep the fix in Buildchain.";
273
264
  const nextAction = frictionClass === "late-fail-fast"
274
265
  ? "Move the missing/stale RC evidence check earlier or make the promotion workflow consume the exact PR-stage RC passport before any publish side effect."
275
- : ["duplicate-channel-pr", "duplicate-heavy-build"].includes(frictionClass)
276
- ? "Deduplicate the PR/build path or tighten Buildchain workflow gates so the next channel promotion reaches publish exactly once."
277
- : "Fix the concrete promotion failure above, then rerun through the protected channel workflow; do not treat successful RC resolution as the failure diagnosis.";
266
+ : "Deduplicate the PR/build path or tighten Buildchain workflow gates so the next channel promotion reaches publish exactly once.";
278
267
  fs.mkdirSync(outputDir, { recursive: true });
279
268
  const bodyFile = path.join(outputDir, "issue-body.md");
280
269
  const body = buildWorkflowFrictionBody({