@kungfu-tech/buildchain 4.0.2-alpha.9 → 4.0.3-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +14 -5
- package/CONTRIBUTING.md +58 -0
- package/README.md +3 -3
- package/actions/promote-buildchain-ref/README.md +1 -1
- package/actions/release-candidate-promote/README.md +31 -0
- package/architecture/agent-change-map.md +190 -126
- package/architecture/{v4-architecture-constitution.md → architecture-constitution.md} +33 -30
- package/architecture/{v3-core-mechanism-inventory.md → baseline-core-mechanism-inventory.md} +1 -1
- package/architecture/{v4-bootstrap-authority.json → bootstrap-authority.json} +3 -3
- package/architecture/{v3-v4-capability-closure.md → capability-parity-closure.md} +3 -3
- package/architecture/{v3-v4-live-capability-inventory.json → capability-parity-live-capability-inventory.json} +4 -4
- package/architecture/{v4-capability-state-machine-manifest.json → capability-state-machine-manifest.json} +2 -2
- package/architecture/{v4-capability-state-machine-manifest.schema.json → capability-state-machine-manifest.schema.json} +2 -2
- package/architecture/ci-lane-change-budget.json +384 -0
- package/architecture/{v4-cross-platform-adopter-qualification.json → cross-platform-adopter-qualification.json} +4 -4
- package/architecture/{v4-delivery-authority-parity.json → delivery-authority-parity.json} +17 -17
- package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.json → delivery-warrant-shadow-bootstrap-plan.json} +4 -4
- package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.md → delivery-warrant-shadow-bootstrap-plan.md} +7 -7
- package/architecture/{v4-floating-consumer-policy.json → floating-consumer-policy.json} +2 -2
- package/architecture/{v4-floating-consumer-policy.md → floating-consumer-policy.md} +1 -1
- package/architecture/implementation-naming.json +1273 -0
- package/architecture/internal-capabilities.json +201 -154
- package/architecture/maintainability-debt.json +205 -146
- package/architecture/maintainability-policy.json +37 -33
- package/architecture/{v4-next-development-parity.json → next-development-parity.json} +12 -12
- package/architecture/{v4-partial-mutation-recovery-qualification.json → partial-mutation-recovery-qualification.json} +8 -5
- package/architecture/{v4-platform-stage-checkpoints.json → platform-stage-checkpoints.json} +3 -3
- package/architecture/{v4-provider-operation-journal-contract.json → provider-operation-journal-contract.json} +10 -7
- package/architecture/publication-facade-patches.json +64 -0
- package/architecture/{v4-publication-rehearsal-parity.json → publication-rehearsal-parity.json} +4 -4
- package/architecture/{v4-release-activation-shadow-domain.json → release-activation-shadow-domain.json} +9 -6
- package/architecture/release-tail-contract-inventory.json +6 -6
- package/architecture/{v4-release-topology.json → release-topology.json} +163 -72
- package/architecture/{v4-release-train-parity.json → release-train-parity.json} +2 -2
- package/architecture/{v4-runtime-ref-resume-authority.json → runtime-ref-resume-authority.json} +1 -1
- package/architecture/{v4-runtime-semantic-closure.json → runtime-semantic-closure.json} +2 -2
- package/architecture/{v4-rust-libnode-bridge-evaluation.json → rust-libnode-bridge-evaluation.json} +3 -3
- package/architecture/{v4-rust-libnode-bridge-spike.md → rust-libnode-bridge-spike.md} +6 -6
- package/architecture/rust-wasm-production-authority.json +58 -0
- package/architecture/{v4-stable-publication-fence.json → stable-publication-fence.json} +7 -4
- package/architecture/{v4-stage-capsule-contract.json → stage-capsule-contract.json} +1 -1
- package/architecture/{v4-stage-capsule-qualification.json → stage-capsule-qualification.json} +8 -8
- package/architecture/{v4-stage-capsule-resume-planner.json → stage-capsule-resume-planner.json} +2 -2
- package/architecture/{v4-stage-capsule-store-contract.json → stage-capsule-store-contract.json} +4 -4
- package/architecture/{v4-tail-reseal-parity.json → tail-reseal-parity.json} +35 -33
- package/architecture/universal-workflow-bootstrap.json +176 -0
- package/architecture/universal-workflow-fault-campaign.json +72 -0
- package/architecture/universal-workflow-train-admission.json +40 -0
- package/architecture/workflow-taxonomy.json +1462 -0
- package/bin/buildchain.mjs +10 -10
- package/bin/internal/adopter-delivery-cli.mjs +9 -9
- package/contracts/buildchain-v2-residuals-v1.json +57 -48
- package/contracts/dev-delivery-authority-v2.schema.json +16 -2
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
- package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.lock +1 -1
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.toml +1 -1
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/src/main.rs +3 -3
- package/dist/site/buildchain-contract.json +98 -53
- package/dist/site/buildchain-site.json +351 -102
- package/dist/site/capability-registry.json +7 -7
- package/dist/site/controller-registry.json +50 -13
- package/dist/site/kfd-claims.json +2773 -1052
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +14 -14
- package/dist/site/node-api-registry.json +13176 -10733
- package/dist/site/page-registry.json +332 -83
- package/dist/site/public-surface-audit.json +3227 -1222
- package/dist/site/publication-authority-registry.json +1135 -363
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +18 -9
- package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
- package/dist/site/site-manifest.json +18 -18
- package/dist/site/workflow-registry.json +5367 -1931
- package/docs/MAP.md +5 -3
- package/docs/auditable-demo.md +1 -1
- package/docs/cli.md +21 -8
- package/docs/dev-delivery-warrant.md +1 -1
- package/docs/engineering-housekeeper.md +3 -3
- package/docs/kfd-support.md +26 -2
- package/docs/next-development-transition.md +26 -3
- package/docs/node-api-reference.md +618 -358
- package/docs/oci-publication.md +173 -0
- package/docs/publication-authority.md +2 -2
- package/docs/publish-transaction.md +36 -3
- package/docs/release-candidate.md +3 -3
- package/docs/release-flow.md +67 -19
- package/docs/release-governance.md +8 -8
- package/docs/release-passport.md +27 -2
- package/docs/reusable-build-surface.md +17 -1
- package/docs/v4-adopter-delivery.md +4 -4
- package/docs/v4-canonical-contracts.md +7 -7
- package/docs/v4-delivery-warrant-read-candidate.md +3 -3
- package/docs/v4-delivery-warrant-semantic-diff.md +3 -3
- package/docs/v4-production-release.md +77 -8
- package/docs/v4-publication-rehearsal.md +3 -3
- package/docs/v4-runtime-ref-resume-authority.md +2 -2
- package/docs/v4-rust-wasm-production-authority.md +58 -0
- package/docs/v4-stage-capsule.md +9 -9
- package/docs/v4-tail-reseal.md +2 -2
- package/docs/workflow-catalog.md +155 -0
- package/docs/workflow-path-migration.md +109 -0
- package/package.json +39 -24
- package/packages/compatibility/adopter-delivery.js +16 -0
- package/packages/compatibility/cross-platform-adopter-qualification.js +12 -0
- package/packages/compatibility/floating-consumer-policy.js +14 -0
- package/packages/compatibility/publication-qualification.js +11 -0
- package/packages/compatibility/publication-rehearsal.js +18 -0
- package/packages/compatibility/runtime-ref-resume-authority.js +13 -0
- package/packages/compatibility/tail-reseal-receipt.js +7 -0
- package/packages/compatibility/tail-reseal.js +11 -0
- package/packages/core/{v4-adopter-delivery-parity.js → adopter-delivery-parity.js} +12 -12
- package/packages/core/{v4-adopter-delivery.js → adopter-delivery.js} +24 -24
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/buildchain-contract.js +6 -6
- package/packages/core/buildchain-domain.wasm +0 -0
- package/packages/core/buildchain-kfd-claims.js +2 -2
- package/packages/core/buildchain-publication-authority.js +43 -26
- package/packages/core/{v4-canonical-contracts.js → canonical-contracts.js} +39 -103
- package/packages/core/ci-lane-change-budget.js +14 -1
- package/packages/core/controller-evidence.js +4 -1
- package/packages/core/{v4-cross-platform-adopter-qualification.js → cross-platform-adopter-qualification.js} +19 -19
- package/packages/core/{v4-delivery-warrant-fixture-runner.js → delivery-warrant-fixture-runner.js} +36 -32
- package/packages/core/{v4-delivery-warrant-read-candidate.js → delivery-warrant-read-candidate.js} +40 -40
- package/packages/core/{v4-delivery-warrant-semantic-diff-gate.js → delivery-warrant-semantic-diff-gate.js} +58 -59
- package/packages/core/{v4-delivery-warrant-shadow-adapter.js → delivery-warrant-shadow-adapter.js} +15 -15
- package/packages/core/dev-delivery-candidate-identity.js +40 -6
- package/packages/core/dev-delivery-execution-transfer.js +6 -6
- package/packages/core/dev-delivery-native-proof.js +12 -8
- package/packages/core/dev-delivery-warrant-legacy-recovery.js +1 -1
- package/packages/core/dev-delivery-warrant-native-compatibility.js +4 -4
- package/packages/core/dev-delivery-warrant-state.js +14 -15
- package/packages/core/dev-delivery-warrant.js +15 -5
- package/packages/core/domain-wasm-artifact.js +7 -0
- package/packages/core/domain-wasm.js +216 -0
- package/packages/core/{v4-floating-consumer-evidence.js → floating-consumer-evidence.js} +14 -14
- package/packages/core/{v4-floating-consumer-policy.js → floating-consumer-policy.js} +28 -30
- package/packages/core/{v4-floating-consumer-release-passport.js → floating-consumer-release-passport.js} +25 -25
- package/packages/core/github-governance-authority.js +4 -4
- package/packages/core/index.js +4 -8
- package/packages/core/kfd-adopter-manifest.js +46 -47
- package/packages/core/next-development-projection.js +26 -3
- package/packages/core/next-development-transition.js +5 -6
- package/packages/core/oci-compose-qualification.js +143 -0
- package/packages/core/oci-publication-bundle.js +281 -0
- package/packages/core/oci-publication-graph.js +206 -0
- package/packages/core/paper-agent-entry.js +30 -4
- package/packages/core/paper-fleet.js +1 -1
- package/packages/core/paper-runtime-channels.js +348 -0
- package/packages/core/paper-scaffold-content.js +10 -0
- package/packages/core/paper.js +37 -71
- package/packages/core/partial-mutation-recovery-qualification.js +18 -0
- package/packages/core/{v4-platform-stage-checkpoints.js → platform-stage-checkpoints.js} +37 -37
- package/packages/core/product-publication.js +59 -0
- package/packages/core/{v4-protected-publication-source.js → protected-publication-source.js} +22 -24
- package/packages/core/provider-operation-journal.js +62 -0
- package/packages/core/{v4-provider-readback-idempotency.js → provider-readback-idempotency.js} +40 -125
- package/packages/core/public-export-compatibility.js +33 -0
- package/packages/core/publication-development.js +72 -0
- package/packages/core/{v4-publication-qualification.js → publication-qualification.js} +17 -17
- package/packages/core/{v4-publication-rehearsal-capsule.js → publication-rehearsal-capsule.js} +23 -23
- package/packages/core/publication-rehearsal-projection.js +2 -2
- package/packages/core/{v4-publication-rehearsal-provider-bindings.js → publication-rehearsal-provider-bindings.js} +4 -4
- package/packages/core/publication-rehearsal-runtime.js +21 -21
- package/packages/core/{v4-publication-rehearsal.js → publication-rehearsal.js} +33 -33
- package/packages/core/publication-sealed-bundle.js +78 -13
- package/packages/core/release-activation-shadow.js +32 -0
- package/packages/core/release-candidate.js +6 -6
- package/packages/core/release-invocation.js +64 -0
- package/packages/core/release-line-dry-run.js +1 -1
- package/packages/core/release-passport-contract.js +5 -5
- package/packages/core/release-passport.js +41 -40
- package/packages/core/release-tail-product-capabilities.js +9 -0
- package/packages/core/release-tail-provider-plane.js +68 -1048
- package/packages/core/{v4-runtime-ref-resume-authority.js → runtime-ref-resume-authority.js} +36 -40
- package/packages/core/{v4-runtime-selector-persistence.js → runtime-selector-persistence.js} +7 -7
- package/packages/core/stable-publication-fence.js +28 -0
- package/packages/core/{v4-stage-capsule-local-store.js → stage-capsule-local-store.js} +56 -54
- package/packages/core/{v4-stage-capsule-qualification-campaign.js → stage-capsule-qualification-campaign.js} +37 -38
- package/packages/core/{v4-stage-capsule-qualification.js → stage-capsule-qualification.js} +28 -29
- package/packages/core/{v4-stage-capsule-resume-planner.js → stage-capsule-resume-planner.js} +29 -29
- package/packages/core/{v4-stage-capsule-store.js → stage-capsule-store.js} +59 -56
- package/packages/core/{v4-stage-capsule.js → stage-capsule.js} +45 -45
- package/packages/core/{v4-tail-reseal-contract.js → tail-reseal-contract.js} +6 -6
- package/packages/core/{v4-tail-reseal-github.js → tail-reseal-github.js} +12 -12
- package/packages/core/{v4-tail-reseal-receipt.js → tail-reseal-receipt.js} +22 -22
- package/packages/core/{v4-tail-reseal.js → tail-reseal.js} +29 -29
- package/packages/core/universal-workflow-bootstrap.js +586 -0
- package/scripts/{v4-architecture.mjs → architecture.mjs} +6 -6
- package/scripts/binary-publication-evidence.mjs +135 -0
- package/scripts/{v4-bridge-bootstrap.mjs → bridge-bootstrap.mjs} +14 -18
- package/scripts/{v4-bridge-evidence.mjs → bridge-evidence.mjs} +8 -8
- package/scripts/build-contract-core.mjs +1 -14
- package/scripts/build-domain-wasm.mjs +177 -0
- package/scripts/{v3-v4-capability-catalog.mjs → capability-parity-catalog.mjs} +19 -19
- package/scripts/check-action-bundles.mjs +12 -2
- package/scripts/{check-v3-v4-capability-inventory.mjs → check-capability-parity-inventory.mjs} +42 -42
- package/scripts/check-ci-lane-change-budget.mjs +4 -1
- package/scripts/check-core-mechanism-inventory.mjs +8 -4
- package/scripts/{check-v4-floating-consumer-policy-contract.mjs → check-floating-consumer-policy-contract.mjs} +10 -10
- package/scripts/check-implementation-naming.mjs +135 -0
- package/scripts/check-inventory.mjs +39 -47
- package/scripts/check-maintainability.mjs +25 -115
- package/scripts/{check-v4-public-dogfood-contract.mjs → check-public-dogfood-contract.mjs} +37 -24
- package/scripts/{check-v4-release-topology.mjs → check-release-topology.mjs} +131 -52
- package/scripts/{check-v4-runtime-semantic-closure.mjs → check-runtime-semantic-closure.mjs} +23 -17
- package/scripts/check-universal-workflow-bootstrap.mjs +266 -0
- package/scripts/check-workflow-taxonomy.mjs +6 -0
- package/scripts/{v4-consumer-policy.mjs → consumer-policy.mjs} +15 -15
- package/scripts/copy-domain-wasm.mjs +14 -0
- package/scripts/{v4-cross-platform-adopter-qualification.mjs → cross-platform-adopter-qualification.mjs} +9 -9
- package/scripts/{v4-declarative-promotion-admission.mjs → declarative-promotion-admission.mjs} +4 -4
- package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
- package/scripts/dev-delivery-authority.mjs +8 -8
- package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
- package/scripts/dev-delivery-warrant-options.mjs +15 -10
- package/scripts/dev-delivery-warrant-store.mjs +98 -13
- package/scripts/dev-delivery-warrant-transition.mjs +109 -0
- package/scripts/dev-delivery-warrant.mjs +80 -103
- package/scripts/dev-pr-auto-merge.mjs +15 -15
- package/scripts/dev-pr-delivery-warrant.mjs +1 -1
- package/scripts/generate-channel-build-workflow.mjs +7 -2
- package/scripts/generate-channel-promotion-workflow.mjs +19 -34
- package/scripts/generate-release-candidate-passport.mjs +23 -23
- package/scripts/generate-site-bundle.mjs +28 -28
- package/scripts/generate-universal-workflow-facades.mjs +498 -0
- package/scripts/generate-workflow-taxonomy.mjs +25 -0
- package/scripts/github-output.mjs +31 -0
- package/scripts/{v4-host-adapter.mjs → host-adapter.mjs} +1 -1
- package/scripts/implementation-references.mjs +25 -0
- package/scripts/init-repo.mjs +1 -1
- package/scripts/maintainability-metrics.mjs +16 -5
- package/scripts/maintainability-public-surface.mjs +115 -0
- package/scripts/next-development-review.mjs +313 -0
- package/scripts/oci-compose-preview.mjs +261 -0
- package/scripts/paper-work-fleet-cli.mjs +2 -0
- package/scripts/{v4-platform-stage-checkpoint-rehearsal.mjs → platform-stage-checkpoint-rehearsal.mjs} +17 -17
- package/scripts/{v4-product-publication-intent.mjs → product-publication-intent.mjs} +28 -13
- package/scripts/publication-candidate-kind.mjs +93 -0
- package/scripts/publication-candidate-sealer.mjs +16 -1
- package/scripts/{v4-publication-rehearsal-fixture.mjs → publication-rehearsal-fixture.mjs} +5 -5
- package/scripts/publication-settlement.mjs +211 -0
- package/scripts/release-asset-client.mjs +91 -0
- package/scripts/{v4-release-candidate-adapter.mjs → release-candidate-adapter.mjs} +4 -4
- package/scripts/release-candidate-resolver.mjs +24 -35
- package/scripts/release-tail.mjs +5 -5
- package/scripts/resume-from-candidate-run.mjs +35 -42
- package/scripts/site-capability-metadata.mjs +9 -0
- package/scripts/source-verification-evidence.mjs +344 -0
- package/scripts/stable-candidate-qualification.mjs +1 -1
- package/scripts/{v4-stage-capsule-qualification.mjs → stage-capsule-qualification.mjs} +62 -62
- package/scripts/{v4-stage-capsule-resume-rehearsal.mjs → stage-capsule-resume-rehearsal.mjs} +6 -6
- package/scripts/{v4-tail-reseal-macos-rehearsal.mjs → tail-reseal-macos-rehearsal.mjs} +9 -9
- package/scripts/{v4-tail-reseal.mjs → tail-reseal.mjs} +19 -19
- package/scripts/universal-facade-maintainability.mjs +91 -0
- package/scripts/universal-workflow-backflow.mjs +212 -0
- package/scripts/universal-workflow-engine.mjs +620 -0
- package/scripts/universal-workflow-self-dogfood.mjs +205 -0
- package/scripts/verify-version-state-delta.mjs +175 -0
- package/scripts/{v4-warrant-shadow-plan.mjs → warrant-shadow-plan.mjs} +6 -6
- package/scripts/workflow-taxonomy.mjs +507 -0
- package/templates/native-dev-delivery.yml +4 -7
- package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
- package/templates/universal-buildchain-bootstrap.yml +28 -0
- package/actions/v4-release-candidate-promote/README.md +0 -3
- package/packages/core/v4-partial-mutation-recovery-qualification.js +0 -395
- package/packages/core/v4-product-publication.js +0 -387
- package/packages/core/v4-provider-operation-journal.js +0 -531
- package/packages/core/v4-release-activation-shadow.js +0 -519
- package/packages/core/v4-release-invocation.js +0 -425
- package/packages/core/v4-stable-publication-fence.js +0 -357
- /package/architecture/{v4-adopter-delivery-parity.json → adopter-delivery-parity.json} +0 -0
- /package/architecture/{v3-core-mechanism-inventory.json → baseline-core-mechanism-inventory.json} +0 -0
- /package/architecture/{v4-canonical-contract-fixtures.json → canonical-contract-fixtures.json} +0 -0
- /package/architecture/{v4-compatibility-facts-parity.json → compatibility-facts-parity.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.schema.json → delivery-warrant-shadow-bootstrap-plan.schema.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-fixtures.json → delivery-warrant-shadow-fixtures.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-fixtures.schema.json → delivery-warrant-shadow-fixtures.schema.json} +0 -0
- /package/architecture/{v4-exception-ledger.json → exception-ledger.json} +0 -0
- /package/architecture/{v4-exception-ledger.schema.json → exception-ledger.schema.json} +0 -0
- /package/architecture/{v4-release-invocation-fixtures.json → release-invocation-fixtures.json} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
|
|
@@ -19,7 +20,10 @@ function requiredString(value, label) {
|
|
|
19
20
|
|
|
20
21
|
function safeRelativePath(value, label) {
|
|
21
22
|
const normalized = requiredString(value, label).replaceAll("\\", "/");
|
|
22
|
-
if (
|
|
23
|
+
if (
|
|
24
|
+
normalized.startsWith("/") ||
|
|
25
|
+
normalized.split("/").some((part) => part === ".." || part === "")
|
|
26
|
+
) {
|
|
23
27
|
throw new Error(`${label} must be a safe relative path`);
|
|
24
28
|
}
|
|
25
29
|
return normalized;
|
|
@@ -41,7 +45,8 @@ function sha256File(filePath) {
|
|
|
41
45
|
const chunk = Buffer.allocUnsafe(8 * 1024 * 1024);
|
|
42
46
|
try {
|
|
43
47
|
let bytesRead = 0;
|
|
44
|
-
while ((bytesRead = fs.readSync(descriptor, chunk, 0, chunk.length, null)) > 0)
|
|
48
|
+
while ((bytesRead = fs.readSync(descriptor, chunk, 0, chunk.length, null)) > 0)
|
|
49
|
+
hash.update(chunk.subarray(0, bytesRead));
|
|
45
50
|
} finally {
|
|
46
51
|
fs.closeSync(descriptor);
|
|
47
52
|
}
|
|
@@ -60,8 +65,16 @@ function normalizeFile(entry, label) {
|
|
|
60
65
|
};
|
|
61
66
|
}
|
|
62
67
|
|
|
68
|
+
function fileInventory(files, label) {
|
|
69
|
+
return (files || []).map((entry, index) => normalizeFile(entry, `${label}[${index}]`))
|
|
70
|
+
.sort((left, right) => left.path.localeCompare(right.path));
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
function candidatePayload(candidate) {
|
|
64
|
-
if (
|
|
74
|
+
if (
|
|
75
|
+
candidate?.contract !== PUBLICATION_ARTIFACT_CANDIDATE_CONTRACT ||
|
|
76
|
+
Number(candidate?.schemaVersion) !== 1
|
|
77
|
+
) {
|
|
65
78
|
throw new Error("publication artifact candidate contract mismatch");
|
|
66
79
|
}
|
|
67
80
|
const { candidateDigest: _candidateDigest, ...payload } = candidate;
|
|
@@ -91,9 +104,7 @@ export function createPublicationSealedBundle({
|
|
|
91
104
|
githubReleaseRequired = true,
|
|
92
105
|
} = {}) {
|
|
93
106
|
const { digest } = candidatePayload(candidate);
|
|
94
|
-
const files = (candidate.files
|
|
95
|
-
.map((entry, index) => normalizeFile(entry, `candidate.files[${index}]`))
|
|
96
|
-
.sort((left, right) => left.path.localeCompare(right.path));
|
|
107
|
+
const files = fileInventory(candidate.files, "candidate.files");
|
|
97
108
|
if (new Set(files.map((entry) => entry.path)).size !== files.length) {
|
|
98
109
|
throw new Error("publication sealed bundle candidate paths must be unique");
|
|
99
110
|
}
|
|
@@ -119,6 +130,7 @@ export function createPublicationSealedBundle({
|
|
|
119
130
|
sha256: npmTarball.sha256,
|
|
120
131
|
integrity: requiredString(npmIntegrity, "npmIntegrity"),
|
|
121
132
|
},
|
|
133
|
+
...(candidate.npmPackages ? { npmPackages: candidate.npmPackages } : {}),
|
|
122
134
|
releaseAssets,
|
|
123
135
|
completion: {
|
|
124
136
|
githubReleaseRequired: Boolean(githubReleaseRequired),
|
|
@@ -130,8 +142,56 @@ export function createPublicationSealedBundle({
|
|
|
130
142
|
};
|
|
131
143
|
}
|
|
132
144
|
|
|
145
|
+
function verifyNpmPackageSet(manifest, files, resolvedRoot) {
|
|
146
|
+
const npmPackages = manifest.npmPackages;
|
|
147
|
+
if (JSON.stringify(npmPackages) !== JSON.stringify(manifest.candidate.npmPackages)) {
|
|
148
|
+
throw new Error("publication sealed bundle npm package inventory differs from candidate");
|
|
149
|
+
}
|
|
150
|
+
if (npmPackages) {
|
|
151
|
+
if (
|
|
152
|
+
!Array.isArray(npmPackages) ||
|
|
153
|
+
npmPackages.length < 2 ||
|
|
154
|
+
new Set(npmPackages.map((entry) => entry.name)).size !== npmPackages.length ||
|
|
155
|
+
new Set(npmPackages.map((entry) => entry.path)).size !== npmPackages.length
|
|
156
|
+
) {
|
|
157
|
+
throw new Error("publication sealed bundle npm package inventory must be unique");
|
|
158
|
+
}
|
|
159
|
+
for (const entry of npmPackages) {
|
|
160
|
+
const file = selectFile(files, entry.path, "npmPackages.path");
|
|
161
|
+
const absolutePath = path.resolve(resolvedRoot, file.path);
|
|
162
|
+
const metadata = JSON.parse(
|
|
163
|
+
execFileSync("tar", ["-xOf", path.basename(absolutePath), "package/package.json"], {
|
|
164
|
+
cwd: path.dirname(absolutePath),
|
|
165
|
+
encoding: "utf8",
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
168
|
+
const integrity = `sha512-${crypto.createHash("sha512").update(fs.readFileSync(absolutePath)).digest("base64")}`;
|
|
169
|
+
if (
|
|
170
|
+
entry.name !== metadata.name ||
|
|
171
|
+
entry.version !== metadata.version ||
|
|
172
|
+
entry.size !== file.size ||
|
|
173
|
+
entry.sha256 !== file.sha256 ||
|
|
174
|
+
entry.integrity !== integrity
|
|
175
|
+
) {
|
|
176
|
+
throw new Error("publication sealed bundle npm package identity or integrity mismatch");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const main = npmPackages.filter((entry) => entry.role === "main");
|
|
180
|
+
if (
|
|
181
|
+
main.length !== 1 ||
|
|
182
|
+
Object.keys(manifest.npm).some((key) => main[0][key] !== manifest.npm[key])
|
|
183
|
+
) {
|
|
184
|
+
throw new Error("publication sealed bundle npm main package mismatch");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return npmPackages;
|
|
188
|
+
}
|
|
189
|
+
|
|
133
190
|
export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
|
|
134
|
-
if (
|
|
191
|
+
if (
|
|
192
|
+
manifest?.contract !== PUBLICATION_SEALED_BUNDLE_CONTRACT ||
|
|
193
|
+
Number(manifest?.schemaVersion) !== 1
|
|
194
|
+
) {
|
|
135
195
|
throw new Error("publication sealed bundle contract mismatch");
|
|
136
196
|
}
|
|
137
197
|
const resolvedRoot = path.resolve(requiredString(bundleRoot, "bundleRoot"));
|
|
@@ -139,12 +199,8 @@ export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
|
|
|
139
199
|
if (normalizeSha256(manifest.root, "manifest.root") !== digest) {
|
|
140
200
|
throw new Error("publication sealed bundle root mismatch");
|
|
141
201
|
}
|
|
142
|
-
const files = (manifest.files
|
|
143
|
-
|
|
144
|
-
.sort((left, right) => left.path.localeCompare(right.path));
|
|
145
|
-
const candidateFiles = (manifest.candidate.files || [])
|
|
146
|
-
.map((entry, index) => normalizeFile(entry, `candidate.files[${index}]`))
|
|
147
|
-
.sort((left, right) => left.path.localeCompare(right.path));
|
|
202
|
+
const files = fileInventory(manifest.files, "manifest.files");
|
|
203
|
+
const candidateFiles = fileInventory(manifest.candidate.files, "candidate.files");
|
|
148
204
|
if (JSON.stringify(files) !== JSON.stringify(candidateFiles)) {
|
|
149
205
|
throw new Error("publication sealed bundle file inventory differs from candidate");
|
|
150
206
|
}
|
|
@@ -169,6 +225,7 @@ export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
|
|
|
169
225
|
) {
|
|
170
226
|
throw new Error("publication sealed bundle npm tarball inventory mismatch");
|
|
171
227
|
}
|
|
228
|
+
const npmPackages = verifyNpmPackageSet(manifest, files, resolvedRoot);
|
|
172
229
|
const releaseAssets = (manifest.releaseAssets || []).map((entry, index) => {
|
|
173
230
|
const selected = selectFile(files, entry.path, `manifest.releaseAssets[${index}].path`);
|
|
174
231
|
const normalized = normalizeFile(entry, `manifest.releaseAssets[${index}]`);
|
|
@@ -194,6 +251,14 @@ export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
|
|
|
194
251
|
...entry,
|
|
195
252
|
absolutePath: path.resolve(resolvedRoot, entry.path),
|
|
196
253
|
})),
|
|
254
|
+
...(npmPackages
|
|
255
|
+
? {
|
|
256
|
+
npmPackages: npmPackages.map((entry) => ({
|
|
257
|
+
...entry,
|
|
258
|
+
absolutePath: path.resolve(resolvedRoot, entry.path),
|
|
259
|
+
})),
|
|
260
|
+
}
|
|
261
|
+
: {}),
|
|
197
262
|
manifest,
|
|
198
263
|
};
|
|
199
264
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ContractFault } from "./canonical-contracts.js";
|
|
2
|
+
import { DomainWasmFault, invokeDomainWasm } from "./domain-wasm.js";
|
|
3
|
+
|
|
4
|
+
export const RELEASE_ACTIVATION_REQUEST_CONTRACT =
|
|
5
|
+
"buildchain-v4-release-activation-request/v1";
|
|
6
|
+
export const RELEASE_ACTIVATION_PLAN_CONTRACT =
|
|
7
|
+
"buildchain-v4-release-activation-plan/v1";
|
|
8
|
+
export const RELEASE_ACTIVATION_STATE_CONTRACT =
|
|
9
|
+
"buildchain-v4-release-activation-state/v1";
|
|
10
|
+
|
|
11
|
+
function project(request) {
|
|
12
|
+
try {
|
|
13
|
+
return invokeDomainWasm("release-activation", request);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
if (error instanceof DomainWasmFault) {
|
|
16
|
+
throw new ContractFault(error.code, error.path, error.message);
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function planReleaseActivation(request) {
|
|
23
|
+
return project(request).plan;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function foldReleaseActivation(request) {
|
|
27
|
+
return project(request).state;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function projectReleaseActivation(request) {
|
|
31
|
+
return project(request);
|
|
32
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { verifyFloatingConsumerPolicyReceipt } from "./floating-consumer-policy.js";
|
|
3
3
|
import { normalizeControllerReceiptReferences, validateControllerReceiptReference } from "./controller-evidence.js";
|
|
4
4
|
|
|
5
5
|
export const RELEASE_CANDIDATE_PASSPORT_CONTRACT = "kungfu-buildchain-release-candidate-passport";
|
|
@@ -172,7 +172,7 @@ function normalizeGateProfileEvidence(gateAggregate = undefined) {
|
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
function
|
|
175
|
+
function isBuildchainRuntime(buildchain = {}) {
|
|
176
176
|
return [buildchain.ref, buildchain.workflowShellRef]
|
|
177
177
|
.some((value) => /^v4(?:-alpha)?$/u.test(String(value || "")))
|
|
178
178
|
|| /^4\./u.test(String(buildchain.version || ""));
|
|
@@ -184,7 +184,7 @@ function normalizeConsumerPolicyEvidence(value, expected = {}) {
|
|
|
184
184
|
throw new Error("consumerPolicyReceipt must be an object");
|
|
185
185
|
}
|
|
186
186
|
const receipt = value.receipt || value;
|
|
187
|
-
const verification =
|
|
187
|
+
const verification = verifyFloatingConsumerPolicyReceipt({
|
|
188
188
|
receipt,
|
|
189
189
|
receiptRoot: value.receiptRoot || "",
|
|
190
190
|
repository: expected.repository,
|
|
@@ -198,11 +198,11 @@ function normalizeConsumerPolicyEvidence(value, expected = {}) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
function validateConsumerPolicyEvidence(passport, check) {
|
|
201
|
-
if (
|
|
201
|
+
if (isBuildchainRuntime(passport.buildchain)) {
|
|
202
202
|
check(Boolean(passport.consumerPolicy), "Buildchain v4 release candidate requires consumer policy evidence");
|
|
203
203
|
}
|
|
204
204
|
if (!passport.consumerPolicy) return;
|
|
205
|
-
const verification =
|
|
205
|
+
const verification = verifyFloatingConsumerPolicyReceipt({
|
|
206
206
|
receipt: passport.consumerPolicy.receipt,
|
|
207
207
|
receiptRoot: passport.consumerPolicy.receiptRoot,
|
|
208
208
|
repository: passport.repository,
|
|
@@ -406,7 +406,7 @@ export function createReleaseCandidatePassport({
|
|
|
406
406
|
sourceSha: normalizedSummary.publishSource?.ref === "publish-gate/anchor" ? (consumerPolicyReceipt?.receipt || consumerPolicyReceipt)?.caller?.sourceSha : sourceSha,
|
|
407
407
|
runtimeSha: resolvedBuildchain.sha,
|
|
408
408
|
});
|
|
409
|
-
if (
|
|
409
|
+
if (isBuildchainRuntime(resolvedBuildchain) && !normalizedConsumerPolicy) {
|
|
410
410
|
throw new Error("Buildchain v4 release candidate passport requires a valid floating consumer policy receipt");
|
|
411
411
|
}
|
|
412
412
|
const controllerReceiptEvidence = normalizeControllerReceiptReferences({
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ContractFault } from "./canonical-contracts.js";
|
|
2
|
+
import { DomainWasmFault, invokeDomainWasm } from "./domain-wasm.js";
|
|
3
|
+
|
|
4
|
+
export const RELEASE_INVOCATION_CONTRACT =
|
|
5
|
+
"kungfu-buildchain-v4-release-invocation/v1";
|
|
6
|
+
export const RELEASE_INVOCATION_ADAPTER_CONTRACT =
|
|
7
|
+
"kungfu-buildchain-v4-release-invocation-adapter/v1";
|
|
8
|
+
export const RELEASE_TRANSACTION_CONTRACT =
|
|
9
|
+
"kungfu-buildchain-v4-release-transaction/v1";
|
|
10
|
+
export const RELEASE_RECEIPT_CONTRACT =
|
|
11
|
+
"kungfu-buildchain-v4-release-receipt/v1";
|
|
12
|
+
export const RELEASE_PROVIDER_CONTRACT =
|
|
13
|
+
"kungfu-buildchain-release-tail-provider/v1";
|
|
14
|
+
|
|
15
|
+
function invoke(operation, payload) {
|
|
16
|
+
try {
|
|
17
|
+
return invokeDomainWasm(operation, payload);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if (error instanceof DomainWasmFault) {
|
|
20
|
+
throw new ContractFault(error.code, error.path, error.message);
|
|
21
|
+
}
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createReleaseInvocation(value) {
|
|
27
|
+
const projected = invoke("release-invocation", value);
|
|
28
|
+
return { ...projected, invocation: value };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function adaptReleaseInvocation(value) {
|
|
32
|
+
const projected = invoke("release-invocation-adapter", value);
|
|
33
|
+
return { ...projected, invocation: value.invocation };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function planReleaseRoute({
|
|
37
|
+
requestedSha,
|
|
38
|
+
observedSha,
|
|
39
|
+
comparisonStatus,
|
|
40
|
+
requestedChannel = "",
|
|
41
|
+
targetRef,
|
|
42
|
+
dryRun = false,
|
|
43
|
+
resume = false,
|
|
44
|
+
}) {
|
|
45
|
+
return Object.freeze(
|
|
46
|
+
invoke("release-route", {
|
|
47
|
+
requestedSha,
|
|
48
|
+
observedSha,
|
|
49
|
+
comparisonStatus,
|
|
50
|
+
requestedChannel,
|
|
51
|
+
targetRef,
|
|
52
|
+
dryRun,
|
|
53
|
+
resume,
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function createDomainReleaseTransaction(value) {
|
|
59
|
+
return invoke("release-transaction", value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function createReleaseReceipt(value) {
|
|
63
|
+
return invoke("release-receipt", value);
|
|
64
|
+
}
|
|
@@ -201,7 +201,7 @@ function explainReleaseLineDryRun({
|
|
|
201
201
|
);
|
|
202
202
|
plan.branchUpdates.push(
|
|
203
203
|
{ ref: targetRef, action: "would move to alpha version-state commit" },
|
|
204
|
-
{ ref: `dev/v${rule.major}/v${rule.major}.${rule.minor}`, action: "would align dev with the published alpha state" },
|
|
204
|
+
{ ref: `dev/v${rule.major}/v${rule.major}.${rule.minor}`, action: rule.major === 4 ? "would prepare the next alpha version on dev through a separate protected PR after publication" : "would align dev with the published alpha state" },
|
|
205
205
|
);
|
|
206
206
|
plan.versionState.targetVersions = [exactAlpha.replace(/^next v?/, "").replace(/^v/, "")];
|
|
207
207
|
plan.notes.push("Alpha promotion opens or advances the test channel; it does not move production refs.");
|
|
@@ -405,7 +405,7 @@ export function prepareReleasePassportKfdSections({ kfd1, kfd2Claims, kfd3, kfdA
|
|
|
405
405
|
};
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
-
export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, sourceSha = "", checkedAt } = {}) {
|
|
408
|
+
export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", sourceSha = "", checkedAt } = {}) {
|
|
409
409
|
if (!manifest) {
|
|
410
410
|
if (comparisonMatrix || gateResults.length > 0) {
|
|
411
411
|
throw new Error("KFD support and product-gate inputs require --kfd-adopter-manifest-json; --kfd-support-matrix-json is comparison-only");
|
|
@@ -414,7 +414,7 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
|
|
|
414
414
|
}
|
|
415
415
|
const manifestGate = createKfdAdopterManifestGate({
|
|
416
416
|
manifest, packageArtifactRoot: installedKfdPackageArtifactRoot(), gateResults,
|
|
417
|
-
expectedSourceSha: sourceSha, checkedAt,
|
|
417
|
+
expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha, checkedAt,
|
|
418
418
|
});
|
|
419
419
|
const legacyProjection = createKfdLegacySupportMatrixProjection({ manifest, manifestGate });
|
|
420
420
|
if (comparisonMatrix) {
|
|
@@ -425,18 +425,18 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
|
|
|
425
425
|
}
|
|
426
426
|
return {
|
|
427
427
|
manifest, manifestGate, legacyProjection,
|
|
428
|
-
binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedSourceSha: sourceSha }),
|
|
428
|
+
binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha }),
|
|
429
429
|
};
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
-
export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedSourceSha = "" } = {}) {
|
|
432
|
+
export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", expectedSourceSha = "" } = {}) {
|
|
433
433
|
if (!binding) {
|
|
434
434
|
return passportLegacyProjection
|
|
435
435
|
? [{ code: "kfdSupport.authority", message: "legacy KFD support projection requires the standard adopter manifest binding" }]
|
|
436
436
|
: [];
|
|
437
437
|
}
|
|
438
438
|
const issues = validateKfdAdopterReleaseBinding(binding, {
|
|
439
|
-
manifest, manifestGate, legacyProjection, expectedSourceSha,
|
|
439
|
+
manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha,
|
|
440
440
|
}).issues.map((entry) => ({ code: `kfdAdopter.${entry.path || entry.code}`, message: entry.message, details: entry }));
|
|
441
441
|
if (!artifactBinding || passportStableJson(artifactBinding) !== passportStableJson(binding)) {
|
|
442
442
|
issues.push({ code: "kfdAdopter.artifactEvidence", message: "release passport and artifact evidence must bind the same exact KFD adopter closure" });
|
|
@@ -33,20 +33,20 @@ import { normalizeControllerReceiptReferences } from "./controller-evidence.js";
|
|
|
33
33
|
import {
|
|
34
34
|
normalizeGitHubArtifactAttestationPolicy,
|
|
35
35
|
} from "./github-artifact-attestation.js";
|
|
36
|
-
import {
|
|
36
|
+
import { verifyFloatingConsumerPolicyCertification } from "./floating-consumer-evidence.js";
|
|
37
37
|
import {
|
|
38
38
|
normalizePromotionEvidence,
|
|
39
39
|
normalizePromotionRouting,
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
normalizeRuntimeResumeEvidence,
|
|
41
|
+
isPromotionRouting,
|
|
42
42
|
releasePassportCertificationVerificationOptions,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} from "./
|
|
43
|
+
requireConsumerPolicyCertification,
|
|
44
|
+
resolveConsumerPolicyCertificationIdentity,
|
|
45
|
+
} from "./floating-consumer-release-passport.js";
|
|
46
46
|
import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
} from "./
|
|
47
|
+
verifyRuntimeAuthorizationReceipt,
|
|
48
|
+
verifyRuntimeResumeLineage,
|
|
49
|
+
} from "./runtime-ref-resume-authority.js";
|
|
50
50
|
|
|
51
51
|
export { RELEASE_CHECK_REPORT_CONTRACT, RELEASE_PASSPORT_CONTRACT };
|
|
52
52
|
export const ARTIFACT_EVIDENCE_CONTRACT = "kungfu-buildchain-artifact-evidence";
|
|
@@ -1204,9 +1204,9 @@ export function createReleasePassport(options = {}) {
|
|
|
1204
1204
|
kfdSupportEvidencePath = "",
|
|
1205
1205
|
invariantPassports = undefined,
|
|
1206
1206
|
releaseEvidence = [],
|
|
1207
|
-
v4ConsumerPolicyCertification = undefined,
|
|
1208
|
-
v4ConsumerPolicyCertificationRoot = "",
|
|
1209
|
-
|
|
1207
|
+
v4ConsumerPolicyCertification: domainConsumerPolicyCertification = undefined,
|
|
1208
|
+
v4ConsumerPolicyCertificationRoot: domainConsumerPolicyCertificationRoot = "",
|
|
1209
|
+
domainRuntimeResumeEvidence = undefined,
|
|
1210
1210
|
kfdAgentHubEvidence = undefined,
|
|
1211
1211
|
kfdAgentHubEvidencePath = "",
|
|
1212
1212
|
controllerReceipts = [],
|
|
@@ -1223,9 +1223,9 @@ export function createReleasePassport(options = {}) {
|
|
|
1223
1223
|
const normalizedTrustedPublishing = normalizeTrustedPublishing(trustedPublishing, { workflow, publish });
|
|
1224
1224
|
const normalizedTransaction = normalizeTransaction(transaction);
|
|
1225
1225
|
const { promotion, buildEvidence } = preparePromotionBuild(options);
|
|
1226
|
-
const
|
|
1226
|
+
const normalizedRuntimeResume = normalizeRuntimeResumeEvidence(domainRuntimeResumeEvidence, {
|
|
1227
1227
|
repository,
|
|
1228
|
-
sourceSha:
|
|
1228
|
+
sourceSha: runtimeResumeSourceSha(release, sourceSha),
|
|
1229
1229
|
resumeRuntimeSha: promotion.routing?.runtime?.resolvedSha || "",
|
|
1230
1230
|
consumerPolicyReceiptRoot: promotion.consumerPolicy?.certification?.receiptRoot || "",
|
|
1231
1231
|
});
|
|
@@ -1374,7 +1374,7 @@ export function createReleasePassport(options = {}) {
|
|
|
1374
1374
|
["invariantPassports", invariantPassports],
|
|
1375
1375
|
["releaseEvidence", releaseEvidence],
|
|
1376
1376
|
["v4ConsumerPolicy", promotion.consumerPolicy],
|
|
1377
|
-
["v4RuntimeResume",
|
|
1377
|
+
["v4RuntimeResume", normalizedRuntimeResume],
|
|
1378
1378
|
["controllerReceipts", normalizedControllerReceipts],
|
|
1379
1379
|
["githubArtifactAttestations", normalizedGitHubArtifactAttestations],
|
|
1380
1380
|
]),
|
|
@@ -1431,7 +1431,7 @@ export function createReleasePassport(options = {}) {
|
|
|
1431
1431
|
};
|
|
1432
1432
|
}
|
|
1433
1433
|
|
|
1434
|
-
function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, sourceSha, checkedAt }) {
|
|
1434
|
+
function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, repository, sourceSha, checkedAt }) {
|
|
1435
1435
|
const manifestMeta = parseJsonInputWithMeta(manifestJson, undefined, { cwd, label: "kfdAdopterManifestJson" });
|
|
1436
1436
|
const supportMatrixMeta = parseJsonInputWithMeta(supportMatrixJson, undefined, { cwd, label: "kfdSupportMatrixJson" });
|
|
1437
1437
|
const productGateMetas = (productGateJsons || [])
|
|
@@ -1442,7 +1442,7 @@ function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson,
|
|
|
1442
1442
|
manifest: manifestMeta.value,
|
|
1443
1443
|
gateResults: productGateMetas.map((meta) => meta.value),
|
|
1444
1444
|
comparisonMatrix: supportMatrixMeta.value,
|
|
1445
|
-
sourceSha,
|
|
1445
|
+
expectedAdopterId: repository || "kungfu-systems/buildchain", expectedSourceRepository: repository, sourceSha,
|
|
1446
1446
|
checkedAt,
|
|
1447
1447
|
});
|
|
1448
1448
|
}
|
|
@@ -1497,9 +1497,9 @@ export function collectGitHubReleasePassport({
|
|
|
1497
1497
|
invariantPassportJsons = [],
|
|
1498
1498
|
invariantPassportCommand = "",
|
|
1499
1499
|
releaseEvidenceJsons = [],
|
|
1500
|
-
v4ConsumerPolicyCertificationJson = "",
|
|
1501
|
-
v4ConsumerPolicyCertificationRoot = "",
|
|
1502
|
-
v4RuntimeResumeEvidenceJson = "",
|
|
1500
|
+
v4ConsumerPolicyCertificationJson: domainConsumerPolicyCertificationJson = "",
|
|
1501
|
+
v4ConsumerPolicyCertificationRoot: domainConsumerPolicyCertificationRoot = "",
|
|
1502
|
+
v4RuntimeResumeEvidenceJson: domainRuntimeResumeEvidenceJson = "",
|
|
1503
1503
|
kfdAgentHubEvidenceJson = "",
|
|
1504
1504
|
controllerReceiptReferences = [],
|
|
1505
1505
|
githubArtifactAttestationPolicyJsons = [],
|
|
@@ -1575,9 +1575,9 @@ export function collectGitHubReleasePassport({
|
|
|
1575
1575
|
}),
|
|
1576
1576
|
)
|
|
1577
1577
|
.filter((meta) => meta.value);
|
|
1578
|
-
const
|
|
1579
|
-
|
|
1580
|
-
const
|
|
1578
|
+
const consumerPolicyCertificationMeta =
|
|
1579
|
+
parseConsumerPolicyCertification(domainConsumerPolicyCertificationJson, cwd);
|
|
1580
|
+
const domainRuntimeResumeEvidence = parseJsonInput(domainRuntimeResumeEvidenceJson, undefined, {
|
|
1581
1581
|
cwd,
|
|
1582
1582
|
label: "v4RuntimeResumeEvidenceJson",
|
|
1583
1583
|
});
|
|
@@ -1620,7 +1620,7 @@ export function collectGitHubReleasePassport({
|
|
|
1620
1620
|
const productMechanism = defaultProductMechanism({ repository, productName });
|
|
1621
1621
|
const kfdAdopterEvidence = collectKfdAdopterReleaseInputs({
|
|
1622
1622
|
cwd, manifestJson: kfdAdopterManifestJson, supportMatrixJson: kfdSupportMatrixJson,
|
|
1623
|
-
productGateJsons: kfdProductGateJsons, sourceSha, checkedAt: resolvedCheckedAt,
|
|
1623
|
+
productGateJsons: kfdProductGateJsons, repository, sourceSha, checkedAt: resolvedCheckedAt,
|
|
1624
1624
|
});
|
|
1625
1625
|
const {
|
|
1626
1626
|
manifest: kfdAdopterManifest,
|
|
@@ -1706,9 +1706,9 @@ export function collectGitHubReleasePassport({
|
|
|
1706
1706
|
kfdSupportEvidencePath: kfdSupport ? "kfd-support.json" : "",
|
|
1707
1707
|
invariantPassports,
|
|
1708
1708
|
releaseEvidence: releaseEvidenceAttachments.map(({ reference }) => reference),
|
|
1709
|
-
v4ConsumerPolicyCertification:
|
|
1710
|
-
v4ConsumerPolicyCertificationRoot,
|
|
1711
|
-
|
|
1709
|
+
v4ConsumerPolicyCertification: consumerPolicyCertificationMeta.value,
|
|
1710
|
+
v4ConsumerPolicyCertificationRoot: domainConsumerPolicyCertificationRoot,
|
|
1711
|
+
domainRuntimeResumeEvidence,
|
|
1712
1712
|
kfdAgentHubEvidence: kfdAgentHubEvidenceMeta.value
|
|
1713
1713
|
? { ...kfdAgentHubEvidenceMeta, path: "kfd-agent-hub-evidence.json" }
|
|
1714
1714
|
: undefined,
|
|
@@ -2060,7 +2060,8 @@ function validateReleaseEvidenceContracts({
|
|
|
2060
2060
|
manifestGate: kfdAdopterManifestGate,
|
|
2061
2061
|
legacyProjection: kfdSupportEvidence,
|
|
2062
2062
|
passportLegacyProjection: passport?.kfdSupport,
|
|
2063
|
-
|
|
2063
|
+
expectedAdopterId: optionalString(passport?.product?.repository) || "kungfu-systems/buildchain",
|
|
2064
|
+
expectedSourceRepository: optionalString(passport?.product?.repository), expectedSourceSha: optionalString(passport?.release?.sourceSha),
|
|
2064
2065
|
})) {
|
|
2065
2066
|
issues.push(issue("error", entry.code, entry.message, entry.details));
|
|
2066
2067
|
}
|
|
@@ -2649,8 +2650,8 @@ export function createReleaseCheckReport({
|
|
|
2649
2650
|
releaseEvidenceDocuments,
|
|
2650
2651
|
issues,
|
|
2651
2652
|
});
|
|
2652
|
-
|
|
2653
|
-
|
|
2653
|
+
validateConsumerPolicyPassportSection({ passport, issues });
|
|
2654
|
+
validateRuntimeResumePassportSection({ passport, issues });
|
|
2654
2655
|
validatePublishEvidenceSection({ passport, publishEvidence, normalizedPublishEvidence, issues });
|
|
2655
2656
|
const evidenceIndex = indexEvidenceArtifacts(evidenceArtifacts);
|
|
2656
2657
|
validateReleaseArtifacts({ artifacts, evidenceIndex, issues });
|
|
@@ -2804,14 +2805,14 @@ export function makeReleasePassportFixtureAssets(dir) {
|
|
|
2804
2805
|
export function validateKnownReleasePassportContracts() {
|
|
2805
2806
|
return [...CONTRACTS];
|
|
2806
2807
|
}
|
|
2807
|
-
function
|
|
2808
|
+
function parseConsumerPolicyCertification(input, cwd) {
|
|
2808
2809
|
return parseJsonInputWithMeta(input, undefined, {
|
|
2809
2810
|
cwd,
|
|
2810
2811
|
label: "v4ConsumerPolicyCertificationJson",
|
|
2811
2812
|
});
|
|
2812
2813
|
}
|
|
2813
2814
|
|
|
2814
|
-
function
|
|
2815
|
+
function runtimeResumeSourceSha(release, fallback = "") {
|
|
2815
2816
|
const builtSourceSha = releaseField(
|
|
2816
2817
|
release || {},
|
|
2817
2818
|
"builtSourceSha",
|
|
@@ -2823,10 +2824,10 @@ function v4RuntimeResumeSourceSha(release, fallback = "") {
|
|
|
2823
2824
|
}
|
|
2824
2825
|
|
|
2825
2826
|
|
|
2826
|
-
function
|
|
2827
|
+
function validateConsumerPolicyPassportSection({ passport, issues }) {
|
|
2827
2828
|
const routing = passport?.promotionRouting;
|
|
2828
2829
|
const evidence = passport?.v4ConsumerPolicy;
|
|
2829
|
-
if (
|
|
2830
|
+
if (isPromotionRouting(routing) && !evidence) {
|
|
2830
2831
|
issues.push(issue(
|
|
2831
2832
|
"error",
|
|
2832
2833
|
"v4ConsumerPolicy.missing",
|
|
@@ -2835,7 +2836,7 @@ function validateV4ConsumerPolicyPassportSection({ passport, issues }) {
|
|
|
2835
2836
|
return;
|
|
2836
2837
|
}
|
|
2837
2838
|
if (!evidence) return;
|
|
2838
|
-
const verification =
|
|
2839
|
+
const verification = verifyFloatingConsumerPolicyCertification(
|
|
2839
2840
|
releasePassportCertificationVerificationOptions({
|
|
2840
2841
|
evidence,
|
|
2841
2842
|
passport,
|
|
@@ -2847,26 +2848,26 @@ function validateV4ConsumerPolicyPassportSection({ passport, issues }) {
|
|
|
2847
2848
|
}
|
|
2848
2849
|
}
|
|
2849
2850
|
|
|
2850
|
-
function
|
|
2851
|
+
function validateRuntimeResumePassportSection({ passport, issues }) {
|
|
2851
2852
|
const evidence = passport?.v4RuntimeResume;
|
|
2852
2853
|
if (!evidence) return;
|
|
2853
2854
|
const consumerPolicyReceiptRoot = passport?.v4ConsumerPolicy?.certification?.receiptRoot || "";
|
|
2854
|
-
const authorization =
|
|
2855
|
+
const authorization = verifyRuntimeAuthorizationReceipt({
|
|
2855
2856
|
receipt: evidence.authorization,
|
|
2856
2857
|
receiptRoot: evidence.authorizationRoot,
|
|
2857
2858
|
repository: passport?.product?.repository || "",
|
|
2858
|
-
sourceSha:
|
|
2859
|
+
sourceSha: runtimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
|
|
2859
2860
|
runtimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
2860
2861
|
consumerPolicyReceiptRoot,
|
|
2861
2862
|
});
|
|
2862
2863
|
for (const failure of authorization.failures) {
|
|
2863
2864
|
issues.push(issue("error", `v4RuntimeResume.authorization.${failure}`, failure));
|
|
2864
2865
|
}
|
|
2865
|
-
const lineage =
|
|
2866
|
+
const lineage = verifyRuntimeResumeLineage({
|
|
2866
2867
|
lineage: evidence.lineage,
|
|
2867
2868
|
lineageRoot: evidence.lineageRoot,
|
|
2868
2869
|
repository: passport?.product?.repository || "",
|
|
2869
|
-
sourceSha:
|
|
2870
|
+
sourceSha: runtimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
|
|
2870
2871
|
resumeRuntimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
2871
2872
|
consumerPolicyReceiptRoot,
|
|
2872
2873
|
});
|
|
@@ -17,6 +17,15 @@ export const RELEASE_TAIL_PRODUCT_CAPABILITIES = Object.freeze([
|
|
|
17
17
|
receiptKind: "product-package-publication",
|
|
18
18
|
transactionState: "publishing",
|
|
19
19
|
}),
|
|
20
|
+
Object.freeze({
|
|
21
|
+
id: "product.oci.publish",
|
|
22
|
+
executor: "provider-adapter",
|
|
23
|
+
adapter: "oci-image-family",
|
|
24
|
+
effectKind: "oci-family-publication",
|
|
25
|
+
observationKind: "oci-family-readback",
|
|
26
|
+
receiptKind: "oci-family-publication",
|
|
27
|
+
transactionState: "publishing",
|
|
28
|
+
}),
|
|
20
29
|
Object.freeze({
|
|
21
30
|
id: "product.release-refs.converge",
|
|
22
31
|
executor: "provider-adapter",
|