@kungfu-tech/buildchain 2.12.7-alpha.9 → 2.12.8-alpha.0

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.
@@ -336,7 +336,11 @@ Missing required artifacts can be published on the next run. Conflicting
336
336
  refs, digests, or declared provenance put the transaction into
337
337
  `repair_required`; `abandoned` and
338
338
  `failed_permanently` also fail closed unless `publish-transaction-override` is
339
- set for a controlled repair.
339
+ set for a controlled repair. The same override may replace a stale transaction
340
+ only when its version, exact tag, target ref, and channel are unchanged, the
341
+ transaction is not complete, and it contains no published artifacts or
342
+ evidence. This lets a newly admitted source retry a previously failed paper
343
+ publication without weakening already-published facts.
340
344
 
341
345
  In strict buildchain promotion, ref movement is also gated by the old ABV
342
346
  governance semantics:
@@ -4,7 +4,7 @@
4
4
  "product": {
5
5
  "name": "Buildchain",
6
6
  "package": "@kungfu-tech/buildchain",
7
- "version": "2.12.7-alpha.9",
7
+ "version": "2.12.8-alpha.0",
8
8
  "repository": "https://github.com/kungfu-systems/buildchain"
9
9
  },
10
10
  "majorLine": "v2",
@@ -50,7 +50,7 @@
50
50
  "retryable GitHub fallback fetches use a bounded attempt budget before exact source SHA and tree verification"
51
51
  ],
52
52
  "breakingDigest": "sha256:a6a35370d6b0d0f46e1b2712dcc01961fe53c2febde95409a27a485c10a36650",
53
- "auditDigest": "sha256:4dc810c734e3b597297932839d3919219b93c69a985fc1b8ecc91a08299b940e"
53
+ "auditDigest": "sha256:d468a640a96539be038335ca4ec2d1800e263cad553d8ee790f268a9e8dfc981"
54
54
  },
55
55
  {
56
56
  "contractVersion": 1,
@@ -159,7 +159,7 @@
159
159
  "GitHub Release passport and evidence publication is delegated to promote-buildchain-ref after the semver release transaction completes"
160
160
  ],
161
161
  "breakingDigest": "sha256:6dbae32ce3d7aab3be6957065105af574794581847b7637314dad45f5349c919",
162
- "auditDigest": "sha256:10c3132362feab7e8e3f612eedc2e62b9b90ff0ed2fcf8445ce75caef55c26d5"
162
+ "auditDigest": "sha256:3de1fbbaad4c5b09cf958bed1aeba4fd9a3e101baa96076088c9c4a91c2d9784"
163
163
  },
164
164
  {
165
165
  "contractVersion": 1,
@@ -269,7 +269,7 @@
269
269
  "semver GitHub Releases are created or updated only after transaction completion, with prerelease/latest metadata derived from the public release tag"
270
270
  ],
271
271
  "breakingDigest": "sha256:a59f0910e6df842e7699139472e5dd69ac2fdd7f7213bf2cb346d1d622556874",
272
- "auditDigest": "sha256:0a6b261a43f59477497d99f840e83b11a2cfa6545a3d89c9952f47d7ebed33dc"
272
+ "auditDigest": "sha256:2ee7b15a8f2e04ecb798d315c99c29dbb7ad857b87256f8f09a2cb4c024e7cf6"
273
273
  },
274
274
  {
275
275
  "contractVersion": 1,
@@ -527,7 +527,7 @@
527
527
  "manual entries carry source file digests so downstream sites and agents can detect stale hand-written documentation"
528
528
  ],
529
529
  "breakingDigest": "sha256:7d0d2819e3a3e72989d9c57b5efe9d0bc0a79bc0f2c82a0c7b9d6c5a211a91f2",
530
- "auditDigest": "sha256:653df5708fa73f074129b3bf1e047f7f204f42e4521e2b0d7521618f01f9f345"
530
+ "auditDigest": "sha256:147a919feefa45c601f1e1fbf00a2d57bb0343294303adac2ea1f196a453ca4b"
531
531
  },
532
532
  {
533
533
  "contractVersion": 1,
@@ -549,7 +549,7 @@
549
549
  "agents can discover supported Node APIs without importing internal file paths"
550
550
  ],
551
551
  "breakingDigest": "sha256:48f925608d3e2131d90936b07dc2a30341204cae3e6e785c0f77d61ad755c945",
552
- "auditDigest": "sha256:6cb094e42fb35ae6a3b166fbe179a4663f019737cd82bad6279ffaf690110737"
552
+ "auditDigest": "sha256:c8026ded876e5eb3fb4e709747768f95328a80edc36fd148a0929287605b09f3"
553
553
  },
