@kungfu-tech/buildchain 4.0.1-alpha.3 → 4.0.1-alpha.31
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/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/internal-capabilities.json +117 -8
- package/architecture/maintainability-policy.json +43 -25
- package/architecture/release-tail-contract-inventory.json +5 -2
- package/architecture/v3-core-mechanism-inventory.json +89 -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-warrant-shadow-fixtures.json +15 -6
- package/architecture/v4-floating-consumer-policy.json +6 -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-tail-reseal-parity.json +150 -0
- package/bin/buildchain.mjs +23 -2
- 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/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 +7 -1
- 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-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 +4 -2
- package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
- package/contracts/v4-tail-reseal-v1.schema.json +276 -0
- package/dist/site/agent-index.json +4 -0
- package/dist/site/artifact-schemas.json +8 -0
- package/dist/site/buildchain-contract.json +1393 -28
- package/dist/site/buildchain-site.json +477 -32
- package/dist/site/capability-registry.json +17 -14
- package/dist/site/cli-registry.json +159 -1
- package/dist/site/kfd-claims.json +455 -15
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +53 -7
- package/dist/site/node-api-registry.json +13921 -9565
- package/dist/site/page-registry.json +442 -21
- package/dist/site/public-surface-audit.json +440 -11
- package/dist/site/publication-authority-registry.json +44 -8
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +22 -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 +35 -11
- package/dist/site/workflow-registry.json +142 -8
- package/docs/MAP.md +7 -2
- package/docs/cli-reference.md +193 -0
- package/docs/cli.md +8 -0
- package/docs/dev-alpha-candidate-patrol.md +8 -0
- package/docs/dev-delivery-warrant.md +30 -5
- package/docs/next-development-transition.md +118 -0
- package/docs/node-api-reference.md +578 -285
- package/docs/release-candidate.md +7 -0
- package/docs/release-tail-provider-plane.md +30 -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-tail-reseal.md +73 -0
- package/docs/versioning.md +4 -3
- package/package.json +30 -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/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 +84 -0
- package/packages/core/buildchain-contract.js +93 -141
- 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-execution-transfer.js +21 -1
- package/packages/core/dev-delivery-native-proof.js +43 -27
- package/packages/core/dev-delivery-process-boundary.js +19 -7
- package/packages/core/dev-delivery-provider-heartbeat.js +18 -6
- package/packages/core/dev-delivery-warrant-state.js +32 -10
- package/packages/core/dev-delivery-warrant.js +9 -3
- package/packages/core/github-governance-authority.js +1 -0
- package/packages/core/index.js +5 -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/published-delivery-authority.js +266 -0
- package/packages/core/release-candidate-recovery.js +70 -15
- package/packages/core/release-candidate.js +2 -2
- package/packages/core/release-passport.js +36 -9
- 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 +18 -4
- package/packages/core/v4-floating-consumer-policy.js +143 -20
- package/packages/core/v4-floating-consumer-release-passport.js +35 -8
- 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-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 +24 -2
- package/scripts/artifact-signing-controller-core.mjs +1 -1
- package/scripts/buildchain-cli-help.mjs +30 -0
- 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 +23 -4
- package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
- package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
- package/scripts/dev-delivery-source-proof-reuse.mjs +13 -97
- package/scripts/dev-delivery-warrant-store.mjs +10 -6
- package/scripts/dev-delivery-warrant.mjs +5 -1
- package/scripts/dev-pr-auto-merge.mjs +1 -1
- package/scripts/dev-pr-delivery-warrant.mjs +1 -0
- package/scripts/dev-pr-prequeue-guard.mjs +0 -18
- package/scripts/dev-qualification-patrol.mjs +9 -9
- package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
- package/scripts/generate-channel-promotion-workflow.mjs +2 -2
- package/scripts/generate-next-development-guidance.mjs +49 -0
- package/scripts/generate-release-candidate-passport.mjs +152 -0
- package/scripts/generate-site-bundle.mjs +46 -3
- package/scripts/init-repo.mjs +22 -4
- 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/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 +560 -30
- package/scripts/site-capability-metadata.mjs +29 -0
- package/scripts/stable-candidate-qualification.mjs +9 -10
- package/scripts/v4-consumer-policy.mjs +5 -5
- 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 +2 -0
|
@@ -7,6 +7,15 @@ 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";
|
|
12
21
|
import { devDeliveryWorkflowContractSurface } from "./dev-delivery-contract-surface.js";
|
|
@@ -18,11 +27,47 @@ export {
|
|
|
18
27
|
parseBuildchainRefIdentity,
|
|
19
28
|
};
|
|
20
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
|
+
|
|
21
60
|
export const BUILDCHAIN_RUNTIME_CONTRACT_WORLD = "kungfu-buildchain-runtime-contract-world";
|
|
22
61
|
export const BUILDCHAIN_CONTRACT_LOCK = "kungfu-buildchain-contract-lock";
|
|
23
62
|
|
|
24
63
|
const DEFAULT_POLICY = "major-compatible";
|
|
25
|
-
|
|
64
|
+
|
|
65
|
+
function compatibilityAuthority() {
|
|
66
|
+
return {
|
|
67
|
+
compatibilityFacts: createHistoricalBuildchainCompatibilityFacts(),
|
|
68
|
+
compatibilityProofs: createHistoricalBuildchainCompatibilityProofs(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
26
71
|
|
|
27
72
|
function optionalString(value) {
|
|
28
73
|
return value === undefined || value === null ? "" : String(value);
|
|
@@ -796,26 +841,60 @@ export function createBuildchainContractWorld({
|
|
|
796
841
|
version: pkg.version || "",
|
|
797
842
|
repository: pkg.repository?.url || pkg.repository || "https://github.com/kungfu-systems/buildchain",
|
|
798
843
|
},
|
|
799
|
-
majorLine,
|
|
800
|
-
|
|
844
|
+
majorLine, compatibilityPolicy: DEFAULT_POLICY,
|
|
845
|
+
...compatibilityAuthority(),
|
|
801
846
|
surfaces,
|
|
802
847
|
};
|
|
803
848
|
return finalizeBuildchainContractWorld(base);
|
|
804
849
|
}
|
|
805
850
|
|
|
806
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
|
+
}
|
|
807
864
|
const world = {
|
|
808
865
|
...contractWorld,
|
|
809
|
-
|
|
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
|
+
}),
|
|
810
884
|
};
|
|
811
885
|
const compatibilityModel = {
|
|
812
886
|
schemaVersion: world.schemaVersion,
|
|
813
887
|
contract: world.contract,
|
|
814
888
|
majorLine: world.majorLine,
|
|
889
|
+
compatibilityFactRegistryRoot: world.compatibilityFactRegistryRoot,
|
|
890
|
+
compatibilityFactCutRoot: world.compatibilityFactCutRoot,
|
|
891
|
+
compatibilityProofRegistryRoot: world.compatibilityProofRegistryRoot,
|
|
815
892
|
surfaces: world.surfaces.map((entry) => ({
|
|
816
893
|
id: entry.id,
|
|
817
894
|
kind: entry.kind,
|
|
818
895
|
breakingDigest: entry.breakingDigest,
|
|
896
|
+
compatibilityProofRoots: entry.compatibilityProofRoots || [],
|
|
897
|
+
compatibilityFactRoots: entry.compatibilityFactRoots || [],
|
|
819
898
|
})),
|
|
820
899
|
};
|
|
821
900
|
const digestModel = {
|
|
@@ -847,6 +926,9 @@ export function createBuildchainContractLock({
|
|
|
847
926
|
contract: contractWorld.contract,
|
|
848
927
|
contractDigest: contractWorld.contractDigest,
|
|
849
928
|
compatibilityDigest: contractWorld.compatibilityDigest,
|
|
929
|
+
compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
|
|
930
|
+
compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
|
|
931
|
+
compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
|
|
850
932
|
majorLine: contractWorld.majorLine,
|
|
851
933
|
compatibilityPolicy,
|
|
852
934
|
acceptedAt,
|
|
@@ -854,6 +936,8 @@ export function createBuildchainContractLock({
|
|
|
854
936
|
id: entry.id,
|
|
855
937
|
kind: entry.kind,
|
|
856
938
|
breakingDigest: entry.breakingDigest,
|
|
939
|
+
compatibilityProofRoots: entry.compatibilityProofRoots || [],
|
|
940
|
+
compatibilityFactRoots: entry.compatibilityFactRoots || [],
|
|
857
941
|
})),
|
|
858
942
|
},
|
|
859
943
|
};
|
|
@@ -890,143 +974,8 @@ export function readBuildchainContractLock(filePath) {
|
|
|
890
974
|
return value;
|
|
891
975
|
}
|
|
892
976
|
|
|
893
|
-
function
|
|
894
|
-
return
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
function evaluateChannelBinding({
|
|
898
|
-
lock,
|
|
899
|
-
workflowShellRef,
|
|
900
|
-
runtimeRef,
|
|
901
|
-
expectedChannel,
|
|
902
|
-
expectedMajor,
|
|
903
|
-
allowOpaqueRuntime,
|
|
904
|
-
}) {
|
|
905
|
-
if (!workflowShellRef && !expectedChannel && !expectedMajor) return null;
|
|
906
|
-
return evaluateBuildchainChannelBinding({
|
|
907
|
-
workflowShellRef,
|
|
908
|
-
runtimeRef,
|
|
909
|
-
lockRef: lock?.buildchain?.ref || "",
|
|
910
|
-
lockMajorLine: lock?.buildchain?.majorLine || "",
|
|
911
|
-
expectedChannel,
|
|
912
|
-
expectedMajor,
|
|
913
|
-
allowOpaqueRuntime,
|
|
914
|
-
});
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
export function evaluateBuildchainContractLock({
|
|
918
|
-
lock,
|
|
919
|
-
current,
|
|
920
|
-
runtimeRef = "",
|
|
921
|
-
runtimeSha = "",
|
|
922
|
-
runtimeClass = "",
|
|
923
|
-
compatibilityPolicy = "",
|
|
924
|
-
workflowShellRef = "",
|
|
925
|
-
expectedChannel = "",
|
|
926
|
-
expectedMajor = "",
|
|
927
|
-
allowOpaqueRuntime = false,
|
|
928
|
-
} = {}) {
|
|
929
|
-
if (!current || current.contract !== BUILDCHAIN_RUNTIME_CONTRACT_WORLD) {
|
|
930
|
-
throw new Error("current must be a Buildchain runtime contract world");
|
|
931
|
-
}
|
|
932
|
-
const binding = evaluateChannelBinding({
|
|
933
|
-
lock,
|
|
934
|
-
workflowShellRef,
|
|
935
|
-
runtimeRef,
|
|
936
|
-
expectedChannel,
|
|
937
|
-
expectedMajor,
|
|
938
|
-
allowOpaqueRuntime,
|
|
939
|
-
});
|
|
940
|
-
if (binding?.ok === false) {
|
|
941
|
-
return {
|
|
942
|
-
ok: false,
|
|
943
|
-
status: binding.status,
|
|
944
|
-
drift: false,
|
|
945
|
-
compatible: false,
|
|
946
|
-
issueRecommended: false,
|
|
947
|
-
reasons: binding.reasons,
|
|
948
|
-
channelBinding: binding,
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
const floatingRuntime = FLOATING_CLASSES.has(runtimeClass);
|
|
952
|
-
if (!floatingRuntime) {
|
|
953
|
-
return {
|
|
954
|
-
ok: true,
|
|
955
|
-
status: "non-floating-runtime",
|
|
956
|
-
drift: false,
|
|
957
|
-
compatible: true,
|
|
958
|
-
issueRecommended: false,
|
|
959
|
-
reason: `runtime class ${runtimeClass || "unknown"} is not a stable floating ref`,
|
|
960
|
-
};
|
|
961
|
-
}
|
|
962
|
-
if (!lock) {
|
|
963
|
-
return {
|
|
964
|
-
ok: true,
|
|
965
|
-
status: "missing-lock",
|
|
966
|
-
drift: false,
|
|
967
|
-
compatible: true,
|
|
968
|
-
issueRecommended: false,
|
|
969
|
-
reason: "consumer repository has no Buildchain contract lock",
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
const accepted = lock.buildchain || {};
|
|
973
|
-
const policy = compatibilityPolicy || accepted.compatibilityPolicy || DEFAULT_POLICY;
|
|
974
|
-
const shaDrift = !!accepted.resolvedSha && !!runtimeSha && accepted.resolvedSha !== runtimeSha;
|
|
975
|
-
const contractDrift = !!accepted.contractDigest && accepted.contractDigest !== current.contractDigest;
|
|
976
|
-
if (!shaDrift && !contractDrift) {
|
|
977
|
-
return {
|
|
978
|
-
ok: true,
|
|
979
|
-
status: "unchanged",
|
|
980
|
-
drift: false,
|
|
981
|
-
compatible: true,
|
|
982
|
-
issueRecommended: false,
|
|
983
|
-
policy,
|
|
984
|
-
accepted,
|
|
985
|
-
current: contractSummary(current, runtimeRef, runtimeSha),
|
|
986
|
-
};
|
|
987
|
-
}
|
|
988
|
-
const reasons = [];
|
|
989
|
-
if (accepted.contract !== current.contract) {
|
|
990
|
-
reasons.push(`contract changed from ${accepted.contract || "(unknown)"} to ${current.contract}`);
|
|
991
|
-
}
|
|
992
|
-
if (accepted.majorLine && accepted.majorLine !== current.majorLine) {
|
|
993
|
-
reasons.push(`major line changed from ${accepted.majorLine} to ${current.majorLine}`);
|
|
994
|
-
}
|
|
995
|
-
if (policy === "exact" && accepted.contractDigest !== current.contractDigest) {
|
|
996
|
-
reasons.push("exact policy requires the contract digest to remain unchanged");
|
|
997
|
-
}
|
|
998
|
-
if (!["major-compatible", "allow-additive", "exact"].includes(policy)) {
|
|
999
|
-
reasons.push(`unsupported compatibility policy: ${policy}`);
|
|
1000
|
-
}
|
|
1001
|
-
const currentSurfaces = surfaceMap(current.surfaces);
|
|
1002
|
-
for (const oldSurface of accepted.surfaces || []) {
|
|
1003
|
-
const nextSurface = currentSurfaces.get(oldSurface.id);
|
|
1004
|
-
if (!nextSurface) {
|
|
1005
|
-
reasons.push(`surface removed: ${oldSurface.id}`);
|
|
1006
|
-
continue;
|
|
1007
|
-
}
|
|
1008
|
-
const compatibleBreakingDigests = new Set(nextSurface.compatibleBreakingDigests || []);
|
|
1009
|
-
if (
|
|
1010
|
-
nextSurface.breakingDigest !== oldSurface.breakingDigest
|
|
1011
|
-
&& !compatibleBreakingDigests.has(oldSurface.breakingDigest)
|
|
1012
|
-
) {
|
|
1013
|
-
reasons.push(`surface breaking digest changed: ${oldSurface.id}`);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
const compatible = reasons.length === 0;
|
|
1017
|
-
return {
|
|
1018
|
-
ok: compatible,
|
|
1019
|
-
status: compatible ? "compatible-drift" : "breaking-drift",
|
|
1020
|
-
drift: shaDrift || contractDrift,
|
|
1021
|
-
shaDrift,
|
|
1022
|
-
contractDrift,
|
|
1023
|
-
compatible,
|
|
1024
|
-
issueRecommended: true,
|
|
1025
|
-
policy,
|
|
1026
|
-
reasons,
|
|
1027
|
-
accepted,
|
|
1028
|
-
current: contractSummary(current, runtimeRef, runtimeSha),
|
|
1029
|
-
};
|
|
977
|
+
export function evaluateBuildchainContractLock(options = {}) {
|
|
978
|
+
return evaluateFactBackedBuildchainContractLock(options);
|
|
1030
979
|
}
|
|
1031
980
|
|
|
1032
981
|
export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "") {
|
|
@@ -1036,6 +985,9 @@ export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "")
|
|
|
1036
985
|
contract: contractWorld.contract,
|
|
1037
986
|
contractDigest: contractWorld.contractDigest,
|
|
1038
987
|
compatibilityDigest: contractWorld.compatibilityDigest,
|
|
988
|
+
compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
|
|
989
|
+
compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
|
|
990
|
+
compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
|
|
1039
991
|
majorLine: contractWorld.majorLine,
|
|
1040
992
|
surfaceCount: Array.isArray(contractWorld.surfaces) ? contractWorld.surfaces.length : 0,
|
|
1041
993
|
};
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { adopterDeliveryGateDigest } from "./adopter-delivery-gate.js";
|
|
2
|
+
import { validateAdopterDeliveryGateResult } from "./adopter-delivery-passport.js";
|
|
3
|
+
|
|
4
|
+
export const BUILDCHAIN_DELIVERY_BOOTSTRAP_CONTRACT =
|
|
5
|
+
"kungfu-buildchain-delivery-infrastructure-bootstrap/v1";
|
|
6
|
+
|
|
7
|
+
const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
8
|
+
const SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
9
|
+
const SEMVER_PATTERN =
|
|
10
|
+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
11
|
+
|
|
12
|
+
function issue(code, message) {
|
|
13
|
+
return { code, message };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function exactRoot(value) {
|
|
17
|
+
return ROOT_PATTERN.test(value ?? "");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function exactCut(cut) {
|
|
21
|
+
return (
|
|
22
|
+
cut &&
|
|
23
|
+
typeof cut === "object" &&
|
|
24
|
+
typeof cut.version === "string" &&
|
|
25
|
+
SHA_PATTERN.test(cut.sourceCommit ?? "") &&
|
|
26
|
+
exactRoot(cut.packageRoot) &&
|
|
27
|
+
exactRoot(cut.gateRoot) &&
|
|
28
|
+
typeof cut.protocol?.id === "string" &&
|
|
29
|
+
typeof cut.protocol?.version === "string" &&
|
|
30
|
+
exactRoot(cut.protocol?.root) &&
|
|
31
|
+
typeof cut.profile?.id === "string" &&
|
|
32
|
+
typeof cut.profile?.version === "string" &&
|
|
33
|
+
exactRoot(cut.profile?.root)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function parseSemver(value) {
|
|
38
|
+
const match = SEMVER_PATTERN.exec(value ?? "");
|
|
39
|
+
if (!match) return null;
|
|
40
|
+
return {
|
|
41
|
+
core: match.slice(1, 4).map(Number),
|
|
42
|
+
prerelease: match[4] ? match[4].split(".") : [],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function compareIdentifier(left, right) {
|
|
47
|
+
const leftNumber = /^\d+$/.test(left) ? Number(left) : null;
|
|
48
|
+
const rightNumber = /^\d+$/.test(right) ? Number(right) : null;
|
|
49
|
+
if (leftNumber !== null && rightNumber !== null) {
|
|
50
|
+
return Math.sign(leftNumber - rightNumber);
|
|
51
|
+
}
|
|
52
|
+
if (leftNumber !== null) return -1;
|
|
53
|
+
if (rightNumber !== null) return 1;
|
|
54
|
+
return left === right ? 0 : left < right ? -1 : 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function compareSemver(leftValue, rightValue) {
|
|
58
|
+
const left = parseSemver(leftValue);
|
|
59
|
+
const right = parseSemver(rightValue);
|
|
60
|
+
if (!left || !right) return null;
|
|
61
|
+
for (let index = 0; index < left.core.length; index += 1) {
|
|
62
|
+
if (left.core[index] !== right.core[index]) {
|
|
63
|
+
return Math.sign(left.core[index] - right.core[index]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (left.prerelease.length === 0 || right.prerelease.length === 0) {
|
|
67
|
+
if (left.prerelease.length === right.prerelease.length) return 0;
|
|
68
|
+
return left.prerelease.length === 0 ? 1 : -1;
|
|
69
|
+
}
|
|
70
|
+
const width = Math.max(left.prerelease.length, right.prerelease.length);
|
|
71
|
+
for (let index = 0; index < width; index += 1) {
|
|
72
|
+
if (left.prerelease[index] === undefined) return -1;
|
|
73
|
+
if (right.prerelease[index] === undefined) return 1;
|
|
74
|
+
const comparison = compareIdentifier(
|
|
75
|
+
left.prerelease[index],
|
|
76
|
+
right.prerelease[index],
|
|
77
|
+
);
|
|
78
|
+
if (comparison !== 0) return comparison;
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function sameProtocol(left, right) {
|
|
84
|
+
return (
|
|
85
|
+
left?.id === right?.id &&
|
|
86
|
+
left?.version === right?.version &&
|
|
87
|
+
left?.root === right?.root
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function validTransition(transition, authority, candidate) {
|
|
92
|
+
if (!transition || typeof transition !== "object") return false;
|
|
93
|
+
const body = structuredClone(transition);
|
|
94
|
+
const transitionRoot = body.transitionRoot;
|
|
95
|
+
delete body.transitionRoot;
|
|
96
|
+
return (
|
|
97
|
+
exactRoot(transitionRoot) &&
|
|
98
|
+
adopterDeliveryGateDigest(body) === transitionRoot &&
|
|
99
|
+
body.fromGateRoot === authority.gateRoot &&
|
|
100
|
+
body.toGateRoot === candidate.gateRoot &&
|
|
101
|
+
body.fromProtocolRoot === authority.protocol.root &&
|
|
102
|
+
body.toProtocolRoot === candidate.protocol.root &&
|
|
103
|
+
body.fromProfileRoot === authority.profile.root &&
|
|
104
|
+
body.toProfileRoot === candidate.profile.root &&
|
|
105
|
+
exactRoot(body.compatibilityProofRoot) &&
|
|
106
|
+
exactRoot(body.independentReviewRoot)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateWarrant(warrant, candidate) {
|
|
111
|
+
return (
|
|
112
|
+
warrant &&
|
|
113
|
+
typeof warrant === "object" &&
|
|
114
|
+
warrant.outcome === "merged" &&
|
|
115
|
+
warrant.sourceHead === candidate.sourceCommit &&
|
|
116
|
+
exactRoot(warrant.sourceProofRoot) &&
|
|
117
|
+
exactRoot(warrant.nativeProofRoot) &&
|
|
118
|
+
exactRoot(warrant.integrationProofRoot)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function qualifyBuildchainDeliveryInfrastructureBootstrap({
|
|
123
|
+
authority,
|
|
124
|
+
candidate,
|
|
125
|
+
gateResult,
|
|
126
|
+
warrant,
|
|
127
|
+
transitionEvidence,
|
|
128
|
+
} = {}) {
|
|
129
|
+
const issues = [];
|
|
130
|
+
if (!exactCut(authority)) {
|
|
131
|
+
issues.push(
|
|
132
|
+
issue("bootstrap.authority.cut", "N-1 authority cut is incomplete"),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (!exactCut(candidate)) {
|
|
136
|
+
issues.push(
|
|
137
|
+
issue("bootstrap.candidate.cut", "candidate cut is incomplete"),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
if (authority?.protected !== true || authority?.published !== true) {
|
|
141
|
+
issues.push(
|
|
142
|
+
issue(
|
|
143
|
+
"bootstrap.authority.release",
|
|
144
|
+
"N-1 authority must be both protected and publicly released",
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
if (candidate?.authorityVersion !== authority?.version) {
|
|
149
|
+
issues.push(
|
|
150
|
+
issue(
|
|
151
|
+
"bootstrap.authority.stale",
|
|
152
|
+
"candidate must name the exact N-1 authority version",
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const versionOrder = compareSemver(authority?.version, candidate?.version);
|
|
157
|
+
if (versionOrder === null || versionOrder >= 0) {
|
|
158
|
+
issues.push(
|
|
159
|
+
issue(
|
|
160
|
+
"bootstrap.authority.order",
|
|
161
|
+
"N-1 authority version must precede the candidate version",
|
|
162
|
+
),
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
if (
|
|
166
|
+
authority?.sourceCommit === candidate?.sourceCommit ||
|
|
167
|
+
authority?.packageRoot === candidate?.packageRoot
|
|
168
|
+
) {
|
|
169
|
+
issues.push(
|
|
170
|
+
issue(
|
|
171
|
+
"bootstrap.self-authorization",
|
|
172
|
+
"candidate source or package cannot serve as its own N-1 authority",
|
|
173
|
+
),
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const gateValidation = validateAdopterDeliveryGateResult(gateResult);
|
|
178
|
+
if (!gateValidation.passed) {
|
|
179
|
+
issues.push(
|
|
180
|
+
issue(
|
|
181
|
+
"bootstrap.gate.failed",
|
|
182
|
+
"candidate must retain a passed public adopter delivery gate result",
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (
|
|
187
|
+
gateResult?.artifact?.root !== candidate?.packageRoot ||
|
|
188
|
+
gateResult?.project?.adopterId !== "kungfu-systems/buildchain"
|
|
189
|
+
) {
|
|
190
|
+
issues.push(
|
|
191
|
+
issue(
|
|
192
|
+
"bootstrap.gate.candidate",
|
|
193
|
+
"gate result must bind the exact Buildchain candidate package",
|
|
194
|
+
),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
if (!validateWarrant(warrant, candidate)) {
|
|
198
|
+
issues.push(
|
|
199
|
+
issue(
|
|
200
|
+
"bootstrap.warrant",
|
|
201
|
+
"merged Delivery Warrant evidence must bind the candidate source",
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const transitionRequired =
|
|
207
|
+
!sameProtocol(authority?.protocol, candidate?.protocol) ||
|
|
208
|
+
!sameProtocol(authority?.profile, candidate?.profile) ||
|
|
209
|
+
authority?.gateRoot !== candidate?.gateRoot;
|
|
210
|
+
if (
|
|
211
|
+
transitionRequired &&
|
|
212
|
+
!validTransition(transitionEvidence, authority, candidate)
|
|
213
|
+
) {
|
|
214
|
+
issues.push(
|
|
215
|
+
issue(
|
|
216
|
+
"bootstrap.transition",
|
|
217
|
+
"gate, protocol, or profile changes require exact independent transition evidence",
|
|
218
|
+
),
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const result = {
|
|
223
|
+
schemaVersion: 1,
|
|
224
|
+
contract: BUILDCHAIN_DELIVERY_BOOTSTRAP_CONTRACT,
|
|
225
|
+
status: issues.length === 0 ? "passed" : "failed",
|
|
226
|
+
authority: structuredClone(authority ?? null),
|
|
227
|
+
candidate: structuredClone(candidate ?? null),
|
|
228
|
+
gateResultRoot: gateResult?.gateRoot ?? null,
|
|
229
|
+
warrant: structuredClone(warrant ?? null),
|
|
230
|
+
transitionRequired,
|
|
231
|
+
transitionEvidenceRoot: transitionEvidence?.transitionRoot ?? null,
|
|
232
|
+
issues,
|
|
233
|
+
qualifying: false,
|
|
234
|
+
selfCertified: false,
|
|
235
|
+
releaseAuthorized: false,
|
|
236
|
+
finalAuthority: "protected-n-minus-one-plus-exact-delivery-evidence",
|
|
237
|
+
};
|
|
238
|
+
result.bootstrapRoot = adopterDeliveryGateDigest(result);
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { semanticRoot } from "@kungfu-tech/kfd/scripts/self-conformance-contract.mjs";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
resolvePublishedKfdAdopterCategoryProfiles,
|
|
5
|
+
verifyPublishedKfdAdopterCategoryInstance,
|
|
6
|
+
} from "./kfd-adopter-category-driver.js";
|
|
7
|
+
|
|
8
|
+
export const BUILDCHAIN_DELIVERY_INFRASTRUCTURE_ADOPTER_ID =
|
|
9
|
+
"kungfu-systems/buildchain";
|
|
10
|
+
export const BUILDCHAIN_DELIVERY_INFRASTRUCTURE_PROFILE = Object.freeze({
|
|
11
|
+
id: "kfd.adopter-category/delivery-infrastructure",
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const CATEGORY_INSTANCE_SCHEMA =
|
|
16
|
+
"https://kfd.libkungfu.dev/schemas/kfd-adopter-conformance/category-instance-manifest.schema.json";
|
|
17
|
+
const CATEGORY_INSTANCE_CONTRACT = "kfd.adopter-category-instance-manifest/v1";
|
|
18
|
+
const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
19
|
+
const CLAIM_BOUNDARY = Object.freeze({
|
|
20
|
+
categoryConformanceIsDeclarationOnly: true,
|
|
21
|
+
evidenceTransfer: false,
|
|
22
|
+
runtimePermission: false,
|
|
23
|
+
releaseAuthorization: false,
|
|
24
|
+
independentCertification: false,
|
|
25
|
+
semanticAuthorityTransfer: false,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function exactEvidenceReference(value, index) {
|
|
29
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
30
|
+
throw new TypeError(`evidence[${index}] must be an object`);
|
|
31
|
+
}
|
|
32
|
+
const fields = ["requirementId", "kind", "coordinate", "root", "observedAt"];
|
|
33
|
+
const actual = Object.keys(value).sort();
|
|
34
|
+
const expected = [...fields].sort();
|
|
35
|
+
if (
|
|
36
|
+
actual.length !== expected.length ||
|
|
37
|
+
actual.some((field, fieldIndex) => field !== expected[fieldIndex])
|
|
38
|
+
) {
|
|
39
|
+
throw new TypeError(`evidence[${index}] has an invalid field set`);
|
|
40
|
+
}
|
|
41
|
+
for (const field of ["requirementId", "kind", "coordinate", "observedAt"]) {
|
|
42
|
+
if (typeof value[field] !== "string" || value[field].length === 0) {
|
|
43
|
+
throw new TypeError(`evidence[${index}].${field} must be non-empty`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!ROOT_PATTERN.test(value.root ?? "")) {
|
|
47
|
+
throw new TypeError(`evidence[${index}].root must be a sha256 root`);
|
|
48
|
+
}
|
|
49
|
+
return structuredClone(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function releaseBound(adopterManifest, artifact, release) {
|
|
53
|
+
return (adopterManifest?.releaseBindings ?? []).some(
|
|
54
|
+
(binding) =>
|
|
55
|
+
semanticRoot(binding.artifact) === semanticRoot(artifact) &&
|
|
56
|
+
semanticRoot(binding.releasePassport) === semanticRoot(release) &&
|
|
57
|
+
binding.kfdPackageRoot === adopterManifest.kfdCut.package.artifactRoot,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createBuildchainDeliveryInfrastructureInstanceManifest({
|
|
62
|
+
instanceId,
|
|
63
|
+
adopterManifest,
|
|
64
|
+
source,
|
|
65
|
+
artifact,
|
|
66
|
+
release,
|
|
67
|
+
evidence = [],
|
|
68
|
+
} = {}) {
|
|
69
|
+
if (typeof instanceId !== "string" || instanceId.length === 0) {
|
|
70
|
+
throw new TypeError("instanceId must be non-empty");
|
|
71
|
+
}
|
|
72
|
+
if (
|
|
73
|
+
adopterManifest?.adopter?.id !==
|
|
74
|
+
BUILDCHAIN_DELIVERY_INFRASTRUCTURE_ADOPTER_ID
|
|
75
|
+
) {
|
|
76
|
+
throw new TypeError(
|
|
77
|
+
`adopterManifest must identify ${BUILDCHAIN_DELIVERY_INFRASTRUCTURE_ADOPTER_ID}`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (!releaseBound(adopterManifest, artifact, release)) {
|
|
81
|
+
throw new TypeError(
|
|
82
|
+
"adopterManifest must bind the exact Buildchain artifact and release",
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const selection = {
|
|
87
|
+
schemaVersion: 1,
|
|
88
|
+
contract: "kfd.adopter-category-profile-selection/v1",
|
|
89
|
+
profiles: [structuredClone(BUILDCHAIN_DELIVERY_INFRASTRUCTURE_PROFILE)],
|
|
90
|
+
};
|
|
91
|
+
const resolution = resolvePublishedKfdAdopterCategoryProfiles(selection);
|
|
92
|
+
if (!resolution.valid) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`published delivery-infrastructure profile did not resolve: ${JSON.stringify(resolution.issues)}`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const project = {
|
|
99
|
+
adopterId: BUILDCHAIN_DELIVERY_INFRASTRUCTURE_ADOPTER_ID,
|
|
100
|
+
source: structuredClone(source),
|
|
101
|
+
artifact: structuredClone(artifact),
|
|
102
|
+
release: structuredClone(release),
|
|
103
|
+
};
|
|
104
|
+
const projectRoot = semanticRoot(project);
|
|
105
|
+
const adopterManifestRoot = semanticRoot(adopterManifest);
|
|
106
|
+
const packageRoot = adopterManifest.kfdCut.package.artifactRoot;
|
|
107
|
+
const requirementIds = new Set(
|
|
108
|
+
resolution.requirements.map((requirement) => requirement.id),
|
|
109
|
+
);
|
|
110
|
+
const suppliedEvidence = evidence.map(exactEvidenceReference);
|
|
111
|
+
for (const [index, entry] of suppliedEvidence.entries()) {
|
|
112
|
+
if (!requirementIds.has(entry.requirementId)) {
|
|
113
|
+
throw new TypeError(
|
|
114
|
+
`evidence[${index}].requirementId is not selected by the published profile`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
$schema: CATEGORY_INSTANCE_SCHEMA,
|
|
121
|
+
schemaVersion: 1,
|
|
122
|
+
contract: CATEGORY_INSTANCE_CONTRACT,
|
|
123
|
+
instanceId,
|
|
124
|
+
rootAlgorithm: "sha256-kfd-canonical-json-v1",
|
|
125
|
+
project,
|
|
126
|
+
adopterManifest: {
|
|
127
|
+
contract: adopterManifest.contract,
|
|
128
|
+
manifestId: adopterManifest.manifestId,
|
|
129
|
+
root: adopterManifestRoot,
|
|
130
|
+
},
|
|
131
|
+
kfdCut: {
|
|
132
|
+
packageVersion: adopterManifest.kfdCut.package.version,
|
|
133
|
+
packageRoot,
|
|
134
|
+
categoryCatalogRoot: resolution.catalogRoot,
|
|
135
|
+
},
|
|
136
|
+
selection,
|
|
137
|
+
selectionRoot: resolution.selectionRoot,
|
|
138
|
+
requirements: resolution.requirements.map((requirement) => ({
|
|
139
|
+
id: requirement.id,
|
|
140
|
+
evidence: suppliedEvidence
|
|
141
|
+
.filter((entry) => entry.requirementId === requirement.id)
|
|
142
|
+
.map(({ requirementId: _requirementId, ...entry }) => ({
|
|
143
|
+
...entry,
|
|
144
|
+
projectInstanceId: instanceId,
|
|
145
|
+
projectRoot,
|
|
146
|
+
adopterManifestRoot,
|
|
147
|
+
kfdPackageRoot: packageRoot,
|
|
148
|
+
categorySelectionRoot: resolution.selectionRoot,
|
|
149
|
+
})),
|
|
150
|
+
})),
|
|
151
|
+
claimBoundary: structuredClone(CLAIM_BOUNDARY),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function verifyBuildchainDeliveryInfrastructureInstance(
|
|
156
|
+
manifest,
|
|
157
|
+
{ adopterManifest, verifiedAt, maxAgeSeconds } = {},
|
|
158
|
+
) {
|
|
159
|
+
return verifyPublishedKfdAdopterCategoryInstance(manifest, {
|
|
160
|
+
adopterManifest,
|
|
161
|
+
verifiedAt,
|
|
162
|
+
maxAgeSeconds,
|
|
163
|
+
});
|
|
164
|
+
}
|