@kungfu-tech/buildchain 4.0.0 → 4.0.1-alpha.10
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 +13 -5
- package/actions/promote-buildchain-ref/README.md +11 -6
- package/actions/release-tail/README.md +8 -0
- package/architecture/ci-lane-change-budget.json +187 -0
- package/architecture/decisions/0002-next-development-transition.md +101 -0
- package/architecture/decisions/0003-two-phase-delivery-warrant.md +152 -0
- package/architecture/internal-capabilities.json +219 -7
- package/architecture/maintainability-policy.json +246 -29
- package/architecture/release-tail-contract-inventory.json +5 -2
- package/architecture/v3-core-mechanism-inventory.json +91 -0
- package/architecture/v4-adopter-delivery-parity.json +32 -5
- package/architecture/v4-capability-state-machine-manifest.json +73 -0
- package/architecture/v4-compatibility-facts-parity.json +77 -0
- package/architecture/v4-delivery-authority-parity.json +250 -0
- package/architecture/v4-delivery-warrant-shadow-fixtures.json +41 -9
- package/architecture/v4-floating-consumer-policy.json +81 -0
- package/architecture/v4-floating-consumer-policy.md +32 -0
- package/architecture/v4-next-development-parity.json +192 -0
- package/architecture/v4-publication-rehearsal-parity.json +84 -0
- package/architecture/v4-release-train-parity.json +1 -0
- package/architecture/v4-runtime-ref-resume-authority.json +64 -0
- package/architecture/v4-stage-capsule-qualification.json +2 -2
- package/architecture/v4-tail-reseal-parity.json +150 -0
- package/bin/buildchain.mjs +32 -3
- package/bin/internal/adopter-delivery-cli.mjs +70 -0
- package/bin/internal/command-registry.mjs +3 -0
- package/bin/internal/compatibility-facts-cli.mjs +101 -0
- package/bin/internal/trust-release-release-handlers.mjs +5 -0
- package/contracts/dev-delivery-authority-v2.schema.json +662 -0
- package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
- package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
- package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
- package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
- package/contracts/fixtures/v4-compatibility-facts-v1/shared.json +1129 -0
- package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +59 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
- package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
- package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +229 -0
- package/contracts/next-development-request-v1.schema.json +66 -0
- package/contracts/next-development-transition-v1.schema.json +292 -0
- package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
- package/contracts/v4-compatibility-facts-v1.schema.json +230 -0
- package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +107 -0
- package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
- package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
- package/contracts/v4-tail-reseal-v1.schema.json +276 -0
- package/dist/site/agent-index.json +5 -0
- package/dist/site/artifact-schemas.json +10 -0
- package/dist/site/buildchain-contract.json +1562 -44
- package/dist/site/buildchain-site.json +684 -42
- package/dist/site/capability-registry.json +17 -14
- package/dist/site/cli-registry.json +205 -3
- package/dist/site/controller-registry.json +62 -6
- package/dist/site/kfd-claims.json +551 -22
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +55 -9
- package/dist/site/node-api-registry.json +15247 -8690
- package/dist/site/page-registry.json +647 -29
- package/dist/site/public-surface-audit.json +876 -55
- package/dist/site/publication-authority-registry.json +44 -8
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +26 -0
- package/dist/site/schemas/dev-delivery-authority-v2.schema.json +662 -0
- package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
- package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
- package/dist/site/schemas/v4-compatibility-facts-v1.schema.json +230 -0
- package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
- package/dist/site/site-manifest.json +37 -13
- package/dist/site/workflow-registry.json +200 -22
- package/docs/MAP.md +10 -2
- package/docs/cli-reference.md +404 -13
- package/docs/cli.md +8 -0
- package/docs/dev-alpha-candidate-patrol.md +8 -0
- package/docs/dev-delivery-qualification-landing-adr.md +251 -0
- package/docs/dev-delivery-warrant.md +361 -30
- package/docs/lifecycle-protocol.md +41 -0
- package/docs/next-development-transition.md +118 -0
- package/docs/node-api-reference.md +748 -322
- package/docs/release-tail-provider-plane.md +30 -0
- package/docs/reusable-build-surface.md +41 -0
- package/docs/runtime-train-validation.md +10 -0
- package/docs/v4-adopter-delivery.md +133 -0
- package/docs/v4-compatibility-facts.md +91 -0
- package/docs/v4-publication-rehearsal.md +130 -0
- package/docs/v4-runtime-ref-resume-authority.md +69 -0
- package/docs/v4-tail-reseal.md +73 -0
- package/docs/versioning.md +4 -2
- package/package.json +36 -6
- package/packages/core/adopter-delivery-passport.js +259 -0
- package/packages/core/adopter-delivery-vectors.js +158 -0
- package/packages/core/adopter-delivery-vectors.json +77 -0
- package/packages/core/artifact-signing.js +61 -0
- package/packages/core/buildchain-agent-manuals.js +3 -0
- package/packages/core/buildchain-compatibility-authority.js +336 -0
- package/packages/core/buildchain-compatibility-fact.js +394 -0
- package/packages/core/buildchain-compatibility-facts.json +217 -0
- package/packages/core/buildchain-compatibility-proof.js +566 -0
- package/packages/core/buildchain-config.js +150 -1
- package/packages/core/buildchain-contract.js +96 -143
- package/packages/core/buildchain-delivery-bootstrap.js +240 -0
- package/packages/core/buildchain-delivery-infrastructure.js +164 -0
- package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
- package/packages/core/buildchain-publication-authority.js +1 -0
- package/packages/core/channel-candidate.js +8 -0
- package/packages/core/channel-promotion-baseline.js +55 -0
- package/packages/core/ci-lane-change-budget.js +247 -0
- package/packages/core/dev-alpha-candidate-selection.js +10 -2
- package/packages/core/dev-delivery-authority-candidate.js +270 -0
- package/packages/core/dev-delivery-authority-evidence.js +146 -0
- package/packages/core/dev-delivery-authority-landing.js +461 -0
- package/packages/core/dev-delivery-authority-observation.js +48 -0
- package/packages/core/dev-delivery-authority-qualification.js +591 -0
- package/packages/core/dev-delivery-authority-settlement.js +213 -0
- package/packages/core/dev-delivery-authority-state.js +583 -0
- package/packages/core/dev-delivery-candidate-identity.js +13 -0
- package/packages/core/dev-delivery-contract-surface.js +76 -0
- package/packages/core/dev-delivery-execution-failure.js +133 -0
- package/packages/core/dev-delivery-execution-transfer.js +592 -0
- package/packages/core/dev-delivery-landing-admission-core.js +119 -0
- package/packages/core/dev-delivery-landing-readback.js +598 -0
- package/packages/core/dev-delivery-landing-terminal-evidence.js +271 -0
- package/packages/core/dev-delivery-landing-testing-port.js +6 -0
- package/packages/core/dev-delivery-native-execution.js +110 -0
- package/packages/core/dev-delivery-native-proof.js +562 -0
- package/packages/core/dev-delivery-process-boundary.js +563 -0
- package/packages/core/dev-delivery-proof.js +37 -3
- package/packages/core/dev-delivery-provider-attempt.js +127 -0
- package/packages/core/dev-delivery-provider-heartbeat.js +382 -0
- package/packages/core/dev-delivery-warrant-cancellation.js +1 -0
- package/packages/core/dev-delivery-warrant-qualification.js +145 -0
- package/packages/core/dev-delivery-warrant-settlement.js +237 -36
- package/packages/core/dev-delivery-warrant-state.js +587 -0
- package/packages/core/dev-delivery-warrant.js +328 -370
- package/packages/core/github-governance-authority.js +1 -0
- package/packages/core/index.js +7 -0
- package/packages/core/kungfu-temporal-fact.js +557 -0
- package/packages/core/legacy-kfd-adopter-driver.js +167 -0
- package/packages/core/next-development-candidate-reservation.js +186 -0
- package/packages/core/next-development-controller.js +728 -0
- package/packages/core/next-development-projection.js +287 -0
- package/packages/core/next-development-transition.js +738 -0
- package/packages/core/paper-agent-entry.js +11 -5
- package/packages/core/paper.js +16 -5
- package/packages/core/publication-authority.js +5 -5
- package/packages/core/published-delivery-authority.js +266 -0
- package/packages/core/release-candidate-recovery.js +66 -11
- package/packages/core/release-candidate.js +79 -19
- package/packages/core/release-passport.js +271 -38
- package/packages/core/v4-adopter-delivery-parity.js +3 -3
- package/packages/core/v4-adopter-delivery.js +359 -0
- package/packages/core/v4-canonical-contracts.js +5 -0
- package/packages/core/v4-delivery-warrant-read-candidate.js +10 -3
- package/packages/core/v4-floating-consumer-evidence.js +338 -0
- package/packages/core/v4-floating-consumer-policy.js +569 -0
- package/packages/core/v4-floating-consumer-release-passport.js +153 -0
- package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
- package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
- package/packages/core/v4-publication-rehearsal.js +481 -0
- package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
- package/packages/core/v4-runtime-selector-persistence.js +228 -0
- package/packages/core/v4-tail-reseal-contract.js +26 -0
- package/packages/core/v4-tail-reseal-github.js +178 -0
- package/packages/core/v4-tail-reseal-receipt.js +225 -0
- package/packages/core/v4-tail-reseal.js +594 -0
- package/packages/core/workflow-yaml-contract.js +72 -2
- package/scripts/audit-publication-control-plane.mjs +31 -31
- package/scripts/buildchain-cli-help.mjs +41 -2
- package/scripts/check-ci-lane-change-budget.mjs +100 -0
- package/scripts/check-inventory.mjs +14 -3
- package/scripts/check-v4-floating-consumer-policy-contract.mjs +217 -0
- package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
- package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
- package/scripts/dev-delivery-authority-command-adapters.mjs +206 -0
- package/scripts/dev-delivery-authority-provider.mjs +28 -0
- package/scripts/dev-delivery-authority.mjs +490 -0
- package/scripts/dev-delivery-native-run.mjs +177 -0
- package/scripts/dev-delivery-process-boundary.mjs +260 -0
- package/scripts/dev-delivery-proof.mjs +67 -2
- package/scripts/dev-delivery-provider-heartbeat.mjs +215 -0
- package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
- package/scripts/dev-delivery-source-proof-reuse.mjs +547 -0
- package/scripts/dev-delivery-two-phase-resume.mjs +345 -0
- package/scripts/dev-delivery-two-phase.mjs +573 -0
- package/scripts/dev-delivery-warrant-options.mjs +266 -0
- package/scripts/dev-delivery-warrant-store.mjs +231 -0
- package/scripts/dev-delivery-warrant.mjs +232 -194
- package/scripts/dev-pr-auto-merge.mjs +37 -48
- package/scripts/dev-pr-delivery-warrant.mjs +216 -2
- package/scripts/dev-pr-prequeue-guard.mjs +399 -0
- package/scripts/dev-qualification-patrol.mjs +9 -9
- package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
- package/scripts/ensure-github-release.mjs +3 -3
- package/scripts/generate-channel-build-workflow.mjs +3 -0
- package/scripts/generate-channel-promotion-workflow.mjs +114 -14
- package/scripts/generate-next-development-guidance.mjs +49 -0
- package/scripts/generate-release-candidate-passport.mjs +192 -32
- package/scripts/generate-site-bundle.mjs +69 -4
- package/scripts/init-repo.mjs +26 -4
- package/scripts/inspect-artifact-signing-requests.mjs +6 -0
- package/scripts/next-development-self-dogfood-harness.mjs +460 -0
- package/scripts/next-development-self-dogfood.mjs +597 -0
- package/scripts/next-development-transition.mjs +47 -0
- package/scripts/npm-publish-transaction.mjs +103 -91
- package/scripts/promotion-channel-router.mjs +4 -4
- package/scripts/release-candidate-anchor-provenance.mjs +99 -0
- package/scripts/release-tail.mjs +51 -3
- package/scripts/release-train-self-dogfood.mjs +94 -92
- package/scripts/resume-from-candidate-run.mjs +565 -41
- package/scripts/seal-artifact-signing-requests.mjs +6 -0
- package/scripts/site-capability-metadata.mjs +43 -0
- package/scripts/stable-candidate-qualification.mjs +9 -10
- package/scripts/v4-consumer-policy.mjs +231 -0
- package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
- package/scripts/v4-tail-reseal-macos-rehearsal.mjs +134 -0
- package/scripts/v4-tail-reseal.mjs +416 -0
- package/templates/native-dev-delivery.yml +143 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
+
import { verifyV4FloatingConsumerPolicyReceipt } from "./v4-floating-consumer-policy.js";
|
|
2
3
|
import { normalizeControllerReceiptReferences, validateControllerReceiptReference } from "./controller-evidence.js";
|
|
3
4
|
|
|
4
5
|
export const RELEASE_CANDIDATE_PASSPORT_CONTRACT = "kungfu-buildchain-release-candidate-passport";
|
|
@@ -171,6 +172,64 @@ function normalizeGateProfileEvidence(gateAggregate = undefined) {
|
|
|
171
172
|
};
|
|
172
173
|
}
|
|
173
174
|
|
|
175
|
+
function isV4BuildchainRuntime(buildchain = {}) {
|
|
176
|
+
return [buildchain.ref, buildchain.workflowShellRef]
|
|
177
|
+
.some((value) => /^v4(?:-alpha)?$/u.test(String(value || "")))
|
|
178
|
+
|| /^4\./u.test(String(buildchain.version || ""));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function normalizeConsumerPolicyEvidence(value, expected = {}) {
|
|
182
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
183
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
184
|
+
throw new Error("consumerPolicyReceipt must be an object");
|
|
185
|
+
}
|
|
186
|
+
const receipt = value.receipt || value;
|
|
187
|
+
const verification = verifyV4FloatingConsumerPolicyReceipt({
|
|
188
|
+
receipt,
|
|
189
|
+
receiptRoot: value.receiptRoot || "",
|
|
190
|
+
repository: expected.repository,
|
|
191
|
+
sourceSha: expected.sourceSha,
|
|
192
|
+
resolvedRuntimeSha: expected.runtimeSha,
|
|
193
|
+
});
|
|
194
|
+
if (!verification.ok) {
|
|
195
|
+
throw new Error(`consumer policy receipt invalid: ${verification.failures.map((failure) => failure.code).join(", ")}`);
|
|
196
|
+
}
|
|
197
|
+
return { receiptRoot: verification.receiptRoot, receipt };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function validateConsumerPolicyEvidence(passport, check) {
|
|
201
|
+
if (isV4BuildchainRuntime(passport.buildchain)) {
|
|
202
|
+
check(Boolean(passport.consumerPolicy), "Buildchain v4 release candidate requires consumer policy evidence");
|
|
203
|
+
}
|
|
204
|
+
if (!passport.consumerPolicy) return;
|
|
205
|
+
const verification = verifyV4FloatingConsumerPolicyReceipt({
|
|
206
|
+
receipt: passport.consumerPolicy.receipt,
|
|
207
|
+
receiptRoot: passport.consumerPolicy.receiptRoot,
|
|
208
|
+
repository: passport.repository,
|
|
209
|
+
sourceSha: passport.target?.ref === "publish-gate/anchor" ? passport.consumerPolicy.receipt?.caller?.sourceSha : passport.source?.headSha,
|
|
210
|
+
resolvedRuntimeSha: passport.buildchain?.sha,
|
|
211
|
+
});
|
|
212
|
+
for (const failure of verification.failures) {
|
|
213
|
+
check(false, `consumer policy evidence invalid: ${failure.code}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function validateEvidenceBoundCandidateHash(passport, check) {
|
|
218
|
+
if (!passport.familyEvidence && !passport.consumerPolicy) return;
|
|
219
|
+
const expectedCandidateHash = sha256Json({
|
|
220
|
+
repository: passport.repository,
|
|
221
|
+
target: passport.target,
|
|
222
|
+
source: passport.source,
|
|
223
|
+
platformMatrix: passport.platformMatrix,
|
|
224
|
+
buildchain: passport.buildchain,
|
|
225
|
+
...(passport.gateProfileEvidence ? { gateProfileEvidence: passport.gateProfileEvidence } : {}),
|
|
226
|
+
...(passport.familyEvidence ? { familyEvidence: passport.familyEvidence } : {}),
|
|
227
|
+
...(passport.consumerPolicy ? { consumerPolicy: passport.consumerPolicy } : {}),
|
|
228
|
+
...(passport.controllerReceipts ? { controllerReceipts: passport.controllerReceipts } : {}),
|
|
229
|
+
});
|
|
230
|
+
check(passport.candidateHash === expectedCandidateHash, "candidate hash mismatch");
|
|
231
|
+
}
|
|
232
|
+
|
|
174
233
|
function normalizeFamilyReleaseEvidence(value = undefined) {
|
|
175
234
|
if (value === undefined || value === null || value === "") return undefined;
|
|
176
235
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -320,6 +379,7 @@ export function createReleaseCandidatePassport({
|
|
|
320
379
|
buildchain = {},
|
|
321
380
|
gateAggregate = undefined,
|
|
322
381
|
familyEvidence = undefined,
|
|
382
|
+
consumerPolicyReceipt = undefined,
|
|
323
383
|
controllerReceipts = [],
|
|
324
384
|
controllerReceiptReferences = [],
|
|
325
385
|
workflow = {},
|
|
@@ -335,6 +395,20 @@ export function createReleaseCandidatePassport({
|
|
|
335
395
|
const resolvedVersion = version || normalizedSummary.publishSource?.consumerVersion || inferVersionFromReleaseManifest(normalizedSummary);
|
|
336
396
|
const gateProfileEvidence = normalizeGateProfileEvidence(gateAggregate);
|
|
337
397
|
const normalizedFamilyEvidence = normalizeFamilyReleaseEvidence(familyEvidence);
|
|
398
|
+
const resolvedBuildchain = {
|
|
399
|
+
ref: optionalString(buildchain.ref || normalizedSummary.runtime?.ref),
|
|
400
|
+
sha: optionalString(buildchain.sha || normalizedSummary.runtime?.sha),
|
|
401
|
+
version: optionalString(buildchain.version),
|
|
402
|
+
workflowShellRef: optionalString(buildchain.workflowShellRef || normalizedSummary.runtime?.workflowShellRef),
|
|
403
|
+
};
|
|
404
|
+
const normalizedConsumerPolicy = normalizeConsumerPolicyEvidence(consumerPolicyReceipt, {
|
|
405
|
+
repository: repository || normalizedSummary.git?.repository || "",
|
|
406
|
+
sourceSha: normalizedSummary.publishSource?.ref === "publish-gate/anchor" ? (consumerPolicyReceipt?.receipt || consumerPolicyReceipt)?.caller?.sourceSha : sourceSha,
|
|
407
|
+
runtimeSha: resolvedBuildchain.sha,
|
|
408
|
+
});
|
|
409
|
+
if (isV4BuildchainRuntime(resolvedBuildchain) && !normalizedConsumerPolicy) {
|
|
410
|
+
throw new Error("Buildchain v4 release candidate passport requires a valid floating consumer policy receipt");
|
|
411
|
+
}
|
|
338
412
|
const controllerReceiptEvidence = normalizeControllerReceiptReferences({
|
|
339
413
|
receipts: controllerReceipts,
|
|
340
414
|
references: controllerReceiptReferences,
|
|
@@ -366,12 +440,7 @@ export function createReleaseCandidatePassport({
|
|
|
366
440
|
builtSourceSha: nonEmptyString(mergeRefSha || sourceSha, "builtSourceSha"),
|
|
367
441
|
builtSourceTreeSha: resolvedTreeHash,
|
|
368
442
|
},
|
|
369
|
-
buildchain:
|
|
370
|
-
ref: optionalString(buildchain.ref || normalizedSummary.runtime?.ref),
|
|
371
|
-
sha: optionalString(buildchain.sha || normalizedSummary.runtime?.sha),
|
|
372
|
-
version: optionalString(buildchain.version),
|
|
373
|
-
workflowShellRef: optionalString(buildchain.workflowShellRef || normalizedSummary.runtime?.workflowShellRef),
|
|
374
|
-
},
|
|
443
|
+
buildchain: resolvedBuildchain,
|
|
375
444
|
workflow: {
|
|
376
445
|
name: optionalString(workflow.name),
|
|
377
446
|
runId: optionalString(workflow.runId || normalizedSummary.git?.runId),
|
|
@@ -386,6 +455,7 @@ export function createReleaseCandidatePassport({
|
|
|
386
455
|
},
|
|
387
456
|
...(gateProfileEvidence ? { gateProfileEvidence } : {}),
|
|
388
457
|
...(normalizedFamilyEvidence ? { familyEvidence: normalizedFamilyEvidence } : {}),
|
|
458
|
+
...(normalizedConsumerPolicy ? { consumerPolicy: normalizedConsumerPolicy } : {}),
|
|
389
459
|
...(controllerReceiptEvidence.length > 0 ? { controllerReceipts: controllerReceiptEvidence } : {}),
|
|
390
460
|
};
|
|
391
461
|
candidate.candidateHash = sha256Json({
|
|
@@ -396,6 +466,7 @@ export function createReleaseCandidatePassport({
|
|
|
396
466
|
buildchain: candidate.buildchain,
|
|
397
467
|
...(candidate.gateProfileEvidence ? { gateProfileEvidence: candidate.gateProfileEvidence } : {}),
|
|
398
468
|
...(candidate.familyEvidence ? { familyEvidence: candidate.familyEvidence } : {}),
|
|
469
|
+
...(candidate.consumerPolicy ? { consumerPolicy: candidate.consumerPolicy } : {}),
|
|
399
470
|
...(candidate.controllerReceipts ? { controllerReceipts: candidate.controllerReceipts } : {}),
|
|
400
471
|
});
|
|
401
472
|
return candidate;
|
|
@@ -463,6 +534,7 @@ export function validateReleaseCandidatePassport({
|
|
|
463
534
|
check(Boolean(passport.gateProfileEvidence.digest), "gate profile evidence digest is required");
|
|
464
535
|
check(Boolean(passport.gateProfileEvidence.matrixDigest), "gate profile matrix digest is required");
|
|
465
536
|
}
|
|
537
|
+
validateConsumerPolicyEvidence(passport, check);
|
|
466
538
|
if (requireFamilyEvidence || familyEvidenceRoot || familyInitiativeId || familyAssignmentId) {
|
|
467
539
|
check(Boolean(passport.familyEvidence), "family evidence is required");
|
|
468
540
|
}
|
|
@@ -514,18 +586,6 @@ export function validateReleaseCandidatePassport({
|
|
|
514
586
|
controllerIds.add(reference.controllerId);
|
|
515
587
|
}
|
|
516
588
|
}
|
|
517
|
-
|
|
518
|
-
const expectedCandidateHash = sha256Json({
|
|
519
|
-
repository: passport.repository,
|
|
520
|
-
target: passport.target,
|
|
521
|
-
source: passport.source,
|
|
522
|
-
platformMatrix: passport.platformMatrix,
|
|
523
|
-
buildchain: passport.buildchain,
|
|
524
|
-
...(passport.gateProfileEvidence ? { gateProfileEvidence: passport.gateProfileEvidence } : {}),
|
|
525
|
-
familyEvidence: passport.familyEvidence,
|
|
526
|
-
...(passport.controllerReceipts ? { controllerReceipts: passport.controllerReceipts } : {}),
|
|
527
|
-
});
|
|
528
|
-
check(passport.candidateHash === expectedCandidateHash, "candidate hash mismatch");
|
|
529
|
-
}
|
|
589
|
+
validateEvidenceBoundCandidateHash(passport, check);
|
|
530
590
|
return { ok: errors.length === 0, errors };
|
|
531
591
|
}
|
|
@@ -33,6 +33,17 @@ import { normalizeControllerReceiptReferences } from "./controller-evidence.js";
|
|
|
33
33
|
import {
|
|
34
34
|
normalizeGitHubArtifactAttestationPolicy,
|
|
35
35
|
} from "./github-artifact-attestation.js";
|
|
36
|
+
import { verifyV4FloatingConsumerPolicyCertification } from "./v4-floating-consumer-evidence.js";
|
|
37
|
+
import {
|
|
38
|
+
isV4PromotionRouting,
|
|
39
|
+
releasePassportCertificationVerificationOptions,
|
|
40
|
+
requireV4ConsumerPolicyCertification,
|
|
41
|
+
resolveV4ConsumerPolicyCertificationIdentity,
|
|
42
|
+
} from "./v4-floating-consumer-release-passport.js";
|
|
43
|
+
import {
|
|
44
|
+
verifyV4RuntimeAuthorizationReceipt,
|
|
45
|
+
verifyV4RuntimeResumeLineage,
|
|
46
|
+
} from "./v4-runtime-ref-resume-authority.js";
|
|
36
47
|
|
|
37
48
|
export { RELEASE_CHECK_REPORT_CONTRACT, RELEASE_PASSPORT_CONTRACT };
|
|
38
49
|
export const ARTIFACT_EVIDENCE_CONTRACT = "kungfu-buildchain-artifact-evidence";
|
|
@@ -390,6 +401,13 @@ function parseJsonInputWithMeta(value, fallback = undefined, { cwd = process.cwd
|
|
|
390
401
|
};
|
|
391
402
|
}
|
|
392
403
|
|
|
404
|
+
function parseV4ConsumerPolicyCertification(input, cwd) {
|
|
405
|
+
return parseJsonInputWithMeta(input, undefined, {
|
|
406
|
+
cwd,
|
|
407
|
+
label: "v4ConsumerPolicyCertificationJson",
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
393
411
|
function mergeAuthoritativePassportBase(passport, basePassport = undefined, { requireKfd = false } = {}) {
|
|
394
412
|
if (!basePassport) {
|
|
395
413
|
if (requireKfd) {
|
|
@@ -422,11 +440,17 @@ function mergeAuthoritativePassportBase(passport, basePassport = undefined, { re
|
|
|
422
440
|
kfd3: basePassport.evidence?.kfd3 || passport.evidence?.kfd3 || "",
|
|
423
441
|
},
|
|
424
442
|
};
|
|
425
|
-
for (const key of [
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
443
|
+
for (const key of [
|
|
444
|
+
"versionImpact",
|
|
445
|
+
"surfaceImpacts",
|
|
446
|
+
"promotionRouting",
|
|
447
|
+
"v4ConsumerPolicy",
|
|
448
|
+
"v4RuntimeResume",
|
|
449
|
+
"transaction",
|
|
450
|
+
"trustedPublishing",
|
|
451
|
+
"distTagPromotion",
|
|
452
|
+
])
|
|
453
|
+
if (basePassport[key] !== undefined) merged[key] = basePassport[key];
|
|
430
454
|
if (basePassport.controllerReceipts !== undefined) {
|
|
431
455
|
merged.controllerReceipts = basePassport.controllerReceipts;
|
|
432
456
|
}
|
|
@@ -1085,6 +1109,143 @@ function normalizePromotionRouting(value = undefined) {
|
|
|
1085
1109
|
return JSON.parse(JSON.stringify(value));
|
|
1086
1110
|
}
|
|
1087
1111
|
|
|
1112
|
+
function normalizePromotionEvidence({
|
|
1113
|
+
release = {},
|
|
1114
|
+
v4ConsumerPolicyCertification: certification,
|
|
1115
|
+
v4ConsumerPolicyCertificationRoot: certificationRoot,
|
|
1116
|
+
v4RuntimeResumeEvidence,
|
|
1117
|
+
repository,
|
|
1118
|
+
sourceSha,
|
|
1119
|
+
cwd,
|
|
1120
|
+
}) {
|
|
1121
|
+
const routing = normalizePromotionRouting(release.promotionRouting);
|
|
1122
|
+
const identity = resolveV4ConsumerPolicyCertificationIdentity({
|
|
1123
|
+
release,
|
|
1124
|
+
routing,
|
|
1125
|
+
runtimeResume: v4RuntimeResumeEvidence,
|
|
1126
|
+
sourceSha,
|
|
1127
|
+
});
|
|
1128
|
+
return {
|
|
1129
|
+
routing,
|
|
1130
|
+
consumerPolicy: requireV4ConsumerPolicyCertification({
|
|
1131
|
+
value: certification,
|
|
1132
|
+
repository,
|
|
1133
|
+
sourceSha: identity.sourceSha,
|
|
1134
|
+
runtimeSha: identity.runtimeSha,
|
|
1135
|
+
routing,
|
|
1136
|
+
cwd,
|
|
1137
|
+
certificationRoot,
|
|
1138
|
+
}),
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
function normalizeV4RuntimeResumeEvidence(value, expected = {}) {
|
|
1143
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
1144
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1145
|
+
throw new Error("v4RuntimeResumeEvidence must be a JSON object");
|
|
1146
|
+
}
|
|
1147
|
+
const authorizationVerification = verifyV4RuntimeAuthorizationReceipt({
|
|
1148
|
+
receipt: value.authorization,
|
|
1149
|
+
receiptRoot: value.authorizationRoot,
|
|
1150
|
+
repository: expected.repository,
|
|
1151
|
+
sourceSha: expected.sourceSha,
|
|
1152
|
+
runtimeSha: expected.resumeRuntimeSha,
|
|
1153
|
+
consumerPolicyReceiptRoot: expected.consumerPolicyReceiptRoot,
|
|
1154
|
+
});
|
|
1155
|
+
if (!authorizationVerification.ok) {
|
|
1156
|
+
throw new Error(`v4 runtime authorization invalid: ${authorizationVerification.failures.join(", ")}`);
|
|
1157
|
+
}
|
|
1158
|
+
const lineageVerification = verifyV4RuntimeResumeLineage({
|
|
1159
|
+
lineage: value.lineage,
|
|
1160
|
+
lineageRoot: value.lineageRoot,
|
|
1161
|
+
repository: expected.repository,
|
|
1162
|
+
sourceSha: expected.sourceSha,
|
|
1163
|
+
resumeRuntimeSha: expected.resumeRuntimeSha,
|
|
1164
|
+
consumerPolicyReceiptRoot: expected.consumerPolicyReceiptRoot,
|
|
1165
|
+
});
|
|
1166
|
+
if (!lineageVerification.ok) {
|
|
1167
|
+
throw new Error(`v4 runtime resume lineage invalid: ${lineageVerification.failures.join(", ")}`);
|
|
1168
|
+
}
|
|
1169
|
+
if (value.lineage?.authorizationRoot !== value.authorizationRoot) {
|
|
1170
|
+
throw new Error("v4 runtime resume lineage authorization root mismatch");
|
|
1171
|
+
}
|
|
1172
|
+
return {
|
|
1173
|
+
authorizationRoot: value.authorizationRoot,
|
|
1174
|
+
authorization: structuredClone(value.authorization),
|
|
1175
|
+
lineageRoot: value.lineageRoot,
|
|
1176
|
+
lineage: structuredClone(value.lineage),
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
function v4RuntimeResumeSourceSha(release, fallback = "") {
|
|
1181
|
+
const builtSourceSha = releaseField(
|
|
1182
|
+
release || {},
|
|
1183
|
+
"builtSourceSha",
|
|
1184
|
+
"built_source_sha",
|
|
1185
|
+
);
|
|
1186
|
+
return release?.treeEquivalent === true && builtSourceSha
|
|
1187
|
+
? builtSourceSha
|
|
1188
|
+
: fallback;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
function prepareBuildEvidence({
|
|
1193
|
+
buildSummary,
|
|
1194
|
+
buildFacts,
|
|
1195
|
+
platformArtifactManifests,
|
|
1196
|
+
distTagPromotionEvidence,
|
|
1197
|
+
}) {
|
|
1198
|
+
return {
|
|
1199
|
+
buildSummary: buildSummary
|
|
1200
|
+
? normalizeEvidenceDocument(buildSummary, "buildSummary")
|
|
1201
|
+
: undefined,
|
|
1202
|
+
buildFacts: (buildFacts || [])
|
|
1203
|
+
.map((value, index) =>
|
|
1204
|
+
normalizeEvidenceDocument(value, `buildFacts[${index}]`),
|
|
1205
|
+
)
|
|
1206
|
+
.filter(Boolean),
|
|
1207
|
+
platformArtifactManifests: (platformArtifactManifests || [])
|
|
1208
|
+
.map((manifest, index) =>
|
|
1209
|
+
normalizePlatformArtifactManifest(manifest, index),
|
|
1210
|
+
)
|
|
1211
|
+
.filter(Boolean),
|
|
1212
|
+
distTagPromotionEvidence: distTagPromotionEvidence
|
|
1213
|
+
? normalizeEvidenceDocument(
|
|
1214
|
+
distTagPromotionEvidence,
|
|
1215
|
+
"distTagPromotionEvidence",
|
|
1216
|
+
)
|
|
1217
|
+
: undefined,
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
function preparePromotionBuild(options) {
|
|
1222
|
+
return {
|
|
1223
|
+
promotion: normalizePromotionEvidence(options),
|
|
1224
|
+
buildEvidence: prepareBuildEvidence(options),
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
function normalizeReleaseSourceFields(release) {
|
|
1229
|
+
return {
|
|
1230
|
+
builtSourceSha: releaseField(release, "builtSourceSha", "built_source_sha"),
|
|
1231
|
+
builtSourceTreeSha: releaseField(
|
|
1232
|
+
release,
|
|
1233
|
+
"builtSourceTreeSha",
|
|
1234
|
+
"built_source_tree_sha",
|
|
1235
|
+
),
|
|
1236
|
+
promotionChannelSha: releaseField(
|
|
1237
|
+
release,
|
|
1238
|
+
"promotionChannelSha",
|
|
1239
|
+
"promotion_channel_sha",
|
|
1240
|
+
),
|
|
1241
|
+
promotionChannelTreeSha: releaseField(
|
|
1242
|
+
release,
|
|
1243
|
+
"promotionChannelTreeSha",
|
|
1244
|
+
"promotion_channel_tree_sha",
|
|
1245
|
+
),
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1088
1249
|
export function createArtifactEvidence({ assets = [], repository = "", tag = "", sourceSha = "", workflow = {}, kfdAdopter = undefined } = {}) {
|
|
1089
1250
|
const normalizedAssets = assets.map((asset, index) => normalizeAsset(asset, index));
|
|
1090
1251
|
return buildReleaseArtifactEvidence({ normalizedAssets, repository, tag, sourceSha, workflow, kfdAdopter });
|
|
@@ -1120,7 +1281,8 @@ function prepareReleaseKfdAdopterArtifacts({ kfdAdopter, assets, repository, tag
|
|
|
1120
1281
|
};
|
|
1121
1282
|
}
|
|
1122
1283
|
|
|
1123
|
-
export function createReleasePassport({
|
|
1284
|
+
export function createReleasePassport(options = {}) {
|
|
1285
|
+
const {
|
|
1124
1286
|
cwd = process.cwd(),
|
|
1125
1287
|
repository = "",
|
|
1126
1288
|
tag = "",
|
|
@@ -1161,13 +1323,16 @@ export function createReleasePassport({
|
|
|
1161
1323
|
kfdSupportEvidencePath = "",
|
|
1162
1324
|
invariantPassports = undefined,
|
|
1163
1325
|
releaseEvidence = [],
|
|
1326
|
+
v4ConsumerPolicyCertification = undefined,
|
|
1327
|
+
v4ConsumerPolicyCertificationRoot = "",
|
|
1328
|
+
v4RuntimeResumeEvidence = undefined,
|
|
1164
1329
|
kfdAgentHubEvidence = undefined,
|
|
1165
1330
|
kfdAgentHubEvidencePath = "",
|
|
1166
1331
|
controllerReceipts = [],
|
|
1167
1332
|
controllerReceiptReferences = [],
|
|
1168
1333
|
githubArtifactAttestations = [],
|
|
1169
1334
|
checkedAt = "",
|
|
1170
|
-
} =
|
|
1335
|
+
} = options;
|
|
1171
1336
|
const normalizedTag = nonEmptyString(tag, "tag");
|
|
1172
1337
|
const { normalized: normalizedKfdAdopter, artifactEvidence } = prepareReleaseKfdAdopterArtifacts({
|
|
1173
1338
|
kfdAdopter, assets, repository, tag: normalizedTag, sourceSha, workflow,
|
|
@@ -1176,17 +1341,13 @@ export function createReleasePassport({
|
|
|
1176
1341
|
const normalizedPackageSet = normalizePackageSet(packageSet, { packageName, packageVersion, publish });
|
|
1177
1342
|
const normalizedTrustedPublishing = normalizeTrustedPublishing(trustedPublishing, { workflow, publish });
|
|
1178
1343
|
const normalizedTransaction = normalizeTransaction(transaction);
|
|
1179
|
-
const
|
|
1180
|
-
const
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
.
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
.filter(Boolean);
|
|
1187
|
-
const normalizedDistTagPromotionEvidence = distTagPromotionEvidence
|
|
1188
|
-
? normalizeEvidenceDocument(distTagPromotionEvidence, "distTagPromotionEvidence")
|
|
1189
|
-
: undefined;
|
|
1344
|
+
const { promotion, buildEvidence } = preparePromotionBuild(options);
|
|
1345
|
+
const normalizedV4RuntimeResume = normalizeV4RuntimeResumeEvidence(v4RuntimeResumeEvidence, {
|
|
1346
|
+
repository,
|
|
1347
|
+
sourceSha: v4RuntimeResumeSourceSha(release, sourceSha),
|
|
1348
|
+
resumeRuntimeSha: promotion.routing?.runtime?.resolvedSha || "",
|
|
1349
|
+
consumerPolicyReceiptRoot: promotion.consumerPolicy?.certification?.receiptRoot || "",
|
|
1350
|
+
});
|
|
1190
1351
|
const normalizedImpact = normalizeImpactLedger(impact, { tag: normalizedTag, line });
|
|
1191
1352
|
const generatedAt = optionalString(checkedAt) || nowIso();
|
|
1192
1353
|
const kfd1Metadata = resolveKfd1Metadata();
|
|
@@ -1205,16 +1366,13 @@ export function createReleasePassport({
|
|
|
1205
1366
|
support: kfdSupportEvidencePath,
|
|
1206
1367
|
},
|
|
1207
1368
|
});
|
|
1208
|
-
const
|
|
1209
|
-
const builtSourceTreeSha = releaseField(release, "builtSourceTreeSha", "built_source_tree_sha");
|
|
1210
|
-
const promotionChannelSha = releaseField(release, "promotionChannelSha", "promotion_channel_sha");
|
|
1211
|
-
const promotionChannelTreeSha = releaseField(release, "promotionChannelTreeSha", "promotion_channel_tree_sha");
|
|
1369
|
+
const sourceFields = normalizeReleaseSourceFields(release);
|
|
1212
1370
|
const treeEquivalent = release.treeEquivalent === true;
|
|
1213
1371
|
const recoveryTreeEquivalent = Boolean(
|
|
1214
1372
|
treeEquivalent &&
|
|
1215
|
-
builtSourceTreeSha &&
|
|
1216
|
-
promotionChannelTreeSha &&
|
|
1217
|
-
builtSourceTreeSha === promotionChannelTreeSha,
|
|
1373
|
+
sourceFields.builtSourceTreeSha &&
|
|
1374
|
+
sourceFields.promotionChannelTreeSha &&
|
|
1375
|
+
sourceFields.builtSourceTreeSha === sourceFields.promotionChannelTreeSha,
|
|
1218
1376
|
);
|
|
1219
1377
|
const normalizedControllerReceipts = normalizeControllerReceiptReferences({
|
|
1220
1378
|
receipts: controllerReceipts,
|
|
@@ -1222,8 +1380,8 @@ export function createReleasePassport({
|
|
|
1222
1380
|
expectedSourceSha: sourceSha,
|
|
1223
1381
|
acceptedSourceShas: acceptedControllerSourceShas({
|
|
1224
1382
|
treeEquivalent,
|
|
1225
|
-
builtSourceSha,
|
|
1226
|
-
promotionChannelSha,
|
|
1383
|
+
builtSourceSha: sourceFields.builtSourceSha,
|
|
1384
|
+
promotionChannelSha: sourceFields.promotionChannelSha,
|
|
1227
1385
|
sourceSha,
|
|
1228
1386
|
recoveryTreeEquivalent,
|
|
1229
1387
|
}),
|
|
@@ -1285,9 +1443,9 @@ export function createReleasePassport({
|
|
|
1285
1443
|
releaseSha,
|
|
1286
1444
|
releaseMaterialSha,
|
|
1287
1445
|
builtSourceSha: optionalString(release.builtSourceSha || release.built_source_sha),
|
|
1288
|
-
builtSourceTreeSha,
|
|
1446
|
+
builtSourceTreeSha: sourceFields.builtSourceTreeSha,
|
|
1289
1447
|
promotionChannelSha: optionalString(release.promotionChannelSha || release.promotion_channel_sha),
|
|
1290
|
-
promotionChannelTreeSha,
|
|
1448
|
+
promotionChannelTreeSha: sourceFields.promotionChannelTreeSha,
|
|
1291
1449
|
treeEquivalent: release.treeEquivalent === undefined ? undefined : Boolean(release.treeEquivalent),
|
|
1292
1450
|
publishToolingSha: optionalString(
|
|
1293
1451
|
release.publishToolingSha ||
|
|
@@ -1325,15 +1483,17 @@ export function createReleasePassport({
|
|
|
1325
1483
|
["versionMaterial", versionMaterial],
|
|
1326
1484
|
["trustedPublishing", normalizedTrustedPublishing],
|
|
1327
1485
|
["transaction", normalizedTransaction],
|
|
1328
|
-
["promotionRouting",
|
|
1329
|
-
["buildSummary",
|
|
1330
|
-
["buildFacts",
|
|
1331
|
-
["platformArtifactManifests",
|
|
1332
|
-
["distTagPromotion",
|
|
1486
|
+
["promotionRouting", promotion.routing],
|
|
1487
|
+
["buildSummary", buildEvidence.buildSummary],
|
|
1488
|
+
["buildFacts", buildEvidence.buildFacts],
|
|
1489
|
+
["platformArtifactManifests", buildEvidence.platformArtifactManifests],
|
|
1490
|
+
["distTagPromotion", buildEvidence.distTagPromotionEvidence],
|
|
1333
1491
|
...kfdParts.sectionEntries,
|
|
1334
1492
|
["kfdAgentHub", normalizedKfdAgentHub],
|
|
1335
1493
|
["invariantPassports", invariantPassports],
|
|
1336
1494
|
["releaseEvidence", releaseEvidence],
|
|
1495
|
+
["v4ConsumerPolicy", promotion.consumerPolicy],
|
|
1496
|
+
["v4RuntimeResume", normalizedV4RuntimeResume],
|
|
1337
1497
|
["controllerReceipts", normalizedControllerReceipts],
|
|
1338
1498
|
["githubArtifactAttestations", normalizedGitHubArtifactAttestations],
|
|
1339
1499
|
]),
|
|
@@ -1360,21 +1520,21 @@ export function createReleasePassport({
|
|
|
1360
1520
|
artifactEvidence: artifactEvidencePath,
|
|
1361
1521
|
publishEvidence: publishEvidencePath,
|
|
1362
1522
|
transactionState: transactionStatePath,
|
|
1363
|
-
buildSummary:
|
|
1364
|
-
buildFacts:
|
|
1523
|
+
buildSummary: buildEvidence.buildSummary?.path || "",
|
|
1524
|
+
buildFacts: buildEvidence.buildFacts.map((fact) => ({
|
|
1365
1525
|
path: fact.path || "",
|
|
1366
1526
|
sha256: fact.sha256 || "",
|
|
1367
1527
|
contract: fact.fields?.contract || "",
|
|
1368
1528
|
id: fact.fields?.id || "",
|
|
1369
1529
|
digest: fact.fields?.digest || "",
|
|
1370
1530
|
})),
|
|
1371
|
-
platformArtifactManifests:
|
|
1531
|
+
platformArtifactManifests: buildEvidence.platformArtifactManifests.map((manifest) => ({
|
|
1372
1532
|
path: manifest.path,
|
|
1373
1533
|
sha256: manifest.sha256,
|
|
1374
1534
|
platform: manifest.platform,
|
|
1375
1535
|
artifactName: manifest.artifactName,
|
|
1376
1536
|
})),
|
|
1377
|
-
distTagPromotionEvidence:
|
|
1537
|
+
distTagPromotionEvidence: buildEvidence.distTagPromotionEvidence?.path || "",
|
|
1378
1538
|
...kfdParts.evidence,
|
|
1379
1539
|
kfdAgentHub: normalizedKfdAgentHub ? optionalString(kfdAgentHubEvidencePath || "kfd-agent-hub-evidence.json") : "",
|
|
1380
1540
|
invariantPassports: invariantPassports ? "invariantPassports" : "",
|
|
@@ -1456,6 +1616,9 @@ export function collectGitHubReleasePassport({
|
|
|
1456
1616
|
invariantPassportJsons = [],
|
|
1457
1617
|
invariantPassportCommand = "",
|
|
1458
1618
|
releaseEvidenceJsons = [],
|
|
1619
|
+
v4ConsumerPolicyCertificationJson = "",
|
|
1620
|
+
v4ConsumerPolicyCertificationRoot = "",
|
|
1621
|
+
v4RuntimeResumeEvidenceJson = "",
|
|
1459
1622
|
kfdAgentHubEvidenceJson = "",
|
|
1460
1623
|
controllerReceiptReferences = [],
|
|
1461
1624
|
githubArtifactAttestationPolicyJsons = [],
|
|
@@ -1531,6 +1694,12 @@ export function collectGitHubReleasePassport({
|
|
|
1531
1694
|
}),
|
|
1532
1695
|
)
|
|
1533
1696
|
.filter((meta) => meta.value);
|
|
1697
|
+
const v4ConsumerPolicyCertificationMeta =
|
|
1698
|
+
parseV4ConsumerPolicyCertification(v4ConsumerPolicyCertificationJson, cwd);
|
|
1699
|
+
const v4RuntimeResumeEvidence = parseJsonInput(v4RuntimeResumeEvidenceJson, undefined, {
|
|
1700
|
+
cwd,
|
|
1701
|
+
label: "v4RuntimeResumeEvidenceJson",
|
|
1702
|
+
});
|
|
1534
1703
|
const kfdAgentHubEvidenceMeta = parseJsonInputWithMeta(
|
|
1535
1704
|
kfdAgentHubEvidenceJson,
|
|
1536
1705
|
undefined,
|
|
@@ -1656,6 +1825,9 @@ export function collectGitHubReleasePassport({
|
|
|
1656
1825
|
kfdSupportEvidencePath: kfdSupport ? "kfd-support.json" : "",
|
|
1657
1826
|
invariantPassports,
|
|
1658
1827
|
releaseEvidence: releaseEvidenceAttachments.map(({ reference }) => reference),
|
|
1828
|
+
v4ConsumerPolicyCertification: v4ConsumerPolicyCertificationMeta.value,
|
|
1829
|
+
v4ConsumerPolicyCertificationRoot,
|
|
1830
|
+
v4RuntimeResumeEvidence,
|
|
1659
1831
|
kfdAgentHubEvidence: kfdAgentHubEvidenceMeta.value
|
|
1660
1832
|
? { ...kfdAgentHubEvidenceMeta, path: "kfd-agent-hub-evidence.json" }
|
|
1661
1833
|
: undefined,
|
|
@@ -2125,6 +2297,65 @@ function validateReleaseEvidenceAttachments({
|
|
|
2125
2297
|
return { evidenceArtifacts, releaseEvidence };
|
|
2126
2298
|
}
|
|
2127
2299
|
|
|
2300
|
+
function validateV4ConsumerPolicyPassportSection({ passport, issues }) {
|
|
2301
|
+
const routing = passport?.promotionRouting;
|
|
2302
|
+
const evidence = passport?.v4ConsumerPolicy;
|
|
2303
|
+
if (isV4PromotionRouting(routing) && !evidence) {
|
|
2304
|
+
issues.push(issue(
|
|
2305
|
+
"error",
|
|
2306
|
+
"v4ConsumerPolicy.missing",
|
|
2307
|
+
"Buildchain v4 Release Passport requires an external floating consumer policy certification",
|
|
2308
|
+
));
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
if (!evidence) return;
|
|
2312
|
+
const verification = verifyV4FloatingConsumerPolicyCertification(
|
|
2313
|
+
releasePassportCertificationVerificationOptions({
|
|
2314
|
+
evidence,
|
|
2315
|
+
passport,
|
|
2316
|
+
routing,
|
|
2317
|
+
}),
|
|
2318
|
+
);
|
|
2319
|
+
for (const failure of verification.failures) {
|
|
2320
|
+
issues.push(issue("error", `v4ConsumerPolicy.${failure.code}`, failure.message));
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
function validateV4RuntimeResumePassportSection({ passport, issues }) {
|
|
2325
|
+
const evidence = passport?.v4RuntimeResume;
|
|
2326
|
+
if (!evidence) return;
|
|
2327
|
+
const consumerPolicyReceiptRoot = passport?.v4ConsumerPolicy?.certification?.receiptRoot || "";
|
|
2328
|
+
const authorization = verifyV4RuntimeAuthorizationReceipt({
|
|
2329
|
+
receipt: evidence.authorization,
|
|
2330
|
+
receiptRoot: evidence.authorizationRoot,
|
|
2331
|
+
repository: passport?.product?.repository || "",
|
|
2332
|
+
sourceSha: v4RuntimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
|
|
2333
|
+
runtimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
2334
|
+
consumerPolicyReceiptRoot,
|
|
2335
|
+
});
|
|
2336
|
+
for (const failure of authorization.failures) {
|
|
2337
|
+
issues.push(issue("error", `v4RuntimeResume.authorization.${failure}`, failure));
|
|
2338
|
+
}
|
|
2339
|
+
const lineage = verifyV4RuntimeResumeLineage({
|
|
2340
|
+
lineage: evidence.lineage,
|
|
2341
|
+
lineageRoot: evidence.lineageRoot,
|
|
2342
|
+
repository: passport?.product?.repository || "",
|
|
2343
|
+
sourceSha: v4RuntimeResumeSourceSha(passport?.release, passport?.release?.sourceSha || ""),
|
|
2344
|
+
resumeRuntimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
2345
|
+
consumerPolicyReceiptRoot,
|
|
2346
|
+
});
|
|
2347
|
+
for (const failure of lineage.failures) {
|
|
2348
|
+
issues.push(issue("error", `v4RuntimeResume.lineage.${failure}`, failure));
|
|
2349
|
+
}
|
|
2350
|
+
if (evidence.lineage?.authorizationRoot !== evidence.authorizationRoot) {
|
|
2351
|
+
issues.push(issue(
|
|
2352
|
+
"error",
|
|
2353
|
+
"v4RuntimeResume.authorization-root-mismatch",
|
|
2354
|
+
"runtime resume lineage must bind the embedded authorization receipt root",
|
|
2355
|
+
));
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2128
2359
|
function validatePublishEvidenceSection({ passport, publishEvidence, normalizedPublishEvidence, issues }) {
|
|
2129
2360
|
const publishEvidenceSupplied =
|
|
2130
2361
|
Boolean(passport?.evidence?.publishEvidence) ||
|
|
@@ -2597,6 +2828,8 @@ export function createReleaseCheckReport({
|
|
|
2597
2828
|
releaseEvidenceDocuments,
|
|
2598
2829
|
issues,
|
|
2599
2830
|
});
|
|
2831
|
+
validateV4ConsumerPolicyPassportSection({ passport, issues });
|
|
2832
|
+
validateV4RuntimeResumePassportSection({ passport, issues });
|
|
2600
2833
|
validatePublishEvidenceSection({ passport, publishEvidence, normalizedPublishEvidence, issues });
|
|
2601
2834
|
const evidenceIndex = indexEvidenceArtifacts(evidenceArtifacts);
|
|
2602
2835
|
validateReleaseArtifacts({ artifacts, evidenceIndex, issues });
|
|
@@ -31,10 +31,10 @@ const root = path.resolve(
|
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
export const V4_ADOPTER_DELIVERY_PARITY_SOURCE = Object.freeze({
|
|
34
|
-
v3Commit: "
|
|
34
|
+
v3Commit: "6b96bdad8d9f8ccf9275f27d9370a226a9c78465",
|
|
35
35
|
vectorSuiteRoot:
|
|
36
|
-
"sha256:
|
|
37
|
-
kfdPackage: "@kungfu-tech/kfd@1.0.0-alpha.
|
|
36
|
+
"sha256:c978707556406ffda4ef4192032332c01c2da1cebb6ad8c4f0edfc65d5cef0c7",
|
|
37
|
+
kfdPackage: "@kungfu-tech/kfd@1.0.0-alpha.65",
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
function clone(value) {
|