554
554
  {
555
555
  "contractVersion": 1,
@@ -600,7 +600,7 @@
600
600
  "controllerDescriptor": {
601
601
  "contract": "buildchain.controller-descriptor/v1",
602
602
  "digest": "sha256:373723a73d188194d389dee04c394d3b79cb0c016a370f2f5d0f60979a02ed48",
603
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
603
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
604
604
  "inputClassifications": {
605
605
  "buildchain-ref": {
606
606
  "classification": "included",
@@ -746,7 +746,7 @@
746
746
  "controllerDescriptor": {
747
747
  "contract": "buildchain.controller-descriptor/v1",
748
748
  "digest": "sha256:ce2ada5daf86cbe6e58327c190fdfe07510952cc8820cf445eb4342daae4da18",
749
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
749
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
750
750
  "inputClassifications": {
751
751
  "BUILDCHAIN_ARTIFACT_RELAY_S3_DOWNLOAD_ROLE_ARN": {
752
752
  "classification": "redacted",
@@ -1001,7 +1001,7 @@
1001
1001
  "missing receipts are non-qualifying and must not be represented as a successful controller run"
1002
1002
  ],
1003
1003
  "breakingDigest": "sha256:e264a79f9f399038c2fcfd21e4168c68c2e1485ee5c651c02242a02b622ac2be",
1004
- "auditDigest": "sha256:4dc810c734e3b597297932839d3919219b93c69a985fc1b8ecc91a08299b940e"
1004
+ "auditDigest": "sha256:d468a640a96539be038335ca4ec2d1800e263cad553d8ee790f268a9e8dfc981"
1005
1005
  },
1006
1006
  {
1007
1007
  "contractVersion": 1,
@@ -1107,7 +1107,7 @@
1107
1107
  "controllerDescriptor": {
1108
1108
  "contract": "buildchain.controller-descriptor/v1",
1109
1109
  "digest": "sha256:0ed17d03e410ca1b7726422716522a5e9096eee7badb197401291d53198518ea",
1110
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
1110
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
1111
1111
  "inputClassifications": {
1112
1112
  "BUILDCHAIN_ARTIFACT_RELAY_S3_DOWNLOAD_ROLE_ARN": {
1113
1113
  "classification": "redacted",
@@ -1433,7 +1433,7 @@
1433
1433
  "controllerDescriptor": {
1434
1434
  "contract": "buildchain.controller-descriptor/v1",
1435
1435
  "digest": "sha256:29569f4b754595792a16742d1c4c63838b54601674a2cb6c96261a72c962dece",
1436
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
1436
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
1437
1437
  "inputClassifications": {
1438
1438
  "artifact-name": {
1439
1439
  "classification": "included",
@@ -1603,7 +1603,7 @@
1603
1603
  "controllerDescriptor": {
1604
1604
  "contract": "buildchain.controller-descriptor/v1",
1605
1605
  "digest": "sha256:f08c4970f33c059f8e0b43110f0063172fb1015ac914bdb0c8e9646692fb9f06",
1606
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
1606
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
1607
1607
  "inputClassifications": {
1608
1608
  "artifact-path": {
1609
1609
  "classification": "digest-only",
@@ -1835,7 +1835,7 @@
1835
1835
  "controllerDescriptor": {
1836
1836
  "contract": "buildchain.controller-descriptor/v1",
1837
1837
  "digest": "sha256:6b132790b9798e8a5dfbe095701d8e024c160a08bc7c4bd477ee79feef7a9cfd",
1838
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
1838
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
1839
1839
  "inputClassifications": {
1840
1840
  "artifact-name": {
1841
1841
  "classification": "included",
@@ -1930,7 +1930,7 @@
1930
1930
  "missing receipts are non-qualifying and must not be represented as a successful controller run"
1931
1931
  ],
1932
1932
  "breakingDigest": "sha256:3f76502666069c2727d23efcfdb08fb80f89ced1955a69e29f11525ae88aca1d",
1933
- "auditDigest": "sha256:53dfff0c1fbe8b8a06a7536d4f1dee30829db35c266d2b180c8c3ce3f3678b84"
1933
+ "auditDigest": "sha256:f83405748e500d31a237240438f7f410c1bb2b4ef39ab7323131fa54f38c1a59"
1934
1934
  },
1935
1935
  {
1936
1936
  "contractVersion": 1,
@@ -2016,7 +2016,7 @@
2016
2016
  "controllerDescriptor": {
2017
2017
  "contract": "buildchain.controller-descriptor/v1",
2018
2018
  "digest": "sha256:0613ea545fe2d630f34e665c8e6fe99df3f5333d75051a7176e9cf991e494f59",
2019
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
2019
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
2020
2020
  "inputClassifications": {
2021
2021
  "artifact-name": {
2022
2022
  "classification": "included",
@@ -2246,6 +2246,7 @@
2246
2246
  "package-manager",
2247
2247
  "publication-admission-json",
2248
2248
  "publication-auto-admission",
2249
+ "publication-auto-no-gate",
2249
2250
  "publication-control-plane-audit-json",
2250
2251
  "publication-expected-json",
2251
2252
  "publication-gate-aggregate-json",
@@ -2285,8 +2286,8 @@
2285
2286
  ],
2286
2287
  "controllerDescriptor": {
2287
2288
  "contract": "buildchain.controller-descriptor/v1",
2288
- "digest": "sha256:c2f1fd6e984606b077b27bb243b66077162c2c4be03f99c0d8f917bf7bf4d0d1",
2289
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
2289
+ "digest": "sha256:c5dfeb63bbe3507e3c58f74e2a5792e6558002e3aafab6453cc8b8837db2a729",
2290
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
2290
2291
  "inputClassifications": {
2291
2292
  "BUILDCHAIN_ISSUE_APP_ID": {
2292
2293
  "classification": "redacted",
@@ -2392,6 +2393,10 @@
2392
2393
  "classification": "included",
2393
2394
  "source": "workflow-call-input"
2394
2395
  },
2396
+ "publication-auto-no-gate": {
2397
+ "classification": "included",
2398
+ "source": "workflow-call-input"
2399
+ },
2395
2400
  "publication-control-plane-audit-json": {
2396
2401
  "classification": "digest-only",
2397
2402
  "source": "workflow-call-input"
@@ -2545,7 +2550,7 @@
2545
2550
  "missing receipts are non-qualifying and must not be represented as a successful controller run"
2546
2551
  ],
2547
2552
  "breakingDigest": "sha256:46238f8fc3c20924decc57ecad142a462fc4739c6bc21409d5cd2457fc1c3cdd",
2548
- "auditDigest": "sha256:10c3132362feab7e8e3f612eedc2e62b9b90ff0ed2fcf8445ce75caef55c26d5"
2553
+ "auditDigest": "sha256:3de1fbbaad4c5b09cf958bed1aeba4fd9a3e101baa96076088c9c4a91c2d9784"
2549
2554
  },
2550
2555
  {
2551
2556
  "contractVersion": 1,
@@ -2603,7 +2608,7 @@
2603
2608
  "controllerDescriptor": {
2604
2609
  "contract": "buildchain.controller-descriptor/v1",
2605
2610
  "digest": "sha256:9b9f9a2320c4349903d72ee46e329211b5538ed5ebebaa93559df4eafb835997",
2606
- "registryDigest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05",
2611
+ "registryDigest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04",
2607
2612
  "inputClassifications": {
2608
2613
  "buildchain-ref": {
2609
2614
  "classification": "included",
@@ -2674,5 +2679,5 @@
2674
2679
  }
2675
2680
  ],
2676
2681
  "compatibilityDigest": "sha256:af162b86ab4506e9b5f1d3c59b41f3fd57fbad79ff4d749a7f12ff16460517f8",
2677
- "contractDigest": "sha256:a773ef118ff98b52ff14a78b0bcc7efbda77d5e5e7a552a31fe6791a4c7d4d76"
2682
+ "contractDigest": "sha256:ba8515f9e3d74cacb6a7689ab49e21deed5116182ee53357e666c04fe7fa1ca1"
2678
2683
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-bundle",
4
- "generatedAt": "2026-07-15T01:57:21.646Z",
5
- "publishedAt": "2026-07-15T01:57:21.646Z",
4
+ "generatedAt": "2026-07-15T14:09:00.322Z",
5
+ "publishedAt": "2026-07-15T14:09:00.322Z",
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": "eb671ea63ee94e0dc91adfa6e8f722e5acc5af45",
22
+ "sourceRevision": "42c34f932c8572f8c55f41ded39b7fb597e15947",
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.9",
40
+ "version": "2.12.8-alpha.0",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "source": {
@@ -179,7 +179,7 @@
179
179
  ],
180
180
  "maturity": "stable",
181
181
  "sourcePath": "actions/promote-buildchain-ref/README.md",
182
- "digest": "sha256:0a1794dde5d99af7d505df1ab2ef5c6189fe560faa614f675856bab602813bbf",
182
+ "digest": "sha256:6eb0f59b3323daf80d065310d3188cf5dc8a69039080fba7009cc68515a1331a",
183
183
  "headings": [
184
184
  {
185
185
  "level": 1,
@@ -197,7 +197,7 @@
197
197
  "anchor": "publish-transactions"
198
198
  }
199
199
  ],
200
- "markdown": "# promote-buildchain-ref\n\nInternal buildchain action for promoting verified buildchain release-line and\ncompatibility refs from buildchain release channels:\n\n- `alpha/v2/v2.0` creates or reuses the next exact prerelease tag such as\n `v2.0.1-alpha.0`, writes that version into package version state, points the\n alpha and dev channel branches at the version commit, then promotes\n `v2.0-alpha` and, when this is the highest published alpha minor, `v2-alpha`;\n- `release/v2/v2.0` creates or reuses the next exact release tag such as\n `v2.0.0`, writes that version into package version state, points the release\n channel branch and release tags at the release commit, then prepares a second\n source commit for the next exact prerelease tag such as `v2.0.1-alpha.0` and\n points the alpha/dev channel branches plus `v2.0-alpha` at that prerelease\n commit, and moves `v2-alpha` only if no higher v2 minor has published an alpha;\n- `publish-gate/major` accepts a reviewed PR from a production release line such\n as `release/v2/v2.0`, writes the next major production version such as\n `v3.0.0`, points `publish-gate/major`, `release/v3/v3.0`, `v3.0`, and `v3`\n at that release commit, then prepares `v3.0.1-alpha.0` for\n `alpha/v3/v3.0`, `dev/v3/v3.0`, `v3.0-alpha`, and `v3-alpha`. The older `major-gate`\n branch name is a compatibility alias only.\n\nThe release branch name defines the minor line. For example,\n`release/v2/v2.1` creates `v2.1.N`, promotes `v2.1`, and promotes `v2` only\nwhen the next minor tag such as `v2.2` does not already exist.\n\nThe action updates version state in `lerna.json`, root `package.json`, and\nworkspace package manifests discovered from package manager metadata\n(`package.json` workspaces, `lerna.json` packages, or `pnpm-workspace.yaml`).\nPackage manager detection is adaptive (`pnpm`, `npm`, or `yarn`) and is recorded\nin logs.\n\nRepositories can also provide `buildchain.toml` to declare version-state files\nand `lifecycle.verify`. TOML-configured version files take precedence over\npackage-manager discovery and can target JSON, TOML, or regex-based files. The\nversion commit itself is written through the GitHub Git Data API so the ref\ngraph is the durable source of truth. Repositories without any supported version\nstate degrade to ref-only promotion only when strict version state is disabled.\n\nJSON and TOML version entries whose declared key already matches the requested\nversion are treated as semantic no-ops. TOML changes use a parser-verified\nlossless key edit, so repository formatting is preserved and formatter-only\nrelease-preparation commits are not created. If a unique lossless edit cannot\nbe proven, promotion fails closed instead of rewriting the full TOML document.\n\n## Dry Run\n\nUse `dry-run: \"true\"` or the CLI `buildchain release --dry-run` before merging a\nchannel PR when you need to understand what Buildchain would do. This dry-run is\nat the Buildchain release-line level. It explains:\n\n- the legal source branch for the target channel;\n- exact release or alpha tags that would be created or reused;\n- floating tags and channel branches that would move;\n- version-state files and verification lifecycle that would apply;\n- branch protection, PR lineage, and release-from-alpha checks;\n- publish transaction behavior when `lifecycle.publish` or\n `publish-transaction` is enabled.\n\nIt does not move refs, move tags, write package files, run publish commands, or\npublish npm packages. The GitHub action dry-run still calls GitHub APIs to\nresolve the current target SHA and concrete pending ref updates, but every\nwrite is reported as a dry-run update.\n\nRepositories whose package version is anchored to an explicitly selected\nupstream release can opt into manual next-anchor behavior:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n```\n\nIn this mode, the action validates the configured version files and anchor\nmanifest through the repository's verify lifecycle, but it does not rewrite the\npackage version to match the Buildchain release tag. After a production\nrelease, it sets `next-anchor-required=true` and does not auto-create the next\nalpha branch or tag. The repository must create the next upstream anchor line\nexplicitly, then run the normal channel promotion flow for that line.\n\nWhen branch protection requires pull requests, generated version-state commits\nstill run through promotion automation first. The action updates\nBuildchain-managed channel protection before generated bookkeeping, adds the\nauthenticated promotion token user or app to the bypass allowlist, creates the\nconfigured required check on the exact generated version-state commit, then\ntries to apply that commit directly. If GitHub still rejects release\nfinalization bookkeeping, Buildchain creates or reuses a same-repository\n`buildchain/version-state/*` PR based on the current target channel head and\nreturns `finalization-needed=true`; a later idempotent promotion run can resume\nfrom the durable transaction state. Strict alpha promotion still fails with a\nconfiguration diagnostic instead of opening a post-publish human PR. Reusable\nwrapper callers should allow `checks: write` so the generated check is owned by\nGitHub Actions and matches the managed branch protection rule.\n\nStable promotion also protects concurrent development work. The reusable\nwrapper checks out the exact current `dev/vN/vN.M` head as a reconciliation\nworkspace. If next-alpha bookkeeping cannot fast-forward that branch, the\naction reruns the declared version-state generation and verification from that\ndev tree, creates a two-parent reconciliation commit from the regenerated\nfiles, and fails closed if the checkout moved before the mutation boundary.\nThis prevents generated projections from an older release tree from replacing\ncapabilities that reached dev while the release was in progress.\n\nFor Buildchain-owned automation, callers may pass\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`. The action still configures managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches with one\nrequired approving review, strict GitHub Actions checks, admin enforcement,\nconversation resolution, no force pushes, and no deletions; the bypass\nallowance only lets the named automation identity apply generated version-state\nor channel bookkeeping without a second human review after the reviewed channel\nPR has already merged. Direct action calls automatically include the current\npromotion token's authenticated user or app when GitHub exposes it; explicit\ninputs are supplemental allowlist entries for less discoverable release\nauthorities.\n\n## Publish Transactions\n\nPromotion can also own external publish side effects. Enable this only from a\ntrusted channel workflow:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n generated-ref-update-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ github.sha }}\n target-ref: release/v2/v2.0\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n publish-required-artifacts-json: >-\n [\n {\"kind\":\"npm\",\"name\":\"@kungfu-tech/buildchain\",\"ref\":\"2.0.0\",\"digest\":\"sha256:...\"}\n ]\n```\n\nFor anchored/manual package repositories that build through the reusable\nworkflow, keep the publish entrypoint on the `publish-gate/*` source-lock\ncontract:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: release/v22/v22.22\n require-publish-source-lock: \"true\"\n publish-source-ref: ${{ needs.build.outputs.publish-source-ref }}\n publish-source-sha: ${{ needs.build.outputs.publish-source-sha }}\n publish-source-locked: ${{ needs.build.outputs.publish-source-locked }}\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n```\n\n`target-ref` remains the channel promotion target that must point at `sha`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. Direct `alpha/*` or `release/*` channel refs are\nnot valid publish source locks when `require-publish-source-lock` is enabled,\nand a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.\nThe reusable promote workflow serializes non-dry-run promotion intents per\nrepository and re-reads `target-ref` before checkout, dependency installation,\nrelease-candidate resolution, or publish-gate writes. If a queued intent asks\nfor an older SHA after the protected channel has advanced, the workflow records\nthe requested/current SHA pair, verifies that the current target is ahead of\nthe requested commit, and exits successfully as a superseded no-op. Diverged,\nbehind, or unreadable comparisons still fail closed.\nAfter queued-intent revalidation, the reusable workflow runs the canonical\nrelease-candidate resolver in metadata-only mode before installing candidate\ndependencies or starting the full promotion job. The full job resolves and\ndownloads the evidence again before any publish-gate or publication mutation.\nThis preserves the final exact-evidence trust check while making missing or\nstale PR-stage evidence fail early.\nThe action repeats that check at its mutation boundary for governed promotion\ncalls, closing the race between workflow preflight and action start. Direct\nnon-governed calls and dry-runs keep the strict target mismatch error so local\ndiagnostics cannot silently reinterpret a stale request.\nExpected manual dry-run failures remain visible in the workflow result and do\nnot create automated workflow-friction issues; issue reporting is reserved for\nnon-dry-run promotion failures.\nThe reusable build workflow performs the cheaper channel-ref preflight earlier:\nafter source-lock resolution and before the build matrix, it requires the target\nchannel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point\nat the locked `publish-source-sha`. If not, maintainers should merge the source\ncommit through the channel PR first.\n\nFor promote-only release candidates, attach the PR-stage reusable build evidence\nand fail before publish-gate side effects if it no longer matches:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nThe action validates repository, channel, source identity, platform matrix, and\nthe aggregate build-summary hash before it writes version state, opens\nrelease-state, runs publish transaction logic, or moves tags/branches. Source\nidentity accepts the exact source SHA, the PR merge ref SHA, or the promoted\nchannel HEAD's Git tree SHA matching the passport tree hash. If validation\nfails, run or attach the verified channel PR build first instead of promoting a\nstale or unproven artifact set.\n\nWhen enabled, the action creates or resumes a release transaction keyed by\nrepository, version, source SHA, and target ref. It persists that transaction to\na machine-managed branch under `buildchain/release-state/<version>`, with\n`state.json` and, once available, `evidence.json`. Fresh GitHub runners read\nthat durable ref before running publish, so reruns do not depend on a previous\nrunner's local `.buildchain` directory.\n\nThe action runs `lifecycle.publish` from `buildchain.toml` or the explicit\n`publish-command` input, then validates publish evidence before exact tags and\nfloating refs move. If durable state persistence fails, the action fails closed\nbefore publish or public ref finalization.\n\n`publish-mode` defaults to `publish-final-version`, the token-free path for\nnormal npm Trusted Publishing. Same-version alpha-to-latest recovery must be\ndeclared as `publish-mode: promote-existing-version` and\n`publish-auth: npm-token`; Buildchain runs `npm whoami` before it creates\nrelease-state or moves any `npm dist-tag`. The Trusted Publishing mode is not\nallowed to perform `npm dist-tag add`.\n\nBuildchain itself uses this path for npm. Its `lifecycle.publish` runs\n`node scripts/npm-publish-transaction.mjs`, which publishes\n`@kungfu-tech/buildchain` through npm Trusted Publishing and writes npm\nartifact evidence into the transaction before release refs move. The separate\n`.github/workflows/npm-publish.yml` workflow is dry-run only.\n\nPublish lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION\nBUILDCHAIN_CHANNEL\nBUILDCHAIN_SOURCE_SHA\nBUILDCHAIN_TARGET_REF\nBUILDCHAIN_RELEASE_STATE\nBUILDCHAIN_EVIDENCE_DIR\nBUILDCHAIN_RELEASE_SHA\nBUILDCHAIN_RELEASE_MATERIAL_SHA\nBUILDCHAIN_PUBLISH_TOOLING_SHA\nBUILDCHAIN_PUBLISH_EVIDENCE\nBUILDCHAIN_REQUIRED_ARTIFACTS\n```\n\n`BUILDCHAIN_REQUIRED_ARTIFACTS` is the normalized requirement array after the\naction resolves a missing artifact `ref` to `BUILDCHAIN_VERSION`, or expands an\noptional `ref_template` containing exactly one `{version}`, and binds any\ndeclared provenance to the current release coordinate. Template expansion\nhappens after exact version selection; ambiguous or unsupported templates fail\nbefore `lifecycle.publish`. Requirement descriptors may omit `digest`; final\npublish evidence may not.\n\nThe action outputs `transaction-id`, `transaction-state`,\n`transaction-exact-tag`, `public-release-tag`, `transaction-release-sha`,\n`transaction-state-ref`, `transaction-state-sha`, `transaction-state-path`,\n`publish-evidence-path`, and `release-passport-path`, `release-passport-output-dir`,\n`release-passport-state-sha`, and `finalization-needed`.\n`transaction-state-ref` is the durable recovery location.\n`release-passport-state-sha` is the durable ref commit after the generated\n`release-passport/*` files have been uploaded into that recovery ref.\n`finalization-needed=true` means publish evidence is valid, but protected branch\nor ref finalization needs a later idempotent promotion run. For release\nfinalization, Buildchain may create a same-repository generated version-state\nPR when GitHub rejects the direct protected ref update; that PR is Buildchain\nbookkeeping, not a consumer-authored release change.\nSet `github-release: \"true\"` when the semver promotion should also publish the\npublic GitHub Release. After the release transaction reaches `complete` and\n`finalization-needed` is false, the action creates or updates the GitHub Release\nfor `public-release-tag`, applies deterministic semver metadata\n(`prerelease=true` and `make_latest=false` for prerelease tags, latest for stable\ntags), and uploads the publish evidence file plus generated release passport\nassets. For anchored/manual package releases, `public-release-tag` is derived\nfrom the published package version, while `transaction-exact-tag` remains the\ninternal Buildchain transaction ref for recovery and audit. If the transaction is\nnot complete yet, the action defers GitHub Release publication to the next\nidempotent promotion run.\n\nAfter a publish transaction reaches `complete`, the action generates the unified\n`buildchain-release-passport` in `.buildchain/release-passport` by default and\npersists those files under `release-passport/` in the durable release-state ref.\nSet `release-passport-product-name` to record the consumer product name, for\nexample `Libnode`, instead of the default `Buildchain`.\nSet `release-passport-kfd-1-witness-jsons` to newline-separated KFD-1\ncontract-world witness JSON paths when released artifacts must prove\nbyte-for-byte KFD contract surfaces. Buildchain imports the KFD metadata from\n`@kungfu-tech/kfd`, freezes the witness, verifies artifact bytes, and writes the\nresult under the KFD-provided `kfd-1` passport section.\nSet `release-passport-kfd-2-claim-jsons` to newline-separated KFD-2 public\nrelease trust claim JSON paths when a release makes additional human/agent\nvisible claims. Buildchain requires each public claim to bind declared sources,\nmachine-readable evidence, hashes, artifact coordinates, verification results,\naudit boundary, responsibility state, and residual risk. Unbound claims fail\npassport verification; prose-only claims downgrade the KFD-2 audit.\nSet `release-passport-kfd-3-prebuild-witness-jsons` to newline-separated KFD-3\ncollaboration-interface pre-build witness paths, then provide artifact-side\nevidence with `release-passport-kfd-3-artifact-witness-jsons` or a\nproduct-owned `release-passport-kfd-3-artifact-verify-command` such as\n`kungfu agent verify --json`. Buildchain compares declared shipped public\nsurfaces with artifact-exposed public surfaces and writes the result under the\nKFD-provided `kfd-3` passport section.\nBuildchain's own release workflow sets `release-passport-buildchain-self-kfd:\n\"true\"`. In that mode the action generates Buildchain-owned KFD-1/2/3 witnesses\ninside the final version-state workspace, after the release transaction has\nmaterialized generated files such as `package.json` and `dist/site/*`. This\nkeeps self-hosted KFD witness hashes bound to the exact published package\ninstead of to a pre-promotion checkout.\nWhen present, the passport includes the aggregate build summary, platform\nartifact manifests, npm publish evidence, dist-tag promotion evidence, the\nrelease-state ref, trusted publishing metadata, and the Buildchain transaction\nresult. After the first passport upload, Buildchain backfills the durable\nrelease-state SHA into `buildchain.release.json` and persists the passport\nagain, so the consumer-side passport is a complete audit entrypoint. Set\n`release-passport: \"false\"` only for a controlled recovery run that must skip\npassport generation.\n\nFinalization recovery is anchored to the durable transaction, not to a single\nworkflow run SHA. After generated version-state bookkeeping is applied, the\ncurrent channel head can be the generated version-state commit or a historical\nmerge commit that contains or corresponds to the recorded `release_material_sha`;\nit does not have to equal the original `source_sha` or the transaction\n`release_sha`. Reruns accept exact tags that already point at the transaction\nrelease/material SHA or the finalized channel head, and continue moving any\nmissing floating tags or dev/alpha refs before marking the transaction\n`complete`.\n\nNormal reruns accept already-published artifacts only when evidence matches.\nMissing required artifacts can be published on the next run. Conflicting\nrefs, digests, or declared provenance put the transaction into\n`repair_required`; `abandoned` and\n`failed_permanently` also fail closed unless `publish-transaction-override` is\nset for a controlled repair.\n\nIn strict buildchain promotion, ref movement is also gated by the old ABV\ngovernance semantics:\n\n- when detailed target branch protection is readable, it must enforce\n protection for administrators and require approving PR review plus the strict\n `check` job from the `Verify` workflow; when GitHub withholds that\n administration endpoint from the workflow token, the exact transaction must\n instead prove a protected current head, same-repository merged PR,\n independent approval, and the required successful `check` from its configured\n GitHub App;\n- post-publish channel reconciliation reuses an already qualifying\n provider-enforced policy when the workflow token cannot read or rewrite the\n administrative protection document, and fails closed if the public branch\n summary no longer carries the required check for everyone;\n- alpha promotion must come from a merged same-repository PR\n `dev/vN/vN.M -> alpha/vN/vN.M`, or from a strict same-line\n `publish-gate/alpha/vN/vN.M/<version> -> alpha/vN/vN.M` source-lock PR;\n- release promotion must come from a merged same-repository PR\n `alpha/vN/vN.M -> release/vN/vN.M`, or from a strict same-line\n `publish-gate/release/vN/vN.M/<version> -> release/vN/vN.M` source-lock PR;\n- major promotion must come from a merged same-repository PR\n `release/vN/vN.M -> publish-gate/major`;\n- release promotion must have an exact alpha tag for the same patch line, and\n the release source tree must match that alpha tag tree, so release does not\n introduce new code after alpha;\n- anchored/manual release promotion may differ from that alpha tree only in\n declared `version.files` and the configured anchor manifest, and only when the\n checked-out release material has passed `lifecycle.verify` or the explicit\n `verification-command`;\n- generated release and next-alpha version-state trees can be verified locally\n with either the `verification-command` input or `buildchain.toml`\n `lifecycle.verify` before any tags or channel refs move.\n\nThe promotion workflow should use `BUILDCHAIN_PROMOTION_TOKEN` for non-dry-run\npromotion. The token is the buildchain equivalent of the old ABV runner release\nauthority: protected branch review and check rules guard human channel merges,\nwhile the reusable build trust gate now checks the source-lock channel HEAD and\nmerged same-repository PR lineage before heavy build runners start. This action\nstill independently rechecks PR lineage, alpha/release tree equivalence, and\ngenerated version-state verification before moving channel refs and tags.\nGenerated version-state direct ref updates can use a separate\n`generated-ref-update-token`; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. Consumers that protect\n`dev/*`, `alpha/*`, or `release/*` with one required review should configure\n`BUILDCHAIN_PROMOTION_TOKEN` as the bypass-capable release authority, so\npost-publish dev/alpha/release bookkeeping completes without a human PR.\nThe reusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, so flow-internal promotion\ncan complete generated `dev`/`alpha`/`release` bookkeeping while ordinary human\npushes and PR merges remain governed by the one-review branch protection rule.\nThe promotion action also auto-discovers the current token's authenticated user\nor app and adds it to the managed bypass allowlist, so consumers do not have to\ndeclare the same release authority twice.\n\nThe tag names intentionally follow the old ABV release semantics:\nexact release tags are `vX.Y.Z`, exact alpha tags are `vX.Y.Z-alpha.N`, floating\nrelease tags are minor/major tags such as `v2.0` and `v2`, and floating alpha\ntags are minor-line tags such as `v2.0-alpha` plus cross-minor major tags such\nas `v2-alpha`. A major alpha tag only moves for the highest minor in that major\nwith a published alpha, so older-line maintenance cannot roll consumers back.\nBare tags such as `1.0.0` are not\nmaintained as buildchain release entrypoints.\n\nRepository rulesets should protect exact tags, not every `v*` tag. A ruleset\nsuch as `refs/tags/v*` also protects floating channel tags like `v2.0-alpha` and `v2-alpha`,\nwhich Buildchain must update after exact tags and publish evidence are durable.\nUse an exact-tag rule such as `refs/tags/v*.*.*` for immutable evidence tags and\nleave floating channel tags mutable for the promotion token."
200
+ "markdown": "# promote-buildchain-ref\n\nInternal buildchain action for promoting verified buildchain release-line and\ncompatibility refs from buildchain release channels:\n\n- `alpha/v2/v2.0` creates or reuses the next exact prerelease tag such as\n `v2.0.1-alpha.0`, writes that version into package version state, points the\n alpha and dev channel branches at the version commit, then promotes\n `v2.0-alpha` and, when this is the highest published alpha minor, `v2-alpha`;\n- `release/v2/v2.0` creates or reuses the next exact release tag such as\n `v2.0.0`, writes that version into package version state, points the release\n channel branch and release tags at the release commit, then prepares a second\n source commit for the next exact prerelease tag such as `v2.0.1-alpha.0` and\n points the alpha/dev channel branches plus `v2.0-alpha` at that prerelease\n commit, and moves `v2-alpha` only if no higher v2 minor has published an alpha;\n- `publish-gate/major` accepts a reviewed PR from a production release line such\n as `release/v2/v2.0`, writes the next major production version such as\n `v3.0.0`, points `publish-gate/major`, `release/v3/v3.0`, `v3.0`, and `v3`\n at that release commit, then prepares `v3.0.1-alpha.0` for\n `alpha/v3/v3.0`, `dev/v3/v3.0`, `v3.0-alpha`, and `v3-alpha`. The older `major-gate`\n branch name is a compatibility alias only.\n\nThe release branch name defines the minor line. For example,\n`release/v2/v2.1` creates `v2.1.N`, promotes `v2.1`, and promotes `v2` only\nwhen the next minor tag such as `v2.2` does not already exist.\n\nThe action updates version state in `lerna.json`, root `package.json`, and\nworkspace package manifests discovered from package manager metadata\n(`package.json` workspaces, `lerna.json` packages, or `pnpm-workspace.yaml`).\nPackage manager detection is adaptive (`pnpm`, `npm`, or `yarn`) and is recorded\nin logs.\n\nRepositories can also provide `buildchain.toml` to declare version-state files\nand `lifecycle.verify`. TOML-configured version files take precedence over\npackage-manager discovery and can target JSON, TOML, or regex-based files. The\nversion commit itself is written through the GitHub Git Data API so the ref\ngraph is the durable source of truth. Repositories without any supported version\nstate degrade to ref-only promotion only when strict version state is disabled.\n\nJSON and TOML version entries whose declared key already matches the requested\nversion are treated as semantic no-ops. TOML changes use a parser-verified\nlossless key edit, so repository formatting is preserved and formatter-only\nrelease-preparation commits are not created. If a unique lossless edit cannot\nbe proven, promotion fails closed instead of rewriting the full TOML document.\n\n## Dry Run\n\nUse `dry-run: \"true\"` or the CLI `buildchain release --dry-run` before merging a\nchannel PR when you need to understand what Buildchain would do. This dry-run is\nat the Buildchain release-line level. It explains:\n\n- the legal source branch for the target channel;\n- exact release or alpha tags that would be created or reused;\n- floating tags and channel branches that would move;\n- version-state files and verification lifecycle that would apply;\n- branch protection, PR lineage, and release-from-alpha checks;\n- publish transaction behavior when `lifecycle.publish` or\n `publish-transaction` is enabled.\n\nIt does not move refs, move tags, write package files, run publish commands, or\npublish npm packages. The GitHub action dry-run still calls GitHub APIs to\nresolve the current target SHA and concrete pending ref updates, but every\nwrite is reported as a dry-run update.\n\nRepositories whose package version is anchored to an explicitly selected\nupstream release can opt into manual next-anchor behavior:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n```\n\nIn this mode, the action validates the configured version files and anchor\nmanifest through the repository's verify lifecycle, but it does not rewrite the\npackage version to match the Buildchain release tag. After a production\nrelease, it sets `next-anchor-required=true` and does not auto-create the next\nalpha branch or tag. The repository must create the next upstream anchor line\nexplicitly, then run the normal channel promotion flow for that line.\n\nWhen branch protection requires pull requests, generated version-state commits\nstill run through promotion automation first. The action updates\nBuildchain-managed channel protection before generated bookkeeping, adds the\nauthenticated promotion token user or app to the bypass allowlist, creates the\nconfigured required check on the exact generated version-state commit, then\ntries to apply that commit directly. If GitHub still rejects release\nfinalization bookkeeping, Buildchain creates or reuses a same-repository\n`buildchain/version-state/*` PR based on the current target channel head and\nreturns `finalization-needed=true`; a later idempotent promotion run can resume\nfrom the durable transaction state. Strict alpha promotion still fails with a\nconfiguration diagnostic instead of opening a post-publish human PR. Reusable\nwrapper callers should allow `checks: write` so the generated check is owned by\nGitHub Actions and matches the managed branch protection rule.\n\nStable promotion also protects concurrent development work. The reusable\nwrapper checks out the exact current `dev/vN/vN.M` head as a reconciliation\nworkspace. If next-alpha bookkeeping cannot fast-forward that branch, the\naction reruns the declared version-state generation and verification from that\ndev tree, creates a two-parent reconciliation commit from the regenerated\nfiles, and fails closed if the checkout moved before the mutation boundary.\nThis prevents generated projections from an older release tree from replacing\ncapabilities that reached dev while the release was in progress.\n\nFor Buildchain-owned automation, callers may pass\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`. The action still configures managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches with one\nrequired approving review, strict GitHub Actions checks, admin enforcement,\nconversation resolution, no force pushes, and no deletions; the bypass\nallowance only lets the named automation identity apply generated version-state\nor channel bookkeeping without a second human review after the reviewed channel\nPR has already merged. Direct action calls automatically include the current\npromotion token's authenticated user or app when GitHub exposes it; explicit\ninputs are supplemental allowlist entries for less discoverable release\nauthorities.\n\n## Publish Transactions\n\nPromotion can also own external publish side effects. Enable this only from a\ntrusted channel workflow:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n generated-ref-update-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ github.sha }}\n target-ref: release/v2/v2.0\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n publish-required-artifacts-json: >-\n [\n {\"kind\":\"npm\",\"name\":\"@kungfu-tech/buildchain\",\"ref\":\"2.0.0\",\"digest\":\"sha256:...\"}\n ]\n```\n\nFor anchored/manual package repositories that build through the reusable\nworkflow, keep the publish entrypoint on the `publish-gate/*` source-lock\ncontract:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: release/v22/v22.22\n require-publish-source-lock: \"true\"\n publish-source-ref: ${{ needs.build.outputs.publish-source-ref }}\n publish-source-sha: ${{ needs.build.outputs.publish-source-sha }}\n publish-source-locked: ${{ needs.build.outputs.publish-source-locked }}\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n```\n\n`target-ref` remains the channel promotion target that must point at `sha`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. Direct `alpha/*` or `release/*` channel refs are\nnot valid publish source locks when `require-publish-source-lock` is enabled,\nand a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.\nThe reusable promote workflow serializes non-dry-run promotion intents per\nrepository and re-reads `target-ref` before checkout, dependency installation,\nrelease-candidate resolution, or publish-gate writes. If a queued intent asks\nfor an older SHA after the protected channel has advanced, the workflow records\nthe requested/current SHA pair, verifies that the current target is ahead of\nthe requested commit, and exits successfully as a superseded no-op. Diverged,\nbehind, or unreadable comparisons still fail closed.\nAfter queued-intent revalidation, the reusable workflow runs the canonical\nrelease-candidate resolver in metadata-only mode before installing candidate\ndependencies or starting the full promotion job. The full job resolves and\ndownloads the evidence again before any publish-gate or publication mutation.\nThis preserves the final exact-evidence trust check while making missing or\nstale PR-stage evidence fail early.\nThe action repeats that check at its mutation boundary for governed promotion\ncalls, closing the race between workflow preflight and action start. Direct\nnon-governed calls and dry-runs keep the strict target mismatch error so local\ndiagnostics cannot silently reinterpret a stale request.\nExpected manual dry-run failures remain visible in the workflow result and do\nnot create automated workflow-friction issues; issue reporting is reserved for\nnon-dry-run promotion failures.\nThe reusable build workflow performs the cheaper channel-ref preflight earlier:\nafter source-lock resolution and before the build matrix, it requires the target\nchannel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point\nat the locked `publish-source-sha`. If not, maintainers should merge the source\ncommit through the channel PR first.\n\nFor promote-only release candidates, attach the PR-stage reusable build evidence\nand fail before publish-gate side effects if it no longer matches:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nThe action validates repository, channel, source identity, platform matrix, and\nthe aggregate build-summary hash before it writes version state, opens\nrelease-state, runs publish transaction logic, or moves tags/branches. Source\nidentity accepts the exact source SHA, the PR merge ref SHA, or the promoted\nchannel HEAD's Git tree SHA matching the passport tree hash. If validation\nfails, run or attach the verified channel PR build first instead of promoting a\nstale or unproven artifact set.\n\nWhen enabled, the action creates or resumes a release transaction keyed by\nrepository, version, source SHA, and target ref. It persists that transaction to\na machine-managed branch under `buildchain/release-state/<version>`, with\n`state.json` and, once available, `evidence.json`. Fresh GitHub runners read\nthat durable ref before running publish, so reruns do not depend on a previous\nrunner's local `.buildchain` directory.\n\nThe action runs `lifecycle.publish` from `buildchain.toml` or the explicit\n`publish-command` input, then validates publish evidence before exact tags and\nfloating refs move. If durable state persistence fails, the action fails closed\nbefore publish or public ref finalization.\n\n`publish-mode` defaults to `publish-final-version`, the token-free path for\nnormal npm Trusted Publishing. Same-version alpha-to-latest recovery must be\ndeclared as `publish-mode: promote-existing-version` and\n`publish-auth: npm-token`; Buildchain runs `npm whoami` before it creates\nrelease-state or moves any `npm dist-tag`. The Trusted Publishing mode is not\nallowed to perform `npm dist-tag add`.\n\nBuildchain itself uses this path for npm. Its `lifecycle.publish` runs\n`node scripts/npm-publish-transaction.mjs`, which publishes\n`@kungfu-tech/buildchain` through npm Trusted Publishing and writes npm\nartifact evidence into the transaction before release refs move. The separate\n`.github/workflows/npm-publish.yml` workflow is dry-run only.\n\nPublish lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION\nBUILDCHAIN_CHANNEL\nBUILDCHAIN_SOURCE_SHA\nBUILDCHAIN_TARGET_REF\nBUILDCHAIN_RELEASE_STATE\nBUILDCHAIN_EVIDENCE_DIR\nBUILDCHAIN_RELEASE_SHA\nBUILDCHAIN_RELEASE_MATERIAL_SHA\nBUILDCHAIN_PUBLISH_TOOLING_SHA\nBUILDCHAIN_PUBLISH_EVIDENCE\nBUILDCHAIN_REQUIRED_ARTIFACTS\n```\n\n`BUILDCHAIN_REQUIRED_ARTIFACTS` is the normalized requirement array after the\naction resolves a missing artifact `ref` to `BUILDCHAIN_VERSION`, or expands an\noptional `ref_template` containing exactly one `{version}`, and binds any\ndeclared provenance to the current release coordinate. Template expansion\nhappens after exact version selection; ambiguous or unsupported templates fail\nbefore `lifecycle.publish`. Requirement descriptors may omit `digest`; final\npublish evidence may not.\n\nThe action outputs `transaction-id`, `transaction-state`,\n`transaction-exact-tag`, `public-release-tag`, `transaction-release-sha`,\n`transaction-state-ref`, `transaction-state-sha`, `transaction-state-path`,\n`publish-evidence-path`, and `release-passport-path`, `release-passport-output-dir`,\n`release-passport-state-sha`, and `finalization-needed`.\n`transaction-state-ref` is the durable recovery location.\n`release-passport-state-sha` is the durable ref commit after the generated\n`release-passport/*` files have been uploaded into that recovery ref.\n`finalization-needed=true` means publish evidence is valid, but protected branch\nor ref finalization needs a later idempotent promotion run. For release\nfinalization, Buildchain may create a same-repository generated version-state\nPR when GitHub rejects the direct protected ref update; that PR is Buildchain\nbookkeeping, not a consumer-authored release change.\nSet `github-release: \"true\"` when the semver promotion should also publish the\npublic GitHub Release. After the release transaction reaches `complete` and\n`finalization-needed` is false, the action creates or updates the GitHub Release\nfor `public-release-tag`, applies deterministic semver metadata\n(`prerelease=true` and `make_latest=false` for prerelease tags, latest for stable\ntags), and uploads the publish evidence file plus generated release passport\nassets. For anchored/manual package releases, `public-release-tag` is derived\nfrom the published package version, while `transaction-exact-tag` remains the\ninternal Buildchain transaction ref for recovery and audit. If the transaction is\nnot complete yet, the action defers GitHub Release publication to the next\nidempotent promotion run.\n\nAfter a publish transaction reaches `complete`, the action generates the unified\n`buildchain-release-passport` in `.buildchain/release-passport` by default and\npersists those files under `release-passport/` in the durable release-state ref.\nSet `release-passport-product-name` to record the consumer product name, for\nexample `Libnode`, instead of the default `Buildchain`.\nSet `release-passport-kfd-1-witness-jsons` to newline-separated KFD-1\ncontract-world witness JSON paths when released artifacts must prove\nbyte-for-byte KFD contract surfaces. Buildchain imports the KFD metadata from\n`@kungfu-tech/kfd`, freezes the witness, verifies artifact bytes, and writes the\nresult under the KFD-provided `kfd-1` passport section.\nSet `release-passport-kfd-2-claim-jsons` to newline-separated KFD-2 public\nrelease trust claim JSON paths when a release makes additional human/agent\nvisible claims. Buildchain requires each public claim to bind declared sources,\nmachine-readable evidence, hashes, artifact coordinates, verification results,\naudit boundary, responsibility state, and residual risk. Unbound claims fail\npassport verification; prose-only claims downgrade the KFD-2 audit.\nSet `release-passport-kfd-3-prebuild-witness-jsons` to newline-separated KFD-3\ncollaboration-interface pre-build witness paths, then provide artifact-side\nevidence with `release-passport-kfd-3-artifact-witness-jsons` or a\nproduct-owned `release-passport-kfd-3-artifact-verify-command` such as\n`kungfu agent verify --json`. Buildchain compares declared shipped public\nsurfaces with artifact-exposed public surfaces and writes the result under the\nKFD-provided `kfd-3` passport section.\nBuildchain's own release workflow sets `release-passport-buildchain-self-kfd:\n\"true\"`. In that mode the action generates Buildchain-owned KFD-1/2/3 witnesses\ninside the final version-state workspace, after the release transaction has\nmaterialized generated files such as `package.json` and `dist/site/*`. This\nkeeps self-hosted KFD witness hashes bound to the exact published package\ninstead of to a pre-promotion checkout.\nWhen present, the passport includes the aggregate build summary, platform\nartifact manifests, npm publish evidence, dist-tag promotion evidence, the\nrelease-state ref, trusted publishing metadata, and the Buildchain transaction\nresult. After the first passport upload, Buildchain backfills the durable\nrelease-state SHA into `buildchain.release.json` and persists the passport\nagain, so the consumer-side passport is a complete audit entrypoint. Set\n`release-passport: \"false\"` only for a controlled recovery run that must skip\npassport generation.\n\nFinalization recovery is anchored to the durable transaction, not to a single\nworkflow run SHA. After generated version-state bookkeeping is applied, the\ncurrent channel head can be the generated version-state commit or a historical\nmerge commit that contains or corresponds to the recorded `release_material_sha`;\nit does not have to equal the original `source_sha` or the transaction\n`release_sha`. Reruns accept exact tags that already point at the transaction\nrelease/material SHA or the finalized channel head, and continue moving any\nmissing floating tags or dev/alpha refs before marking the transaction\n`complete`.\n\nNormal reruns accept already-published artifacts only when evidence matches.\nMissing required artifacts can be published on the next run. Conflicting\nrefs, digests, or declared provenance put the transaction into\n`repair_required`; `abandoned` and\n`failed_permanently` also fail closed unless `publish-transaction-override` is\nset for a controlled repair. The same override may replace a stale transaction\nonly when its version, exact tag, target ref, and channel are unchanged, the\ntransaction is not complete, and it contains no published artifacts or\nevidence. This lets a newly admitted source retry a previously failed paper\npublication without weakening already-published facts.\n\nIn strict buildchain promotion, ref movement is also gated by the old ABV\ngovernance semantics:\n\n- when detailed target branch protection is readable, it must enforce\n protection for administrators and require approving PR review plus the strict\n `check` job from the `Verify` workflow; when GitHub withholds that\n administration endpoint from the workflow token, the exact transaction must\n instead prove a protected current head, same-repository merged PR,\n independent approval, and the required successful `check` from its configured\n GitHub App;\n- post-publish channel reconciliation reuses an already qualifying\n provider-enforced policy when the workflow token cannot read or rewrite the\n administrative protection document, and fails closed if the public branch\n summary no longer carries the required check for everyone;\n- alpha promotion must come from a merged same-repository PR\n `dev/vN/vN.M -> alpha/vN/vN.M`, or from a strict same-line\n `publish-gate/alpha/vN/vN.M/<version> -> alpha/vN/vN.M` source-lock PR;\n- release promotion must come from a merged same-repository PR\n `alpha/vN/vN.M -> release/vN/vN.M`, or from a strict same-line\n `publish-gate/release/vN/vN.M/<version> -> release/vN/vN.M` source-lock PR;\n- major promotion must come from a merged same-repository PR\n `release/vN/vN.M -> publish-gate/major`;\n- release promotion must have an exact alpha tag for the same patch line, and\n the release source tree must match that alpha tag tree, so release does not\n introduce new code after alpha;\n- anchored/manual release promotion may differ from that alpha tree only in\n declared `version.files` and the configured anchor manifest, and only when the\n checked-out release material has passed `lifecycle.verify` or the explicit\n `verification-command`;\n- generated release and next-alpha version-state trees can be verified locally\n with either the `verification-command` input or `buildchain.toml`\n `lifecycle.verify` before any tags or channel refs move.\n\nThe promotion workflow should use `BUILDCHAIN_PROMOTION_TOKEN` for non-dry-run\npromotion. The token is the buildchain equivalent of the old ABV runner release\nauthority: protected branch review and check rules guard human channel merges,\nwhile the reusable build trust gate now checks the source-lock channel HEAD and\nmerged same-repository PR lineage before heavy build runners start. This action\nstill independently rechecks PR lineage, alpha/release tree equivalence, and\ngenerated version-state verification before moving channel refs and tags.\nGenerated version-state direct ref updates can use a separate\n`generated-ref-update-token`; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. Consumers that protect\n`dev/*`, `alpha/*`, or `release/*` with one required review should configure\n`BUILDCHAIN_PROMOTION_TOKEN` as the bypass-capable release authority, so\npost-publish dev/alpha/release bookkeeping completes without a human PR.\nThe reusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, so flow-internal promotion\ncan complete generated `dev`/`alpha`/`release` bookkeeping while ordinary human\npushes and PR merges remain governed by the one-review branch protection rule.\nThe promotion action also auto-discovers the current token's authenticated user\nor app and adds it to the managed bypass allowlist, so consumers do not have to\ndeclare the same release authority twice.\n\nThe tag names intentionally follow the old ABV release semantics:\nexact release tags are `vX.Y.Z`, exact alpha tags are `vX.Y.Z-alpha.N`, floating\nrelease tags are minor/major tags such as `v2.0` and `v2`, and floating alpha\ntags are minor-line tags such as `v2.0-alpha` plus cross-minor major tags such\nas `v2-alpha`. A major alpha tag only moves for the highest minor in that major\nwith a published alpha, so older-line maintenance cannot roll consumers back.\nBare tags such as `1.0.0` are not\nmaintained as buildchain release entrypoints.\n\nRepository rulesets should protect exact tags, not every `v*` tag. A ruleset\nsuch as `refs/tags/v*` also protects floating channel tags like `v2.0-alpha` and `v2-alpha`,\nwhich Buildchain must update after exact tags and publish evidence are durable.\nUse an exact-tag rule such as `refs/tags/v*.*.*` for immutable evidence tags and\nleave floating channel tags mutable for the promotion token."
201
201
  },
202
202
  {
203
203
  "id": "action:report-buildchain-issue",
@@ -1031,7 +1031,7 @@
1031
1031
  ],
1032
1032
  "maturity": "stable",
1033
1033
  "sourcePath": "docs/publication-artifacts.md",
1034
- "digest": "sha256:03a7f0b1dab5aa5e124b5ff2b740fffeaa56c10277543c8419ec7c414afcf2ce",
1034
+ "digest": "sha256:0b9a7ee83c72be20eef49ff4830e83fff167e08b0497bf5964e1826366da1aa4",
1035
1035
  "headings": [
1036
1036
  {
1037
1037
  "level": 1,
@@ -1064,7 +1064,7 @@
1064
1064
  "anchor": "site-consumption"
1065
1065
  }
1066
1066
  ],
1067
- "markdown": "# Publication Artifact Workflow\n\nBuildchain supports `project.type = \"publication-artifact\"` for repositories\nthat produce auditable papers, reports, specifications, or similar publication\npackages. These repositories are artifact producers. They should not be forced\nto become `web-surface` repositories just because a downstream site later\nrenders the paper.\n\nThe split is:\n\n```text\npaper repo = source, PDF, metadata, source bundle, publication manifest\npapers site = layout, navigation, public web surface, downstream rendering\n```\n\n## Configuration\n\nThe paper repository owns `.buildchain/buildchain.toml`:\n\n```toml\nschema = 1\n\n[project]\ntype = \"publication-artifact\"\nname = \"paper-observer-declared-timelines\"\n\n[publication]\nkind = \"paper\"\ntitle = \"Observer-Declared Timelines for Real-World Agent Work\"\nversion = \"0.1.0\"\nprimary_artifact = \"_build/main.pdf\"\nartifact_paths = [\"_build/main.pdf\"]\nmetadata_paths = [\"README.md\", \"docs/MAP.md\"]\nsource_paths = [\"paper\", \"README.md\", \"LICENSE\", \"Makefile\"]\nsite_consumers = [\"papers.libkungfu.dev\"]\nmanifest_path = \".buildchain/publication/publication-artifact.json\"\nsource_bundle_path = \".buildchain/publication/source.tar.gz\"\n\n[publication.archive]\nid = \"observer-declared-timelines\"\ncanonical_url = \"https://papers.libkungfu.dev/observer-declared-timelines/\"\nlatest_url = \"https://papers.libkungfu.dev/observer-declared-timelines/latest/\"\nlatest_evidence_url = \"https://papers.libkungfu.dev/observer-declared-timelines/latest/buildchain.release.json\"\nimmutable_base_url = \"https://papers.libkungfu.dev/archive\"\nregistry_path = \".buildchain/publication/publication-registry.json\"\n\n[publication.toolchain]\ntype = \"latex-docker\"\nimage = \"ghcr.io/kungfu-systems/build-images/latex-pdf-builder\"\ndigest = \"sha256:c20f3809e96836c1c78e97c76939d12f1de3fed0ea9b7c40c43332ec2ea480f8\"\ncommand = \"latexmk -pdf -outdir=_build paper/main.tex\"\n\n[publish]\nkind = \"npm-paper-package\"\npackage = \"@kungfu-tech/paper-observer-declared-timelines\"\nauth = \"trusted-publishing\"\n\n[lifecycle.build]\ncommand = \"make pdf\"\n\n[lifecycle.verify]\ncommand = \"make check\"\n```\n\n`primary_artifact` is the human-facing publication output, usually a PDF.\n`source_paths` are archived into a source bundle. `metadata_paths` are hashed\nand recorded so a site can consume the paper facts without scraping prose.\n\n`publication.archive` turns the publication into an append-only public archive\ncontract:\n\n- `canonical_url` is the stable human reader page.\n- `latest_url` and `latest_evidence_url` are movable aliases for the latest\n reader page and latest evidence.\n- `immutable_base_url` plus `id` and `publication.version` produce a versioned\n prefix such as\n `https://papers.libkungfu.dev/archive/observer-declared-timelines/v0.1.0/`.\n- `immutable_url_prefix` can be used instead when the repository already owns\n the full version prefix.\n- `registry_path` records every published version and its manifest, passport,\n source bundle, primary artifact, URLs, and SHA-256 digests.\n\nImmutable archive prefixes are append-only. Do not run site deployment commands\nwith `sync --delete` or equivalent deletion semantics over those prefixes. A\nsame-version republish is allowed only when the immutable digest is unchanged;\nif PDF, source bundle, route, metadata, or toolchain evidence changes for an\nexisting version, Buildchain fails before the registry is rewritten.\n\nThe Buildchain web-surface adapter consumes this boundary from a surface-local\n`manifest.json` whose `archivePolicy.contract` is\n`kungfu-buildchain-publication-archive-policy`. It excludes the derived archive\nroot from every owning or parent `sync --delete`, verifies existing object\ndigests, uploads only missing immutable files with `--no-overwrite`, and verifies\nthem again before mutable site content is synchronized. A current package set\ndoes not need to rebuild or enumerate every historical version: the protected\narchive root remains outside deletion even when older versions disappear from\nthe current artifact.\n\n`publication.toolchain` makes the source-to-PDF transformation part of the\nmachine-readable contract. `latex-docker` is the preferred LaTeX profile. The\nBuildchain paper scaffold and reusable workflow default to\n`ghcr.io/kungfu-systems/build-images/latex-pdf-builder:v1.2.0`, pinned by the\ndigest above. The workflow pulls the declared image by digest and runs the\ndeclared command in that pinned container. `custom-command` remains available\nfor compatibility, but the passport records it as lower trust because\nBuildchain can record the command boundary without proving the compiler or\nLaTeX distribution digest.\n\n`publish.kind = \"npm-paper-package\"` declares that Buildchain, not the consumer\nrepository, owns the standard paper npm package shape and release transaction\nmechanics. `publish.package` is the public npm package that contains the PDF,\npublication manifest, publication passport, optional archive registry, source\nbundle, and declared metadata files.\n\n## Reusable Workflow\n\nConsumer repositories that only need to build and upload paper evidence can\ncall the build-only wrapper directly:\n\n```yaml\njobs:\n publication:\n uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2\n with:\n toolchain-type: config\n verify-command: make check\n artifact-name: observer-declared-timelines\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe build-only workflow:\n\n- resolves the Buildchain runtime and checks the floating contract lock before\n any paper build runs;\n- resolves the declared publication toolchain from `[publication.toolchain]` or\n workflow inputs;\n- for `latex-docker`, pulls the pinned build-images LaTeX builder digest and\n runs the declared command in the container;\n- for `custom-command`, runs the declared command and records the lower-trust\n boundary in the passport;\n- runs the verify command;\n- creates a source bundle from `publication.source_paths`;\n- writes `.buildchain/publication/publication-artifact.json`;\n- writes `.buildchain/publication/publication-artifact-passport.json`;\n- when `[publication.archive]` is configured, writes\n `.buildchain/publication/publication-registry.json` and verifies same-version\n immutability;\n- uploads one GitHub artifact containing the PDF, manifest, passport, optional\n registry, and source bundle.\n\nIt does not publish npm packages, deploy web pages, or create GitHub Releases.\n\nThe paper release preset additionally hydrates every prior published package\nregistry from the npm registry before generating the current manifest. npm\npackage integrity authenticates each downloaded source; Buildchain verifies the\nregistry self-digest, merges immutable records, and fails if a cumulative\nregistry drops an accepted version or changes immutable route/artifact facts.\nThe synthesized package therefore carries complete history even on a clean\nrunner. Its cumulative registry and file SHA-256 values are bound into the paper\nrelease build summary and release passport evidence.\n\n## Paper Release Preset\n\nPaper repositories that publish a versioned npm package should use the\nBuildchain-managed release preset instead of copying npm transaction scripts or\npromotion YAML:\n\n```yaml\nname: Paper Release\n\non:\n push:\n branches:\n - alpha/v1/v1.0\n - release/v1/v1.0\n workflow_dispatch:\n inputs:\n buildchain-ref:\n description: \"Temporary Buildchain runtime ref\"\n required: false\n default: \"\"\n\njobs:\n paper-release:\n uses: kungfu-systems/buildchain/.github/workflows/paper-release-sealed.yml@v2\n permissions:\n actions: read\n checks: write\n contents: write\n id-token: write\n issues: write\n with:\n buildchain-ref: ${{ inputs.buildchain-ref || '' }}\n publisher-workflow-path: .github/workflows/paper-release.yml\n toolchain-type: config\n verify-command: make check\n artifact-paths: _build/paper-name.pdf\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe sealed preset does not accept a long-lived promotion token. It builds and\npackages the paper in a read-only job, then a credential-free authority job\ndownloads that exact candidate, audits the external control plane, and seals a\ncapability over the source tree, Buildchain runtime, controller receipt, PDF,\nand npm package bytes. Only the final job receives write and OIDC permissions;\nit downloads the admitted candidate, recomputes the capability binding, and\npublishes without executing consumer build commands. npm binds the OIDC identity\nto the consumer workflow named by `publisher-workflow-path`.\n\nThe preset:\n\n- resolves the floating Buildchain runtime once and binds the exact SHA into the\n publication candidate and authority capability;\n- builds the PDF through the declared pinned LaTeX Docker toolchain or custom\n command in a read-only job;\n- verifies the paper repository;\n- writes the publication manifest, publication passport, optional archive\n registry, and source bundle;\n- synthesizes an npm package from `[publication]` and `[publish]` declarations\n under `.buildchain/publication/npm-package`;\n- computes npm-style `sha512` integrity from `npm pack --dry-run` and passes\n it as `publish-required-artifacts-json`;\n- creates a `publish-gate/<alpha|release>/.../<version>` source lock for the\n channel commit and requires `promote-buildchain-ref` to verify that lock\n before any publish side effect;\n- verifies the complete candidate again after authority and publishes the\n package through npm Trusted Publishing without rebuilding it;\n- writes Buildchain release/passport evidence; and\n- creates or updates the exact-version GitHub Release by default, uploading\n every file declared by `publication.primary_artifact` and\n `publication.artifact_paths` alongside the release evidence.\n\nConsumers can opt out of the GitHub Release with `github-release: false`, but\nthe default is on so downstream release propagation can observe\n`release.published` without hand-written `gh release` steps.\n\nDeclared publication artifacts are resolved from the generated publication\nmanifest rather than repeated in consumer workflow YAML. Publication fails\nbefore upload if a declared artifact is missing or if its basename would\ncollide with another GitHub Release asset.\n\nFor npm Trusted Publishing, register the consumer workflow file that calls this\npreset, for example `.github/workflows/paper-release.yml`, against the declared\npackage in npm. The trusted publisher is the consumer repository and workflow\nfile; the implementation still runs inside Buildchain's reusable workflow.\n\nStandard paper repositories should not carry local copies of\n`scripts/npm-publish-transaction.mjs`, package-generation scripts, or\npromotion/ref-lock YAML. If the default package shape is insufficient, extend\nBuildchain rather than forking the mechanics into each paper repository.\n\n## CLI And Node API\n\nGenerate the publication manifest locally or in CI:\n\n```sh\nbuildchain publication-artifact manifest --source-sha \"$(git rev-parse HEAD)\" --json\n```\n\nGenerate the npm package contents after the manifest exists:\n\n```sh\nbuildchain publication-artifact npm-package --json\n```\n\nNode API:\n\n```js\nimport {\n collectPublicationArtifact,\n writePublicationArtifact,\n} from \"@kungfu-tech/buildchain/publication-artifact\";\n\nimport {\n collectPublicationPackageFacts,\n preparePublicationNpmPackage,\n} from \"@kungfu-tech/buildchain/publication-package\";\n```\n\n`writePublicationArtifact()` is the single implementation used by the CLI and\nthe reusable workflow. The generated manifest records:\n\n- publication title, kind, authors, and primary artifact;\n- artifact paths, byte sizes, and SHA-256 digests;\n- metadata paths and SHA-256 digests;\n- source SHA, tree SHA, source files, and source bundle digest;\n- publication toolchain type, image, digest, command, invocation mode, and trust\n classification;\n- timestamp and reproducibility policy;\n- downstream site-consumption hints;\n- optional archive routes for canonical, latest, latest evidence, immutable\n version prefix, and public artifact URLs.\n\nThe companion publication artifact passport records the same source and\nartifact evidence plus an explicit responsibility split. Buildchain proves\ndeclared files and hashes; it does not peer-review paper claims.\n\nWhen archive config is present, the registry uses the\n`kungfu-buildchain-publication-artifact-registry` contract. A site repository\ncan render latest pages and historical version indexes from that registry\nwithout rebuilding old PDFs from the latest npm package or paper source.\n\n## Site Consumption\n\nA downstream papers site should treat the publication manifest as the single\nfact source for the artifact. The site owns rendering and navigation; it should\nnot reinterpret the paper repository as a web deployment source.\nFor registry-level routing, sites should first consume the package-owned\nBuildchain fact source:\n\n```text\nnode_modules/@kungfu-tech/buildchain/dist/site/publication-registry.json\n```\n\nor the equivalent package export:\n\n```js\nimport registry from \"@kungfu-tech/buildchain/site/publication-registry.json\" with { type: \"json\" };\n```\n\nThat registry uses the `kungfu-buildchain-publication-release-registry`\ncontract. It separates mutable canonical/latest reader routes from immutable\nversion prefixes, publication artifacts, source bundles, and passport evidence\nso site repositories can render `/papers/**` without maintaining a parallel\nfixture truth source.\n\nFor `paper-observer-declared-timelines`, the expected adoption path is:\n\n```text\npaper repo builds PDF + manifest + source bundle\npaper repo updates publication-registry.json\npapers site consumes publication-artifact.json\npapers site consumes publication-registry.json for history\nsite renders paper page and links the PDF/source bundle\n```\n\nThis mirrors web-surface governance without mixing producer and renderer\nresponsibilities."
1067
+ "markdown": "# Publication Artifact Workflow\n\nBuildchain supports `project.type = \"publication-artifact\"` for repositories\nthat produce auditable papers, reports, specifications, or similar publication\npackages. These repositories are artifact producers. They should not be forced\nto become `web-surface` repositories just because a downstream site later\nrenders the paper.\n\nThe split is:\n\n```text\npaper repo = source, PDF, metadata, source bundle, publication manifest\npapers site = layout, navigation, public web surface, downstream rendering\n```\n\n## Configuration\n\nThe paper repository owns `.buildchain/buildchain.toml`:\n\n```toml\nschema = 1\n\n[project]\ntype = \"publication-artifact\"\nname = \"paper-observer-declared-timelines\"\n\n[publication]\nkind = \"paper\"\ntitle = \"Observer-Declared Timelines for Real-World Agent Work\"\nversion = \"0.1.0\"\nprimary_artifact = \"_build/main.pdf\"\nartifact_paths = [\"_build/main.pdf\"]\nmetadata_paths = [\"README.md\", \"docs/MAP.md\"]\nsource_paths = [\"paper\", \"README.md\", \"LICENSE\", \"Makefile\"]\nsite_consumers = [\"papers.libkungfu.dev\"]\nmanifest_path = \".buildchain/publication/publication-artifact.json\"\nsource_bundle_path = \".buildchain/publication/source.tar.gz\"\n\n[publication.archive]\nid = \"observer-declared-timelines\"\ncanonical_url = \"https://papers.libkungfu.dev/observer-declared-timelines/\"\nlatest_url = \"https://papers.libkungfu.dev/observer-declared-timelines/latest/\"\nlatest_evidence_url = \"https://papers.libkungfu.dev/observer-declared-timelines/latest/buildchain.release.json\"\nimmutable_base_url = \"https://papers.libkungfu.dev/archive\"\nregistry_path = \".buildchain/publication/publication-registry.json\"\n\n[publication.toolchain]\ntype = \"latex-docker\"\nimage = \"ghcr.io/kungfu-systems/build-images/latex-pdf-builder\"\ndigest = \"sha256:c20f3809e96836c1c78e97c76939d12f1de3fed0ea9b7c40c43332ec2ea480f8\"\ncommand = \"latexmk -pdf -outdir=_build paper/main.tex\"\n\n[publish]\nkind = \"npm-paper-package\"\npackage = \"@kungfu-tech/paper-observer-declared-timelines\"\nauth = \"trusted-publishing\"\n\n[lifecycle.build]\ncommand = \"make pdf\"\n\n[lifecycle.verify]\ncommand = \"make check\"\n```\n\n`primary_artifact` is the human-facing publication output, usually a PDF.\n`source_paths` are archived into a source bundle. `metadata_paths` are hashed\nand recorded so a site can consume the paper facts without scraping prose.\n\n`publication.archive` turns the publication into an append-only public archive\ncontract:\n\n- `canonical_url` is the stable human reader page.\n- `latest_url` and `latest_evidence_url` are movable aliases for the latest\n reader page and latest evidence.\n- `immutable_base_url` plus `id` and `publication.version` produce a versioned\n prefix such as\n `https://papers.libkungfu.dev/archive/observer-declared-timelines/v0.1.0/`.\n- `immutable_url_prefix` can be used instead when the repository already owns\n the full version prefix.\n- `registry_path` records every published version and its manifest, passport,\n source bundle, primary artifact, URLs, and SHA-256 digests.\n\nImmutable archive prefixes are append-only. Do not run site deployment commands\nwith `sync --delete` or equivalent deletion semantics over those prefixes. A\nsame-version republish is allowed only when the immutable digest is unchanged;\nif PDF, source bundle, route, metadata, or toolchain evidence changes for an\nexisting version, Buildchain fails before the registry is rewritten.\n\nThe Buildchain web-surface adapter consumes this boundary from a surface-local\n`manifest.json` whose `archivePolicy.contract` is\n`kungfu-buildchain-publication-archive-policy`. It excludes the derived archive\nroot from every owning or parent `sync --delete`, verifies existing object\ndigests, uploads only missing immutable files with `--no-overwrite`, and verifies\nthem again before mutable site content is synchronized. A current package set\ndoes not need to rebuild or enumerate every historical version: the protected\narchive root remains outside deletion even when older versions disappear from\nthe current artifact.\n\n`publication.toolchain` makes the source-to-PDF transformation part of the\nmachine-readable contract. `latex-docker` is the preferred LaTeX profile. The\nBuildchain paper scaffold and reusable workflow default to\n`ghcr.io/kungfu-systems/build-images/latex-pdf-builder:v1.2.0`, pinned by the\ndigest above. The workflow pulls the declared image by digest and runs the\ndeclared command in that pinned container. `custom-command` remains available\nfor compatibility, but the passport records it as lower trust because\nBuildchain can record the command boundary without proving the compiler or\nLaTeX distribution digest.\n\n`publish.kind = \"npm-paper-package\"` declares that Buildchain, not the consumer\nrepository, owns the standard paper npm package shape and release transaction\nmechanics. `publish.package` is the public npm package that contains the PDF,\npublication manifest, publication passport, optional archive registry, source\nbundle, and declared metadata files.\n\n## Reusable Workflow\n\nConsumer repositories that only need to build and upload paper evidence can\ncall the build-only wrapper directly:\n\n```yaml\njobs:\n publication:\n uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2\n with:\n toolchain-type: config\n verify-command: make check\n artifact-name: observer-declared-timelines\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe build-only workflow:\n\n- resolves the Buildchain runtime and checks the floating contract lock before\n any paper build runs;\n- resolves the declared publication toolchain from `[publication.toolchain]` or\n workflow inputs;\n- for `latex-docker`, pulls the pinned build-images LaTeX builder digest and\n runs the declared command in the container;\n- for `custom-command`, runs the declared command and records the lower-trust\n boundary in the passport;\n- runs the verify command;\n- creates a source bundle from `publication.source_paths`;\n- writes `.buildchain/publication/publication-artifact.json`;\n- writes `.buildchain/publication/publication-artifact-passport.json`;\n- when `[publication.archive]` is configured, writes\n `.buildchain/publication/publication-registry.json` and verifies same-version\n immutability;\n- uploads one GitHub artifact containing the PDF, manifest, passport, optional\n registry, and source bundle.\n\nIt does not publish npm packages, deploy web pages, or create GitHub Releases.\n\nThe paper release preset additionally hydrates every prior published package\nregistry from the npm registry before generating the current manifest. npm\npackage integrity authenticates each downloaded source; Buildchain verifies the\nregistry self-digest, merges immutable records, and fails if a cumulative\nregistry drops an accepted version or changes immutable route/artifact facts.\nThe synthesized package therefore carries complete history even on a clean\nrunner. Its cumulative registry and file SHA-256 values are bound into the paper\nrelease build summary and release passport evidence.\n\n## Paper Release Preset\n\nPaper repositories that publish a versioned npm package should use the\nBuildchain-managed release preset instead of copying npm transaction scripts or\npromotion YAML:\n\n```yaml\nname: Paper Release\n\non:\n push:\n branches:\n - alpha/v1/v1.0\n - release/v1/v1.0\n workflow_dispatch:\n inputs:\n buildchain-ref:\n description: \"Temporary Buildchain runtime ref\"\n required: false\n default: \"\"\n\njobs:\n paper-release:\n uses: kungfu-systems/buildchain/.github/workflows/paper-release-sealed.yml@v2\n permissions:\n actions: read\n checks: write\n contents: write\n id-token: write\n issues: write\n with:\n buildchain-ref: ${{ inputs.buildchain-ref || '' }}\n publisher-workflow-path: .github/workflows/paper-release.yml\n toolchain-type: config\n verify-command: make check\n artifact-paths: _build/paper-name.pdf\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n secrets:\n BUILDCHAIN_PROMOTION_TOKEN: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n```\n\nThe sealed preset does not use a long-lived token for npm publication. It may\naccept an optional `BUILDCHAIN_PROMOTION_TOKEN` only for machine-generated\nversion-state updates on protected channel branches; npm publication remains\nbound to GitHub OIDC trusted publishing. The preset builds and packages the\npaper in a read-only job, then a credential-free authority job downloads that\nexact candidate, audits the external control plane, and seals a capability over\nthe source tree, Buildchain runtime, controller receipt, PDF, and npm package\nbytes. Only the final job receives write and OIDC permissions; it downloads the\nadmitted candidate, recomputes the capability binding, and publishes without\nexecuting consumer build commands. npm binds the OIDC identity to the consumer\nworkflow named by `publisher-workflow-path`.\n\nThe preset:\n\n- resolves the floating Buildchain runtime once and binds the exact SHA into the\n publication candidate and authority capability;\n- builds the PDF through the declared pinned LaTeX Docker toolchain or custom\n command in a read-only job;\n- verifies the paper repository;\n- writes the publication manifest, publication passport, optional archive\n registry, and source bundle;\n- synthesizes an npm package from `[publication]` and `[publish]` declarations\n under `.buildchain/publication/npm-package`;\n- computes npm-style `sha512` integrity from `npm pack --dry-run` and passes\n it as `publish-required-artifacts-json`;\n- creates a `publish-gate/<alpha|release>/.../<version>` source lock for the\n channel commit and requires `promote-buildchain-ref` to verify that lock\n before any publish side effect;\n- verifies the complete candidate again after authority and publishes the\n package through npm Trusted Publishing without rebuilding it;\n- writes Buildchain release/passport evidence; and\n- creates or updates the exact-version GitHub Release by default, uploading\n every file declared by `publication.primary_artifact` and\n `publication.artifact_paths` alongside the release evidence.\n\nConsumers can opt out of the GitHub Release with `github-release: false`, but\nthe default is on so downstream release propagation can observe\n`release.published` without hand-written `gh release` steps.\n\nDeclared publication artifacts are resolved from the generated publication\nmanifest rather than repeated in consumer workflow YAML. Publication fails\nbefore upload if a declared artifact is missing or if its basename would\ncollide with another GitHub Release asset.\n\nFor npm Trusted Publishing, register the consumer workflow file that calls this\npreset, for example `.github/workflows/paper-release.yml`, against the declared\npackage in npm. The trusted publisher is the consumer repository and workflow\nfile; the implementation still runs inside Buildchain's reusable workflow.\n\nStandard paper repositories should not carry local copies of\n`scripts/npm-publish-transaction.mjs`, package-generation scripts, or\npromotion/ref-lock YAML. If the default package shape is insufficient, extend\nBuildchain rather than forking the mechanics into each paper repository.\n\n## CLI And Node API\n\nGenerate the publication manifest locally or in CI:\n\n```sh\nbuildchain publication-artifact manifest --source-sha \"$(git rev-parse HEAD)\" --json\n```\n\nGenerate the npm package contents after the manifest exists:\n\n```sh\nbuildchain publication-artifact npm-package --json\n```\n\nNode API:\n\n```js\nimport {\n collectPublicationArtifact,\n writePublicationArtifact,\n} from \"@kungfu-tech/buildchain/publication-artifact\";\n\nimport {\n collectPublicationPackageFacts,\n preparePublicationNpmPackage,\n} from \"@kungfu-tech/buildchain/publication-package\";\n```\n\n`writePublicationArtifact()` is the single implementation used by the CLI and\nthe reusable workflow. The generated manifest records:\n\n- publication title, kind, authors, and primary artifact;\n- artifact paths, byte sizes, and SHA-256 digests;\n- metadata paths and SHA-256 digests;\n- source SHA, tree SHA, source files, and source bundle digest;\n- publication toolchain type, image, digest, command, invocation mode, and trust\n classification;\n- timestamp and reproducibility policy;\n- downstream site-consumption hints;\n- optional archive routes for canonical, latest, latest evidence, immutable\n version prefix, and public artifact URLs.\n\nThe companion publication artifact passport records the same source and\nartifact evidence plus an explicit responsibility split. Buildchain proves\ndeclared files and hashes; it does not peer-review paper claims.\n\nWhen archive config is present, the registry uses the\n`kungfu-buildchain-publication-artifact-registry` contract. A site repository\ncan render latest pages and historical version indexes from that registry\nwithout rebuilding old PDFs from the latest npm package or paper source.\n\n## Site Consumption\n\nA downstream papers site should treat the publication manifest as the single\nfact source for the artifact. The site owns rendering and navigation; it should\nnot reinterpret the paper repository as a web deployment source.\nFor registry-level routing, sites should first consume the package-owned\nBuildchain fact source:\n\n```text\nnode_modules/@kungfu-tech/buildchain/dist/site/publication-registry.json\n```\n\nor the equivalent package export:\n\n```js\nimport registry from \"@kungfu-tech/buildchain/site/publication-registry.json\" with { type: \"json\" };\n```\n\nThat registry uses the `kungfu-buildchain-publication-release-registry`\ncontract. It separates mutable canonical/latest reader routes from immutable\nversion prefixes, publication artifacts, source bundles, and passport evidence\nso site repositories can render `/papers/**` without maintaining a parallel\nfixture truth source.\n\nFor `paper-observer-declared-timelines`, the expected adoption path is:\n\n```text\npaper repo builds PDF + manifest + source bundle\npaper repo updates publication-registry.json\npapers site consumes publication-artifact.json\npapers site consumes publication-registry.json for history\nsite renders paper page and links the PDF/source bundle\n```\n\nThis mirrors web-surface governance without mixing producer and renderer\nresponsibilities."
1068
1068
  },
1069
1069
  {
1070
1070
  "id": "manual:publication-authority",
@@ -1078,7 +1078,7 @@
1078
1078
  ],
1079
1079
  "maturity": "preview",
1080
1080
  "sourcePath": "docs/publication-authority.md",
1081
- "digest": "sha256:06ba05f9d8a2685a0896334b6013a97c45b7d71163cf6898e5a6274baf7f0296",
1081
+ "digest": "sha256:05bc22c7e5885e591bc121fc43f588e5d49ccf0a8de6a642811c1d0d03dcee1e",
1082
1082
  "headings": [
1083
1083
  {
1084
1084
  "level": 1,
@@ -1111,7 +1111,7 @@
1111
1111
  "anchor": "publication-lanes"
1112
1112
  }
1113
1113
  ],
1114
- "markdown": "---\nstatus: draft\nperiod: ongoing\ntheme: sealed-publication-authority\ndoc_type: protocol\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-07-15\nai_provenance:\n model_family: GPT-5\n product: Codex\n generated_at: 2026-07-15\n limits: Live provider configuration must be re-audited; no credential values are represented.\n---\n\n# Sealed Publication Authority\n\nBuildchain publication authority is a closed-world, fail-closed protocol. It does\nnot mint registry or cloud credentials. It independently verifies whether an\nalready protected publication job is allowed to request a short-lived provider\ncredential for one exact product, target, version, channel, and artifact digest.\n\nThe machine-readable authority inventory is\n`dist/site/publication-authority-registry.json`. Any workflow with a write,\nenvironment, OIDC, cloud credential, registry publish, release, or Git push\nsignal must have an explicit descriptor. A new authority-bearing workflow that\nis absent from the inventory fails site generation. Unknown workflows and every\ndescriptor not marked `product-publication` are denied product publication.\n\n## Evidence chain\n\nA qualifying admission binds exact source and runtime SHAs; contract, consumer\npolicy, qualifying controller receipt, Shifu/Gate aggregate, artifact, runner,\nand control-plane digests; repository, authority workflow, provider publisher\nworkflow, Environment policy,\nproduct, target, version, and channel; plus a unique nonce and a lifetime of no\nmore than 15 minutes. Every expected binding is mandatory at verification time;\nan omitted expected field is not a wildcard.\n\nThe independent verifier recomputes every digest and ignores a producer's own\nallow/deny conclusion. It fetches the exact evidence run, validates the actual\nrelease-candidate passport and referenced qualifying controller receipt,\nrecomputes the Shifu Gate aggregate or explicit consumer-owned no-Gate policy,\nrecomputes the downloaded artifact manifests, and hashes every declared product\npayload file against those manifests. The `.buildchain/` diagnostics envelope is\nbound by the manifest digest but excluded from the product-byte set because it can\nbe finalized after the lifecycle scan. The verifier also compares the PR evidence tree to the\nadmitted post-merge source commit tree. It rejects an unknown\nworkflow, stale or replayed nonce, runner downgrade, control-plane drift,\nsource/runtime mismatch, and artifact substitution. A successful result is a\nscoped capability receipt, not a bearer credential.\n\n## Runner and control-plane evidence\n\nRunner evidence uses exactly four classes: `ephemeral`, `reimaged`,\n`persistent-measured`, and `unqualified`. Ephemeral runners also record their\njob-isolation boundary. Reimaged and persistent runners qualify only when a\nclean baseline is proven and baseline, toolchain, cache-contract, and task-\nisolation digests are all present. Otherwise they still emit diagnostic\nevidence with `qualificationStatus = unqualified`, but cannot receive a product\ncapability.\n\nThe external audit records digests and pass/fail status for repository Actions\ndefaults, classic branch protection or an active matching repository ruleset,\ndeclared protected Environment policy or an explicit no-Environment binding,\njob-scoped credentials,\nabsence of long-lived workflow publication credentials, provider authority,\nand authorized runner class. Provider modes are `npm-trusted-publisher`,\n`github-token`, and `oidc-role`. The OIDC-role mode consumes only a sanitized\nprovider audit containing a role digest and qualifying decision; raw IAM policy,\ntokens, or credentials are rejected. Package-owner, cloud-root, GitHub\nadministrator, and registry-root credentials remain outside Buildchain's trust\nboundary. Missing or unreadable facts fail closed.\n\nAn unauthenticated local npm CLI is not evidence that Trusted Publishing is\nmissing. `npm whoami` reports only the local CLI session and does not report the\nOIDC identity that npm creates during `npm publish`. The default read-only audit\ntherefore binds the exact provider, repository, caller workflow, optional\nEnvironment, job-scoped OIDC permission, and absence of long-lived credentials,\nthen records `provider-at-transaction`: npm makes the final authorization\ndecision when `npm publish` exchanges the job's OIDC token. A missing or drifted\ntrusted-publisher configuration consequently denies the transaction safely; it\nis not preflighted through an unrelated long-lived npm login.\n\nAn authenticated external auditor can add stronger point-in-time evidence by\nsupplying sanitized `npm trust list --json` output with `--npm-trust-json`. This\nchanges the publisher fact to `audited-control-plane`; the workflow never runs\n`npm trust list` itself and never receives that auditor's npm credential.\n\nThe credential-free collector proves effective Actions and runner scope from\nthe publication workflow fetched at `--workflow-ref`: explicit read-only\nworkflow defaults, job-scoped write/OIDC permissions, and an exact GitHub-hosted\nrunner label. It does not call repository Actions-default or self-hosted-runner\nadministration endpoints. Branch/ruleset and OIDC subject facts remain live\nread-only provider queries. When the detailed branch-protection endpoint is not\nreadable with the workflow token, `--source-sha` binds the provider's public\nprotected-branch summary to the exact merged PR, independent approval, required\nsuccessful check, same-repository lineage, and current branch head. This records\nprovider-enforced transaction evidence without treating an unavailable\nadministration endpoint as an unprotected branch. It avoids turning a\nrepository-admin token into a publication prerequisite.\n\nFor non-dry-run workflows, missing admission, runner, control-plane, Gate, or\nexpected-binding evidence is rejected before Buildchain downloads candidate\nartifacts. The denial explicitly records that npm Trusted Publishing and OIDC\nwere not evaluated, so downstream diagnostics cannot misclassify an admission\nassembly failure as an npm authentication failure.\n\nBuildchain's own `workflow_run` promotion lane may assemble those inputs only\nfor `kungfu-systems/buildchain`. It downloads the exact prior RC passport,\nsummary, referenced controller receipt, manifests, and product payloads; proves\nthe admitted channel commit has the same Git tree as the RC; performs the live\nread-only control-plane audit; records the GitHub-hosted job as ephemeral runner\nprovenance; and creates an explicit Buildchain-owned no-Gate decision. The\nindependent verifier then recomputes every receipt and payload digest exactly as\nit does for externally supplied admission. The self-assembly mode rejects other\nrepositories, unknown refs, non-exact source SHAs, and any caller other than\n`.github/workflows/buildchain-ref-promotion.yml`. Manual apply and external\nconsumer workflows still require their own explicit admission inputs.\n\nBefore authority verification, the reusable promotion controller runs the same\nrelease transaction selector in read-only mode. That plan supplies one exact\npublication version and tag to the admission verifier, the publish-gate source\nlock, and the real promotion action. The verifier rejects a capability for a\ndifferent version, and the promotion action rechecks the planned version before\nany publish transaction side effect. Release-candidate fixture versions are\nartifact evidence only; they never name Buildchain's own source-lock or\npublication capability.\n\nEvidence publication is a separate authority class and never grants product\npublication.\n\n## API and CLI\n\nUse `@kungfu-tech/buildchain/publication-authority` or run:\n\n```bash\nbuildchain verify publication-admission admission.json \\\n --registry-json publication-authority-registry.json \\\n --runner-json runner.json \\\n --control-plane-audit-json control-plane.json \\\n --publication-evidence-json publication-evidence.json \\\n --expected-json expected.json \\\n --used-nonce previous-run-nonce \\\n --json\n```\n\nThe read-only live collector defaults to npm trusted publishing. Other product\nproviders select an explicit adapter:\n\n```bash\nbuildchain audit publication-control-plane \\\n --repository kungfu-systems/buildchain \\\n --branch dev/v2/v2.12 \\\n --source-sha <exact-merged-branch-sha> \\\n --workflow .github/workflows/release-candidate-promote.yml \\\n --workflow-ref <exact-buildchain-sha> \\\n --publisher-workflow .github/workflows/buildchain-ref-promotion.yml \\\n --job promote \\\n --environment none\n\n# Optional stronger external evidence; generate the JSON outside the workflow.\nbuildchain audit publication-control-plane \\\n --repository kungfu-systems/buildchain \\\n --branch dev/v2/v2.12 \\\n --workflow .github/workflows/release-candidate-promote.yml \\\n --publisher-workflow .github/workflows/buildchain-ref-promotion.yml \\\n --job promote \\\n --environment none \\\n --npm-trust-json sanitized-npm-trust.json\n\nbuildchain audit publication-control-plane \\\n --repository kungfu-systems/buildchain \\\n --branch release/v2/v2.12 \\\n --workflow .github/workflows/.binary-release-assets.yml \\\n --job publish \\\n --environment buildchain-release-assets \\\n --publisher-mode github-token\n\nbuildchain audit publication-control-plane \\\n --repository OWNER/CONSUMER \\\n --workflow-repository kungfu-systems/buildchain \\\n --branch main \\\n --workflow .github/workflows/.web-surface.yml \\\n --job production-apply \\\n --environment production \\\n --publisher-mode oidc-role \\\n --provider-audit-json sanitized-oidc-role-audit.json\n```\n\nThe authority workflow identifies the reusable implementation that performs the\npublication job. The publisher workflow identifies the caller filename bound by\nthe provider's trusted-publisher policy; these identities are deliberately\nseparate. `--environment none` is an explicit assertion that the job declares no\nGitHub Environment and the provider policy has no Environment restriction. A\nnamed Environment must exist, be protected, and be declared by the job. The\nBuildchain receipt alone is never sufficient authorization.\n\n## Publication lanes\n\n`Binary Distribution` is evidence-only. It builds platform archives and a\nrelease evidence bundle with read-only repository permissions. GitHub Release\nasset writes live in `Binary Release Assets`, which downloads an exact prior\nevidence run, verifies its bundle digest against the sealed capability, and is\nthe only binary job with `contents: write` in the protected\n`buildchain-release-assets` Environment.\n\nThe npm/promotion, paper, binary-release, and web-production lanes all depend on\nthe independent verifier. Preview, staging, build, source-check, controller,\nand failure-evidence lanes do not inherit product publication capability."
1114
+ "markdown": "---\nstatus: draft\nperiod: ongoing\ntheme: sealed-publication-authority\ndoc_type: protocol\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-07-15\nai_provenance:\n model_family: GPT-5\n product: Codex\n generated_at: 2026-07-15\n limits: Live provider configuration must be re-audited; no credential values are represented.\n---\n\n# Sealed Publication Authority\n\nBuildchain publication authority is a closed-world, fail-closed protocol. It does\nnot mint registry or cloud credentials. It independently verifies whether an\nalready protected publication job is allowed to request a short-lived provider\ncredential for one exact product, target, version, channel, and artifact digest.\n\nThe machine-readable authority inventory is\n`dist/site/publication-authority-registry.json`. Any workflow with a write,\nenvironment, OIDC, cloud credential, registry publish, release, or Git push\nsignal must have an explicit descriptor. A new authority-bearing workflow that\nis absent from the inventory fails site generation. Unknown workflows and every\ndescriptor not marked `product-publication` are denied product publication.\n\n## Evidence chain\n\nA qualifying admission binds exact source and runtime SHAs; contract, consumer\npolicy, qualifying controller receipt, Shifu/Gate aggregate, artifact, runner,\nand control-plane digests; repository, authority workflow, provider publisher\nworkflow, Environment policy,\nproduct, target, version, and channel; plus a unique nonce and a lifetime of no\nmore than 15 minutes. Every expected binding is mandatory at verification time;\nan omitted expected field is not a wildcard.\n\nThe independent verifier recomputes every digest and ignores a producer's own\nallow/deny conclusion. It fetches the exact evidence run, validates the actual\nrelease-candidate passport and referenced qualifying controller receipt,\nrecomputes the Shifu Gate aggregate or explicit consumer-owned no-Gate policy,\nrecomputes the downloaded artifact manifests, and hashes every declared product\npayload file against those manifests. The `.buildchain/` diagnostics envelope is\nbound by the manifest digest but excluded from the product-byte set because it can\nbe finalized after the lifecycle scan. The verifier also compares the PR evidence tree to the\nadmitted post-merge source commit tree. It rejects an unknown\nworkflow, stale or replayed nonce, runner downgrade, control-plane drift,\nsource/runtime mismatch, and artifact substitution. A successful result is a\nscoped capability receipt, not a bearer credential.\n\n## Runner and control-plane evidence\n\nRunner evidence uses exactly four classes: `ephemeral`, `reimaged`,\n`persistent-measured`, and `unqualified`. Ephemeral runners also record their\njob-isolation boundary. Reimaged and persistent runners qualify only when a\nclean baseline is proven and baseline, toolchain, cache-contract, and task-\nisolation digests are all present. Otherwise they still emit diagnostic\nevidence with `qualificationStatus = unqualified`, but cannot receive a product\ncapability.\n\nThe external audit records digests and pass/fail status for repository Actions\ndefaults, classic branch protection or an active matching repository ruleset,\ndeclared protected Environment policy or an explicit no-Environment binding,\njob-scoped credentials,\nabsence of long-lived workflow publication credentials, provider authority,\nand authorized runner class. Provider modes are `npm-trusted-publisher`,\n`github-token`, and `oidc-role`. The OIDC-role mode consumes only a sanitized\nprovider audit containing a role digest and qualifying decision; raw IAM policy,\ntokens, or credentials are rejected. Package-owner, cloud-root, GitHub\nadministrator, and registry-root credentials remain outside Buildchain's trust\nboundary. Missing or unreadable facts fail closed.\n\nAn unauthenticated local npm CLI is not evidence that Trusted Publishing is\nmissing. `npm whoami` reports only the local CLI session and does not report the\nOIDC identity that npm creates during `npm publish`. The default read-only audit\ntherefore binds the exact provider, repository, caller workflow, optional\nEnvironment, job-scoped OIDC permission, and absence of long-lived credentials,\nthen records `provider-at-transaction`: npm makes the final authorization\ndecision when `npm publish` exchanges the job's OIDC token. A missing or drifted\ntrusted-publisher configuration consequently denies the transaction safely; it\nis not preflighted through an unrelated long-lived npm login.\n\nAn authenticated external auditor can add stronger point-in-time evidence by\nsupplying sanitized `npm trust list --json` output with `--npm-trust-json`. This\nchanges the publisher fact to `audited-control-plane`; the workflow never runs\n`npm trust list` itself and never receives that auditor's npm credential.\n\nThe credential-free collector proves effective Actions and runner scope from\nthe publication workflow fetched at `--workflow-ref`: explicit read-only\nworkflow defaults, job-scoped write/OIDC permissions, and an exact GitHub-hosted\nrunner label. It does not call repository Actions-default or self-hosted-runner\nadministration endpoints. Branch/ruleset and OIDC subject facts remain live\nread-only provider queries. When the detailed branch-protection endpoint is not\nreadable with the workflow token, `--source-sha` binds the provider's public\nprotected-branch summary to the exact merged PR, independent approval, required\nsuccessful check, same-repository lineage, and current branch head. This records\nprovider-enforced transaction evidence without treating an unavailable\nadministration endpoint as an unprotected branch. It avoids turning a\nrepository-admin token into a publication prerequisite.\n\nFor non-dry-run workflows, missing admission, runner, control-plane, Gate, or\nexpected-binding evidence is rejected before Buildchain downloads candidate\nartifacts. The denial explicitly records that npm Trusted Publishing and OIDC\nwere not evaluated, so downstream diagnostics cannot misclassify an admission\nassembly failure as an npm authentication failure.\n\nAn explicitly opted-in managed `workflow_run` promotion lane may assemble those\ninputs from evidence owned by its caller repository. It downloads the exact prior RC passport,\nsummary, referenced controller receipt, manifests, and product payloads; proves\nthe admitted channel commit has the same Git tree as the RC; performs the live\nread-only control-plane audit; records the GitHub-hosted job as ephemeral runner\nprovenance; and consumes either a caller-supplied Gate aggregate or an explicit\ncaller no-Gate decision. The\nindependent verifier then recomputes every receipt and payload digest exactly as\nit does for externally supplied admission. Automatic assembly keeps Buildchain\nas the canonical authority repository, requires evidence to belong to the\ncaller, binds a repository-local publisher workflow, and rejects unknown refs,\nnon-exact source SHAs, package/target mismatches, or an undeclared Gate policy.\nManual apply and consumers that do not opt in still require their own explicit\nadmission inputs.\n\nBefore authority verification, the reusable promotion controller runs the same\nrelease transaction selector in read-only mode. That plan supplies one exact\npublication version and tag to the admission verifier, the publish-gate source\nlock, and the real promotion action. The verifier rejects a capability for a\ndifferent version, and the promotion action rechecks the planned version before\nany publish transaction side effect. Release-candidate fixture versions are\nartifact evidence only; they never name Buildchain's own source-lock or\npublication capability.\n\nEvidence publication is a separate authority class and never grants product\npublication.\n\n## API and CLI\n\nUse `@kungfu-tech/buildchain/publication-authority` or run:\n\n```bash\nbuildchain verify publication-admission admission.json \\\n --registry-json publication-authority-registry.json \\\n --runner-json runner.json \\\n --control-plane-audit-json control-plane.json \\\n --publication-evidence-json publication-evidence.json \\\n --expected-json expected.json \\\n --used-nonce previous-run-nonce \\\n --json\n```\n\nThe read-only live collector defaults to npm trusted publishing. Other product\nproviders select an explicit adapter:\n\n```bash\nbuildchain audit publication-control-plane \\\n --repository kungfu-systems/buildchain \\\n --branch dev/v2/v2.12 \\\n --source-sha <exact-merged-branch-sha> \\\n --workflow .github/workflows/release-candidate-promote.yml \\\n --workflow-ref <exact-buildchain-sha> \\\n --publisher-workflow .github/workflows/buildchain-ref-promotion.yml \\\n --job promote \\\n --environment none\n\n# Optional stronger external evidence; generate the JSON outside the workflow.\nbuildchain audit publication-control-plane \\\n --repository kungfu-systems/buildchain \\\n --branch dev/v2/v2.12 \\\n --workflow .github/workflows/release-candidate-promote.yml \\\n --publisher-workflow .github/workflows/buildchain-ref-promotion.yml \\\n --job promote \\\n --environment none \\\n --npm-trust-json sanitized-npm-trust.json\n\nbuildchain audit publication-control-plane \\\n --repository kungfu-systems/buildchain \\\n --branch release/v2/v2.12 \\\n --workflow .github/workflows/.binary-release-assets.yml \\\n --job publish \\\n --environment buildchain-release-assets \\\n --publisher-mode github-token\n\nbuildchain audit publication-control-plane \\\n --repository OWNER/CONSUMER \\\n --workflow-repository kungfu-systems/buildchain \\\n --branch main \\\n --workflow .github/workflows/.web-surface.yml \\\n --job production-apply \\\n --environment production \\\n --publisher-mode oidc-role \\\n --provider-audit-json sanitized-oidc-role-audit.json\n```\n\nThe authority workflow identifies the reusable implementation that performs the\npublication job. The publisher workflow identifies the caller filename bound by\nthe provider's trusted-publisher policy; these identities are deliberately\nseparate. `--environment none` is an explicit assertion that the job declares no\nGitHub Environment and the provider policy has no Environment restriction. A\nnamed Environment must exist, be protected, and be declared by the job. The\nBuildchain receipt alone is never sufficient authorization.\n\n## Publication lanes\n\n`Binary Distribution` is evidence-only. It builds platform archives and a\nrelease evidence bundle with read-only repository permissions. GitHub Release\nasset writes live in `Binary Release Assets`, which downloads an exact prior\nevidence run, verifies its bundle digest against the sealed capability, and is\nthe only binary job with `contents: write` in the protected\n`buildchain-release-assets` Environment.\n\nThe npm/promotion, paper, binary-release, and web-production lanes all depend on\nthe independent verifier. Preview, staging, build, source-check, controller,\nand failure-evidence lanes do not inherit product publication capability."
1115
1115
  },
1116
1116
  {
1117
1117
  "id": "manual:publish-transaction",
@@ -1248,7 +1248,7 @@
1248
1248
  ],
1249
1249
  "maturity": "stable",
1250
1250
  "sourcePath": "docs/release-candidate.md",
1251
- "digest": "sha256:841d6f3281ba6dfe80527e4f149807bdbd05d41f9e94afe1c446fcd6d29e307c",
1251
+ "digest": "sha256:6a20c6e3e483327d5ccbe70271f7fb4752731bd0523eeddb96f27b2b6ebf1cf8",
1252
1252
  "headings": [
1253
1253
  {
1254
1254
  "level": 1,
@@ -1256,7 +1256,7 @@
1256
1256
  "anchor": "release-candidate-passport"
1257
1257
  }
1258
1258
  ],
1259
- "markdown": "# Release Candidate Passport\n\nThe release-candidate passport is the pre-promotion evidence contract produced\nafter a reusable build matrix succeeds and before any publish-gate side effects\nrun. It is different from the release passport:\n\n- `release-candidate-passport.json` proves which source SHA, channel, runtime,\n workflow run, and platform artifacts were verified before promotion.\n- `buildchain.release.json` is generated after publish finalization and remains\n the durable audit entrypoint for the published release.\n\nEnable it on the reusable build workflow:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n artifact-name: libnode\n release-candidate: true\n publish-channel: alpha\n publish-source-ref: publish-gate/alpha/v22/v22.22/22.22.3-kf.3-alpha.7\n```\n\nWhen the platform matrix and aggregate summaries complete, Buildchain uploads:\n\n```text\n<artifact-name>-release-candidate-<publish-source-sha>\n```\n\nThe passport contract is `kungfu-buildchain-release-candidate-passport`. It\ncontains:\n\n- repository and pull request context;\n- target channel, target ref, and product version or a non-publish\n `source-<shortSha>` candidate label;\n- source head SHA, merge ref SHA, and the Git `HEAD^{tree}` SHA for PR merge\n equivalence after the channel PR lands;\n- Buildchain runtime ref/SHA and workflow shell ref;\n- workflow run id/attempt/url;\n- normalized platform matrix and artifact summaries;\n- the hash of the aggregate `build-summary.json`.\n\nPromotion workflows that should not rebuild artifacts can enable:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nWith `promote-only-release-candidate: \"true\"`, promotion fails before\nversion-state, publish transaction, tag, or branch side effects when the\npassport does not match the repository, channel, source identity, platform\nmatrix, or build-summary hash. Source identity accepts the exact PR source SHA,\nthe PR merge ref SHA, or an exact Git tree match with the promoted channel HEAD;\nthis keeps post-merge channel commits strict without forcing a rebuild. The\nBuildchain-owned promotion workflow resolves the matching same-repository\nmerged channel PR and downloads its PR-stage RC passport automatically before\npromotion starts. The consumer wrapper defaults to a PR-stage workflow file\nnamed `build.yml` with display name `Build`, and filters the RC passport and\nbuild summary by the configured `artifact-name` before promotion. It also\ndownloads payload artifacts from the same PR-stage run, validates the required\npayload count, passes downloaded platform manifests into the release passport,\nand either forwards an explicit `publish-required-artifacts-json` value or\ngenerates one before calling `promote-buildchain-ref`. Before that call, the\nwrapper creates or updates `publish-gate/{alpha,release,major}` to the\npromotion channel commit and passes that ref, target SHA, and `locked=true` to\nthe promote action with `require-publish-source-lock: \"true\"`. Consumers using\nfloating `@v2` therefore get publish-side source-lock drift protection without\ncopying resolver or promote YAML. The default npm path\ngenerates that requirement list from the downloaded `.tgz` payloads themselves:\nBuildchain reads `package/package.json` inside each tarball for the real scoped\npackage name and version, computes npm-style `sha512-...` integrity over the\ntarball bytes, marks `publish-package-main` as `role: main`, and marks every\nother package as `role: platform`. Consumer workflows therefore stay\ndeclarative and do not need their own artifact download or publish-evidence\ngeneration scripts.\n\nBy default, the wrapper forwards GitHub Release publication to the underlying\n`promote-buildchain-ref` semver model. Once the release transaction is complete,\nthe action creates or updates the public GitHub Release, applies\nprerelease/latest metadata from the semver tag, and uploads the publish evidence\nfile together with the generated release passport assets. This keeps\nnpm/registry publication, Buildchain release passport persistence, and\n`release.published` propagation in one declarative reusable workflow. Consumers\nthat do not publish GitHub Releases can opt out with `github-release: false`.\nFor anchored/manual package releases, the public GitHub Release tag defaults to\n`v<publishedVersion>` while the internal transaction exact tag remains recorded\nin the release passport.\n\nProducts that publish KFD release trust evidence can keep that path declarative\ntoo. Pass KFD-1 self contract witnesses, KFD-2 public claim files, and KFD-3\npre-build/artifact evidence into the wrapper:\n\n```yaml\njobs:\n promote:\n uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@v2\n with:\n channel: alpha\n artifact-name: libnode\n release-passport-kfd-1-witness-jsons: .buildchain/kfd/kfd-1/standard-contract.witness.json\n release-passport-kfd-2-claim-jsons: .buildchain/kfd/kfd-2/release-claims.json\n release-passport-kfd-3-prebuild-witness-jsons: .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json\n release-passport-kfd-3-artifact-verify-command: kungfu agent verify --json\n```\n\nBuildchain forwards those declarations into `promote-buildchain-ref`, verifies\nKFD-1 source/artifact contract surfaces, audits KFD-2 public release claims, and\ncompares KFD-3 declared shipped public surfaces with artifact-exposed public\nsurfaces. The release passport records the results under `kfd-1`, `kfd-2`, and\nthe KFD-provided `kfd-3` section."
1259
+ "markdown": "# Release Candidate Passport\n\nThe release-candidate passport is the pre-promotion evidence contract produced\nafter a reusable build matrix succeeds and before any publish-gate side effects\nrun. It is different from the release passport:\n\n- `release-candidate-passport.json` proves which source SHA, channel, runtime,\n workflow run, and platform artifacts were verified before promotion.\n- `buildchain.release.json` is generated after publish finalization and remains\n the durable audit entrypoint for the published release.\n\nEnable it on the reusable build workflow:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n artifact-name: libnode\n release-candidate: true\n publish-channel: alpha\n publish-source-ref: publish-gate/alpha/v22/v22.22/22.22.3-kf.3-alpha.7\n```\n\nWhen the platform matrix and aggregate summaries complete, Buildchain uploads:\n\n```text\n<artifact-name>-release-candidate-<publish-source-sha>\n```\n\nThe passport contract is `kungfu-buildchain-release-candidate-passport`. It\ncontains:\n\n- repository and pull request context;\n- target channel, target ref, and product version or a non-publish\n `source-<shortSha>` candidate label;\n- source head SHA, merge ref SHA, and the Git `HEAD^{tree}` SHA for PR merge\n equivalence after the channel PR lands;\n- Buildchain runtime ref/SHA and workflow shell ref;\n- workflow run id/attempt/url;\n- normalized platform matrix and artifact summaries;\n- the hash of the aggregate `build-summary.json`.\n\nPromotion workflows that should not rebuild artifacts can enable:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nWith `promote-only-release-candidate: \"true\"`, promotion fails before\nversion-state, publish transaction, tag, or branch side effects when the\npassport does not match the repository, channel, source identity, platform\nmatrix, or build-summary hash. Source identity accepts the exact PR source SHA,\nthe PR merge ref SHA, or an exact Git tree match with the promoted channel HEAD;\nthis keeps post-merge channel commits strict without forcing a rebuild. The\nBuildchain-owned promotion workflow resolves the matching same-repository\nmerged channel PR and downloads its PR-stage RC passport automatically before\npromotion starts. The consumer wrapper defaults to a PR-stage workflow file\nnamed `build.yml` with display name `Build`, and filters the RC passport and\nbuild summary by the configured `artifact-name` before promotion. It also\ndownloads payload artifacts from the same PR-stage run, validates the required\npayload count, passes downloaded platform manifests into the release passport,\nand either forwards an explicit `publish-required-artifacts-json` value or\ngenerates one before calling `promote-buildchain-ref`. Before that call, the\nwrapper creates or updates `publish-gate/{alpha,release,major}` to the\npromotion channel commit and passes that ref, target SHA, and `locked=true` to\nthe promote action with `require-publish-source-lock: \"true\"`. Consumers using\nfloating `@v2` therefore get publish-side source-lock drift protection without\ncopying resolver or promote YAML. The default npm path\ngenerates that requirement list from the downloaded `.tgz` payloads themselves:\nBuildchain reads `package/package.json` inside each tarball for the real scoped\npackage name and version, computes npm-style `sha512-...` integrity over the\ntarball bytes, marks `publish-package-main` as `role: main`, and marks every\nother package as `role: platform`. Consumer workflows therefore stay\ndeclarative and do not need their own artifact download or publish-evidence\ngeneration scripts.\n\nBy default, the wrapper forwards GitHub Release publication to the underlying\n`promote-buildchain-ref` semver model. Once the release transaction is complete,\nthe action creates or updates the public GitHub Release, applies\nprerelease/latest metadata from the semver tag, and uploads the publish evidence\nfile together with the generated release passport assets. This keeps\nnpm/registry publication, Buildchain release passport persistence, and\n`release.published` propagation in one declarative reusable workflow. Consumers\nthat do not publish GitHub Releases can opt out with `github-release: false`.\nFor anchored/manual package releases, the public GitHub Release tag defaults to\n`v<publishedVersion>` while the internal transaction exact tag remains recorded\nin the release passport.\n\nProducts that publish KFD release trust evidence can keep that path declarative\ntoo. Pass KFD-1 self contract witnesses, KFD-2 public claim files, and KFD-3\npre-build/artifact evidence into the wrapper:\n\n```yaml\njobs:\n promote:\n uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@v2\n with:\n channel: alpha\n artifact-name: libnode\n release-passport-kfd-1-witness-jsons: .buildchain/kfd/kfd-1/standard-contract.witness.json\n release-passport-kfd-2-claim-jsons: .buildchain/kfd/kfd-2/release-claims.json\n release-passport-kfd-3-prebuild-witness-jsons: .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json\n release-passport-kfd-3-artifact-verify-command: kungfu agent verify --json\n```\n\nBuildchain forwards those declarations into `promote-buildchain-ref`, verifies\nKFD-1 source/artifact contract surfaces, audits KFD-2 public release claims, and\ncompares KFD-3 declared shipped public surfaces with artifact-exposed public\nsurfaces. The release passport records the results under `kfd-1`, `kfd-2`, and\nthe KFD-provided `kfd-3` section.\n\nManaged consumers may also ask the promotion wrapper to assemble sealed\npublication evidence from the exact release candidate instead of producing\nshort-lived admission JSON in repository-specific workflow code:\n\n```yaml\n publication-auto-admission: true\n publication-auto-no-gate: true\n publication-publisher-workflow-path: .github/workflows/buildchain-ref-promotion.yml\n publication-product: Example Product\n publication-target: npm:@example/product\n publication-package-name: \"@example/product\"\n```\n\n`publication-auto-no-gate` is an explicit consumer decision, not a default. A\nconsumer with a Shifu Gate registry supplies `publication-gate-aggregate-json`\ninstead. Buildchain still requires caller-owned RC evidence, an exact authority\nruntime and source SHA, a repository-local publisher workflow, matching npm\ntarget/package identity, and a qualifying control-plane audit."
1260
1260
  },
1261
1261
  {
1262
1262
  "id": "manual:release-flow",
@@ -2474,7 +2474,7 @@
2474
2474
  "path": "docs/publication-authority.md",
2475
2475
  "plane": "verify",
2476
2476
  "exists": true,
2477
- "digest": "sha256:06ba05f9d8a2685a0896334b6013a97c45b7d71163cf6898e5a6274baf7f0296"
2477
+ "digest": "sha256:05bc22c7e5885e591bc121fc43f588e5d49ccf0a8de6a642811c1d0d03dcee1e"
2478
2478
  },
2479
2479
  {
2480
2480
  "id": "release-candidate",
@@ -2482,7 +2482,7 @@
2482
2482
  "path": "docs/release-candidate.md",
2483
2483
  "plane": "verify",
2484
2484
  "exists": true,
2485
- "digest": "sha256:841d6f3281ba6dfe80527e4f149807bdbd05d41f9e94afe1c446fcd6d29e307c"
2485
+ "digest": "sha256:6a20c6e3e483327d5ccbe70271f7fb4752731bd0523eeddb96f27b2b6ebf1cf8"
2486
2486
  },
2487
2487
  {
2488
2488
  "id": "release-propagation",
@@ -1441,6 +1441,10 @@
1441
1441
  "classification": "included",
1442
1442
  "source": "workflow-call-input"
1443
1443
  },
1444
+ "publication-auto-no-gate": {
1445
+ "classification": "included",
1446
+ "source": "workflow-call-input"
1447
+ },
1444
1448
  "publication-control-plane-audit-json": {
1445
1449
  "classification": "digest-only",
1446
1450
  "source": "workflow-call-input"
@@ -1627,7 +1631,7 @@
1627
1631
  "controller-receipt"
1628
1632
  ]
1629
1633
  },
1630
- "digest": "sha256:c2f1fd6e984606b077b27bb243b66077162c2c4be03f99c0d8f917bf7bf4d0d1"
1634
+ "digest": "sha256:c5dfeb63bbe3507e3c58f74e2a5792e6558002e3aafab6453cc8b8837db2a729"
1631
1635
  },
1632
1636
  {
1633
1637
  "schemaVersion": 1,
@@ -1733,5 +1737,5 @@
1733
1737
  "digest": "sha256:9b9f9a2320c4349903d72ee46e329211b5538ed5ebebaa93559df4eafb835997"
1734
1738
  }
1735
1739
  ],
1736
- "digest": "sha256:aeb2d6b05cdd8e8118d6cc2c82cf4b7bf00f934b809479017a12b69c299d0e05"
1740
+ "digest": "sha256:22be9d05109396f2b5c44a74fb0f67e4a554c462662c5a41e44e466c4d90ed04"
1737
1741
  }