@kungfu-tech/buildchain 4.0.2-alpha.50 → 4.0.2-alpha.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/architecture/agent-change-map.md +1 -0
- package/architecture/maintainability-debt.json +1 -0
- package/architecture/maintainability-policy.json +3 -3
- package/dist/site/buildchain-contract.json +2 -2
- package/dist/site/buildchain-site.json +6 -6
- package/dist/site/kfd-claims.json +2 -2
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/page-registry.json +2 -2
- package/dist/site/public-surface-audit.json +2 -2
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +4 -4
- package/dist/site/workflow-registry.json +5 -5
- package/docs/oci-publication.md +13 -0
- package/package.json +1 -1
- package/packages/core/oci-compose-qualification.js +4 -1
- package/scripts/oci-compose-preview.mjs +14 -3
- package/scripts/v3-v4-capability-catalog.mjs +1 -1
|
@@ -153,6 +153,7 @@ Safe change route: Reduce one owned responsibility behind the stable facade, run
|
|
|
153
153
|
|
|
154
154
|
### Current top twenty maintenance hotspots
|
|
155
155
|
|
|
156
|
+
- `tests/v4-product-publication-topology.test.mjs`
|
|
156
157
|
- `.github/workflows/.build.yml`
|
|
157
158
|
- `.github/workflows/.publication-authority.yml`
|
|
158
159
|
- `.github/workflows/bootstrap.yml`
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"repositoryBudgets": {
|
|
28
28
|
"baselineRevision": "9569f69c2cb609372b8a3d65ce5dec8fb7b34a84",
|
|
29
29
|
"maxHandMaintainedSourceFiles": 493,
|
|
30
|
-
"maxHandMaintainedSourceLines":
|
|
30
|
+
"maxHandMaintainedSourceLines": 174652,
|
|
31
31
|
"maxWorkflowFiles": 80,
|
|
32
32
|
"maxWorkflowLines": 26791,
|
|
33
|
-
"latestTransition": "
|
|
34
|
-
"latestTransitionRationale": "Charge
|
|
33
|
+
"latestTransition": "Separate Compose preview registry identity from GitHub governance identity.",
|
|
34
|
+
"latestTransitionRationale": "Charge eleven measured production source lines for explicit scoped registry identity and fail-closed missing-credential checks. Preserve complete settlement, qualification and preview gates without increasing file, function, complexity, debt or exception limits; require independent governance review and credential-routing/write-rejection tests.",
|
|
35
35
|
"rationale": "Bounded modules separate candidate, evidence, native proof and execution, canonical failure verification, closed-set execution transfer, process-boundary verification, Warrant state and qualification, authority state, qualification, Landing acquisition, verified-attempt admission, Landing settlement and fence validation, provider attempt and heartbeat readback, sealed terminal evidence, hosted heartbeat, resume, store, options, command-specific adapters, and CLI orchestration responsibilities. The protected delivery workflow gives candidate and seal jobs no provider write credential, recursively rejects transfer drift, scopes every transfer artifact to the exact provider run attempt, chains every durable heartbeat state and receipt root on a distinct hosted runner domain, and permits qualification or exact failure settlement only after the finalizer verifies live jobs and the latest durable authority state. Public Landing admission and heartbeat always perform non-injectable fresh exact-attempt provider readback, tolerate only a not-yet-materialized seal job while retaining exact native and duplicate-job rejection, and heartbeat-loss coordination never invokes GitHub's run-scoped cancellation API where a successor rerun could race. The hosted process boundary anchors trust in the kernel-resolved versioned Runner.Worker path while accepting an equivalent argv-zero spelling with the same basename; its public boundary marker is allowed only at the one exact non-secret value, so a forged value under the same credential-like name still fails closed. The credentialless transfer seal validates the rooted native reuse decision against the Warrant-bound source, closure, dependency, toolchain, environment and command inputs; qualifiedBase stays in the proof and decision where it is rooted and later independently rechecked, rather than being assumed on the Warrant schema. V2 mutation cannot initialize a second empty authority beside a legacy ref: migration reads and roots the canonical live v1 ref, rechecks it, applies the explicit configured v2 policy, and atomically replaces its bytes through one expected-old non-force update, so old v1 controllers fail closed while the prior commit remains immutable history. Candidate ancestry classifies the GitHub artifact runtime token as credential authority. Every Landing settlement, including an unexpired fence, requires product-owned terminal readback. Terminal cleanup reads the immutable historical attempt, derives workflow and hosted Landing job identity from live run data, reads the exact protected ref head and compares containment against that immutable SHA, and seals merged only when the admitted merge-group head is contained by that protected base; a later different-head merge settles the old attempt as dequeued. Terminal normalization preserves transfer, finalizer boundary, native and seal job, admitted provider attempt, protected-base head, containment result, and terminal readback coordinates. The public reusable workflow truthfully retains its single-flight v1 authority without advertising v2 migration, while bounded v2 remains a separate opt-in CLI, Node API, and schema contract; the tracked self-caller stays on public v4-alpha with matching stable and alpha locks, and transient train selection is dispatch-only. Next-development parity adds one versioned transition authority, one durable controller, one bounded reservation adapter, and pure public-contract recovery evidence while retaining the existing thin floating-channel callers byte-for-byte. The floating-consumer gate reuses the existing contract-world evaluator so SHA drift passes only under the selected lock's compatibility policy, breaking surface drift still fails closed, and external certification reconstructs the receipt from the observed workflow SHA rather than the lock's historical evidence SHA. Tail reseal adds no Stage Capsule effect or general rebuild authority: it verifies the exact retained four-platform bytes, admits one known macOS tail failure through live provider readback, fences signing and finalization to explicit credentials and Warrant identity, and requires standard candidate Passport plus provider and protected readback. Compatibility Facts parity isolates canonical encoding, temporal verification, lifecycle validation, fixture projection, public authority projection, and CLI adaptation into bounded modules; legacy digest and proof arrays are derived only from exact current Fact lineage. Publication Rehearsal adds no production release authority: the content-addressed capsule contract binds source, candidate, manifest, config, canonical data-only provider bindings, provider policy, observations and core version separately from filesystem, runtime and rehearsal-only provider authority; simulate, replay and explicitly authorized provider rehearsal all reuse the release-tail planner, while same-commit local dogfood resolves the new reusable contract and exact current runtime before external callers remain on floating v4-alpha. Cross-runtime candidate recovery preserves original runtime and provider roots and creates resume lineage only after exact public ref, tag, ancestry, npm version and integrity readback. Adopter Delivery restores the reviewed public v3 gate, drivers, Passport binding, N-1 bootstrap and exact archive loader through one public v4 surface while keeping provider and release authority explicit non-claims. Floating Alpha bootstrap uses only the existing exact resolver and protected Alpha private shell to move an otherwise stale floating shell, retains public v4 stable promotion, and removes itself after protected readback. CI lane change-budget enforcement adds a bounded parser, evaluator, guard, and tests without creating another merge authority.",
|
|
36
36
|
"governance": "legacy-debt-sunset-2026q4"
|
|
37
37
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"product": {
|
|
5
5
|
"name": "Buildchain",
|
|
6
6
|
"package": "@kungfu-tech/buildchain",
|
|
7
|
-
"version": "4.0.2-alpha.
|
|
7
|
+
"version": "4.0.2-alpha.52",
|
|
8
8
|
"repository": "https://github.com/kungfu-systems/buildchain"
|
|
9
9
|
},
|
|
10
10
|
"majorLine": "v4",
|
|
@@ -5444,5 +5444,5 @@
|
|
|
5444
5444
|
"compatibilityFactCutRoot": "sha256:f61b975d4a96c921cc4bd37fb3ed9a0596b47004fe34dc7219979d697e3707f9",
|
|
5445
5445
|
"compatibilityProofRegistryRoot": "sha256:b7194b811e4d3af2df4390bc4d1731e16a86215bd64ee18cb630dd5492f4fb63",
|
|
5446
5446
|
"compatibilityDigest": "sha256:20411029d83211dff426fb6535a608902129844a5ccb4788db77d3f81becb839",
|
|
5447
|
-
"contractDigest": "sha256:
|
|
5447
|
+
"contractDigest": "sha256:4fd3bb75ecca81313c2d3cd669dd2e7ec729bb8ba11888ab26a8b6ed9cfc0263"
|
|
5448
5448
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-bundle",
|
|
4
|
-
"generatedAt": "2026-09-
|
|
5
|
-
"publishedAt": "2026-09-
|
|
4
|
+
"generatedAt": "2026-09-07T04:57:43.000Z",
|
|
5
|
+
"publishedAt": "2026-09-07T04:57:43.000Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "14b13cfc51afcadd251eee71d7e42842c35ce273",
|
|
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": "4.0.2-alpha.
|
|
40
|
+
"version": "4.0.2-alpha.52",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"source": {
|
|
@@ -3562,7 +3562,7 @@
|
|
|
3562
3562
|
],
|
|
3563
3563
|
"maturity": "stable",
|
|
3564
3564
|
"sourcePath": "docs/oci-publication.md",
|
|
3565
|
-
"digest": "sha256:
|
|
3565
|
+
"digest": "sha256:daed970a66eb7b7cac87334d09e61449e8662c0655c7a345667bd2ef74f53af8",
|
|
3566
3566
|
"headings": [
|
|
3567
3567
|
{
|
|
3568
3568
|
"level": 1,
|
|
@@ -3590,7 +3590,7 @@
|
|
|
3590
3590
|
"anchor": "evidence-gated-compose-preview"
|
|
3591
3591
|
}
|
|
3592
3592
|
],
|
|
3593
|
-
"markdown": "---\nstatus: draft\nperiod: ongoing\ntheme: oci-publication\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-07\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-06\n invisible_context_boundary: No credentials or production registry state inspected.\n---\n\n# OCI image family publication\n\nBuildchain v4 can publish a sealed family of container images to GHCR through\n`publish-artifact-kind: oci` on the public release candidate promotion workflow.\nThe candidate build produces the image bytes and smoke evidence. The built-in\nprovider verifies and uploads those bytes, reads back every public image digest,\nthen allows release references and GitHub Release evidence to converge.\n\n## Candidate contract\n\nPublish exactly one `oci-family.json` alongside OCI layouts and smoke JSON files\nin the Build artifact. Import `sealOciPublicationBundle` from\n`@kungfu-tech/buildchain/oci-publication` to validate and seal the family. Its\n`body` contains:\n\n- `schema: kungfu-buildchain-oci-family/v1`, consumer `repository`, exact Git\n `sourceSha`, and candidate package `version`.\n- `expectedImages`: the complete set of image names.\n- `images`: one entry for each expected image, with `name`, `repository`,\n `digest`, `layout`, `platform`, `action`, `content`, and `smoke`.\n\nDestinations must be `ghcr.io/<consumer-owner>/<consumer-repo>/<image-name>`.\n`layout` is a relative OCI layout directory. Each image is a single Linux\namd64 or arm64 manifest; OCI and Docker schema 2 manifests are supported.\nLayouts may share blobs and an index; each shared index entry identifies its\nimage with the `org.opencontainers.image.ref.name` annotation.\n\n`content` records the image's original `sourceSha` and `version`, matching its\nOCI revision/version labels. For `action: built`, both equal the candidate.\nFor `action: reused`, they retain the original content provenance while the\nfamily binds the current candidate. `smoke` records a relative `path` and SHA256\n`sha256`; its JSON must identify the image and record `passed: true`. The\nconsumer owns the actual smoke command and must fail the build if it fails.\n\nSealing verifies all config/layer sizes and digests, platform and provenance\nlabels, smoke bytes, and family completeness. Absolute paths, traversal, and\nsymlinks are rejected. The resolver derives the exact required image artifacts\nfrom this sealed family, including when recovering a previous candidate run.\n\n## Authority and publication\n\nThe thin caller grants `packages: write` in addition to its existing promotion\npermissions. Reusable promotion wrappers inherit that caller envelope; npm\nconsumers do not need to request package registry authority. The provider uses\nthe action token only for GHCR, scoped to each declared consumer image.\nNo consumer publish command is executed.\n\nThe rooted product plan declares version-state materialization, OCI family\npublication, then release reference convergence. Each image uses the exact\n`v<version>` tag. A different existing digest aborts publication; a matching\nexisting image is reused. After a partial failure, recovery validates the same\ncandidate bytes and publishes only missing images. GHCR does not provide tag\ncompare-and-swap: callers must serialize publishers for a version, and external\nwriters must not race the publication workflow.\n\nSuccess requires anonymous readback of every declared image at its expected\ndigest. Existing GHCR packages must permit the repository token to write and\nanonymous clients to pull. The provider does not change package visibility or\naccess policy. It attaches `oci-publication-readback.json` to the GitHub Release;\nthe caller should also include the family and smoke JSON files in\n`github-release-payload-patterns`.\n\nSee [Runtime Train Validation](runtime-train-validation.md) for testing an\nunreleased runtime without persisting a train or exact SHA in the workflow.\n\n## Multi-platform images and Compose applications\n\nUse `schema: kungfu-buildchain-oci-family/v2` when the family includes an OCI\nindex or a Compose application. Existing v1 families keep their published\nsingle-platform contract.\n\nAn index entry declares `platform: multi-platform` and the complete `platforms`\narray, for example `[\"linux/amd64\", \"linux/arm64\"]`. Every runnable child must\nhave matching platform and content labels. Descriptor sizes, digests and media\ntypes are verified recursively; nested manifests are uploaded before their\nparent index. BuildKit attestation manifests must identify a runnable child and\ncontain matching in-toto subjects. Missing platforms, duplicate platforms,\nforeign URLs and broken blob references fail sealing. Embedded descriptor `data`\nis accepted only as canonical Base64 for at most 1 MiB, with the declared size\nand digest matching the required local blob byte for byte. Malformed or\ninconsistent embedded content fails sealing; manifests are never rewritten.\nThis follows the [OCI embedded-content contract](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#embedded-content).\n\nA Compose entry declares `kind: compose`, `platform: compose`, and `targetImage`\npointing to an image in the same family. Its unique family name may differ from\nthat image, but its destination repository must match it. The immutable tag is\n`compose-v<version>`; image entries retain `v<version>`.\n\nThe bounded Compose representation is an OCI 1.1 image manifest with\n`artifactType: application/vnd.docker.compose.project`, an empty JSON config\nand one `application/vnd.docker.compose.file+yaml` layer. That layer contains\nJSON, a YAML subset, so structural verification needs no executable YAML loader.\nEvery service image is pinned to a digest and at least one uses the exact\nfamily image. Environment interpolation inside other fields can remain intact.\nThese media types follow the [Docker Compose publisher](https://github.com/docker/compose/blob/v5.1.2/internal/oci/push.go).\n\nCandidate smoke evidence describes its actual pre-publication checks. It must\nnot claim that an unpublished public Compose reference was installed. Public\ninstallation qualification occurs after immutable publication and before a\npreview alias moves.\n\n## Evidence-gated Compose preview\n\nAn optional Compose `preview` declaration contains exactly the supported alias\n`compose-preview`, the previously accepted `previousDigest` (or `none`), and\n`qualificationWorkflow`, a repository workflow path. The immutable family seals\nthis policy before any publication effect.\n\nAfter v4 publication is complete, dispatch that qualification workflow on the\nexact published alpha tag. It must pull the immutable public image and Compose,\nrun fresh installation, restart, account-isolation, runtime-hardening, upgrade\nand rollback checks, and qualify both Linux architectures. The workflow has no\nregistry write authority. Upload one artifact named\n`oci-compose-qualification-<run-id>-<run-attempt>` containing `qualification.json`\nand its hash-bound JSON evidence files.\n\nThe receipt uses `schema: kungfu-buildchain-compose-qualification/v1` and binds\n`repository`, `tag`, published `sourceSha`, sealed `familyRoot`, `runId`,\n`runAttempt`, exact `image` and `application` repository/digest references,\n`previousDigest`, and `passed: true`. Its `checks` object requires all of\n`freshInstall`, `restartPersistence`, `upgradePersistence`, `rollbackPersistence`,\n`accountIsolation`, and `hardenedRuntime` to be true. Its `platforms` object\nrequires `linux/amd64` and `linux/arm64` entries with `passed: true`; `evidence`\ncontains nonempty `{path, sha256}` bindings to the actual JSON results.\n\nA thin consumer workflow listens to completion of that qualification workflow\nand calls `public-release-oci-compose-preview.yml@v4-alpha`, passing\n`BUILDCHAIN_PROMOTION_TOKEN`. The reusable workflow resolves its own exact\nruntime, enforces the dual floating-channel locks, verifies the public v4\nsettlement, family and provider readback roots, and checks the live GitHub run's\nrepository, source, workflow, event, attempt and successful conclusion. It never\nexecutes the consumer's artifact files. Only then does it copy the exact Compose\nmanifest bytes to the declared alias and verify the public digest.\n\nThe expected-old digest is checked immediately before mutation. An already\nmatching target is an idempotent success; any other drift blocks the move.\nPublishers for this alias share repository-level concurrency. GHCR has no atomic\ntag compare-and-swap, so external writers must also avoid racing this workflow.\nThe immutable release retains the appended\n`buildchain-compose-preview-<run-id>-<run-attempt>.json` receipt. A failed\nqualification leaves the existing preview intact, while the immutable alpha\nand its original publication evidence remain available for diagnosis."
|
|
3593
|
+
"markdown": "---\nstatus: draft\nperiod: ongoing\ntheme: oci-publication\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-07\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-06\n invisible_context_boundary: No credentials or production registry state inspected.\n---\n\n# OCI image family publication\n\nCompose preview uses the workflow's scoped `packages: write` token for GHCR\nrequests. The separate `BUILDCHAIN_PROMOTION_TOKEN` serves GitHub governance\nand receipt publication; it is never a fallback registry credential. Missing\nregistry identity fails before a write, and an unsuccessful registry response\nreports only its HTTP status while retaining the exact qualification for recovery.\n\nBuildchain v4 can publish a sealed family of container images to GHCR through\n`publish-artifact-kind: oci` on the public release candidate promotion workflow.\nThe candidate build produces the image bytes and smoke evidence. The built-in\nprovider verifies and uploads those bytes, reads back every public image digest,\nthen allows release references and GitHub Release evidence to converge.\n\n## Candidate contract\n\nPublish exactly one `oci-family.json` alongside OCI layouts and smoke JSON files\nin the Build artifact. Import `sealOciPublicationBundle` from\n`@kungfu-tech/buildchain/oci-publication` to validate and seal the family. Its\n`body` contains:\n\n- `schema: kungfu-buildchain-oci-family/v1`, consumer `repository`, exact Git\n `sourceSha`, and candidate package `version`.\n- `expectedImages`: the complete set of image names.\n- `images`: one entry for each expected image, with `name`, `repository`,\n `digest`, `layout`, `platform`, `action`, `content`, and `smoke`.\n\nDestinations must be `ghcr.io/<consumer-owner>/<consumer-repo>/<image-name>`.\n`layout` is a relative OCI layout directory. Each image is a single Linux\namd64 or arm64 manifest; OCI and Docker schema 2 manifests are supported.\nLayouts may share blobs and an index; each shared index entry identifies its\nimage with the `org.opencontainers.image.ref.name` annotation.\n\n`content` records the image's original `sourceSha` and `version`, matching its\nOCI revision/version labels. For `action: built`, both equal the candidate.\nFor `action: reused`, they retain the original content provenance while the\nfamily binds the current candidate. `smoke` records a relative `path` and SHA256\n`sha256`; its JSON must identify the image and record `passed: true`. The\nconsumer owns the actual smoke command and must fail the build if it fails.\n\nSealing verifies all config/layer sizes and digests, platform and provenance\nlabels, smoke bytes, and family completeness. Absolute paths, traversal, and\nsymlinks are rejected. The resolver derives the exact required image artifacts\nfrom this sealed family, including when recovering a previous candidate run.\n\n## Authority and publication\n\nThe thin caller grants `packages: write` in addition to its existing promotion\npermissions. Reusable promotion wrappers inherit that caller envelope; npm\nconsumers do not need to request package registry authority. The provider uses\nthe action token only for GHCR, scoped to each declared consumer image.\nNo consumer publish command is executed.\n\nThe rooted product plan declares version-state materialization, OCI family\npublication, then release reference convergence. Each image uses the exact\n`v<version>` tag. A different existing digest aborts publication; a matching\nexisting image is reused. After a partial failure, recovery validates the same\ncandidate bytes and publishes only missing images. GHCR does not provide tag\ncompare-and-swap: callers must serialize publishers for a version, and external\nwriters must not race the publication workflow.\n\nSuccess requires anonymous readback of every declared image at its expected\ndigest. Existing GHCR packages must permit the repository token to write and\nanonymous clients to pull. The provider does not change package visibility or\naccess policy. It attaches `oci-publication-readback.json` to the GitHub Release;\nthe caller should also include the family and smoke JSON files in\n`github-release-payload-patterns`.\n\nSee [Runtime Train Validation](runtime-train-validation.md) for testing an\nunreleased runtime without persisting a train or exact SHA in the workflow.\n\n## Multi-platform images and Compose applications\n\nUse `schema: kungfu-buildchain-oci-family/v2` when the family includes an OCI\nindex or a Compose application. Existing v1 families keep their published\nsingle-platform contract.\n\nAn index entry declares `platform: multi-platform` and the complete `platforms`\narray, for example `[\"linux/amd64\", \"linux/arm64\"]`. Every runnable child must\nhave matching platform and content labels. Descriptor sizes, digests and media\ntypes are verified recursively; nested manifests are uploaded before their\nparent index. BuildKit attestation manifests must identify a runnable child and\ncontain matching in-toto subjects. Missing platforms, duplicate platforms,\nforeign URLs and broken blob references fail sealing. Embedded descriptor `data`\nis accepted only as canonical Base64 for at most 1 MiB, with the declared size\nand digest matching the required local blob byte for byte. Malformed or\ninconsistent embedded content fails sealing; manifests are never rewritten.\nThis follows the [OCI embedded-content contract](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#embedded-content).\n\nA Compose entry declares `kind: compose`, `platform: compose`, and `targetImage`\npointing to an image in the same family. Its unique family name may differ from\nthat image, but its destination repository must match it. The immutable tag is\n`compose-v<version>`; image entries retain `v<version>`.\n\nThe bounded Compose representation is an OCI 1.1 image manifest with\n`artifactType: application/vnd.docker.compose.project`, an empty JSON config\nand one `application/vnd.docker.compose.file+yaml` layer. That layer contains\nJSON, a YAML subset, so structural verification needs no executable YAML loader.\nEvery service image is pinned to a digest and at least one uses the exact\nfamily image. Environment interpolation inside other fields can remain intact.\nThese media types follow the [Docker Compose publisher](https://github.com/docker/compose/blob/v5.1.2/internal/oci/push.go).\n\nCandidate smoke evidence describes its actual pre-publication checks. It must\nnot claim that an unpublished public Compose reference was installed. Public\ninstallation qualification occurs after immutable publication and before a\npreview alias moves.\n\n## Evidence-gated Compose preview\n\nAn optional Compose `preview` declaration contains exactly the supported alias\n`compose-preview`, the previously accepted `previousDigest` (or `none`), and\n`qualificationWorkflow`, a repository workflow path. The immutable family seals\nthis policy before any publication effect.\n\nAfter v4 publication is complete, dispatch that qualification workflow on the\nexact published alpha tag. It must pull the immutable public image and Compose,\nrun fresh installation, restart, account-isolation, runtime-hardening, upgrade\nand rollback checks, and qualify both Linux architectures. The workflow has no\nregistry write authority. Upload one artifact named\n`oci-compose-qualification-<run-id>-<run-attempt>` containing `qualification.json`\nand its hash-bound JSON evidence files.\n\nThe receipt uses `schema: kungfu-buildchain-compose-qualification/v1` and binds\n`repository`, `tag`, published `sourceSha`, sealed `familyRoot`, `runId`,\n`runAttempt`, exact `image` and `application` repository/digest references,\n`previousDigest`, and `passed: true`. Its `checks` object requires all of\n`freshInstall`, `restartPersistence`, `upgradePersistence`, `rollbackPersistence`,\n`accountIsolation`, and `hardenedRuntime` to be true. Its `platforms` object\nrequires `linux/amd64` and `linux/arm64` entries with `passed: true`; `evidence`\ncontains nonempty `{path, sha256}` bindings to the actual JSON results.\n\nA thin consumer workflow listens to completion of that qualification workflow\nand calls `public-release-oci-compose-preview.yml@v4-alpha`, passing\n`BUILDCHAIN_PROMOTION_TOKEN`. The reusable workflow resolves its own exact\nruntime, enforces the dual floating-channel locks, verifies the public v4\nsettlement, family and provider readback roots, and checks the live GitHub run's\nrepository, source, workflow, event, attempt and successful conclusion. It never\nexecutes the consumer's artifact files. Only then does it copy the exact Compose\nmanifest bytes to the declared alias and verify the public digest.\n\nThe expected-old digest is checked immediately before mutation. An already\nmatching target is an idempotent success; any other drift blocks the move.\nPublishers for this alias share repository-level concurrency. GHCR has no atomic\ntag compare-and-swap, so external writers must also avoid racing this workflow.\nThe immutable release retains the appended\n`buildchain-compose-preview-<run-id>-<run-attempt>.json` receipt. A failed\nqualification leaves the existing preview intact, while the immutable alpha\nand its original publication evidence remain available for diagnosis.\n\nThe verified publication Passport distinguishes the built candidate from the\nprotected publication commit. Compose family source identity follows\n`source.builtSourceSha`; `source.builtSourceTreeSha` must equal the admitted\ninvocation tree. Registry readback and qualification runs remain bound to the\nprotected publication SHA. A tree-equivalent protected merge therefore retains\nthe original image identity without accepting a different source tree."
|
|
3594
3594
|
},
|
|
3595
3595
|
{
|
|
3596
3596
|
"id": "manual:ownership",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"contract": "kungfu-buildchain-public-surface-reverse-audit",
|
|
22
22
|
"path": "dist/site/public-surface-audit.json",
|
|
23
23
|
"status": "passed",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "30a7781b240c20641b0e9e96aa4e2780708dfec5b3671c5dd532540d9a4d341a",
|
|
25
25
|
"summary": {
|
|
26
26
|
"cliCommandCount": 117,
|
|
27
27
|
"workflowCount": 115,
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
"contract": "kungfu-buildchain-public-surface-reverse-audit",
|
|
247
247
|
"path": "dist/site/public-surface-audit.json",
|
|
248
248
|
"status": "passed",
|
|
249
|
-
"sha256": "
|
|
249
|
+
"sha256": "30a7781b240c20641b0e9e96aa4e2780708dfec5b3671c5dd532540d9a4d341a",
|
|
250
250
|
"summary": {
|
|
251
251
|
"cliCommandCount": 117,
|
|
252
252
|
"workflowCount": 115,
|
|
@@ -3496,7 +3496,7 @@
|
|
|
3496
3496
|
],
|
|
3497
3497
|
"maturity": "stable",
|
|
3498
3498
|
"sourcePath": "docs/oci-publication.md",
|
|
3499
|
-
"digest": "sha256:
|
|
3499
|
+
"digest": "sha256:daed970a66eb7b7cac87334d09e61449e8662c0655c7a345667bd2ef74f53af8",
|
|
3500
3500
|
"headings": [
|
|
3501
3501
|
{
|
|
3502
3502
|
"level": 1,
|
|
@@ -3524,7 +3524,7 @@
|
|
|
3524
3524
|
"anchor": "evidence-gated-compose-preview"
|
|
3525
3525
|
}
|
|
3526
3526
|
],
|
|
3527
|
-
"markdown": "---\nstatus: draft\nperiod: ongoing\ntheme: oci-publication\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-07\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-06\n invisible_context_boundary: No credentials or production registry state inspected.\n---\n\n# OCI image family publication\n\nBuildchain v4 can publish a sealed family of container images to GHCR through\n`publish-artifact-kind: oci` on the public release candidate promotion workflow.\nThe candidate build produces the image bytes and smoke evidence. The built-in\nprovider verifies and uploads those bytes, reads back every public image digest,\nthen allows release references and GitHub Release evidence to converge.\n\n## Candidate contract\n\nPublish exactly one `oci-family.json` alongside OCI layouts and smoke JSON files\nin the Build artifact. Import `sealOciPublicationBundle` from\n`@kungfu-tech/buildchain/oci-publication` to validate and seal the family. Its\n`body` contains:\n\n- `schema: kungfu-buildchain-oci-family/v1`, consumer `repository`, exact Git\n `sourceSha`, and candidate package `version`.\n- `expectedImages`: the complete set of image names.\n- `images`: one entry for each expected image, with `name`, `repository`,\n `digest`, `layout`, `platform`, `action`, `content`, and `smoke`.\n\nDestinations must be `ghcr.io/<consumer-owner>/<consumer-repo>/<image-name>`.\n`layout` is a relative OCI layout directory. Each image is a single Linux\namd64 or arm64 manifest; OCI and Docker schema 2 manifests are supported.\nLayouts may share blobs and an index; each shared index entry identifies its\nimage with the `org.opencontainers.image.ref.name` annotation.\n\n`content` records the image's original `sourceSha` and `version`, matching its\nOCI revision/version labels. For `action: built`, both equal the candidate.\nFor `action: reused`, they retain the original content provenance while the\nfamily binds the current candidate. `smoke` records a relative `path` and SHA256\n`sha256`; its JSON must identify the image and record `passed: true`. The\nconsumer owns the actual smoke command and must fail the build if it fails.\n\nSealing verifies all config/layer sizes and digests, platform and provenance\nlabels, smoke bytes, and family completeness. Absolute paths, traversal, and\nsymlinks are rejected. The resolver derives the exact required image artifacts\nfrom this sealed family, including when recovering a previous candidate run.\n\n## Authority and publication\n\nThe thin caller grants `packages: write` in addition to its existing promotion\npermissions. Reusable promotion wrappers inherit that caller envelope; npm\nconsumers do not need to request package registry authority. The provider uses\nthe action token only for GHCR, scoped to each declared consumer image.\nNo consumer publish command is executed.\n\nThe rooted product plan declares version-state materialization, OCI family\npublication, then release reference convergence. Each image uses the exact\n`v<version>` tag. A different existing digest aborts publication; a matching\nexisting image is reused. After a partial failure, recovery validates the same\ncandidate bytes and publishes only missing images. GHCR does not provide tag\ncompare-and-swap: callers must serialize publishers for a version, and external\nwriters must not race the publication workflow.\n\nSuccess requires anonymous readback of every declared image at its expected\ndigest. Existing GHCR packages must permit the repository token to write and\nanonymous clients to pull. The provider does not change package visibility or\naccess policy. It attaches `oci-publication-readback.json` to the GitHub Release;\nthe caller should also include the family and smoke JSON files in\n`github-release-payload-patterns`.\n\nSee [Runtime Train Validation](runtime-train-validation.md) for testing an\nunreleased runtime without persisting a train or exact SHA in the workflow.\n\n## Multi-platform images and Compose applications\n\nUse `schema: kungfu-buildchain-oci-family/v2` when the family includes an OCI\nindex or a Compose application. Existing v1 families keep their published\nsingle-platform contract.\n\nAn index entry declares `platform: multi-platform` and the complete `platforms`\narray, for example `[\"linux/amd64\", \"linux/arm64\"]`. Every runnable child must\nhave matching platform and content labels. Descriptor sizes, digests and media\ntypes are verified recursively; nested manifests are uploaded before their\nparent index. BuildKit attestation manifests must identify a runnable child and\ncontain matching in-toto subjects. Missing platforms, duplicate platforms,\nforeign URLs and broken blob references fail sealing. Embedded descriptor `data`\nis accepted only as canonical Base64 for at most 1 MiB, with the declared size\nand digest matching the required local blob byte for byte. Malformed or\ninconsistent embedded content fails sealing; manifests are never rewritten.\nThis follows the [OCI embedded-content contract](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#embedded-content).\n\nA Compose entry declares `kind: compose`, `platform: compose`, and `targetImage`\npointing to an image in the same family. Its unique family name may differ from\nthat image, but its destination repository must match it. The immutable tag is\n`compose-v<version>`; image entries retain `v<version>`.\n\nThe bounded Compose representation is an OCI 1.1 image manifest with\n`artifactType: application/vnd.docker.compose.project`, an empty JSON config\nand one `application/vnd.docker.compose.file+yaml` layer. That layer contains\nJSON, a YAML subset, so structural verification needs no executable YAML loader.\nEvery service image is pinned to a digest and at least one uses the exact\nfamily image. Environment interpolation inside other fields can remain intact.\nThese media types follow the [Docker Compose publisher](https://github.com/docker/compose/blob/v5.1.2/internal/oci/push.go).\n\nCandidate smoke evidence describes its actual pre-publication checks. It must\nnot claim that an unpublished public Compose reference was installed. Public\ninstallation qualification occurs after immutable publication and before a\npreview alias moves.\n\n## Evidence-gated Compose preview\n\nAn optional Compose `preview` declaration contains exactly the supported alias\n`compose-preview`, the previously accepted `previousDigest` (or `none`), and\n`qualificationWorkflow`, a repository workflow path. The immutable family seals\nthis policy before any publication effect.\n\nAfter v4 publication is complete, dispatch that qualification workflow on the\nexact published alpha tag. It must pull the immutable public image and Compose,\nrun fresh installation, restart, account-isolation, runtime-hardening, upgrade\nand rollback checks, and qualify both Linux architectures. The workflow has no\nregistry write authority. Upload one artifact named\n`oci-compose-qualification-<run-id>-<run-attempt>` containing `qualification.json`\nand its hash-bound JSON evidence files.\n\nThe receipt uses `schema: kungfu-buildchain-compose-qualification/v1` and binds\n`repository`, `tag`, published `sourceSha`, sealed `familyRoot`, `runId`,\n`runAttempt`, exact `image` and `application` repository/digest references,\n`previousDigest`, and `passed: true`. Its `checks` object requires all of\n`freshInstall`, `restartPersistence`, `upgradePersistence`, `rollbackPersistence`,\n`accountIsolation`, and `hardenedRuntime` to be true. Its `platforms` object\nrequires `linux/amd64` and `linux/arm64` entries with `passed: true`; `evidence`\ncontains nonempty `{path, sha256}` bindings to the actual JSON results.\n\nA thin consumer workflow listens to completion of that qualification workflow\nand calls `public-release-oci-compose-preview.yml@v4-alpha`, passing\n`BUILDCHAIN_PROMOTION_TOKEN`. The reusable workflow resolves its own exact\nruntime, enforces the dual floating-channel locks, verifies the public v4\nsettlement, family and provider readback roots, and checks the live GitHub run's\nrepository, source, workflow, event, attempt and successful conclusion. It never\nexecutes the consumer's artifact files. Only then does it copy the exact Compose\nmanifest bytes to the declared alias and verify the public digest.\n\nThe expected-old digest is checked immediately before mutation. An already\nmatching target is an idempotent success; any other drift blocks the move.\nPublishers for this alias share repository-level concurrency. GHCR has no atomic\ntag compare-and-swap, so external writers must also avoid racing this workflow.\nThe immutable release retains the appended\n`buildchain-compose-preview-<run-id>-<run-attempt>.json` receipt. A failed\nqualification leaves the existing preview intact, while the immutable alpha\nand its original publication evidence remain available for diagnosis."
|
|
3527
|
+
"markdown": "---\nstatus: draft\nperiod: ongoing\ntheme: oci-publication\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-07\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-06\n invisible_context_boundary: No credentials or production registry state inspected.\n---\n\n# OCI image family publication\n\nCompose preview uses the workflow's scoped `packages: write` token for GHCR\nrequests. The separate `BUILDCHAIN_PROMOTION_TOKEN` serves GitHub governance\nand receipt publication; it is never a fallback registry credential. Missing\nregistry identity fails before a write, and an unsuccessful registry response\nreports only its HTTP status while retaining the exact qualification for recovery.\n\nBuildchain v4 can publish a sealed family of container images to GHCR through\n`publish-artifact-kind: oci` on the public release candidate promotion workflow.\nThe candidate build produces the image bytes and smoke evidence. The built-in\nprovider verifies and uploads those bytes, reads back every public image digest,\nthen allows release references and GitHub Release evidence to converge.\n\n## Candidate contract\n\nPublish exactly one `oci-family.json` alongside OCI layouts and smoke JSON files\nin the Build artifact. Import `sealOciPublicationBundle` from\n`@kungfu-tech/buildchain/oci-publication` to validate and seal the family. Its\n`body` contains:\n\n- `schema: kungfu-buildchain-oci-family/v1`, consumer `repository`, exact Git\n `sourceSha`, and candidate package `version`.\n- `expectedImages`: the complete set of image names.\n- `images`: one entry for each expected image, with `name`, `repository`,\n `digest`, `layout`, `platform`, `action`, `content`, and `smoke`.\n\nDestinations must be `ghcr.io/<consumer-owner>/<consumer-repo>/<image-name>`.\n`layout` is a relative OCI layout directory. Each image is a single Linux\namd64 or arm64 manifest; OCI and Docker schema 2 manifests are supported.\nLayouts may share blobs and an index; each shared index entry identifies its\nimage with the `org.opencontainers.image.ref.name` annotation.\n\n`content` records the image's original `sourceSha` and `version`, matching its\nOCI revision/version labels. For `action: built`, both equal the candidate.\nFor `action: reused`, they retain the original content provenance while the\nfamily binds the current candidate. `smoke` records a relative `path` and SHA256\n`sha256`; its JSON must identify the image and record `passed: true`. The\nconsumer owns the actual smoke command and must fail the build if it fails.\n\nSealing verifies all config/layer sizes and digests, platform and provenance\nlabels, smoke bytes, and family completeness. Absolute paths, traversal, and\nsymlinks are rejected. The resolver derives the exact required image artifacts\nfrom this sealed family, including when recovering a previous candidate run.\n\n## Authority and publication\n\nThe thin caller grants `packages: write` in addition to its existing promotion\npermissions. Reusable promotion wrappers inherit that caller envelope; npm\nconsumers do not need to request package registry authority. The provider uses\nthe action token only for GHCR, scoped to each declared consumer image.\nNo consumer publish command is executed.\n\nThe rooted product plan declares version-state materialization, OCI family\npublication, then release reference convergence. Each image uses the exact\n`v<version>` tag. A different existing digest aborts publication; a matching\nexisting image is reused. After a partial failure, recovery validates the same\ncandidate bytes and publishes only missing images. GHCR does not provide tag\ncompare-and-swap: callers must serialize publishers for a version, and external\nwriters must not race the publication workflow.\n\nSuccess requires anonymous readback of every declared image at its expected\ndigest. Existing GHCR packages must permit the repository token to write and\nanonymous clients to pull. The provider does not change package visibility or\naccess policy. It attaches `oci-publication-readback.json` to the GitHub Release;\nthe caller should also include the family and smoke JSON files in\n`github-release-payload-patterns`.\n\nSee [Runtime Train Validation](runtime-train-validation.md) for testing an\nunreleased runtime without persisting a train or exact SHA in the workflow.\n\n## Multi-platform images and Compose applications\n\nUse `schema: kungfu-buildchain-oci-family/v2` when the family includes an OCI\nindex or a Compose application. Existing v1 families keep their published\nsingle-platform contract.\n\nAn index entry declares `platform: multi-platform` and the complete `platforms`\narray, for example `[\"linux/amd64\", \"linux/arm64\"]`. Every runnable child must\nhave matching platform and content labels. Descriptor sizes, digests and media\ntypes are verified recursively; nested manifests are uploaded before their\nparent index. BuildKit attestation manifests must identify a runnable child and\ncontain matching in-toto subjects. Missing platforms, duplicate platforms,\nforeign URLs and broken blob references fail sealing. Embedded descriptor `data`\nis accepted only as canonical Base64 for at most 1 MiB, with the declared size\nand digest matching the required local blob byte for byte. Malformed or\ninconsistent embedded content fails sealing; manifests are never rewritten.\nThis follows the [OCI embedded-content contract](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#embedded-content).\n\nA Compose entry declares `kind: compose`, `platform: compose`, and `targetImage`\npointing to an image in the same family. Its unique family name may differ from\nthat image, but its destination repository must match it. The immutable tag is\n`compose-v<version>`; image entries retain `v<version>`.\n\nThe bounded Compose representation is an OCI 1.1 image manifest with\n`artifactType: application/vnd.docker.compose.project`, an empty JSON config\nand one `application/vnd.docker.compose.file+yaml` layer. That layer contains\nJSON, a YAML subset, so structural verification needs no executable YAML loader.\nEvery service image is pinned to a digest and at least one uses the exact\nfamily image. Environment interpolation inside other fields can remain intact.\nThese media types follow the [Docker Compose publisher](https://github.com/docker/compose/blob/v5.1.2/internal/oci/push.go).\n\nCandidate smoke evidence describes its actual pre-publication checks. It must\nnot claim that an unpublished public Compose reference was installed. Public\ninstallation qualification occurs after immutable publication and before a\npreview alias moves.\n\n## Evidence-gated Compose preview\n\nAn optional Compose `preview` declaration contains exactly the supported alias\n`compose-preview`, the previously accepted `previousDigest` (or `none`), and\n`qualificationWorkflow`, a repository workflow path. The immutable family seals\nthis policy before any publication effect.\n\nAfter v4 publication is complete, dispatch that qualification workflow on the\nexact published alpha tag. It must pull the immutable public image and Compose,\nrun fresh installation, restart, account-isolation, runtime-hardening, upgrade\nand rollback checks, and qualify both Linux architectures. The workflow has no\nregistry write authority. Upload one artifact named\n`oci-compose-qualification-<run-id>-<run-attempt>` containing `qualification.json`\nand its hash-bound JSON evidence files.\n\nThe receipt uses `schema: kungfu-buildchain-compose-qualification/v1` and binds\n`repository`, `tag`, published `sourceSha`, sealed `familyRoot`, `runId`,\n`runAttempt`, exact `image` and `application` repository/digest references,\n`previousDigest`, and `passed: true`. Its `checks` object requires all of\n`freshInstall`, `restartPersistence`, `upgradePersistence`, `rollbackPersistence`,\n`accountIsolation`, and `hardenedRuntime` to be true. Its `platforms` object\nrequires `linux/amd64` and `linux/arm64` entries with `passed: true`; `evidence`\ncontains nonempty `{path, sha256}` bindings to the actual JSON results.\n\nA thin consumer workflow listens to completion of that qualification workflow\nand calls `public-release-oci-compose-preview.yml@v4-alpha`, passing\n`BUILDCHAIN_PROMOTION_TOKEN`. The reusable workflow resolves its own exact\nruntime, enforces the dual floating-channel locks, verifies the public v4\nsettlement, family and provider readback roots, and checks the live GitHub run's\nrepository, source, workflow, event, attempt and successful conclusion. It never\nexecutes the consumer's artifact files. Only then does it copy the exact Compose\nmanifest bytes to the declared alias and verify the public digest.\n\nThe expected-old digest is checked immediately before mutation. An already\nmatching target is an idempotent success; any other drift blocks the move.\nPublishers for this alias share repository-level concurrency. GHCR has no atomic\ntag compare-and-swap, so external writers must also avoid racing this workflow.\nThe immutable release retains the appended\n`buildchain-compose-preview-<run-id>-<run-attempt>.json` receipt. A failed\nqualification leaves the existing preview intact, while the immutable alpha\nand its original publication evidence remain available for diagnosis.\n\nThe verified publication Passport distinguishes the built candidate from the\nprotected publication commit. Compose family source identity follows\n`source.builtSourceSha`; `source.builtSourceTreeSha` must equal the admitted\ninvocation tree. Registry readback and qualification runs remain bound to the\nprotected publication SHA. A tree-equivalent protected merge therefore retains\nthe original image identity without accepting a different source tree."
|
|
3528
3528
|
},
|
|
3529
3529
|
{
|
|
3530
3530
|
"id": "manual:ownership",
|
|
@@ -10948,8 +10948,8 @@
|
|
|
10948
10948
|
"workflowRegistryPath": "dist/site/workflow-registry.json",
|
|
10949
10949
|
"pageRegistryPath": "dist/site/page-registry.json",
|
|
10950
10950
|
"cliRegistryDigest": "fbc23073bbae240489a2f826b2c26daadc58e704050c5f8df366509f5c5a1c3e",
|
|
10951
|
-
"workflowRegistryDigest": "
|
|
10952
|
-
"pageRegistryDigest": "
|
|
10951
|
+
"workflowRegistryDigest": "d7f9eddd25a41e892b553b5e070cdcc69c4b1213f1bc6a41bbd89c0c97737c8d",
|
|
10952
|
+
"pageRegistryDigest": "4c9fc70dc2f9989c1b962f43f68ed907864251a594463fa10bf6a9a8bd7e5721"
|
|
10953
10953
|
},
|
|
10954
10954
|
"comparison": {
|
|
10955
10955
|
"missingCliRegistry": [],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-publication-release-registry",
|
|
4
|
-
"generatedAt": "2026-09-
|
|
5
|
-
"publishedAt": "2026-09-
|
|
4
|
+
"generatedAt": "2026-09-07T04:57:43.000Z",
|
|
5
|
+
"publishedAt": "2026-09-07T04:57:43.000Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "14b13cfc51afcadd251eee71d7e42842c35ce273",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"package": {
|
|
34
34
|
"name": "@kungfu-tech/buildchain",
|
|
35
|
-
"version": "4.0.2-alpha.
|
|
35
|
+
"version": "4.0.2-alpha.52",
|
|
36
36
|
"versionSource": "package.json#version"
|
|
37
37
|
},
|
|
38
38
|
"sourceKind": "package-site-bundle",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-manifest",
|
|
4
|
-
"generatedAt": "2026-09-
|
|
5
|
-
"publishedAt": "2026-09-
|
|
4
|
+
"generatedAt": "2026-09-07T04:57:43.000Z",
|
|
5
|
+
"publishedAt": "2026-09-07T04:57:43.000Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "14b13cfc51afcadd251eee71d7e42842c35ce273",
|
|
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": "4.0.2-alpha.
|
|
40
|
+
"version": "4.0.2-alpha.52",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"entrypoint": "buildchain-site.json",
|
|
@@ -2746,7 +2746,7 @@
|
|
|
2746
2746
|
"status": "preview",
|
|
2747
2747
|
"owner": "buildchain-workflows",
|
|
2748
2748
|
"maturity": "preview",
|
|
2749
|
-
"introducedVersion": "4.0.2-alpha.
|
|
2749
|
+
"introducedVersion": "4.0.2-alpha.52",
|
|
2750
2750
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
2751
2751
|
"deprecationReplacement": "",
|
|
2752
2752
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -3943,7 +3943,7 @@
|
|
|
3943
3943
|
"status": "preview",
|
|
3944
3944
|
"owner": "buildchain-workflows",
|
|
3945
3945
|
"maturity": "preview",
|
|
3946
|
-
"introducedVersion": "4.0.2-alpha.
|
|
3946
|
+
"introducedVersion": "4.0.2-alpha.52",
|
|
3947
3947
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
3948
3948
|
"deprecationReplacement": "",
|
|
3949
3949
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -6004,7 +6004,7 @@
|
|
|
6004
6004
|
"status": "preview",
|
|
6005
6005
|
"owner": "buildchain-workflows",
|
|
6006
6006
|
"maturity": "preview",
|
|
6007
|
-
"introducedVersion": "4.0.2-alpha.
|
|
6007
|
+
"introducedVersion": "4.0.2-alpha.52",
|
|
6008
6008
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
6009
6009
|
"deprecationReplacement": "",
|
|
6010
6010
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -6035,7 +6035,7 @@
|
|
|
6035
6035
|
"status": "preview",
|
|
6036
6036
|
"owner": "buildchain-workflows",
|
|
6037
6037
|
"maturity": "preview",
|
|
6038
|
-
"introducedVersion": "4.0.2-alpha.
|
|
6038
|
+
"introducedVersion": "4.0.2-alpha.52",
|
|
6039
6039
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
6040
6040
|
"deprecationReplacement": "",
|
|
6041
6041
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -6066,7 +6066,7 @@
|
|
|
6066
6066
|
"status": "preview",
|
|
6067
6067
|
"owner": "buildchain-workflows",
|
|
6068
6068
|
"maturity": "preview",
|
|
6069
|
-
"introducedVersion": "4.0.2-alpha.
|
|
6069
|
+
"introducedVersion": "4.0.2-alpha.52",
|
|
6070
6070
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
6071
6071
|
"deprecationReplacement": "",
|
|
6072
6072
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
package/docs/oci-publication.md
CHANGED
|
@@ -18,6 +18,12 @@ ai_provenance:
|
|
|
18
18
|
|
|
19
19
|
# OCI image family publication
|
|
20
20
|
|
|
21
|
+
Compose preview uses the workflow's scoped `packages: write` token for GHCR
|
|
22
|
+
requests. The separate `BUILDCHAIN_PROMOTION_TOKEN` serves GitHub governance
|
|
23
|
+
and receipt publication; it is never a fallback registry credential. Missing
|
|
24
|
+
registry identity fails before a write, and an unsuccessful registry response
|
|
25
|
+
reports only its HTTP status while retaining the exact qualification for recovery.
|
|
26
|
+
|
|
21
27
|
Buildchain v4 can publish a sealed family of container images to GHCR through
|
|
22
28
|
`publish-artifact-kind: oci` on the public release candidate promotion workflow.
|
|
23
29
|
The candidate build produces the image bytes and smoke evidence. The built-in
|
|
@@ -158,3 +164,10 @@ The immutable release retains the appended
|
|
|
158
164
|
`buildchain-compose-preview-<run-id>-<run-attempt>.json` receipt. A failed
|
|
159
165
|
qualification leaves the existing preview intact, while the immutable alpha
|
|
160
166
|
and its original publication evidence remain available for diagnosis.
|
|
167
|
+
|
|
168
|
+
The verified publication Passport distinguishes the built candidate from the
|
|
169
|
+
protected publication commit. Compose family source identity follows
|
|
170
|
+
`source.builtSourceSha`; `source.builtSourceTreeSha` must equal the admitted
|
|
171
|
+
invocation tree. Registry readback and qualification runs remain bound to the
|
|
172
|
+
protected publication SHA. A tree-equivalent protected merge therefore retains
|
|
173
|
+
the original image identity without accepting a different source tree.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "4.0.2-alpha.
|
|
3
|
+
"version": "4.0.2-alpha.52",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -23,7 +23,10 @@ export function verifyComposePublication({
|
|
|
23
23
|
root === v4ContentRoot("oci-publication-family", body) &&
|
|
24
24
|
family.repository === repository &&
|
|
25
25
|
family.version === version &&
|
|
26
|
-
family.sourceSha === documents.
|
|
26
|
+
family.sourceSha === documents.passport.source.builtSourceSha &&
|
|
27
|
+
documents.passport.source.builtSourceTreeSha ===
|
|
28
|
+
documents.invocation.candidate.tree &&
|
|
29
|
+
readback.sourceSha === documents.invocation.candidate.commit &&
|
|
27
30
|
readback.familyRoot === root &&
|
|
28
31
|
readback.version === version &&
|
|
29
32
|
readback.candidateSourceSha === family.sourceSha &&
|
|
@@ -25,6 +25,18 @@ function gh(args) {
|
|
|
25
25
|
}
|
|
26
26
|
const api = (route) => JSON.parse(gh(["api", route]));
|
|
27
27
|
const read = (file) => JSON.parse(fs.readFileSync(file));
|
|
28
|
+
export function createComposePreviewRegistry(environment, fetchImpl = fetch) {
|
|
29
|
+
const token = environment.BUILDCHAIN_REGISTRY_TOKEN;
|
|
30
|
+
const actor = environment.GITHUB_ACTOR;
|
|
31
|
+
check(
|
|
32
|
+
typeof token === "string" &&
|
|
33
|
+
token.length > 0 &&
|
|
34
|
+
typeof actor === "string" &&
|
|
35
|
+
actor.length > 0,
|
|
36
|
+
"explicit scoped registry identity required",
|
|
37
|
+
);
|
|
38
|
+
return createRegistryClient(token, fetchImpl, actor);
|
|
39
|
+
}
|
|
28
40
|
function output(name, value) {
|
|
29
41
|
fs.appendFileSync(process.env.GITHUB_OUTPUT, `${name}=${value}\n`);
|
|
30
42
|
}
|
|
@@ -69,7 +81,7 @@ export async function promoteComposePreview({
|
|
|
69
81
|
});
|
|
70
82
|
check(
|
|
71
83
|
result.status === 201,
|
|
72
|
-
|
|
84
|
+
`preview write uncertain (HTTP ${result.status}); retain the original qualification for readback`,
|
|
73
85
|
);
|
|
74
86
|
}
|
|
75
87
|
const observed = await fetchManifest(policy.alias);
|
|
@@ -186,8 +198,7 @@ async function run(mode) {
|
|
|
186
198
|
"qualification evidence bytes mismatch",
|
|
187
199
|
);
|
|
188
200
|
}
|
|
189
|
-
const
|
|
190
|
-
const { registry } = createRegistryClient(process.env.GH_TOKEN, fetch, actor);
|
|
201
|
+
const { registry } = createComposePreviewRegistry(process.env);
|
|
191
202
|
async function fetchManifest(ref, allowAbsent = false) {
|
|
192
203
|
const response = await registry(context.application, `manifests/${ref}`, {
|
|
193
204
|
headers: {
|
|
@@ -85,7 +85,7 @@ export function ensureCapabilityCutAncestor({
|
|
|
85
85
|
try {
|
|
86
86
|
execFileSync(
|
|
87
87
|
"git",
|
|
88
|
-
["fetch", "--no-tags", "--depth=
|
|
88
|
+
["fetch", "--no-tags", "--depth=256", "origin", descendantCommit],
|
|
89
89
|
{ cwd: root, stdio: "ignore" },
|
|
90
90
|
);
|
|
91
91
|
} catch {
|