@kungfu-tech/buildchain 4.0.2-alpha.6 → 4.0.2-alpha.8
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 +5 -1
- package/architecture/internal-capabilities.json +3 -1
- package/architecture/maintainability-debt.json +15 -13
- package/architecture/maintainability-policy.json +6 -6
- package/architecture/v4-release-topology.json +73 -0
- package/dist/site/buildchain-contract.json +7 -7
- package/dist/site/buildchain-site.json +7 -7
- package/dist/site/kfd-claims.json +5 -3
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +1 -1
- package/dist/site/node-api-registry.json +3 -3
- package/dist/site/page-registry.json +2 -2
- package/dist/site/public-surface-audit.json +5 -3
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +5 -5
- package/dist/site/workflow-registry.json +7 -5
- package/docs/node-api-reference.md +3 -3
- package/package.json +1 -1
- package/packages/core/release-tail-product-capabilities.js +29 -0
- package/packages/core/release-tail-provider-plane.js +2 -2
- package/packages/core/v4-canonical-contracts.js +4 -0
- package/packages/core/v4-product-publication.js +387 -0
- package/scripts/check-v4-release-topology.mjs +128 -21
- package/scripts/release-candidate-resolver.mjs +8 -9
- package/scripts/resume-from-candidate-run.mjs +1 -1
- package/scripts/v4-product-publication-intent.mjs +114 -0
|
@@ -3308,6 +3308,7 @@
|
|
|
3308
3308
|
"candidate-passport-path",
|
|
3309
3309
|
"failure-after-capability",
|
|
3310
3310
|
"mutation-token",
|
|
3311
|
+
"product-publication-intent-path",
|
|
3311
3312
|
"publication-qualification-path",
|
|
3312
3313
|
"publish-auth",
|
|
3313
3314
|
"publish-command",
|
|
@@ -3321,6 +3322,7 @@
|
|
|
3321
3322
|
"repository",
|
|
3322
3323
|
"required-artifacts-path",
|
|
3323
3324
|
"required-status-check",
|
|
3325
|
+
"resume-transaction-id",
|
|
3324
3326
|
"runtime-commit",
|
|
3325
3327
|
"runtime-tree",
|
|
3326
3328
|
"sealed-bundle-manifest",
|
|
@@ -3332,7 +3334,7 @@
|
|
|
3332
3334
|
"target-sha",
|
|
3333
3335
|
"token"
|
|
3334
3336
|
],
|
|
3335
|
-
"inputCount":
|
|
3337
|
+
"inputCount": 30
|
|
3336
3338
|
},
|
|
3337
3339
|
{
|
|
3338
3340
|
"id": "validate-config",
|
|
@@ -8941,8 +8943,8 @@
|
|
|
8941
8943
|
"workflowRegistryPath": "dist/site/workflow-registry.json",
|
|
8942
8944
|
"pageRegistryPath": "dist/site/page-registry.json",
|
|
8943
8945
|
"cliRegistryDigest": "fbc23073bbae240489a2f826b2c26daadc58e704050c5f8df366509f5c5a1c3e",
|
|
8944
|
-
"workflowRegistryDigest": "
|
|
8945
|
-
"pageRegistryDigest": "
|
|
8946
|
+
"workflowRegistryDigest": "b887d5f02f3f3b25a15f8f15d8c294d001b919378cc00fcda303d6359060b9fe",
|
|
8947
|
+
"pageRegistryDigest": "225249f141d3242a46c66de72f005f119235b7e13b873594f1c503185d7a285e"
|
|
8946
8948
|
},
|
|
8947
8949
|
"comparison": {
|
|
8948
8950
|
"missingCliRegistry": [],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-publication-release-registry",
|
|
4
|
-
"generatedAt": "2026-08-
|
|
5
|
-
"publishedAt": "2026-08-
|
|
4
|
+
"generatedAt": "2026-08-31T02:59:43.000Z",
|
|
5
|
+
"publishedAt": "2026-08-31T02:59: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": "e113193be5efb13eb5a47f7f51f2d59989e4d969",
|
|
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.8",
|
|
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-08-
|
|
5
|
-
"publishedAt": "2026-08-
|
|
4
|
+
"generatedAt": "2026-08-31T02:59:43.000Z",
|
|
5
|
+
"publishedAt": "2026-08-31T02:59: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": "e113193be5efb13eb5a47f7f51f2d59989e4d969",
|
|
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.8",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"entrypoint": "buildchain-site.json",
|
|
@@ -253,7 +253,7 @@
|
|
|
253
253
|
"path": "docs/node-api-reference.md",
|
|
254
254
|
"plane": "use",
|
|
255
255
|
"exists": true,
|
|
256
|
-
"digest": "sha256:
|
|
256
|
+
"digest": "sha256:1f50b0f7a45632b6e08b492687818ccbd3e0f00d7f189a21e1512e1a61df7df8"
|
|
257
257
|
},
|
|
258
258
|
{
|
|
259
259
|
"id": "build-facts",
|
|
@@ -2041,7 +2041,7 @@
|
|
|
2041
2041
|
"status": "preview",
|
|
2042
2042
|
"owner": "buildchain-workflows",
|
|
2043
2043
|
"maturity": "preview",
|
|
2044
|
-
"introducedVersion": "4.0.2-alpha.
|
|
2044
|
+
"introducedVersion": "4.0.2-alpha.8",
|
|
2045
2045
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
2046
2046
|
"deprecationReplacement": "",
|
|
2047
2047
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -2062,7 +2062,7 @@
|
|
|
2062
2062
|
"status": "preview",
|
|
2063
2063
|
"owner": "buildchain-workflows",
|
|
2064
2064
|
"maturity": "preview",
|
|
2065
|
-
"introducedVersion": "4.0.2-alpha.
|
|
2065
|
+
"introducedVersion": "4.0.2-alpha.8",
|
|
2066
2066
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
2067
2067
|
"deprecationReplacement": "",
|
|
2068
2068
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -2083,7 +2083,7 @@
|
|
|
2083
2083
|
"status": "preview",
|
|
2084
2084
|
"owner": "buildchain-workflows",
|
|
2085
2085
|
"maturity": "preview",
|
|
2086
|
-
"introducedVersion": "4.0.2-alpha.
|
|
2086
|
+
"introducedVersion": "4.0.2-alpha.8",
|
|
2087
2087
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
2088
2088
|
"deprecationReplacement": "",
|
|
2089
2089
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -2133,7 +2133,7 @@
|
|
|
2133
2133
|
"status": "preview",
|
|
2134
2134
|
"owner": "buildchain-workflows",
|
|
2135
2135
|
"maturity": "preview",
|
|
2136
|
-
"introducedVersion": "4.0.2-alpha.
|
|
2136
|
+
"introducedVersion": "4.0.2-alpha.8",
|
|
2137
2137
|
"compatibilityPromise": "preserved-through-the-v3-major-line",
|
|
2138
2138
|
"deprecationReplacement": "",
|
|
2139
2139
|
"sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
|
|
@@ -3537,6 +3537,7 @@
|
|
|
3537
3537
|
"candidate-passport-path",
|
|
3538
3538
|
"failure-after-capability",
|
|
3539
3539
|
"mutation-token",
|
|
3540
|
+
"product-publication-intent-path",
|
|
3540
3541
|
"publication-qualification-path",
|
|
3541
3542
|
"publish-auth",
|
|
3542
3543
|
"publish-command",
|
|
@@ -3550,6 +3551,7 @@
|
|
|
3550
3551
|
"repository",
|
|
3551
3552
|
"required-artifacts-path",
|
|
3552
3553
|
"required-status-check",
|
|
3554
|
+
"resume-transaction-id",
|
|
3553
3555
|
"runtime-commit",
|
|
3554
3556
|
"runtime-tree",
|
|
3555
3557
|
"sealed-bundle-manifest",
|
|
@@ -3561,7 +3563,7 @@
|
|
|
3561
3563
|
"target-sha",
|
|
3562
3564
|
"token"
|
|
3563
3565
|
],
|
|
3564
|
-
"inputCount":
|
|
3566
|
+
"inputCount": 30,
|
|
3565
3567
|
"capabilityGroup": "api-cli-reference",
|
|
3566
3568
|
"status": "active",
|
|
3567
3569
|
"owner": "buildchain-actions",
|
|
@@ -510,7 +510,7 @@ Target: `./packages/core/index.js`. Public symbols: 636.
|
|
|
510
510
|
| `RELEASE_PROPAGATION_STAGE_RECEIPT_CONTRACT` | constant: const RELEASE_PROPAGATION_STAGE_RECEIPT_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_PROPAGATION_STAGE_RECEIPT_CONTRACT } from "@kungfu-tech/buildchain";` | `packages/core/release-propagation-work-constants.js:2` |
|
|
511
511
|
| `RELEASE_PROPAGATION_WORK_CONTRACT` | constant: const RELEASE_PROPAGATION_WORK_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_PROPAGATION_WORK_CONTRACT } from "@kungfu-tech/buildchain";` | `packages/core/release-propagation-work-constants.js:1` |
|
|
512
512
|
| `RELEASE_PROPAGATION_WORK_STAGES` | constant: const RELEASE_PROPAGATION_WORK_STAGES | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_PROPAGATION_WORK_STAGES } from "@kungfu-tech/buildchain";` | `packages/core/release-propagation-work-constants.js:4` |
|
|
513
|
-
| `RELEASE_TAIL_CAPABILITY_REGISTRY` | constant: const RELEASE_TAIL_CAPABILITY_REGISTRY | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_CAPABILITY_REGISTRY } from "@kungfu-tech/buildchain";` | `packages/core/release-tail-provider-plane.js:
|
|
513
|
+
| `RELEASE_TAIL_CAPABILITY_REGISTRY` | constant: const RELEASE_TAIL_CAPABILITY_REGISTRY | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_CAPABILITY_REGISTRY } from "@kungfu-tech/buildchain";` | `packages/core/release-tail-provider-plane.js:30` |
|
|
514
514
|
| `RELEASE_TAIL_COMPATIBILITY_CONTRACT` | constant: const RELEASE_TAIL_COMPATIBILITY_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_COMPATIBILITY_CONTRACT } from "@kungfu-tech/buildchain";` | `packages/core/release-tail-compatibility.js:1` |
|
|
515
515
|
| `RELEASE_TAIL_DECLARATION_CONTRACT` | constant: const RELEASE_TAIL_DECLARATION_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_DECLARATION_CONTRACT } from "@kungfu-tech/buildchain";` | `packages/core/release-tail-provider-plane.js:5` |
|
|
516
516
|
| `RELEASE_TAIL_EFFECT_SCHEMA` | constant: const RELEASE_TAIL_EFFECT_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_EFFECT_SCHEMA } from "@kungfu-tech/buildchain";` | `packages/core/release-tail-provider-plane.js:10` |
|
|
@@ -1199,7 +1199,7 @@ Target: `./packages/core/index.js`. Public symbols: 636.
|
|
|
1199
1199
|
| `RELEASE_PROPAGATION_STAGE_RECEIPT_CONTRACT` | constant: const RELEASE_PROPAGATION_STAGE_RECEIPT_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_PROPAGATION_STAGE_RECEIPT_CONTRACT } from "@kungfu-tech/buildchain/core";` | `packages/core/release-propagation-work-constants.js:2` |
|
|
1200
1200
|
| `RELEASE_PROPAGATION_WORK_CONTRACT` | constant: const RELEASE_PROPAGATION_WORK_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_PROPAGATION_WORK_CONTRACT } from "@kungfu-tech/buildchain/core";` | `packages/core/release-propagation-work-constants.js:1` |
|
|
1201
1201
|
| `RELEASE_PROPAGATION_WORK_STAGES` | constant: const RELEASE_PROPAGATION_WORK_STAGES | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_PROPAGATION_WORK_STAGES } from "@kungfu-tech/buildchain/core";` | `packages/core/release-propagation-work-constants.js:4` |
|
|
1202
|
-
| `RELEASE_TAIL_CAPABILITY_REGISTRY` | constant: const RELEASE_TAIL_CAPABILITY_REGISTRY | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_CAPABILITY_REGISTRY } from "@kungfu-tech/buildchain/core";` | `packages/core/release-tail-provider-plane.js:
|
|
1202
|
+
| `RELEASE_TAIL_CAPABILITY_REGISTRY` | constant: const RELEASE_TAIL_CAPABILITY_REGISTRY | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_CAPABILITY_REGISTRY } from "@kungfu-tech/buildchain/core";` | `packages/core/release-tail-provider-plane.js:30` |
|
|
1203
1203
|
| `RELEASE_TAIL_COMPATIBILITY_CONTRACT` | constant: const RELEASE_TAIL_COMPATIBILITY_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_COMPATIBILITY_CONTRACT } from "@kungfu-tech/buildchain/core";` | `packages/core/release-tail-compatibility.js:1` |
|
|
1204
1204
|
| `RELEASE_TAIL_DECLARATION_CONTRACT` | constant: const RELEASE_TAIL_DECLARATION_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_DECLARATION_CONTRACT } from "@kungfu-tech/buildchain/core";` | `packages/core/release-tail-provider-plane.js:5` |
|
|
1205
1205
|
| `RELEASE_TAIL_EFFECT_SCHEMA` | constant: const RELEASE_TAIL_EFFECT_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_EFFECT_SCHEMA } from "@kungfu-tech/buildchain/core";` | `packages/core/release-tail-provider-plane.js:10` |
|
|
@@ -2767,7 +2767,7 @@ Target: `./packages/core/release-tail-provider-plane.js`. Public symbols: 20.
|
|
|
2767
2767
|
| `executeReleaseTailTransaction` | function: async function executeReleaseTailTransaction(transaction, { adapters, checkpoint: checkpointCallback } = {}) | transaction, { adapters, checkpoint: checkpointCallback } = {} | Promise<unknown> | May throw an Error on rejected input or failed operations; follow the linked source contract. | may-write-or-invoke-external-actions | `import { executeReleaseTailTransaction } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:1016` |
|
|
2768
2768
|
| `parseReleaseTailDeclaration` | function: function parseReleaseTailDeclaration(input) | input | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { parseReleaseTailDeclaration } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:491` |
|
|
2769
2769
|
| `readReleaseTailTransaction` | function: function readReleaseTailTransaction(filePath) | filePath | unknown | May throw an Error on rejected input or failed operations; follow the linked source contract. | none-detected-by-static-source-scan | `import { readReleaseTailTransaction } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:830` |
|
|
2770
|
-
| `RELEASE_TAIL_CAPABILITY_REGISTRY` | constant: const RELEASE_TAIL_CAPABILITY_REGISTRY | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_CAPABILITY_REGISTRY } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:
|
|
2770
|
+
| `RELEASE_TAIL_CAPABILITY_REGISTRY` | constant: const RELEASE_TAIL_CAPABILITY_REGISTRY | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_CAPABILITY_REGISTRY } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:30` |
|
|
2771
2771
|
| `RELEASE_TAIL_DECLARATION_CONTRACT` | constant: const RELEASE_TAIL_DECLARATION_CONTRACT | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_DECLARATION_CONTRACT } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:5` |
|
|
2772
2772
|
| `RELEASE_TAIL_EFFECT_SCHEMA` | constant: const RELEASE_TAIL_EFFECT_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_EFFECT_SCHEMA } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:10` |
|
|
2773
2773
|
| `RELEASE_TAIL_OBSERVATION_SCHEMA` | constant: const RELEASE_TAIL_OBSERVATION_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_TAIL_OBSERVATION_SCHEMA } from "@kungfu-tech/buildchain/release-tail-provider-plane";` | `packages/core/release-tail-provider-plane.js:12` |
|
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.8",
|
|
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",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const RELEASE_TAIL_PRODUCT_CAPABILITIES = Object.freeze([
|
|
2
|
+
Object.freeze({
|
|
3
|
+
id: "product.version-state.materialize",
|
|
4
|
+
executor: "provider-adapter",
|
|
5
|
+
adapter: "github-version-state",
|
|
6
|
+
effectKind: "product-version-state-materialization",
|
|
7
|
+
observationKind: "product-version-state-readback",
|
|
8
|
+
receiptKind: "product-version-state",
|
|
9
|
+
transactionState: "preparing",
|
|
10
|
+
}),
|
|
11
|
+
Object.freeze({
|
|
12
|
+
id: "product.package.publish",
|
|
13
|
+
executor: "provider-adapter",
|
|
14
|
+
adapter: "npm-trusted-publishing",
|
|
15
|
+
effectKind: "product-package-publication",
|
|
16
|
+
observationKind: "product-package-readback",
|
|
17
|
+
receiptKind: "product-package-publication",
|
|
18
|
+
transactionState: "publishing",
|
|
19
|
+
}),
|
|
20
|
+
Object.freeze({
|
|
21
|
+
id: "product.release-refs.converge",
|
|
22
|
+
executor: "provider-adapter",
|
|
23
|
+
adapter: "github-release-refs",
|
|
24
|
+
effectKind: "product-release-ref-convergence",
|
|
25
|
+
observationKind: "product-release-ref-readback",
|
|
26
|
+
receiptKind: "product-release-ref-convergence",
|
|
27
|
+
transactionState: "committing",
|
|
28
|
+
}),
|
|
29
|
+
]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
|
|
4
|
+
import { RELEASE_TAIL_PRODUCT_CAPABILITIES } from "./release-tail-product-capabilities.js";
|
|
5
5
|
export const RELEASE_TAIL_DECLARATION_CONTRACT =
|
|
6
6
|
"kungfu-buildchain-release-tail-capabilities";
|
|
7
7
|
export const RELEASE_TAIL_TRANSACTION_POLICY = "buildchain.release-tail/v1";
|
|
@@ -27,8 +27,8 @@ export const RELEASE_TAIL_STATES = Object.freeze([
|
|
|
27
27
|
"repair-required",
|
|
28
28
|
"terminal-failure",
|
|
29
29
|
]);
|
|
30
|
-
|
|
31
30
|
export const RELEASE_TAIL_CAPABILITY_REGISTRY = Object.freeze([
|
|
31
|
+
...RELEASE_TAIL_PRODUCT_CAPABILITIES,
|
|
32
32
|
Object.freeze({
|
|
33
33
|
id: "artifact.publish",
|
|
34
34
|
executor: "provider-adapter",
|
|
@@ -56,6 +56,10 @@ const ROOT_DOMAINS = new Set([
|
|
|
56
56
|
"stable-publication-fence",
|
|
57
57
|
"partial-mutation-recovery-checkpoint",
|
|
58
58
|
"partial-mutation-recovery-plan",
|
|
59
|
+
"v4-product-required-artifacts",
|
|
60
|
+
"v4-product-publication-intent",
|
|
61
|
+
"v4-product-publication-operation",
|
|
62
|
+
"v4-product-publication-plan",
|
|
59
63
|
"tail-reseal-plan",
|
|
60
64
|
"tail-reseal-admission",
|
|
61
65
|
"tail-reseal-artifact-files",
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { v4ContentRoot, validateV4Root } from "./v4-canonical-contracts.js";
|
|
2
|
+
import {
|
|
3
|
+
RELEASE_TAIL_DECLARATION_CONTRACT,
|
|
4
|
+
RELEASE_TAIL_EFFECT_SCHEMA,
|
|
5
|
+
RELEASE_TAIL_OBSERVATION_SCHEMA,
|
|
6
|
+
RELEASE_TAIL_RECEIPT_SCHEMA,
|
|
7
|
+
RELEASE_TAIL_TRANSACTION_POLICY,
|
|
8
|
+
} from "./release-tail-provider-plane.js";
|
|
9
|
+
import { RELEASE_TAIL_PRODUCT_CAPABILITIES } from "./release-tail-product-capabilities.js";
|
|
10
|
+
|
|
11
|
+
export const V4_PRODUCT_PUBLICATION_INTENT_CONTRACT =
|
|
12
|
+
"kungfu-buildchain-v4-product-publication-intent/v1";
|
|
13
|
+
export const V4_PRODUCT_PUBLICATION_PLAN_CONTRACT =
|
|
14
|
+
"kungfu-buildchain-v4-product-publication-plan/v1";
|
|
15
|
+
|
|
16
|
+
const VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-alpha\.(\d+))?$/u;
|
|
17
|
+
const SHA = /^[0-9a-f]{40}$/u;
|
|
18
|
+
const ROOT = /^sha256:[0-9a-f]{64}$/u;
|
|
19
|
+
const REPOSITORY = /^[^/\s]+\/[^/\s]+$/u;
|
|
20
|
+
|
|
21
|
+
function fail(message) {
|
|
22
|
+
throw new Error(`invalid v4 product publication: ${message}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseVersion(value, label) {
|
|
26
|
+
const normalized = String(value || "").trim();
|
|
27
|
+
const match = normalized.match(VERSION);
|
|
28
|
+
if (!match) fail(`${label} must be an exact stable or alpha version`);
|
|
29
|
+
return {
|
|
30
|
+
value: normalized,
|
|
31
|
+
major: Number(match[1]),
|
|
32
|
+
minor: Number(match[2]),
|
|
33
|
+
patch: Number(match[3]),
|
|
34
|
+
alpha: match[4] === undefined ? null : Number(match[4]),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function channelName(value) {
|
|
39
|
+
if (value === "alpha") return "alpha";
|
|
40
|
+
if (["release", "stable", "major"].includes(value)) return "stable";
|
|
41
|
+
fail(`unsupported channel '${value}'`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function assertLane({ channel, targetRef, version }) {
|
|
45
|
+
const expression =
|
|
46
|
+
channel === "alpha"
|
|
47
|
+
? /^alpha\/v(\d+)\/v(\d+)\.(\d+)$/u
|
|
48
|
+
: /^release\/v(\d+)\/v(\d+)\.(\d+)$/u;
|
|
49
|
+
const match = String(targetRef || "").match(expression);
|
|
50
|
+
if (!match) fail(`target ref '${targetRef}' is not a ${channel} lane`);
|
|
51
|
+
if (
|
|
52
|
+
Number(match[1]) !== version.major ||
|
|
53
|
+
Number(match[2]) !== version.major ||
|
|
54
|
+
Number(match[3]) !== version.minor
|
|
55
|
+
)
|
|
56
|
+
fail("target ref does not match the publication version line");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function observedAlphaNumber(version, expected) {
|
|
60
|
+
const parsed = parseVersion(version, "observed version");
|
|
61
|
+
return parsed.major === expected.major &&
|
|
62
|
+
parsed.minor === expected.minor &&
|
|
63
|
+
parsed.patch === expected.patch
|
|
64
|
+
? parsed.alpha
|
|
65
|
+
: null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function requiredString(value, label) {
|
|
69
|
+
const normalized = String(value || "").trim();
|
|
70
|
+
if (!normalized) fail(`${label} must be a non-empty string`);
|
|
71
|
+
return normalized;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function requiredRoot(value, label) {
|
|
75
|
+
const normalized = requiredString(value, label).toLowerCase();
|
|
76
|
+
if (!ROOT.test(normalized)) fail(`${label} must be a sha256 content root`);
|
|
77
|
+
return normalized;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function selectV4ProductPublicationIntent({
|
|
81
|
+
channel,
|
|
82
|
+
targetRef,
|
|
83
|
+
sourceSha,
|
|
84
|
+
sourceTimestamp,
|
|
85
|
+
repository,
|
|
86
|
+
packageName,
|
|
87
|
+
distTag,
|
|
88
|
+
sealedBundleRoot,
|
|
89
|
+
requiredArtifactsRoot,
|
|
90
|
+
candidateVersion,
|
|
91
|
+
recoveredVersion = "",
|
|
92
|
+
observedVersions = [],
|
|
93
|
+
}) {
|
|
94
|
+
const normalizedChannel = channelName(channel);
|
|
95
|
+
if (!SHA.test(String(sourceSha || "")))
|
|
96
|
+
fail("sourceSha must be an exact Git SHA");
|
|
97
|
+
if (!REPOSITORY.test(String(repository || "")))
|
|
98
|
+
fail("repository must be owner/repo");
|
|
99
|
+
const normalizedTimestamp = requiredString(
|
|
100
|
+
sourceTimestamp,
|
|
101
|
+
"sourceTimestamp",
|
|
102
|
+
);
|
|
103
|
+
if (Number.isNaN(Date.parse(normalizedTimestamp)))
|
|
104
|
+
fail("sourceTimestamp must be an ISO timestamp");
|
|
105
|
+
const normalizedPackageName = requiredString(packageName, "packageName");
|
|
106
|
+
const normalizedDistTag = requiredString(distTag, "distTag");
|
|
107
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/u.test(normalizedDistTag))
|
|
108
|
+
fail("distTag must be an npm dist-tag");
|
|
109
|
+
if (!Array.isArray(observedVersions))
|
|
110
|
+
fail("observedVersions must be an array");
|
|
111
|
+
const candidate = parseVersion(candidateVersion, "candidateVersion");
|
|
112
|
+
assertLane({ channel: normalizedChannel, targetRef, version: candidate });
|
|
113
|
+
const observed = [...new Set(observedVersions.map(String))].sort();
|
|
114
|
+
let version;
|
|
115
|
+
let mode = "fresh";
|
|
116
|
+
if (String(recoveredVersion || "").trim()) {
|
|
117
|
+
const recovered = parseVersion(recoveredVersion, "recoveredVersion");
|
|
118
|
+
if (
|
|
119
|
+
recovered.major !== candidate.major ||
|
|
120
|
+
recovered.minor !== candidate.minor ||
|
|
121
|
+
recovered.patch !== candidate.patch ||
|
|
122
|
+
(normalizedChannel === "alpha" && recovered.alpha === null) ||
|
|
123
|
+
(normalizedChannel === "stable" && recovered.alpha !== null)
|
|
124
|
+
)
|
|
125
|
+
fail("recoveredVersion is incompatible with the candidate release line");
|
|
126
|
+
version = recovered.value;
|
|
127
|
+
mode = "resume";
|
|
128
|
+
} else if (normalizedChannel === "alpha") {
|
|
129
|
+
if (candidate.alpha === null)
|
|
130
|
+
fail("fresh alpha publication requires an alpha candidate version");
|
|
131
|
+
const highest = observed.reduce(
|
|
132
|
+
(current, entry) =>
|
|
133
|
+
Math.max(current, observedAlphaNumber(entry, candidate) ?? -1),
|
|
134
|
+
candidate.alpha,
|
|
135
|
+
);
|
|
136
|
+
version = `${candidate.major}.${candidate.minor}.${candidate.patch}-alpha.${highest + 1}`;
|
|
137
|
+
} else {
|
|
138
|
+
version = `${candidate.major}.${candidate.minor}.${candidate.patch}`;
|
|
139
|
+
}
|
|
140
|
+
const intent = {
|
|
141
|
+
schema: V4_PRODUCT_PUBLICATION_INTENT_CONTRACT,
|
|
142
|
+
mode,
|
|
143
|
+
channel: normalizedChannel,
|
|
144
|
+
targetRef,
|
|
145
|
+
sourceSha,
|
|
146
|
+
sourceTimestamp: new Date(normalizedTimestamp).toISOString(),
|
|
147
|
+
repository,
|
|
148
|
+
packageName: normalizedPackageName,
|
|
149
|
+
distTag: normalizedDistTag,
|
|
150
|
+
sealedBundleRoot: requiredRoot(sealedBundleRoot, "sealedBundleRoot"),
|
|
151
|
+
requiredArtifactsRoot: requiredRoot(
|
|
152
|
+
requiredArtifactsRoot,
|
|
153
|
+
"requiredArtifactsRoot",
|
|
154
|
+
),
|
|
155
|
+
candidateVersion: candidate.value,
|
|
156
|
+
version,
|
|
157
|
+
exactTag: `v${version}`,
|
|
158
|
+
observedVersions: observed,
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
...intent,
|
|
162
|
+
intentRoot: v4ContentRoot("v4-product-publication-intent", intent),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function alphaReferences(intent, version) {
|
|
167
|
+
const line = `v${version.major}.${version.minor}`;
|
|
168
|
+
return [
|
|
169
|
+
{ ref: `refs/tags/${intent.exactTag}`, target: "source" },
|
|
170
|
+
{ ref: `refs/heads/${intent.targetRef}`, target: "version-state" },
|
|
171
|
+
{
|
|
172
|
+
ref: `refs/heads/dev/v${version.major}/${line}`,
|
|
173
|
+
target: "version-state",
|
|
174
|
+
},
|
|
175
|
+
{ ref: `refs/tags/${line}-alpha`, target: "version-state" },
|
|
176
|
+
{ ref: `refs/tags/v${version.major}-alpha`, target: "version-state" },
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function stableReferences(intent, version) {
|
|
181
|
+
return [
|
|
182
|
+
{ ref: `refs/tags/${intent.exactTag}`, target: "source" },
|
|
183
|
+
{ ref: `refs/heads/${intent.targetRef}`, target: "version-state" },
|
|
184
|
+
{
|
|
185
|
+
ref: `refs/tags/v${version.major}.${version.minor}`,
|
|
186
|
+
target: "version-state",
|
|
187
|
+
},
|
|
188
|
+
{ ref: `refs/tags/v${version.major}`, target: "version-state" },
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function createV4ProductPublicationPlan({
|
|
193
|
+
intent,
|
|
194
|
+
invocationRoot,
|
|
195
|
+
transactionRoot,
|
|
196
|
+
}) {
|
|
197
|
+
validateV4Root(invocationRoot, "$/productPlan/invocationRoot");
|
|
198
|
+
validateV4Root(transactionRoot, "$/productPlan/transactionRoot");
|
|
199
|
+
const selected = selectV4ProductPublicationIntent({
|
|
200
|
+
channel: intent.channel,
|
|
201
|
+
targetRef: intent.targetRef,
|
|
202
|
+
sourceSha: intent.sourceSha,
|
|
203
|
+
sourceTimestamp: intent.sourceTimestamp,
|
|
204
|
+
repository: intent.repository,
|
|
205
|
+
packageName: intent.packageName,
|
|
206
|
+
distTag: intent.distTag,
|
|
207
|
+
sealedBundleRoot: intent.sealedBundleRoot,
|
|
208
|
+
requiredArtifactsRoot: intent.requiredArtifactsRoot,
|
|
209
|
+
candidateVersion: intent.candidateVersion,
|
|
210
|
+
recoveredVersion: intent.mode === "resume" ? intent.version : "",
|
|
211
|
+
observedVersions: intent.observedVersions,
|
|
212
|
+
});
|
|
213
|
+
if (selected.intentRoot !== intent.intentRoot)
|
|
214
|
+
fail("intentRoot does not match the canonical publication intent");
|
|
215
|
+
const parsed = parseVersion(intent.version, "intent.version");
|
|
216
|
+
const references =
|
|
217
|
+
intent.channel === "alpha"
|
|
218
|
+
? alphaReferences(intent, parsed)
|
|
219
|
+
: stableReferences(intent, parsed);
|
|
220
|
+
const stateRef = `refs/heads/buildchain/v4-product-state/${intent.sourceSha}-${intent.version.replaceAll(".", "-")}`;
|
|
221
|
+
const operations = [
|
|
222
|
+
{
|
|
223
|
+
id: "product.version-state.materialize",
|
|
224
|
+
adapter: "github-version-state",
|
|
225
|
+
authority: "contents-write",
|
|
226
|
+
target: {
|
|
227
|
+
repository: intent.repository,
|
|
228
|
+
version: intent.version,
|
|
229
|
+
sourceSha: intent.sourceSha,
|
|
230
|
+
sourceTimestamp: intent.sourceTimestamp,
|
|
231
|
+
stateRef,
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
id: "product.package.publish",
|
|
236
|
+
adapter: "npm-trusted-publishing",
|
|
237
|
+
authority: "oidc-provider-mutation",
|
|
238
|
+
target: {
|
|
239
|
+
packageName: intent.packageName,
|
|
240
|
+
version: intent.version,
|
|
241
|
+
distTag: intent.distTag,
|
|
242
|
+
sealedBundleRoot: intent.sealedBundleRoot,
|
|
243
|
+
requiredArtifactsRoot: intent.requiredArtifactsRoot,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: "product.release-refs.converge",
|
|
248
|
+
adapter: "github-release-refs",
|
|
249
|
+
authority: "contents-write",
|
|
250
|
+
target: {
|
|
251
|
+
repository: intent.repository,
|
|
252
|
+
sourceSha: intent.sourceSha,
|
|
253
|
+
stateRef,
|
|
254
|
+
references,
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
].map((operation) => ({
|
|
258
|
+
...operation,
|
|
259
|
+
operationRoot: v4ContentRoot("v4-product-publication-operation", operation),
|
|
260
|
+
}));
|
|
261
|
+
const plan = {
|
|
262
|
+
schema: V4_PRODUCT_PUBLICATION_PLAN_CONTRACT,
|
|
263
|
+
intentRoot: intent.intentRoot,
|
|
264
|
+
invocationRoot,
|
|
265
|
+
transactionRoot,
|
|
266
|
+
operationOrder: operations.map(({ id }) => id),
|
|
267
|
+
operations,
|
|
268
|
+
};
|
|
269
|
+
return {
|
|
270
|
+
...plan,
|
|
271
|
+
planRoot: v4ContentRoot("v4-product-publication-plan", plan),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const PRODUCT_CAPABILITIES = Object.fromEntries(
|
|
276
|
+
RELEASE_TAIL_PRODUCT_CAPABILITIES.map((capability) => [
|
|
277
|
+
capability.id,
|
|
278
|
+
{
|
|
279
|
+
...capability,
|
|
280
|
+
destinationKind:
|
|
281
|
+
capability.id === "product.package.publish"
|
|
282
|
+
? "npm-package"
|
|
283
|
+
: capability.adapter,
|
|
284
|
+
},
|
|
285
|
+
]),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
function exactTagPattern(tag) {
|
|
289
|
+
return `^${tag.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}$`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function createV4ProductPublicationDeclaration({ intent, plan }) {
|
|
293
|
+
const rebuilt = createV4ProductPublicationPlan({
|
|
294
|
+
intent,
|
|
295
|
+
invocationRoot: plan.invocationRoot,
|
|
296
|
+
transactionRoot: plan.transactionRoot,
|
|
297
|
+
});
|
|
298
|
+
if (rebuilt.planRoot !== plan.planRoot)
|
|
299
|
+
fail("planRoot does not match the canonical publication plan");
|
|
300
|
+
const operationById = new Map(
|
|
301
|
+
plan.operations.map((operation) => [operation.id, operation]),
|
|
302
|
+
);
|
|
303
|
+
return {
|
|
304
|
+
contract: RELEASE_TAIL_DECLARATION_CONTRACT,
|
|
305
|
+
schemaVersion: 1,
|
|
306
|
+
transactionPolicy: RELEASE_TAIL_TRANSACTION_POLICY,
|
|
307
|
+
subject: {
|
|
308
|
+
repository: intent.repository,
|
|
309
|
+
sourceSha: intent.sourceSha,
|
|
310
|
+
version: intent.version,
|
|
311
|
+
tag: intent.exactTag,
|
|
312
|
+
channel: intent.channel,
|
|
313
|
+
},
|
|
314
|
+
capabilities: plan.operationOrder.map((id) => {
|
|
315
|
+
const operation = operationById.get(id);
|
|
316
|
+
const descriptor = PRODUCT_CAPABILITIES[id];
|
|
317
|
+
if (!operation || !descriptor)
|
|
318
|
+
fail(`unsupported product publication operation '${id}'`);
|
|
319
|
+
return {
|
|
320
|
+
id,
|
|
321
|
+
executor: "provider-adapter",
|
|
322
|
+
adapter: operation.adapter,
|
|
323
|
+
artifactRoles: [
|
|
324
|
+
{ role: "publication-intent", root: intent.intentRoot },
|
|
325
|
+
...(id === "product.package.publish"
|
|
326
|
+
? [
|
|
327
|
+
{ role: "sealed-bundle", root: intent.sealedBundleRoot },
|
|
328
|
+
{
|
|
329
|
+
role: "required-artifacts",
|
|
330
|
+
root: intent.requiredArtifactsRoot,
|
|
331
|
+
},
|
|
332
|
+
]
|
|
333
|
+
: []),
|
|
334
|
+
],
|
|
335
|
+
destination: {
|
|
336
|
+
kind: descriptor.destinationKind,
|
|
337
|
+
locator: `${operation.adapter}:${operation.operationRoot}`,
|
|
338
|
+
},
|
|
339
|
+
channelPolicy: {
|
|
340
|
+
channel: intent.channel,
|
|
341
|
+
tagPattern: exactTagPattern(intent.exactTag),
|
|
342
|
+
authorityMove:
|
|
343
|
+
id === "product.package.publish" ? "none" : "verified-ref",
|
|
344
|
+
},
|
|
345
|
+
activationPolicy: { mode: "none", environment: "none" },
|
|
346
|
+
readbackPredicates: [
|
|
347
|
+
{
|
|
348
|
+
id: `${id}.target-root`,
|
|
349
|
+
kind: "exact-root",
|
|
350
|
+
expected: operation.operationRoot,
|
|
351
|
+
},
|
|
352
|
+
],
|
|
353
|
+
effect: {
|
|
354
|
+
schema: RELEASE_TAIL_EFFECT_SCHEMA,
|
|
355
|
+
kind: descriptor.effectKind,
|
|
356
|
+
},
|
|
357
|
+
observation: {
|
|
358
|
+
schema: RELEASE_TAIL_OBSERVATION_SCHEMA,
|
|
359
|
+
kind: descriptor.observationKind,
|
|
360
|
+
},
|
|
361
|
+
receipt: {
|
|
362
|
+
schema: RELEASE_TAIL_RECEIPT_SCHEMA,
|
|
363
|
+
kind: descriptor.receiptKind,
|
|
364
|
+
},
|
|
365
|
+
operationIdentity: {
|
|
366
|
+
transactionRoot: plan.transactionRoot,
|
|
367
|
+
capabilityId: id,
|
|
368
|
+
subjectRoot: intent.intentRoot,
|
|
369
|
+
targetRoot: operation.operationRoot,
|
|
370
|
+
attemptKey: `${plan.planRoot}:${id}`,
|
|
371
|
+
},
|
|
372
|
+
idempotency: {
|
|
373
|
+
scope: "subject-target",
|
|
374
|
+
duplicate: "readback-before-retry",
|
|
375
|
+
},
|
|
376
|
+
retry: {
|
|
377
|
+
class: "provider-transient",
|
|
378
|
+
localAttempts: 1,
|
|
379
|
+
exhausted: "blocked",
|
|
380
|
+
},
|
|
381
|
+
evidenceRequirements: [
|
|
382
|
+
"provider readback must match the rooted publication operation",
|
|
383
|
+
],
|
|
384
|
+
};
|
|
385
|
+
}),
|
|
386
|
+
};
|
|
387
|
+
}
|