@kungfu-tech/buildchain 4.0.2-alpha.9 → 4.0.3-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +14 -5
- package/CONTRIBUTING.md +58 -0
- package/README.md +3 -3
- package/actions/promote-buildchain-ref/README.md +1 -1
- package/actions/release-candidate-promote/README.md +31 -0
- package/architecture/agent-change-map.md +190 -126
- package/architecture/{v4-architecture-constitution.md → architecture-constitution.md} +33 -30
- package/architecture/{v3-core-mechanism-inventory.md → baseline-core-mechanism-inventory.md} +1 -1
- package/architecture/{v4-bootstrap-authority.json → bootstrap-authority.json} +3 -3
- package/architecture/{v3-v4-capability-closure.md → capability-parity-closure.md} +3 -3
- package/architecture/{v3-v4-live-capability-inventory.json → capability-parity-live-capability-inventory.json} +4 -4
- package/architecture/{v4-capability-state-machine-manifest.json → capability-state-machine-manifest.json} +2 -2
- package/architecture/{v4-capability-state-machine-manifest.schema.json → capability-state-machine-manifest.schema.json} +2 -2
- package/architecture/ci-lane-change-budget.json +384 -0
- package/architecture/{v4-cross-platform-adopter-qualification.json → cross-platform-adopter-qualification.json} +4 -4
- package/architecture/{v4-delivery-authority-parity.json → delivery-authority-parity.json} +17 -17
- package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.json → delivery-warrant-shadow-bootstrap-plan.json} +4 -4
- package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.md → delivery-warrant-shadow-bootstrap-plan.md} +7 -7
- package/architecture/{v4-floating-consumer-policy.json → floating-consumer-policy.json} +2 -2
- package/architecture/{v4-floating-consumer-policy.md → floating-consumer-policy.md} +1 -1
- package/architecture/implementation-naming.json +1273 -0
- package/architecture/internal-capabilities.json +201 -154
- package/architecture/maintainability-debt.json +205 -146
- package/architecture/maintainability-policy.json +37 -33
- package/architecture/{v4-next-development-parity.json → next-development-parity.json} +12 -12
- package/architecture/{v4-partial-mutation-recovery-qualification.json → partial-mutation-recovery-qualification.json} +8 -5
- package/architecture/{v4-platform-stage-checkpoints.json → platform-stage-checkpoints.json} +3 -3
- package/architecture/{v4-provider-operation-journal-contract.json → provider-operation-journal-contract.json} +10 -7
- package/architecture/publication-facade-patches.json +64 -0
- package/architecture/{v4-publication-rehearsal-parity.json → publication-rehearsal-parity.json} +4 -4
- package/architecture/{v4-release-activation-shadow-domain.json → release-activation-shadow-domain.json} +9 -6
- package/architecture/release-tail-contract-inventory.json +6 -6
- package/architecture/{v4-release-topology.json → release-topology.json} +163 -72
- package/architecture/{v4-release-train-parity.json → release-train-parity.json} +2 -2
- package/architecture/{v4-runtime-ref-resume-authority.json → runtime-ref-resume-authority.json} +1 -1
- package/architecture/{v4-runtime-semantic-closure.json → runtime-semantic-closure.json} +2 -2
- package/architecture/{v4-rust-libnode-bridge-evaluation.json → rust-libnode-bridge-evaluation.json} +3 -3
- package/architecture/{v4-rust-libnode-bridge-spike.md → rust-libnode-bridge-spike.md} +6 -6
- package/architecture/rust-wasm-production-authority.json +58 -0
- package/architecture/{v4-stable-publication-fence.json → stable-publication-fence.json} +7 -4
- package/architecture/{v4-stage-capsule-contract.json → stage-capsule-contract.json} +1 -1
- package/architecture/{v4-stage-capsule-qualification.json → stage-capsule-qualification.json} +8 -8
- package/architecture/{v4-stage-capsule-resume-planner.json → stage-capsule-resume-planner.json} +2 -2
- package/architecture/{v4-stage-capsule-store-contract.json → stage-capsule-store-contract.json} +4 -4
- package/architecture/{v4-tail-reseal-parity.json → tail-reseal-parity.json} +35 -33
- package/architecture/universal-workflow-bootstrap.json +176 -0
- package/architecture/universal-workflow-fault-campaign.json +72 -0
- package/architecture/universal-workflow-train-admission.json +40 -0
- package/architecture/workflow-taxonomy.json +1462 -0
- package/bin/buildchain.mjs +10 -10
- package/bin/internal/adopter-delivery-cli.mjs +9 -9
- package/contracts/buildchain-v2-residuals-v1.json +57 -48
- package/contracts/dev-delivery-authority-v2.schema.json +16 -2
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
- package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.lock +1 -1
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.toml +1 -1
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/src/main.rs +3 -3
- package/dist/site/buildchain-contract.json +98 -53
- package/dist/site/buildchain-site.json +351 -102
- package/dist/site/capability-registry.json +7 -7
- package/dist/site/controller-registry.json +50 -13
- package/dist/site/kfd-claims.json +2773 -1052
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +14 -14
- package/dist/site/node-api-registry.json +13176 -10733
- package/dist/site/page-registry.json +332 -83
- package/dist/site/public-surface-audit.json +3227 -1222
- package/dist/site/publication-authority-registry.json +1135 -363
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +18 -9
- package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
- package/dist/site/site-manifest.json +18 -18
- package/dist/site/workflow-registry.json +5367 -1931
- package/docs/MAP.md +5 -3
- package/docs/auditable-demo.md +1 -1
- package/docs/cli.md +21 -8
- package/docs/dev-delivery-warrant.md +1 -1
- package/docs/engineering-housekeeper.md +3 -3
- package/docs/kfd-support.md +26 -2
- package/docs/next-development-transition.md +26 -3
- package/docs/node-api-reference.md +618 -358
- package/docs/oci-publication.md +173 -0
- package/docs/publication-authority.md +2 -2
- package/docs/publish-transaction.md +36 -3
- package/docs/release-candidate.md +3 -3
- package/docs/release-flow.md +67 -19
- package/docs/release-governance.md +8 -8
- package/docs/release-passport.md +27 -2
- package/docs/reusable-build-surface.md +17 -1
- package/docs/v4-adopter-delivery.md +4 -4
- package/docs/v4-canonical-contracts.md +7 -7
- package/docs/v4-delivery-warrant-read-candidate.md +3 -3
- package/docs/v4-delivery-warrant-semantic-diff.md +3 -3
- package/docs/v4-production-release.md +77 -8
- package/docs/v4-publication-rehearsal.md +3 -3
- package/docs/v4-runtime-ref-resume-authority.md +2 -2
- package/docs/v4-rust-wasm-production-authority.md +58 -0
- package/docs/v4-stage-capsule.md +9 -9
- package/docs/v4-tail-reseal.md +2 -2
- package/docs/workflow-catalog.md +155 -0
- package/docs/workflow-path-migration.md +109 -0
- package/package.json +39 -24
- package/packages/compatibility/adopter-delivery.js +16 -0
- package/packages/compatibility/cross-platform-adopter-qualification.js +12 -0
- package/packages/compatibility/floating-consumer-policy.js +14 -0
- package/packages/compatibility/publication-qualification.js +11 -0
- package/packages/compatibility/publication-rehearsal.js +18 -0
- package/packages/compatibility/runtime-ref-resume-authority.js +13 -0
- package/packages/compatibility/tail-reseal-receipt.js +7 -0
- package/packages/compatibility/tail-reseal.js +11 -0
- package/packages/core/{v4-adopter-delivery-parity.js → adopter-delivery-parity.js} +12 -12
- package/packages/core/{v4-adopter-delivery.js → adopter-delivery.js} +24 -24
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/buildchain-contract.js +6 -6
- package/packages/core/buildchain-domain.wasm +0 -0
- package/packages/core/buildchain-kfd-claims.js +2 -2
- package/packages/core/buildchain-publication-authority.js +43 -26
- package/packages/core/{v4-canonical-contracts.js → canonical-contracts.js} +39 -103
- package/packages/core/ci-lane-change-budget.js +14 -1
- package/packages/core/controller-evidence.js +4 -1
- package/packages/core/{v4-cross-platform-adopter-qualification.js → cross-platform-adopter-qualification.js} +19 -19
- package/packages/core/{v4-delivery-warrant-fixture-runner.js → delivery-warrant-fixture-runner.js} +36 -32
- package/packages/core/{v4-delivery-warrant-read-candidate.js → delivery-warrant-read-candidate.js} +40 -40
- package/packages/core/{v4-delivery-warrant-semantic-diff-gate.js → delivery-warrant-semantic-diff-gate.js} +58 -59
- package/packages/core/{v4-delivery-warrant-shadow-adapter.js → delivery-warrant-shadow-adapter.js} +15 -15
- package/packages/core/dev-delivery-candidate-identity.js +40 -6
- package/packages/core/dev-delivery-execution-transfer.js +6 -6
- package/packages/core/dev-delivery-native-proof.js +12 -8
- package/packages/core/dev-delivery-warrant-legacy-recovery.js +1 -1
- package/packages/core/dev-delivery-warrant-native-compatibility.js +4 -4
- package/packages/core/dev-delivery-warrant-state.js +14 -15
- package/packages/core/dev-delivery-warrant.js +15 -5
- package/packages/core/domain-wasm-artifact.js +7 -0
- package/packages/core/domain-wasm.js +216 -0
- package/packages/core/{v4-floating-consumer-evidence.js → floating-consumer-evidence.js} +14 -14
- package/packages/core/{v4-floating-consumer-policy.js → floating-consumer-policy.js} +28 -30
- package/packages/core/{v4-floating-consumer-release-passport.js → floating-consumer-release-passport.js} +25 -25
- package/packages/core/github-governance-authority.js +4 -4
- package/packages/core/index.js +4 -8
- package/packages/core/kfd-adopter-manifest.js +46 -47
- package/packages/core/next-development-projection.js +26 -3
- package/packages/core/next-development-transition.js +5 -6
- package/packages/core/oci-compose-qualification.js +143 -0
- package/packages/core/oci-publication-bundle.js +281 -0
- package/packages/core/oci-publication-graph.js +206 -0
- package/packages/core/paper-agent-entry.js +30 -4
- package/packages/core/paper-fleet.js +1 -1
- package/packages/core/paper-runtime-channels.js +348 -0
- package/packages/core/paper-scaffold-content.js +10 -0
- package/packages/core/paper.js +37 -71
- package/packages/core/partial-mutation-recovery-qualification.js +18 -0
- package/packages/core/{v4-platform-stage-checkpoints.js → platform-stage-checkpoints.js} +37 -37
- package/packages/core/product-publication.js +59 -0
- package/packages/core/{v4-protected-publication-source.js → protected-publication-source.js} +22 -24
- package/packages/core/provider-operation-journal.js +62 -0
- package/packages/core/{v4-provider-readback-idempotency.js → provider-readback-idempotency.js} +40 -125
- package/packages/core/public-export-compatibility.js +33 -0
- package/packages/core/publication-development.js +72 -0
- package/packages/core/{v4-publication-qualification.js → publication-qualification.js} +17 -17
- package/packages/core/{v4-publication-rehearsal-capsule.js → publication-rehearsal-capsule.js} +23 -23
- package/packages/core/publication-rehearsal-projection.js +2 -2
- package/packages/core/{v4-publication-rehearsal-provider-bindings.js → publication-rehearsal-provider-bindings.js} +4 -4
- package/packages/core/publication-rehearsal-runtime.js +21 -21
- package/packages/core/{v4-publication-rehearsal.js → publication-rehearsal.js} +33 -33
- package/packages/core/publication-sealed-bundle.js +78 -13
- package/packages/core/release-activation-shadow.js +32 -0
- package/packages/core/release-candidate.js +6 -6
- package/packages/core/release-invocation.js +64 -0
- package/packages/core/release-line-dry-run.js +1 -1
- package/packages/core/release-passport-contract.js +5 -5
- package/packages/core/release-passport.js +41 -40
- package/packages/core/release-tail-product-capabilities.js +9 -0
- package/packages/core/release-tail-provider-plane.js +68 -1048
- package/packages/core/{v4-runtime-ref-resume-authority.js → runtime-ref-resume-authority.js} +36 -40
- package/packages/core/{v4-runtime-selector-persistence.js → runtime-selector-persistence.js} +7 -7
- package/packages/core/stable-publication-fence.js +28 -0
- package/packages/core/{v4-stage-capsule-local-store.js → stage-capsule-local-store.js} +56 -54
- package/packages/core/{v4-stage-capsule-qualification-campaign.js → stage-capsule-qualification-campaign.js} +37 -38
- package/packages/core/{v4-stage-capsule-qualification.js → stage-capsule-qualification.js} +28 -29
- package/packages/core/{v4-stage-capsule-resume-planner.js → stage-capsule-resume-planner.js} +29 -29
- package/packages/core/{v4-stage-capsule-store.js → stage-capsule-store.js} +59 -56
- package/packages/core/{v4-stage-capsule.js → stage-capsule.js} +45 -45
- package/packages/core/{v4-tail-reseal-contract.js → tail-reseal-contract.js} +6 -6
- package/packages/core/{v4-tail-reseal-github.js → tail-reseal-github.js} +12 -12
- package/packages/core/{v4-tail-reseal-receipt.js → tail-reseal-receipt.js} +22 -22
- package/packages/core/{v4-tail-reseal.js → tail-reseal.js} +29 -29
- package/packages/core/universal-workflow-bootstrap.js +586 -0
- package/scripts/{v4-architecture.mjs → architecture.mjs} +6 -6
- package/scripts/binary-publication-evidence.mjs +135 -0
- package/scripts/{v4-bridge-bootstrap.mjs → bridge-bootstrap.mjs} +14 -18
- package/scripts/{v4-bridge-evidence.mjs → bridge-evidence.mjs} +8 -8
- package/scripts/build-contract-core.mjs +1 -14
- package/scripts/build-domain-wasm.mjs +177 -0
- package/scripts/{v3-v4-capability-catalog.mjs → capability-parity-catalog.mjs} +19 -19
- package/scripts/check-action-bundles.mjs +12 -2
- package/scripts/{check-v3-v4-capability-inventory.mjs → check-capability-parity-inventory.mjs} +42 -42
- package/scripts/check-ci-lane-change-budget.mjs +4 -1
- package/scripts/check-core-mechanism-inventory.mjs +8 -4
- package/scripts/{check-v4-floating-consumer-policy-contract.mjs → check-floating-consumer-policy-contract.mjs} +10 -10
- package/scripts/check-implementation-naming.mjs +135 -0
- package/scripts/check-inventory.mjs +39 -47
- package/scripts/check-maintainability.mjs +25 -115
- package/scripts/{check-v4-public-dogfood-contract.mjs → check-public-dogfood-contract.mjs} +37 -24
- package/scripts/{check-v4-release-topology.mjs → check-release-topology.mjs} +131 -52
- package/scripts/{check-v4-runtime-semantic-closure.mjs → check-runtime-semantic-closure.mjs} +23 -17
- package/scripts/check-universal-workflow-bootstrap.mjs +266 -0
- package/scripts/check-workflow-taxonomy.mjs +6 -0
- package/scripts/{v4-consumer-policy.mjs → consumer-policy.mjs} +15 -15
- package/scripts/copy-domain-wasm.mjs +14 -0
- package/scripts/{v4-cross-platform-adopter-qualification.mjs → cross-platform-adopter-qualification.mjs} +9 -9
- package/scripts/{v4-declarative-promotion-admission.mjs → declarative-promotion-admission.mjs} +4 -4
- package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
- package/scripts/dev-delivery-authority.mjs +8 -8
- package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
- package/scripts/dev-delivery-warrant-options.mjs +15 -10
- package/scripts/dev-delivery-warrant-store.mjs +98 -13
- package/scripts/dev-delivery-warrant-transition.mjs +109 -0
- package/scripts/dev-delivery-warrant.mjs +80 -103
- package/scripts/dev-pr-auto-merge.mjs +15 -15
- package/scripts/dev-pr-delivery-warrant.mjs +1 -1
- package/scripts/generate-channel-build-workflow.mjs +7 -2
- package/scripts/generate-channel-promotion-workflow.mjs +19 -34
- package/scripts/generate-release-candidate-passport.mjs +23 -23
- package/scripts/generate-site-bundle.mjs +28 -28
- package/scripts/generate-universal-workflow-facades.mjs +498 -0
- package/scripts/generate-workflow-taxonomy.mjs +25 -0
- package/scripts/github-output.mjs +31 -0
- package/scripts/{v4-host-adapter.mjs → host-adapter.mjs} +1 -1
- package/scripts/implementation-references.mjs +25 -0
- package/scripts/init-repo.mjs +1 -1
- package/scripts/maintainability-metrics.mjs +16 -5
- package/scripts/maintainability-public-surface.mjs +115 -0
- package/scripts/next-development-review.mjs +313 -0
- package/scripts/oci-compose-preview.mjs +261 -0
- package/scripts/paper-work-fleet-cli.mjs +2 -0
- package/scripts/{v4-platform-stage-checkpoint-rehearsal.mjs → platform-stage-checkpoint-rehearsal.mjs} +17 -17
- package/scripts/{v4-product-publication-intent.mjs → product-publication-intent.mjs} +28 -13
- package/scripts/publication-candidate-kind.mjs +93 -0
- package/scripts/publication-candidate-sealer.mjs +16 -1
- package/scripts/{v4-publication-rehearsal-fixture.mjs → publication-rehearsal-fixture.mjs} +5 -5
- package/scripts/publication-settlement.mjs +211 -0
- package/scripts/release-asset-client.mjs +91 -0
- package/scripts/{v4-release-candidate-adapter.mjs → release-candidate-adapter.mjs} +4 -4
- package/scripts/release-candidate-resolver.mjs +24 -35
- package/scripts/release-tail.mjs +5 -5
- package/scripts/resume-from-candidate-run.mjs +35 -42
- package/scripts/site-capability-metadata.mjs +9 -0
- package/scripts/source-verification-evidence.mjs +344 -0
- package/scripts/stable-candidate-qualification.mjs +1 -1
- package/scripts/{v4-stage-capsule-qualification.mjs → stage-capsule-qualification.mjs} +62 -62
- package/scripts/{v4-stage-capsule-resume-rehearsal.mjs → stage-capsule-resume-rehearsal.mjs} +6 -6
- package/scripts/{v4-tail-reseal-macos-rehearsal.mjs → tail-reseal-macos-rehearsal.mjs} +9 -9
- package/scripts/{v4-tail-reseal.mjs → tail-reseal.mjs} +19 -19
- package/scripts/universal-facade-maintainability.mjs +91 -0
- package/scripts/universal-workflow-backflow.mjs +212 -0
- package/scripts/universal-workflow-engine.mjs +620 -0
- package/scripts/universal-workflow-self-dogfood.mjs +205 -0
- package/scripts/verify-version-state-delta.mjs +175 -0
- package/scripts/{v4-warrant-shadow-plan.mjs → warrant-shadow-plan.mjs} +6 -6
- package/scripts/workflow-taxonomy.mjs +507 -0
- package/templates/native-dev-delivery.yml +4 -7
- package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
- package/templates/universal-buildchain-bootstrap.yml +28 -0
- package/actions/v4-release-candidate-promote/README.md +0 -3
- package/packages/core/v4-partial-mutation-recovery-qualification.js +0 -395
- package/packages/core/v4-product-publication.js +0 -387
- package/packages/core/v4-provider-operation-journal.js +0 -531
- package/packages/core/v4-release-activation-shadow.js +0 -519
- package/packages/core/v4-release-invocation.js +0 -425
- package/packages/core/v4-stable-publication-fence.js +0 -357
- /package/architecture/{v4-adopter-delivery-parity.json → adopter-delivery-parity.json} +0 -0
- /package/architecture/{v3-core-mechanism-inventory.json → baseline-core-mechanism-inventory.json} +0 -0
- /package/architecture/{v4-canonical-contract-fixtures.json → canonical-contract-fixtures.json} +0 -0
- /package/architecture/{v4-compatibility-facts-parity.json → compatibility-facts-parity.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.schema.json → delivery-warrant-shadow-bootstrap-plan.schema.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-fixtures.json → delivery-warrant-shadow-fixtures.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-fixtures.schema.json → delivery-warrant-shadow-fixtures.schema.json} +0 -0
- /package/architecture/{v4-exception-ledger.json → exception-ledger.json} +0 -0
- /package/architecture/{v4-exception-ledger.schema.json → exception-ledger.schema.json} +0 -0
- /package/architecture/{v4-release-invocation-fixtures.json → release-invocation-fixtures.json} +0 -0
|
@@ -2,34 +2,34 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./
|
|
5
|
+
ContractFault,
|
|
6
|
+
domainCanonicalBytes,
|
|
7
|
+
validateClock,
|
|
8
|
+
validateRoot,
|
|
9
|
+
} from "./canonical-contracts.js";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from "./
|
|
11
|
+
STAGE_CAPSULE_CONTRACT,
|
|
12
|
+
STAGE_CAPSULE_IDENTITY_CONTRACT,
|
|
13
|
+
stageCapsuleIdentityRoot,
|
|
14
|
+
stageCapsuleRoot,
|
|
15
|
+
validateStageCapsule,
|
|
16
|
+
} from "./stage-capsule.js";
|
|
17
17
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from "./
|
|
18
|
+
STAGE_CAPSULE_OUTPUT_MANIFEST_CONTRACT,
|
|
19
|
+
stageCapsuleBlobRoot,
|
|
20
|
+
stageCapsuleOutputManifestRoot,
|
|
21
|
+
} from "./stage-capsule-store.js";
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const PLATFORM_STAGE_CHECKPOINT_CONTRACT =
|
|
24
24
|
"buildchain-v4-platform-stage-checkpoint/v1";
|
|
25
|
-
export const
|
|
25
|
+
export const PLATFORM_STAGE_RESTORE_CONTRACT =
|
|
26
26
|
"buildchain-v4-platform-stage-restore/v1";
|
|
27
27
|
|
|
28
28
|
const TOKEN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
29
29
|
const ZERO_ROOT = `sha256:${"0".repeat(64)}`;
|
|
30
30
|
|
|
31
31
|
function fault(code, location, message) {
|
|
32
|
-
throw new
|
|
32
|
+
throw new ContractFault(code, location, message);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function object(value, location) {
|
|
@@ -76,14 +76,14 @@ function tokens(values, location) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
function rootOf(value) {
|
|
79
|
-
return
|
|
79
|
+
return stageCapsuleBlobRoot(domainCanonicalBytes(value));
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
function declaredMap(value, names, location, { roots = false } = {}) {
|
|
83
83
|
exactKeys(value, names, location);
|
|
84
84
|
return names.map((name) => {
|
|
85
85
|
const entry = value[name];
|
|
86
|
-
if (roots)
|
|
86
|
+
if (roots) validateRoot(entry, `${location}/${name}`);
|
|
87
87
|
else if (typeof entry !== "string")
|
|
88
88
|
fault(
|
|
89
89
|
"invalid-stage-checkpoint-value",
|
|
@@ -112,7 +112,7 @@ function safeRelative(relativePath, location) {
|
|
|
112
112
|
return relativePath;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
export function
|
|
115
|
+
export function validatePlatformStageCheckpointDeclaration(value) {
|
|
116
116
|
exactKeys(
|
|
117
117
|
value,
|
|
118
118
|
[
|
|
@@ -250,7 +250,7 @@ export function validateV4PlatformStageCheckpointDeclaration(value) {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
function select(declaration, platformId, stageId) {
|
|
253
|
-
|
|
253
|
+
validatePlatformStageCheckpointDeclaration(declaration);
|
|
254
254
|
const platform = declaration.platforms.find(
|
|
255
255
|
(entry) => entry.id === platformId,
|
|
256
256
|
);
|
|
@@ -273,24 +273,24 @@ function outputManifest(stage, outputs) {
|
|
|
273
273
|
const entries = stage.outputs
|
|
274
274
|
.map(({ name }) => {
|
|
275
275
|
const bytes = Buffer.from(outputs[name]);
|
|
276
|
-
return { name, root:
|
|
276
|
+
return { name, root: stageCapsuleBlobRoot(bytes), size: bytes.length };
|
|
277
277
|
})
|
|
278
278
|
.sort((left, right) => left.name.localeCompare(right.name, "en"));
|
|
279
279
|
const draft = {
|
|
280
|
-
schema:
|
|
280
|
+
schema: STAGE_CAPSULE_OUTPUT_MANIFEST_CONTRACT,
|
|
281
281
|
entries,
|
|
282
282
|
manifestRoot: ZERO_ROOT,
|
|
283
283
|
};
|
|
284
|
-
return { ...draft, manifestRoot:
|
|
284
|
+
return { ...draft, manifestRoot: stageCapsuleOutputManifestRoot(draft) };
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
-
export function
|
|
287
|
+
export function emitPlatformStageCheckpoint(request) {
|
|
288
288
|
const { platform, stage } = select(
|
|
289
289
|
request.declaration,
|
|
290
290
|
request.platformId,
|
|
291
291
|
request.stageId,
|
|
292
292
|
);
|
|
293
|
-
|
|
293
|
+
validateClock(request.recordedAt, "$/request/recordedAt");
|
|
294
294
|
if (request.stageOutcome !== "success")
|
|
295
295
|
return Object.freeze({ emitted: false, reason: "stage-not-successful" });
|
|
296
296
|
if (!Number.isSafeInteger(request.overheadMs) || request.overheadMs < 0)
|
|
@@ -342,7 +342,7 @@ export function emitV4PlatformStageCheckpoint(request) {
|
|
|
342
342
|
shadowLifecycleRoot,
|
|
343
343
|
};
|
|
344
344
|
const identity = {
|
|
345
|
-
schema:
|
|
345
|
+
schema: STAGE_CAPSULE_IDENTITY_CONTRACT,
|
|
346
346
|
sourceRoot: request.inputs["source-tree"],
|
|
347
347
|
platform: platform.id,
|
|
348
348
|
platformRoot: rootOf(platform),
|
|
@@ -360,16 +360,16 @@ export function emitV4PlatformStageCheckpoint(request) {
|
|
|
360
360
|
],
|
|
361
361
|
};
|
|
362
362
|
const capsule = {
|
|
363
|
-
schema:
|
|
363
|
+
schema: STAGE_CAPSULE_CONTRACT,
|
|
364
364
|
writerAuthority: "typescript-v3",
|
|
365
365
|
rustAuthority: "validation-only",
|
|
366
366
|
identity,
|
|
367
|
-
identityRoot:
|
|
367
|
+
identityRoot: stageCapsuleIdentityRoot(identity),
|
|
368
368
|
retentionPromise: request.retentionPromise,
|
|
369
369
|
capsuleRoot: ZERO_ROOT,
|
|
370
370
|
};
|
|
371
|
-
capsule.capsuleRoot =
|
|
372
|
-
|
|
371
|
+
capsule.capsuleRoot = stageCapsuleRoot(capsule);
|
|
372
|
+
validateStageCapsule(capsule);
|
|
373
373
|
const blobs = manifest.entries.map((entry) => ({
|
|
374
374
|
name: entry.name,
|
|
375
375
|
bytes: Buffer.from(request.outputs[entry.name]),
|
|
@@ -381,7 +381,7 @@ export function emitV4PlatformStageCheckpoint(request) {
|
|
|
381
381
|
recordedAt: request.recordedAt,
|
|
382
382
|
});
|
|
383
383
|
const body = {
|
|
384
|
-
schema:
|
|
384
|
+
schema: PLATFORM_STAGE_CHECKPOINT_CONTRACT,
|
|
385
385
|
mode: "shadow-only",
|
|
386
386
|
platform: platform.id,
|
|
387
387
|
stage: stage.id,
|
|
@@ -413,13 +413,13 @@ function ensureEmptyDirectory(targetDirectory) {
|
|
|
413
413
|
return target;
|
|
414
414
|
}
|
|
415
415
|
|
|
416
|
-
export function
|
|
416
|
+
export function restorePlatformStageCheckpoint(request) {
|
|
417
417
|
const { stage } = select(
|
|
418
418
|
request.declaration,
|
|
419
419
|
request.expectedPlatform,
|
|
420
420
|
request.expectedStage,
|
|
421
421
|
);
|
|
422
|
-
|
|
422
|
+
validateClock(request.recordedAt, "$/request/recordedAt");
|
|
423
423
|
const restored = request.store.restore({
|
|
424
424
|
capsuleRoot: request.capsuleRoot,
|
|
425
425
|
recordedAt: request.recordedAt,
|
|
@@ -449,7 +449,7 @@ export function restoreV4PlatformStageCheckpoint(request) {
|
|
|
449
449
|
);
|
|
450
450
|
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
451
451
|
fs.writeFileSync(destination, blob.bytes, { flag: "wx" });
|
|
452
|
-
if (
|
|
452
|
+
if (stageCapsuleBlobRoot(fs.readFileSync(destination)) !== blob.root)
|
|
453
453
|
fault(
|
|
454
454
|
"stage-capsule-root-mismatch",
|
|
455
455
|
`$/restore/${output.name}`,
|
|
@@ -457,7 +457,7 @@ export function restoreV4PlatformStageCheckpoint(request) {
|
|
|
457
457
|
);
|
|
458
458
|
}
|
|
459
459
|
const body = {
|
|
460
|
-
schema:
|
|
460
|
+
schema: PLATFORM_STAGE_RESTORE_CONTRACT,
|
|
461
461
|
platform: request.expectedPlatform,
|
|
462
462
|
stage: request.expectedStage,
|
|
463
463
|
capsuleRoot: request.capsuleRoot,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { invokeDomainWasm } from "./domain-wasm.js";
|
|
2
|
+
|
|
3
|
+
export const PRODUCT_PUBLICATION_INTENT_CONTRACT =
|
|
4
|
+
"kungfu-buildchain-v4-product-publication-intent/v1";
|
|
5
|
+
export const PRODUCT_PUBLICATION_PLAN_CONTRACT =
|
|
6
|
+
"kungfu-buildchain-v4-product-publication-plan/v1";
|
|
7
|
+
|
|
8
|
+
export function selectProductPublicationIntent({
|
|
9
|
+
channel,
|
|
10
|
+
targetRef,
|
|
11
|
+
sourceSha,
|
|
12
|
+
sourceTimestamp,
|
|
13
|
+
repository,
|
|
14
|
+
artifactKind = "npm",
|
|
15
|
+
packageName,
|
|
16
|
+
npmPackages,
|
|
17
|
+
distTag,
|
|
18
|
+
sealedBundleRoot,
|
|
19
|
+
requiredArtifactsRoot,
|
|
20
|
+
candidateVersion,
|
|
21
|
+
recoveredVersion = "",
|
|
22
|
+
observedVersions = [],
|
|
23
|
+
}) {
|
|
24
|
+
return invokeDomainWasm("product-publication-intent", {
|
|
25
|
+
channel,
|
|
26
|
+
targetRef,
|
|
27
|
+
sourceSha,
|
|
28
|
+
sourceTimestamp,
|
|
29
|
+
repository,
|
|
30
|
+
artifactKind,
|
|
31
|
+
...(npmPackages === undefined ? {} : { npmPackages }),
|
|
32
|
+
...(packageName === undefined ? {} : { packageName }),
|
|
33
|
+
...(distTag === undefined ? {} : { distTag }),
|
|
34
|
+
...(sealedBundleRoot === undefined ? {} : { sealedBundleRoot }),
|
|
35
|
+
requiredArtifactsRoot,
|
|
36
|
+
candidateVersion,
|
|
37
|
+
recoveredVersion,
|
|
38
|
+
observedVersions,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function createProductPublicationPlan({
|
|
43
|
+
intent,
|
|
44
|
+
invocationRoot,
|
|
45
|
+
transactionRoot,
|
|
46
|
+
}) {
|
|
47
|
+
return invokeDomainWasm("product-publication-plan", {
|
|
48
|
+
intent,
|
|
49
|
+
invocationRoot,
|
|
50
|
+
transactionRoot,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function createProductPublicationDeclaration({ intent, plan }) {
|
|
55
|
+
return invokeDomainWasm("product-publication-declaration", {
|
|
56
|
+
intent,
|
|
57
|
+
plan,
|
|
58
|
+
});
|
|
59
|
+
}
|
package/packages/core/{v4-protected-publication-source.js → protected-publication-source.js}
RENAMED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { domainContentRoot } from "./canonical-contracts.js";
|
|
2
2
|
|
|
3
3
|
const SHA_PATTERN = /^[0-9a-f]{40}$/u;
|
|
4
4
|
|
|
5
5
|
function exactSha(value, label) {
|
|
6
6
|
const normalized = String(value || "").toLowerCase();
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
return normalized;
|
|
7
|
+
if (SHA_PATTERN.test(normalized)) return normalized;
|
|
8
|
+
throw new Error(`${label} must be an exact Git SHA`);
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
function exactParents(value, label) {
|
|
@@ -17,7 +15,7 @@ function exactParents(value, label) {
|
|
|
17
15
|
return value.map((entry, index) => exactSha(entry, `${label}[${index}]`));
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
export function
|
|
18
|
+
export function bindProtectedPublicationSource({
|
|
21
19
|
repository,
|
|
22
20
|
protectedCommit,
|
|
23
21
|
candidateCommit,
|
|
@@ -26,16 +24,14 @@ export function bindV4ProtectedPublicationSource({
|
|
|
26
24
|
if (!/^[^/\s]+\/[^/\s]+$/u.test(String(repository || ""))) {
|
|
27
25
|
throw new Error("protected publication source requires owner/repository");
|
|
28
26
|
}
|
|
29
|
-
const protectedSource =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
parents: exactParents(candidateCommit?.parents, "candidate source parents"),
|
|
38
|
-
};
|
|
27
|
+
const [protectedSource, candidateSource] = [
|
|
28
|
+
["protected", protectedCommit],
|
|
29
|
+
["candidate", candidateCommit],
|
|
30
|
+
].map(([kind, commit]) => ({
|
|
31
|
+
sha: exactSha(commit?.sha, `${kind} source SHA`),
|
|
32
|
+
tree: exactSha(commit?.tree, `${kind} source tree`),
|
|
33
|
+
parents: exactParents(commit?.parents, `${kind} source parents`),
|
|
34
|
+
}));
|
|
39
35
|
if (protectedSource.tree !== candidateSource.tree) {
|
|
40
36
|
throw new Error(
|
|
41
37
|
"protected publication source tree does not match the qualified candidate tree",
|
|
@@ -45,13 +41,13 @@ export function bindV4ProtectedPublicationSource({
|
|
|
45
41
|
let mode = "exact-commit";
|
|
46
42
|
let pullRequestNumber = null;
|
|
47
43
|
if (protectedSource.sha !== candidateSource.sha) {
|
|
48
|
-
mode = "merge-equivalent";
|
|
49
44
|
const sameParents =
|
|
50
|
-
protectedSource.parents.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
protectedSource.parents.join(",") === candidateSource.parents.join(",");
|
|
46
|
+
const squashParents =
|
|
47
|
+
protectedSource.parents.length === 1 &&
|
|
48
|
+
candidateSource.parents.length === 2 &&
|
|
49
|
+
protectedSource.parents[0] === candidateSource.parents[0];
|
|
50
|
+
if (!sameParents && !squashParents) {
|
|
55
51
|
throw new Error(
|
|
56
52
|
"protected publication source is not parent-equivalent to the qualified merge candidate",
|
|
57
53
|
);
|
|
@@ -70,12 +66,14 @@ export function bindV4ProtectedPublicationSource({
|
|
|
70
66
|
pullRequestNumber <= 0 ||
|
|
71
67
|
pullRequest?.merged !== true ||
|
|
72
68
|
pullRequestMerge !== protectedSource.sha ||
|
|
73
|
-
!candidateSource.parents.includes(pullRequestHead)
|
|
69
|
+
!candidateSource.parents.includes(pullRequestHead) ||
|
|
70
|
+
(squashParents && candidateSource.parents[1] !== pullRequestHead)
|
|
74
71
|
) {
|
|
75
72
|
throw new Error(
|
|
76
73
|
"protected publication source does not match the merged pull request and qualified merge candidate",
|
|
77
74
|
);
|
|
78
75
|
}
|
|
76
|
+
mode = sameParents ? "merge-equivalent" : "squash-equivalent";
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
const binding = {
|
|
@@ -88,6 +86,6 @@ export function bindV4ProtectedPublicationSource({
|
|
|
88
86
|
};
|
|
89
87
|
return {
|
|
90
88
|
...binding,
|
|
91
|
-
bindingRoot:
|
|
89
|
+
bindingRoot: domainContentRoot("candidate-identity", binding),
|
|
92
90
|
};
|
|
93
91
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ContractFault } from "./canonical-contracts.js";
|
|
2
|
+
import { DomainWasmFault, invokeDomainWasm } from "./domain-wasm.js";
|
|
3
|
+
|
|
4
|
+
export const PROVIDER_OPERATION_IDENTITY_CONTRACT =
|
|
5
|
+
"buildchain-v4-provider-operation-identity/v1";
|
|
6
|
+
export const PROVIDER_OPERATION_INTENT_CONTRACT =
|
|
7
|
+
"buildchain-v4-provider-operation-intent/v1";
|
|
8
|
+
export const PROVIDER_OPERATION_ATTEMPT_CONTRACT =
|
|
9
|
+
"buildchain-v4-provider-operation-attempt/v1";
|
|
10
|
+
export const PROVIDER_OPERATION_OBSERVATION_CONTRACT =
|
|
11
|
+
"buildchain-v4-provider-operation-observation/v1";
|
|
12
|
+
export const PROVIDER_OPERATION_CONFIRMATION_CONTRACT =
|
|
13
|
+
"buildchain-v4-provider-operation-confirmation/v1";
|
|
14
|
+
export const PROVIDER_OPERATION_RECONCILIATION_CONTRACT =
|
|
15
|
+
"buildchain-v4-provider-operation-reconciliation/v1";
|
|
16
|
+
export const PROVIDER_OPERATION_JOURNAL_STATE_CONTRACT =
|
|
17
|
+
"buildchain-v4-provider-operation-journal-state/v1";
|
|
18
|
+
|
|
19
|
+
function invoke(operation, payload) {
|
|
20
|
+
try {
|
|
21
|
+
return invokeDomainWasm(operation, payload);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof DomainWasmFault) {
|
|
24
|
+
throw new ContractFault(error.code, error.path, error.message);
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function validateProviderOperationIdentity(value) {
|
|
31
|
+
invoke("provider-operation-identity-validate", value);
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function providerOperationRoot(identity) {
|
|
36
|
+
return invoke("provider-operation-identity-root", identity).root;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function providerOperationEntryRoot(entry) {
|
|
40
|
+
return invoke("provider-operation-entry-root", entry).root;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function validateProviderOperationEntry(entry) {
|
|
44
|
+
invoke("provider-operation-entry-validate", entry);
|
|
45
|
+
return entry;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function foldProviderOperationJournal(entries) {
|
|
49
|
+
return invoke("provider-operation-journal", entries).state;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function providerOperationJournalRoot(entries) {
|
|
53
|
+
return invoke("provider-operation-journal", entries).journalRoot;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function providerOperationJournalStateRoot(entries) {
|
|
57
|
+
return invoke("provider-operation-journal", entries).stateRoot;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function projectProviderOperationFixtures(fixtures) {
|
|
61
|
+
return invoke("provider-operation-fixtures", fixtures);
|
|
62
|
+
}
|
package/packages/core/{v4-provider-readback-idempotency.js → provider-readback-idempotency.js}
RENAMED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "./
|
|
7
|
-
import {
|
|
8
|
-
V4_PROVIDER_OPERATION_OBSERVATION_CONTRACT,
|
|
9
|
-
v4ProviderOperationJournalStateRoot,
|
|
10
|
-
v4ProviderOperationEntryRoot,
|
|
11
|
-
validateV4ProviderOperationEntry,
|
|
12
|
-
} from "./v4-provider-operation-journal.js";
|
|
2
|
+
ContractFault,
|
|
3
|
+
domainContentRoot,
|
|
4
|
+
validateRoot,
|
|
5
|
+
} from "./canonical-contracts.js";
|
|
6
|
+
import { providerOperationJournalStateRoot } from "./provider-operation-journal.js";
|
|
7
|
+
import { DomainWasmFault, invokeDomainWasm } from "./domain-wasm.js";
|
|
13
8
|
|
|
14
|
-
export const
|
|
9
|
+
export const PROVIDER_READBACK_SAMPLE_CONTRACT =
|
|
15
10
|
"buildchain-v4-provider-readback-sample/v1";
|
|
16
|
-
export const
|
|
11
|
+
export const PROVIDER_READBACK_FOLD_CONTRACT =
|
|
17
12
|
"buildchain-v4-provider-readback-fold/v1";
|
|
18
13
|
|
|
19
14
|
const PROVIDERS = Object.freeze({
|
|
@@ -53,7 +48,7 @@ const PROVIDERS = Object.freeze({
|
|
|
53
48
|
});
|
|
54
49
|
|
|
55
50
|
function fault(code, path, message) {
|
|
56
|
-
throw new
|
|
51
|
+
throw new ContractFault(code, path, message);
|
|
57
52
|
}
|
|
58
53
|
|
|
59
54
|
function exactKeys(value, keys, path) {
|
|
@@ -79,12 +74,12 @@ function validateContext(context) {
|
|
|
79
74
|
"$/context",
|
|
80
75
|
);
|
|
81
76
|
for (const key of Object.keys(context))
|
|
82
|
-
|
|
77
|
+
validateRoot(context[key], `$/context/${key}`);
|
|
83
78
|
}
|
|
84
79
|
|
|
85
80
|
function sampleRoot(sample) {
|
|
86
81
|
const { sampleRoot: _sampleRoot, ...payload } = sample;
|
|
87
|
-
return
|
|
82
|
+
return domainContentRoot("provider-readback-sample", payload);
|
|
88
83
|
}
|
|
89
84
|
|
|
90
85
|
function validateSample(sample, path = "$/samples") {
|
|
@@ -101,7 +96,7 @@ function validateSample(sample, path = "$/samples") {
|
|
|
101
96
|
],
|
|
102
97
|
path,
|
|
103
98
|
);
|
|
104
|
-
if (sample.schema !==
|
|
99
|
+
if (sample.schema !== PROVIDER_READBACK_SAMPLE_CONTRACT)
|
|
105
100
|
fault(
|
|
106
101
|
"unsupported-provider-readback-version",
|
|
107
102
|
`${path}/schema`,
|
|
@@ -118,15 +113,15 @@ function validateSample(sample, path = "$/samples") {
|
|
|
118
113
|
"provider readback state is unsupported",
|
|
119
114
|
);
|
|
120
115
|
for (const key of ["operationRoot", "attemptRoot", "sampleRoot"])
|
|
121
|
-
|
|
116
|
+
validateRoot(sample[key], `${path}/${key}`);
|
|
122
117
|
if (sample.observedTargetRoot !== null)
|
|
123
|
-
|
|
118
|
+
validateRoot(sample.observedTargetRoot, `${path}/observedTargetRoot`);
|
|
124
119
|
if (
|
|
125
120
|
!Array.isArray(sample.evidenceRoots) ||
|
|
126
121
|
sample.evidenceRoots.length === 0 ||
|
|
127
122
|
sample.evidenceRoots.some(
|
|
128
123
|
(root, index) => (
|
|
129
|
-
|
|
124
|
+
validateRoot(root, `${path}/evidenceRoots/${index}`),
|
|
130
125
|
false
|
|
131
126
|
),
|
|
132
127
|
)
|
|
@@ -181,13 +176,13 @@ function adaptProviderReadback(provider, response, context) {
|
|
|
181
176
|
"$/response/schema",
|
|
182
177
|
"provider response schema does not match its adapter",
|
|
183
178
|
);
|
|
184
|
-
|
|
179
|
+
validateRoot(
|
|
185
180
|
response[descriptor.subject],
|
|
186
181
|
`$/response/${descriptor.subject}`,
|
|
187
182
|
);
|
|
188
|
-
|
|
183
|
+
validateRoot(response.evidenceRoot, "$/response/evidenceRoot");
|
|
189
184
|
if (response[descriptor.target] !== null)
|
|
190
|
-
|
|
185
|
+
validateRoot(
|
|
191
186
|
response[descriptor.target],
|
|
192
187
|
`$/response/${descriptor.target}`,
|
|
193
188
|
);
|
|
@@ -226,7 +221,7 @@ function adaptProviderReadback(provider, response, context) {
|
|
|
226
221
|
);
|
|
227
222
|
}
|
|
228
223
|
const sample = {
|
|
229
|
-
schema:
|
|
224
|
+
schema: PROVIDER_READBACK_SAMPLE_CONTRACT,
|
|
230
225
|
operationRoot: context.operationRoot,
|
|
231
226
|
attemptRoot: context.attemptRoot,
|
|
232
227
|
state,
|
|
@@ -239,119 +234,39 @@ function adaptProviderReadback(provider, response, context) {
|
|
|
239
234
|
return validateSample(sample);
|
|
240
235
|
}
|
|
241
236
|
|
|
242
|
-
export function
|
|
237
|
+
export function adaptGitHubReleaseReadback(response, context) {
|
|
243
238
|
return adaptProviderReadback("github", response, context);
|
|
244
239
|
}
|
|
245
240
|
|
|
246
|
-
export function
|
|
241
|
+
export function adaptNpmPublicationReadback(response, context) {
|
|
247
242
|
return adaptProviderReadback("npm", response, context);
|
|
248
243
|
}
|
|
249
244
|
|
|
250
|
-
export function
|
|
245
|
+
export function adaptOciManifestReadback(response, context) {
|
|
251
246
|
return adaptProviderReadback("oci", response, context);
|
|
252
247
|
}
|
|
253
248
|
|
|
254
|
-
export function
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
);
|
|
266
|
-
if (!Number.isSafeInteger(coordinates.sequence) || coordinates.sequence < 0)
|
|
267
|
-
fault(
|
|
268
|
-
"malformed-provider-readback",
|
|
269
|
-
"$/coordinates/sequence",
|
|
270
|
-
"readback sequence must be a non-negative safe integer",
|
|
271
|
-
);
|
|
272
|
-
for (const key of ["priorEntryRoot", "operationRoot", "attemptRoot"])
|
|
273
|
-
validateV4Root(coordinates[key], `$/coordinates/${key}`);
|
|
274
|
-
validateV4Clock(coordinates.observedAt, "$/coordinates/observedAt");
|
|
275
|
-
if (!Array.isArray(samples) || samples.length === 0)
|
|
276
|
-
fault(
|
|
277
|
-
"malformed-provider-readback",
|
|
278
|
-
"$/samples",
|
|
279
|
-
"at least one rooted provider readback sample is required",
|
|
280
|
-
);
|
|
281
|
-
const unique = new Map();
|
|
282
|
-
for (const [index, sample] of samples.entries()) {
|
|
283
|
-
validateSample(sample, `$/samples/${index}`);
|
|
284
|
-
if (
|
|
285
|
-
sample.operationRoot !== coordinates.operationRoot ||
|
|
286
|
-
sample.attemptRoot !== coordinates.attemptRoot
|
|
287
|
-
)
|
|
288
|
-
fault(
|
|
289
|
-
"provider-readback-coordinate-mismatch",
|
|
290
|
-
`$/samples/${index}`,
|
|
291
|
-
"provider readback sample does not bind the journal coordinates",
|
|
292
|
-
);
|
|
293
|
-
unique.set(sample.sampleRoot, sample);
|
|
249
|
+
export function foldProviderReadbackSamples(samples, coordinates) {
|
|
250
|
+
try {
|
|
251
|
+
return invokeDomainWasm("provider-readback-fold", {
|
|
252
|
+
samples,
|
|
253
|
+
coordinates,
|
|
254
|
+
});
|
|
255
|
+
} catch (error) {
|
|
256
|
+
if (error instanceof DomainWasmFault) {
|
|
257
|
+
throw new ContractFault(error.code, error.path, error.message);
|
|
258
|
+
}
|
|
259
|
+
throw error;
|
|
294
260
|
}
|
|
295
|
-
const folded = [...unique.values()].sort((left, right) =>
|
|
296
|
-
left.sampleRoot.localeCompare(right.sampleRoot),
|
|
297
|
-
);
|
|
298
|
-
const states = new Set(folded.map((sample) => sample.state));
|
|
299
|
-
if (states.has("already-applied") && states.size !== 1)
|
|
300
|
-
fault(
|
|
301
|
-
"conflicting-provider-readback",
|
|
302
|
-
"$/samples",
|
|
303
|
-
"successful and unresolved readbacks cannot describe one attempt",
|
|
304
|
-
);
|
|
305
|
-
const targets = new Set(
|
|
306
|
-
folded.map((sample) => sample.observedTargetRoot).filter(Boolean),
|
|
307
|
-
);
|
|
308
|
-
if (targets.size > 1)
|
|
309
|
-
fault(
|
|
310
|
-
"conflicting-provider-readback",
|
|
311
|
-
"$/samples",
|
|
312
|
-
"provider readbacks disagree about the observed target",
|
|
313
|
-
);
|
|
314
|
-
const classification = states.has("already-applied")
|
|
315
|
-
? "already-applied"
|
|
316
|
-
: states.has("eventually-visible")
|
|
317
|
-
? "eventually-visible"
|
|
318
|
-
: "not-found";
|
|
319
|
-
const readbackRoots = folded.map((sample) => sample.sampleRoot);
|
|
320
|
-
const observation = {
|
|
321
|
-
kind: "observation",
|
|
322
|
-
schema: V4_PROVIDER_OPERATION_OBSERVATION_CONTRACT,
|
|
323
|
-
sequence: coordinates.sequence,
|
|
324
|
-
priorEntryRoot: coordinates.priorEntryRoot,
|
|
325
|
-
operationRoot: coordinates.operationRoot,
|
|
326
|
-
attemptRoot: coordinates.attemptRoot,
|
|
327
|
-
observedAt: coordinates.observedAt,
|
|
328
|
-
status: classification === "already-applied" ? "succeeded" : "unknown",
|
|
329
|
-
evidenceRoots: readbackRoots,
|
|
330
|
-
entryRoot:
|
|
331
|
-
"sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
|
332
|
-
};
|
|
333
|
-
observation.entryRoot = v4ProviderOperationEntryRoot(observation);
|
|
334
|
-
validateV4ProviderOperationEntry(observation);
|
|
335
|
-
const projection = {
|
|
336
|
-
schema: V4_PROVIDER_READBACK_FOLD_CONTRACT,
|
|
337
|
-
classification,
|
|
338
|
-
readbackRoots,
|
|
339
|
-
observation,
|
|
340
|
-
projectionRoot:
|
|
341
|
-
"sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
|
342
|
-
};
|
|
343
|
-
const { projectionRoot: _projectionRoot, ...payload } = projection;
|
|
344
|
-
projection.projectionRoot = v4ContentRoot("provider-readback-fold", payload);
|
|
345
|
-
return projection;
|
|
346
261
|
}
|
|
347
262
|
|
|
348
263
|
const ADAPTERS = Object.freeze({
|
|
349
|
-
github:
|
|
350
|
-
npm:
|
|
351
|
-
oci:
|
|
264
|
+
github: adaptGitHubReleaseReadback,
|
|
265
|
+
npm: adaptNpmPublicationReadback,
|
|
266
|
+
oci: adaptOciManifestReadback,
|
|
352
267
|
});
|
|
353
268
|
|
|
354
|
-
export function
|
|
269
|
+
export function projectProviderReadbackFixtures(fixtures) {
|
|
355
270
|
const projectCase = (fixture) => {
|
|
356
271
|
const samples = fixture.readbacks.map(({ provider, response }) =>
|
|
357
272
|
ADAPTERS[provider](response, fixtures.context),
|
|
@@ -362,14 +277,14 @@ export function projectV4ProviderReadbackFixtures(fixtures) {
|
|
|
362
277
|
"$/neutralSamples",
|
|
363
278
|
"provider adapters did not produce the retained neutral samples",
|
|
364
279
|
);
|
|
365
|
-
const projection =
|
|
280
|
+
const projection = foldProviderReadbackSamples(
|
|
366
281
|
samples,
|
|
367
282
|
fixtures.coordinates,
|
|
368
283
|
);
|
|
369
284
|
return {
|
|
370
285
|
id: fixture.id,
|
|
371
286
|
...projection,
|
|
372
|
-
journalStateRoot:
|
|
287
|
+
journalStateRoot: providerOperationJournalStateRoot([
|
|
373
288
|
...fixtures.journalPrefix,
|
|
374
289
|
projection.observation,
|
|
375
290
|
]),
|
|
@@ -380,7 +295,7 @@ export function projectV4ProviderReadbackFixtures(fixtures) {
|
|
|
380
295
|
try {
|
|
381
296
|
projectCase(fixture);
|
|
382
297
|
} catch (error) {
|
|
383
|
-
if (error instanceof
|
|
298
|
+
if (error instanceof ContractFault)
|
|
384
299
|
return { id: fixture.id, fault: error.code };
|
|
385
300
|
throw error;
|
|
386
301
|
}
|