@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
|
@@ -61,6 +61,10 @@ const SUPPORTED_SIGNING_PROFILES = new Set([
|
|
|
61
61
|
"windows-authenticode",
|
|
62
62
|
"detached-signature-v1",
|
|
63
63
|
]);
|
|
64
|
+
const SUPPORTED_SIGNING_ENTITLEMENTS_PROFILES = new Set([
|
|
65
|
+
"none",
|
|
66
|
+
"jit-executable-v1",
|
|
67
|
+
]);
|
|
64
68
|
const SUPPORTED_SIGNING_ARTIFACT_KINDS = new Set([
|
|
65
69
|
"auto", "binary", "archive", "blob", "directory", "mach-o", "app-bundle",
|
|
66
70
|
"framework-bundle", "plugin-bundle", "xpc-bundle", "dylib", "pkg", "dmg",
|
|
@@ -99,6 +103,27 @@ function normalizeStringArray(value, label) {
|
|
|
99
103
|
return value.map((entry, index) => assertString(entry, `${label}[${index}]`));
|
|
100
104
|
}
|
|
101
105
|
|
|
106
|
+
function normalizeSigningEntitlementsPaths(value, label) {
|
|
107
|
+
const paths = normalizeStringArray(value, label);
|
|
108
|
+
for (const [index, entry] of paths.entries()) {
|
|
109
|
+
const parts = entry.split("/");
|
|
110
|
+
if (
|
|
111
|
+
entry.startsWith("/") ||
|
|
112
|
+
entry.includes("\\") ||
|
|
113
|
+
entry.includes(",") ||
|
|
114
|
+
parts.some((part) => part === "" || part === "." || part === "..")
|
|
115
|
+
) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`${label}[${index}] must be a safe archive-relative path`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (new Set(paths).size !== paths.length) {
|
|
122
|
+
throw new Error(`${label} must not contain duplicate paths`);
|
|
123
|
+
}
|
|
124
|
+
return paths;
|
|
125
|
+
}
|
|
126
|
+
|
|
102
127
|
function getByDottedKey(target, key) {
|
|
103
128
|
return String(key)
|
|
104
129
|
.split(".")
|
|
@@ -211,6 +236,16 @@ export function normalizeBuildchainConfig(config) {
|
|
|
211
236
|
if (normalized.publication !== undefined) {
|
|
212
237
|
normalized.publication = normalizePublicationSection(normalized.publication);
|
|
213
238
|
}
|
|
239
|
+
if (normalized.publication_rehearsal !== undefined) {
|
|
240
|
+
normalized.publication_rehearsal = normalizePublicationRehearsalSection(
|
|
241
|
+
normalized.publication_rehearsal,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (normalized.adopter_delivery !== undefined) {
|
|
245
|
+
normalized.adopter_delivery = normalizeAdopterDeliverySection(
|
|
246
|
+
normalized.adopter_delivery,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
214
249
|
if (normalized.consumers !== undefined) {
|
|
215
250
|
normalized.consumers = normalizeConsumersSection(normalized.consumers);
|
|
216
251
|
}
|
|
@@ -362,7 +397,16 @@ function normalizeSigningSection(signing) {
|
|
|
362
397
|
const artifacts = signing.artifacts.map((artifact, index) => {
|
|
363
398
|
const label = `signing.artifacts[${index}]`;
|
|
364
399
|
assertPlainObject(artifact, label);
|
|
365
|
-
const allowedKeys = new Set([
|
|
400
|
+
const allowedKeys = new Set([
|
|
401
|
+
"id",
|
|
402
|
+
"path",
|
|
403
|
+
"profile",
|
|
404
|
+
"entitlements_profile",
|
|
405
|
+
"entitlements_paths",
|
|
406
|
+
"kind",
|
|
407
|
+
"platforms",
|
|
408
|
+
"required",
|
|
409
|
+
]);
|
|
366
410
|
for (const key of Object.keys(artifact)) {
|
|
367
411
|
if (!allowedKeys.has(key)) {
|
|
368
412
|
throw new Error(`${label}.${key} is not supported; declare desired signature state only`);
|
|
@@ -377,10 +421,41 @@ function normalizeSigningSection(signing) {
|
|
|
377
421
|
if (!SUPPORTED_SIGNING_ARTIFACT_KINDS.has(kind)) {
|
|
378
422
|
throw new Error(`${label}.kind is not a supported signing artifact kind`);
|
|
379
423
|
}
|
|
424
|
+
const entitlementsProfile =
|
|
425
|
+
artifact.entitlements_profile === undefined
|
|
426
|
+
? "none"
|
|
427
|
+
: assertString(
|
|
428
|
+
artifact.entitlements_profile,
|
|
429
|
+
`${label}.entitlements_profile`,
|
|
430
|
+
);
|
|
431
|
+
if (!SUPPORTED_SIGNING_ENTITLEMENTS_PROFILES.has(entitlementsProfile)) {
|
|
432
|
+
throw new Error(
|
|
433
|
+
`${label}.entitlements_profile must be one of none or jit-executable-v1`,
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
if (entitlementsProfile !== "none" && kind !== "archive") {
|
|
437
|
+
throw new Error(
|
|
438
|
+
`${label}.entitlements_profile ${entitlementsProfile} requires kind = "archive"`,
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
const entitlementsPaths = normalizeSigningEntitlementsPaths(
|
|
442
|
+
artifact.entitlements_paths,
|
|
443
|
+
`${label}.entitlements_paths`,
|
|
444
|
+
);
|
|
445
|
+
if (
|
|
446
|
+
(entitlementsProfile === "none" && entitlementsPaths.length !== 0) ||
|
|
447
|
+
(entitlementsProfile !== "none" && entitlementsPaths.length === 0)
|
|
448
|
+
) {
|
|
449
|
+
throw new Error(
|
|
450
|
+
`${label}.entitlements_paths must be non-empty exactly when entitlements_profile is enabled`,
|
|
451
|
+
);
|
|
452
|
+
}
|
|
380
453
|
return {
|
|
381
454
|
id: artifact.id === undefined ? artifactPath : assertString(artifact.id, `${label}.id`),
|
|
382
455
|
path: artifactPath,
|
|
383
456
|
profile,
|
|
457
|
+
entitlementsProfile,
|
|
458
|
+
entitlementsPaths,
|
|
384
459
|
kind,
|
|
385
460
|
platforms: normalizeStringArray(artifact.platforms, `${label}.platforms`),
|
|
386
461
|
required: optionalBoolean(artifact.required, true),
|
|
@@ -635,6 +710,80 @@ function normalizePublicationSection(publication) {
|
|
|
635
710
|
};
|
|
636
711
|
}
|
|
637
712
|
|
|
713
|
+
function normalizePublicationRehearsalSection(rehearsal) {
|
|
714
|
+
assertPlainObject(rehearsal, "publication_rehearsal");
|
|
715
|
+
const allowed = ["contract", "capsule_path", "candidate_root", "state_path", "evidence_path", "effect_default"];
|
|
716
|
+
const unknown = Object.keys(rehearsal).filter((key) => !allowed.includes(key));
|
|
717
|
+
if (unknown.length > 0) {
|
|
718
|
+
throw new Error(`publication_rehearsal contains unsupported fields: ${unknown.join(", ")}`);
|
|
719
|
+
}
|
|
720
|
+
const normalized = {
|
|
721
|
+
contract: assertString(rehearsal.contract, "publication_rehearsal.contract"),
|
|
722
|
+
capsulePath: posixPath(assertString(rehearsal.capsule_path, "publication_rehearsal.capsule_path")),
|
|
723
|
+
candidateRoot: posixPath(assertString(rehearsal.candidate_root, "publication_rehearsal.candidate_root")),
|
|
724
|
+
statePath: posixPath(assertString(rehearsal.state_path, "publication_rehearsal.state_path")),
|
|
725
|
+
evidencePath: posixPath(assertString(rehearsal.evidence_path, "publication_rehearsal.evidence_path")),
|
|
726
|
+
effectDefault: assertString(rehearsal.effect_default, "publication_rehearsal.effect_default"),
|
|
727
|
+
};
|
|
728
|
+
if (
|
|
729
|
+
normalized.contract !== "buildchain-v4-publication-rehearsal-capsule/v1" ||
|
|
730
|
+
normalized.effectDefault !== "disabled"
|
|
731
|
+
) {
|
|
732
|
+
throw new Error("publication_rehearsal must use the v4 capsule contract with effect_default = disabled");
|
|
733
|
+
}
|
|
734
|
+
for (const [key, value] of Object.entries({
|
|
735
|
+
capsule_path: normalized.capsulePath,
|
|
736
|
+
candidate_root: normalized.candidateRoot,
|
|
737
|
+
state_path: normalized.statePath,
|
|
738
|
+
evidence_path: normalized.evidencePath,
|
|
739
|
+
})) {
|
|
740
|
+
if (value.startsWith("/") || value.includes("\\") || value.split("/").includes("..")) {
|
|
741
|
+
throw new Error(`publication_rehearsal.${key} must be repository-relative`);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
return normalized;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function normalizeAdopterDeliverySection(delivery) {
|
|
748
|
+
assertPlainObject(delivery, "adopter_delivery");
|
|
749
|
+
const allowed = ["contract", "input_path", "readback_path", "bootstrap_path", "archive_path", "result_path", "driver_selector", "artifact_profile_selector"];
|
|
750
|
+
const unknown = Object.keys(delivery).filter((key) => !allowed.includes(key));
|
|
751
|
+
if (unknown.length > 0) {
|
|
752
|
+
throw new Error(`adopter_delivery contains unsupported fields: ${unknown.join(", ")}`);
|
|
753
|
+
}
|
|
754
|
+
const normalized = {
|
|
755
|
+
contract: assertString(delivery.contract, "adopter_delivery.contract"),
|
|
756
|
+
inputPath: posixPath(assertString(delivery.input_path, "adopter_delivery.input_path")),
|
|
757
|
+
readbackPath: posixPath(assertString(delivery.readback_path, "adopter_delivery.readback_path")),
|
|
758
|
+
bootstrapPath: posixPath(assertString(delivery.bootstrap_path, "adopter_delivery.bootstrap_path")),
|
|
759
|
+
archivePath: posixPath(assertString(delivery.archive_path, "adopter_delivery.archive_path")),
|
|
760
|
+
resultPath: posixPath(assertString(delivery.result_path, "adopter_delivery.result_path")),
|
|
761
|
+
driverSelector: assertString(delivery.driver_selector, "adopter_delivery.driver_selector"),
|
|
762
|
+
artifactProfileSelector: assertString(delivery.artifact_profile_selector, "adopter_delivery.artifact_profile_selector"),
|
|
763
|
+
};
|
|
764
|
+
if (normalized.contract !== "kungfu-buildchain-v4-adopter-delivery/v1") {
|
|
765
|
+
throw new Error("adopter_delivery contract is unsupported");
|
|
766
|
+
}
|
|
767
|
+
if (
|
|
768
|
+
!["json-assertion", "kfd-category", "legacy-kfd"].includes(normalized.driverSelector) ||
|
|
769
|
+
!["git-commit", "package"].includes(normalized.artifactProfileSelector)
|
|
770
|
+
) {
|
|
771
|
+
throw new Error("adopter_delivery selector is unsupported");
|
|
772
|
+
}
|
|
773
|
+
for (const [key, value] of Object.entries({
|
|
774
|
+
input_path: normalized.inputPath,
|
|
775
|
+
readback_path: normalized.readbackPath,
|
|
776
|
+
bootstrap_path: normalized.bootstrapPath,
|
|
777
|
+
archive_path: normalized.archivePath,
|
|
778
|
+
result_path: normalized.resultPath,
|
|
779
|
+
})) {
|
|
780
|
+
if (value.startsWith("/") || value.includes("\\") || value.split("/").includes("..")) {
|
|
781
|
+
throw new Error(`adopter_delivery.${key} must be repository-relative`);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return normalized;
|
|
785
|
+
}
|
|
786
|
+
|
|
638
787
|
function normalizePublicationArchive(archive = undefined) {
|
|
639
788
|
if (archive === undefined) {
|
|
640
789
|
return undefined;
|
|
@@ -7,8 +7,18 @@ import {
|
|
|
7
7
|
normalizeBuildchainRef,
|
|
8
8
|
parseBuildchainRefIdentity,
|
|
9
9
|
} from "./buildchain-channel-identity.js";
|
|
10
|
+
import {
|
|
11
|
+
createHistoricalBuildchainCompatibilityFacts,
|
|
12
|
+
createHistoricalBuildchainCompatibilityProofs,
|
|
13
|
+
} from "./buildchain-compatibility-fact.js";
|
|
14
|
+
import {
|
|
15
|
+
assertBuildchainCompatibilityProjection,
|
|
16
|
+
createBuildchainCompatibilityProofRegistry,
|
|
17
|
+
} from "./buildchain-compatibility-authority.js";
|
|
18
|
+
import { evaluateBuildchainContractLock as evaluateFactBackedBuildchainContractLock } from "./buildchain-compatibility-proof.js";
|
|
10
19
|
import { createControllerRegistry } from "./controller-evidence.js";
|
|
11
20
|
import { enumerateWorkflowInputs } from "./public-surface-audit.js";
|
|
21
|
+
import { devDeliveryWorkflowContractSurface } from "./dev-delivery-contract-surface.js";
|
|
12
22
|
|
|
13
23
|
export {
|
|
14
24
|
BUILDCHAIN_CHANNELS,
|
|
@@ -17,11 +27,47 @@ export {
|
|
|
17
27
|
parseBuildchainRefIdentity,
|
|
18
28
|
};
|
|
19
29
|
|
|
30
|
+
export {
|
|
31
|
+
BUILDCHAIN_COMPATIBILITY_FACT_REGISTRY_SCHEMA,
|
|
32
|
+
BUILDCHAIN_COMPATIBILITY_FACT_SCHEMA,
|
|
33
|
+
BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA,
|
|
34
|
+
BUILDCHAIN_COMPATIBILITY_PROOF_SCHEMA,
|
|
35
|
+
BUILDCHAIN_COMPATIBILITY_RELEASE_EVIDENCE_SCHEMA,
|
|
36
|
+
createBuildchainCompatibilityFact,
|
|
37
|
+
createBuildchainCompatibilityFactRegistry,
|
|
38
|
+
createBuildchainCompatibilityProof,
|
|
39
|
+
createHistoricalBuildchainCompatibilityFacts,
|
|
40
|
+
createHistoricalBuildchainCompatibilityProofs,
|
|
41
|
+
verifyBuildchainCompatibilityFact,
|
|
42
|
+
verifyBuildchainCompatibilityFactRegistry,
|
|
43
|
+
verifyBuildchainCompatibilityProof,
|
|
44
|
+
} from "./buildchain-compatibility-fact.js";
|
|
45
|
+
export {
|
|
46
|
+
assertBuildchainCompatibilityProjection,
|
|
47
|
+
createBuildchainCompatibilityPathQuery,
|
|
48
|
+
createBuildchainCompatibilityProofRegistry,
|
|
49
|
+
createBuildchainCompatibilityReleaseEvidence,
|
|
50
|
+
resolveBuildchainCompatibilityProof,
|
|
51
|
+
verifyBuildchainCompatibilityPath,
|
|
52
|
+
} from "./buildchain-compatibility-authority.js";
|
|
53
|
+
export {
|
|
54
|
+
BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
|
|
55
|
+
BUILDCHAIN_LEGACY_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
|
|
56
|
+
createBuildchainCompatibilityVerificationReceipt,
|
|
57
|
+
verifyBuildchainCompatibilityVerificationReceipt,
|
|
58
|
+
} from "./buildchain-compatibility-proof.js";
|
|
59
|
+
|
|
20
60
|
export const BUILDCHAIN_RUNTIME_CONTRACT_WORLD = "kungfu-buildchain-runtime-contract-world";
|
|
21
61
|
export const BUILDCHAIN_CONTRACT_LOCK = "kungfu-buildchain-contract-lock";
|
|
22
62
|
|
|
23
63
|
const DEFAULT_POLICY = "major-compatible";
|
|
24
|
-
|
|
64
|
+
|
|
65
|
+
function compatibilityAuthority() {
|
|
66
|
+
return {
|
|
67
|
+
compatibilityFacts: createHistoricalBuildchainCompatibilityFacts(),
|
|
68
|
+
compatibilityProofs: createHistoricalBuildchainCompatibilityProofs(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
25
71
|
|
|
26
72
|
function optionalString(value) {
|
|
27
73
|
return value === undefined || value === null ? "" : String(value);
|
|
@@ -125,8 +171,7 @@ export function createBuildchainContractWorld({
|
|
|
125
171
|
packageJson = undefined,
|
|
126
172
|
controllerRegistry = undefined,
|
|
127
173
|
} = {}) {
|
|
128
|
-
const pkg = packageJson || readJson(path.join(root, "package.json"), {});
|
|
129
|
-
const majorLine = majorLineFromPackageVersion(pkg.version);
|
|
174
|
+
const pkg = packageJson || readJson(path.join(root, "package.json"), {}), majorLine = majorLineFromPackageVersion(pkg.version);
|
|
130
175
|
const workflowDescriptors = controllerRegistry ? [] : enumerateWorkflowInputs({ root });
|
|
131
176
|
const controllerWorkflowIds = new Set([
|
|
132
177
|
"check",
|
|
@@ -217,6 +262,7 @@ export function createBuildchainContractWorld({
|
|
|
217
262
|
"alpha and stable channel selections use separate consumer contract locks by default",
|
|
218
263
|
],
|
|
219
264
|
}),
|
|
265
|
+
surface(root, devDeliveryWorkflowContractSurface(pkg, majorLine)),
|
|
220
266
|
surface(root, {
|
|
221
267
|
id: "release-candidate-promote",
|
|
222
268
|
kind: "workflow",
|
|
@@ -795,26 +841,60 @@ export function createBuildchainContractWorld({
|
|
|
795
841
|
version: pkg.version || "",
|
|
796
842
|
repository: pkg.repository?.url || pkg.repository || "https://github.com/kungfu-systems/buildchain",
|
|
797
843
|
},
|
|
798
|
-
majorLine,
|
|
799
|
-
|
|
844
|
+
majorLine, compatibilityPolicy: DEFAULT_POLICY,
|
|
845
|
+
...compatibilityAuthority(),
|
|
800
846
|
surfaces,
|
|
801
847
|
};
|
|
802
848
|
return finalizeBuildchainContractWorld(base);
|
|
803
849
|
}
|
|
804
850
|
|
|
805
851
|
export function finalizeBuildchainContractWorld(contractWorld) {
|
|
852
|
+
if (!Array.isArray(contractWorld?.compatibilityFacts) || !Array.isArray(contractWorld?.compatibilityProofs)) {
|
|
853
|
+
throw new Error("contract world requires compatibility Facts and their proof projection");
|
|
854
|
+
}
|
|
855
|
+
const sourceSurfaces = (contractWorld.surfaces || []).map((entry) => ({ ...entry }));
|
|
856
|
+
const proofRegistry = createBuildchainCompatibilityProofRegistry({
|
|
857
|
+
proofs: contractWorld.compatibilityProofs,
|
|
858
|
+
surfaces: sourceSurfaces,
|
|
859
|
+
majorLine: contractWorld.majorLine,
|
|
860
|
+
});
|
|
861
|
+
if (JSON.stringify(contractWorld.compatibilityFacts) !== JSON.stringify(proofRegistry.facts)) {
|
|
862
|
+
throw new Error("contract world compatibility Facts drift from the verified registry");
|
|
863
|
+
}
|
|
806
864
|
const world = {
|
|
807
865
|
...contractWorld,
|
|
808
|
-
|
|
866
|
+
compatibilityFacts: proofRegistry.facts,
|
|
867
|
+
compatibilityFactRegistryRoot: proofRegistry.factRegistryRoot,
|
|
868
|
+
compatibilityFactCutRoot: proofRegistry.factCutRoot,
|
|
869
|
+
compatibilityProofs: proofRegistry.proofs,
|
|
870
|
+
compatibilityProofRegistryRoot: proofRegistry.registryRoot,
|
|
871
|
+
surfaces: sourceSurfaces.map((entry) => {
|
|
872
|
+
const surfaceEntry = { ...entry };
|
|
873
|
+
delete surfaceEntry.compatibleBreakingDigests;
|
|
874
|
+
delete surfaceEntry.compatibilityProofRoots;
|
|
875
|
+
delete surfaceEntry.compatibilityFactRoots;
|
|
876
|
+
const projection = proofRegistry.projections[entry.id] || [];
|
|
877
|
+
if (projection.length > 0) {
|
|
878
|
+
surfaceEntry.compatibleBreakingDigests = projection.map((item) => item.breakingDigest);
|
|
879
|
+
surfaceEntry.compatibilityProofRoots = projection.map((item) => item.proofRoot);
|
|
880
|
+
surfaceEntry.compatibilityFactRoots = projection.map((item) => item.factRoot);
|
|
881
|
+
}
|
|
882
|
+
return surfaceEntry;
|
|
883
|
+
}),
|
|
809
884
|
};
|
|
810
885
|
const compatibilityModel = {
|
|
811
886
|
schemaVersion: world.schemaVersion,
|
|
812
887
|
contract: world.contract,
|
|
813
888
|
majorLine: world.majorLine,
|
|
889
|
+
compatibilityFactRegistryRoot: world.compatibilityFactRegistryRoot,
|
|
890
|
+
compatibilityFactCutRoot: world.compatibilityFactCutRoot,
|
|
891
|
+
compatibilityProofRegistryRoot: world.compatibilityProofRegistryRoot,
|
|
814
892
|
surfaces: world.surfaces.map((entry) => ({
|
|
815
893
|
id: entry.id,
|
|
816
894
|
kind: entry.kind,
|
|
817
895
|
breakingDigest: entry.breakingDigest,
|
|
896
|
+
compatibilityProofRoots: entry.compatibilityProofRoots || [],
|
|
897
|
+
compatibilityFactRoots: entry.compatibilityFactRoots || [],
|
|
818
898
|
})),
|
|
819
899
|
};
|
|
820
900
|
const digestModel = {
|
|
@@ -846,6 +926,9 @@ export function createBuildchainContractLock({
|
|
|
846
926
|
contract: contractWorld.contract,
|
|
847
927
|
contractDigest: contractWorld.contractDigest,
|
|
848
928
|
compatibilityDigest: contractWorld.compatibilityDigest,
|
|
929
|
+
compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
|
|
930
|
+
compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
|
|
931
|
+
compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
|
|
849
932
|
majorLine: contractWorld.majorLine,
|
|
850
933
|
compatibilityPolicy,
|
|
851
934
|
acceptedAt,
|
|
@@ -853,6 +936,8 @@ export function createBuildchainContractLock({
|
|
|
853
936
|
id: entry.id,
|
|
854
937
|
kind: entry.kind,
|
|
855
938
|
breakingDigest: entry.breakingDigest,
|
|
939
|
+
compatibilityProofRoots: entry.compatibilityProofRoots || [],
|
|
940
|
+
compatibilityFactRoots: entry.compatibilityFactRoots || [],
|
|
856
941
|
})),
|
|
857
942
|
},
|
|
858
943
|
};
|
|
@@ -889,143 +974,8 @@ export function readBuildchainContractLock(filePath) {
|
|
|
889
974
|
return value;
|
|
890
975
|
}
|
|
891
976
|
|
|
892
|
-
function
|
|
893
|
-
return
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
function evaluateChannelBinding({
|
|
897
|
-
lock,
|
|
898
|
-
workflowShellRef,
|
|
899
|
-
runtimeRef,
|
|
900
|
-
expectedChannel,
|
|
901
|
-
expectedMajor,
|
|
902
|
-
allowOpaqueRuntime,
|
|
903
|
-
}) {
|
|
904
|
-
if (!workflowShellRef && !expectedChannel && !expectedMajor) return null;
|
|
905
|
-
return evaluateBuildchainChannelBinding({
|
|
906
|
-
workflowShellRef,
|
|
907
|
-
runtimeRef,
|
|
908
|
-
lockRef: lock?.buildchain?.ref || "",
|
|
909
|
-
lockMajorLine: lock?.buildchain?.majorLine || "",
|
|
910
|
-
expectedChannel,
|
|
911
|
-
expectedMajor,
|
|
912
|
-
allowOpaqueRuntime,
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
export function evaluateBuildchainContractLock({
|
|
917
|
-
lock,
|
|
918
|
-
current,
|
|
919
|
-
runtimeRef = "",
|
|
920
|
-
runtimeSha = "",
|
|
921
|
-
runtimeClass = "",
|
|
922
|
-
compatibilityPolicy = "",
|
|
923
|
-
workflowShellRef = "",
|
|
924
|
-
expectedChannel = "",
|
|
925
|
-
expectedMajor = "",
|
|
926
|
-
allowOpaqueRuntime = false,
|
|
927
|
-
} = {}) {
|
|
928
|
-
if (!current || current.contract !== BUILDCHAIN_RUNTIME_CONTRACT_WORLD) {
|
|
929
|
-
throw new Error("current must be a Buildchain runtime contract world");
|
|
930
|
-
}
|
|
931
|
-
const binding = evaluateChannelBinding({
|
|
932
|
-
lock,
|
|
933
|
-
workflowShellRef,
|
|
934
|
-
runtimeRef,
|
|
935
|
-
expectedChannel,
|
|
936
|
-
expectedMajor,
|
|
937
|
-
allowOpaqueRuntime,
|
|
938
|
-
});
|
|
939
|
-
if (binding?.ok === false) {
|
|
940
|
-
return {
|
|
941
|
-
ok: false,
|
|
942
|
-
status: binding.status,
|
|
943
|
-
drift: false,
|
|
944
|
-
compatible: false,
|
|
945
|
-
issueRecommended: false,
|
|
946
|
-
reasons: binding.reasons,
|
|
947
|
-
channelBinding: binding,
|
|
948
|
-
};
|
|
949
|
-
}
|
|
950
|
-
const floatingRuntime = FLOATING_CLASSES.has(runtimeClass);
|
|
951
|
-
if (!floatingRuntime) {
|
|
952
|
-
return {
|
|
953
|
-
ok: true,
|
|
954
|
-
status: "non-floating-runtime",
|
|
955
|
-
drift: false,
|
|
956
|
-
compatible: true,
|
|
957
|
-
issueRecommended: false,
|
|
958
|
-
reason: `runtime class ${runtimeClass || "unknown"} is not a stable floating ref`,
|
|
959
|
-
};
|
|
960
|
-
}
|
|
961
|
-
if (!lock) {
|
|
962
|
-
return {
|
|
963
|
-
ok: true,
|
|
964
|
-
status: "missing-lock",
|
|
965
|
-
drift: false,
|
|
966
|
-
compatible: true,
|
|
967
|
-
issueRecommended: false,
|
|
968
|
-
reason: "consumer repository has no Buildchain contract lock",
|
|
969
|
-
};
|
|
970
|
-
}
|
|
971
|
-
const accepted = lock.buildchain || {};
|
|
972
|
-
const policy = compatibilityPolicy || accepted.compatibilityPolicy || DEFAULT_POLICY;
|
|
973
|
-
const shaDrift = !!accepted.resolvedSha && !!runtimeSha && accepted.resolvedSha !== runtimeSha;
|
|
974
|
-
const contractDrift = !!accepted.contractDigest && accepted.contractDigest !== current.contractDigest;
|
|
975
|
-
if (!shaDrift && !contractDrift) {
|
|
976
|
-
return {
|
|
977
|
-
ok: true,
|
|
978
|
-
status: "unchanged",
|
|
979
|
-
drift: false,
|
|
980
|
-
compatible: true,
|
|
981
|
-
issueRecommended: false,
|
|
982
|
-
policy,
|
|
983
|
-
accepted,
|
|
984
|
-
current: contractSummary(current, runtimeRef, runtimeSha),
|
|
985
|
-
};
|
|
986
|
-
}
|
|
987
|
-
const reasons = [];
|
|
988
|
-
if (accepted.contract !== current.contract) {
|
|
989
|
-
reasons.push(`contract changed from ${accepted.contract || "(unknown)"} to ${current.contract}`);
|
|
990
|
-
}
|
|
991
|
-
if (accepted.majorLine && accepted.majorLine !== current.majorLine) {
|
|
992
|
-
reasons.push(`major line changed from ${accepted.majorLine} to ${current.majorLine}`);
|
|
993
|
-
}
|
|
994
|
-
if (policy === "exact" && accepted.contractDigest !== current.contractDigest) {
|
|
995
|
-
reasons.push("exact policy requires the contract digest to remain unchanged");
|
|
996
|
-
}
|
|
997
|
-
if (!["major-compatible", "allow-additive", "exact"].includes(policy)) {
|
|
998
|
-
reasons.push(`unsupported compatibility policy: ${policy}`);
|
|
999
|
-
}
|
|
1000
|
-
const currentSurfaces = surfaceMap(current.surfaces);
|
|
1001
|
-
for (const oldSurface of accepted.surfaces || []) {
|
|
1002
|
-
const nextSurface = currentSurfaces.get(oldSurface.id);
|
|
1003
|
-
if (!nextSurface) {
|
|
1004
|
-
reasons.push(`surface removed: ${oldSurface.id}`);
|
|
1005
|
-
continue;
|
|
1006
|
-
}
|
|
1007
|
-
const compatibleBreakingDigests = new Set(nextSurface.compatibleBreakingDigests || []);
|
|
1008
|
-
if (
|
|
1009
|
-
nextSurface.breakingDigest !== oldSurface.breakingDigest
|
|
1010
|
-
&& !compatibleBreakingDigests.has(oldSurface.breakingDigest)
|
|
1011
|
-
) {
|
|
1012
|
-
reasons.push(`surface breaking digest changed: ${oldSurface.id}`);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
const compatible = reasons.length === 0;
|
|
1016
|
-
return {
|
|
1017
|
-
ok: compatible,
|
|
1018
|
-
status: compatible ? "compatible-drift" : "breaking-drift",
|
|
1019
|
-
drift: shaDrift || contractDrift,
|
|
1020
|
-
shaDrift,
|
|
1021
|
-
contractDrift,
|
|
1022
|
-
compatible,
|
|
1023
|
-
issueRecommended: true,
|
|
1024
|
-
policy,
|
|
1025
|
-
reasons,
|
|
1026
|
-
accepted,
|
|
1027
|
-
current: contractSummary(current, runtimeRef, runtimeSha),
|
|
1028
|
-
};
|
|
977
|
+
export function evaluateBuildchainContractLock(options = {}) {
|
|
978
|
+
return evaluateFactBackedBuildchainContractLock(options);
|
|
1029
979
|
}
|
|
1030
980
|
|
|
1031
981
|
export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "") {
|
|
@@ -1035,6 +985,9 @@ export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "")
|
|
|
1035
985
|
contract: contractWorld.contract,
|
|
1036
986
|
contractDigest: contractWorld.contractDigest,
|
|
1037
987
|
compatibilityDigest: contractWorld.compatibilityDigest,
|
|
988
|
+
compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
|
|
989
|
+
compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
|
|
990
|
+
compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
|
|
1038
991
|
majorLine: contractWorld.majorLine,
|
|
1039
992
|
surfaceCount: Array.isArray(contractWorld.surfaces) ? contractWorld.surfaces.length : 0,
|
|
1040
993
|
};
|