@kungfu-tech/buildchain 4.0.1-alpha.2 → 4.0.1-alpha.21
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/decisions/0003-two-phase-delivery-warrant.md +152 -0
- package/architecture/internal-capabilities.json +211 -8
- package/architecture/maintainability-policy.json +113 -28
- 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 +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 +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/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 +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 +5 -0
- package/dist/site/artifact-schemas.json +10 -0
- package/dist/site/buildchain-contract.json +1475 -27
- package/dist/site/buildchain-site.json +627 -31
- package/dist/site/capability-registry.json +17 -14
- package/dist/site/cli-registry.json +205 -3
- package/dist/site/kfd-claims.json +490 -16
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +52 -6
- package/dist/site/node-api-registry.json +14736 -8851
- package/dist/site/page-registry.json +593 -21
- package/dist/site/public-surface-audit.json +837 -48
- package/dist/site/publication-authority-registry.json +44 -8
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +24 -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 +34 -10
- package/dist/site/workflow-registry.json +160 -10
- package/docs/MAP.md +8 -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 +351 -38
- package/docs/next-development-transition.md +118 -0
- package/docs/node-api-reference.md +646 -293
- 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 +34 -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 +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-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 +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 +32 -5
- 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/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 +23 -4
- 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 +13 -97
- 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 +1 -1
- package/scripts/dev-pr-delivery-warrant.mjs +11 -0
- 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 +69 -4
- 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/npm-publish-transaction.mjs +2 -2
- 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 +557 -30
- package/scripts/site-capability-metadata.mjs +41 -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 +143 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RELEASE_TAIL_TRANSACTION_POLICY,
|
|
3
|
+
compileReleaseTailDeclaration,
|
|
4
|
+
createReleaseTailTransaction,
|
|
5
|
+
parseReleaseTailDeclaration,
|
|
6
|
+
releaseTailRoot,
|
|
7
|
+
validateReleaseTailTransaction,
|
|
8
|
+
} from "./release-tail-provider-plane.js";
|
|
9
|
+
import {
|
|
10
|
+
V4PublicationRehearsalFault,
|
|
11
|
+
publicationRehearsalByteSorted as byteSorted,
|
|
12
|
+
publicationRehearsalExactKeys as exactKeys,
|
|
13
|
+
publicationRehearsalFault as fault,
|
|
14
|
+
publicationRehearsalRelativePath as relativePath,
|
|
15
|
+
publicationRehearsalRoot as root,
|
|
16
|
+
publicationRehearsalText as text,
|
|
17
|
+
publicationRehearsalToken as token,
|
|
18
|
+
validateV4PublicationRehearsalProviderBindings,
|
|
19
|
+
} from "./v4-publication-rehearsal-provider-bindings.js";
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
V4PublicationRehearsalFault,
|
|
23
|
+
exactKeys as assertPublicationRehearsalExactKeys,
|
|
24
|
+
fault as publicationRehearsalFault,
|
|
25
|
+
root as publicationRehearsalRoot,
|
|
26
|
+
validateV4PublicationRehearsalProviderBindings,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const V4_PUBLICATION_REHEARSAL_CAPSULE_CONTRACT =
|
|
30
|
+
"buildchain-v4-publication-rehearsal-capsule/v1";
|
|
31
|
+
export const V4_PUBLICATION_REHEARSAL_EVIDENCE_CONTRACT =
|
|
32
|
+
"buildchain-v4-publication-rehearsal-evidence/v1";
|
|
33
|
+
export const V4_PUBLICATION_REHEARSAL_AUTHORITY_CONTRACT =
|
|
34
|
+
"buildchain-v4-publication-rehearsal-authority/v1";
|
|
35
|
+
export const V4_PUBLICATION_REHEARSAL_PROVIDER_POLICY_CONTRACT =
|
|
36
|
+
"buildchain-v4-publication-rehearsal-provider-policy/v1";
|
|
37
|
+
export const V4_PUBLICATION_REHEARSAL_CORE_VERSION =
|
|
38
|
+
RELEASE_TAIL_TRANSACTION_POLICY;
|
|
39
|
+
|
|
40
|
+
const ROOT = /^sha256:[0-9a-f]{64}$/u;
|
|
41
|
+
const SHA = /^[0-9a-f]{40}$/u;
|
|
42
|
+
const TOKEN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/u;
|
|
43
|
+
const MODES = new Set(["simulate", "replay", "provider"]);
|
|
44
|
+
|
|
45
|
+
function sourceRoot(source) {
|
|
46
|
+
return releaseTailRoot({
|
|
47
|
+
repository: source.repository,
|
|
48
|
+
revision: source.revision,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function candidateRoot(files) {
|
|
53
|
+
return releaseTailRoot(
|
|
54
|
+
files.map(({ role, path: filePath, size, root: fileRoot }) => ({
|
|
55
|
+
role,
|
|
56
|
+
path: filePath,
|
|
57
|
+
size,
|
|
58
|
+
root: fileRoot,
|
|
59
|
+
})),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function policyPayload(policy) {
|
|
64
|
+
return {
|
|
65
|
+
schema: policy.schema,
|
|
66
|
+
effectDefault: policy.effectDefault,
|
|
67
|
+
allowedCapabilityIds: policy.allowedCapabilityIds,
|
|
68
|
+
allowedAdapters: policy.allowedAdapters,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function capsulePayload(capsule) {
|
|
73
|
+
const payload = structuredClone(capsule);
|
|
74
|
+
delete payload.capsuleRoot;
|
|
75
|
+
return payload;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizeFile(value, index) {
|
|
79
|
+
const location = `$/files/${index}`;
|
|
80
|
+
exactKeys(value, ["role", "path", "size", "root"], location);
|
|
81
|
+
if (!Number.isSafeInteger(value.size) || value.size < 0)
|
|
82
|
+
fault(
|
|
83
|
+
"invalid-publication-rehearsal-file",
|
|
84
|
+
`${location}/size`,
|
|
85
|
+
"non-negative safe integer required",
|
|
86
|
+
);
|
|
87
|
+
return {
|
|
88
|
+
role: token(value.role, `${location}/role`),
|
|
89
|
+
path: relativePath(value.path, `${location}/path`),
|
|
90
|
+
size: value.size,
|
|
91
|
+
root: root(value.root, `${location}/root`),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function normalizeBinding(value, location) {
|
|
96
|
+
exactKeys(value, ["path", "root"], location);
|
|
97
|
+
return {
|
|
98
|
+
path: relativePath(value.path, `${location}/path`),
|
|
99
|
+
root: root(value.root, `${location}/root`),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function normalizeCandidateInputs(value) {
|
|
104
|
+
exactKeys(value.candidate, ["root"], "$/candidate");
|
|
105
|
+
root(value.candidate.root, "$/candidate/root");
|
|
106
|
+
if (!Array.isArray(value.files) || value.files.length === 0)
|
|
107
|
+
fault(
|
|
108
|
+
"invalid-publication-rehearsal-files",
|
|
109
|
+
"$/files",
|
|
110
|
+
"non-empty file inventory required",
|
|
111
|
+
);
|
|
112
|
+
const files = value.files.map(normalizeFile);
|
|
113
|
+
const paths = files.map((entry) => entry.path);
|
|
114
|
+
if (
|
|
115
|
+
JSON.stringify(paths) !==
|
|
116
|
+
JSON.stringify(
|
|
117
|
+
[...new Set(paths)].sort((left, right) =>
|
|
118
|
+
Buffer.from(left).compare(Buffer.from(right)),
|
|
119
|
+
),
|
|
120
|
+
) ||
|
|
121
|
+
value.candidate.root !== candidateRoot(files)
|
|
122
|
+
)
|
|
123
|
+
fault(
|
|
124
|
+
"publication-rehearsal-candidate-root-mismatch",
|
|
125
|
+
"$/candidate/root",
|
|
126
|
+
"candidate inventory is unordered, duplicated, or drifted",
|
|
127
|
+
);
|
|
128
|
+
const manifest = normalizeBinding(value.manifest, "$/manifest");
|
|
129
|
+
const config = normalizeBinding(value.config, "$/config");
|
|
130
|
+
for (const [name, binding] of Object.entries({ manifest, config }))
|
|
131
|
+
if (
|
|
132
|
+
!files.some(
|
|
133
|
+
(entry) => entry.path === binding.path && entry.root === binding.root,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
fault(
|
|
137
|
+
`publication-rehearsal-${name}-root-mismatch`,
|
|
138
|
+
`$/${name}`,
|
|
139
|
+
`${name} is not bound by the candidate inventory`,
|
|
140
|
+
);
|
|
141
|
+
const providerBindings = validateV4PublicationRehearsalProviderBindings(
|
|
142
|
+
value.providerBindings,
|
|
143
|
+
);
|
|
144
|
+
root(value.providerBindingsRoot, "$/providerBindingsRoot");
|
|
145
|
+
if (value.providerBindingsRoot !== releaseTailRoot(providerBindings))
|
|
146
|
+
fault(
|
|
147
|
+
"publication-rehearsal-provider-bindings-root-mismatch",
|
|
148
|
+
"$/providerBindingsRoot",
|
|
149
|
+
"provider bindings payload drifted",
|
|
150
|
+
);
|
|
151
|
+
const inventoryPaths = new Set(paths);
|
|
152
|
+
const requiredInputs = [
|
|
153
|
+
...Object.values(providerBindings.artifacts).map(({ path }) => path),
|
|
154
|
+
...Object.values(providerBindings.documents).map(({ path }) => path),
|
|
155
|
+
...providerBindings.evidence.inputs,
|
|
156
|
+
];
|
|
157
|
+
for (const inputPath of requiredInputs)
|
|
158
|
+
if (!inventoryPaths.has(inputPath))
|
|
159
|
+
fault(
|
|
160
|
+
"publication-rehearsal-provider-binding-file-missing",
|
|
161
|
+
"$/providerBindings",
|
|
162
|
+
`provider input is absent from files: ${inputPath}`,
|
|
163
|
+
);
|
|
164
|
+
return { files, manifest, config, providerBindings };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function normalizeProviderPolicy(value, declaration) {
|
|
168
|
+
exactKeys(
|
|
169
|
+
value,
|
|
170
|
+
[
|
|
171
|
+
"schema",
|
|
172
|
+
"effectDefault",
|
|
173
|
+
"allowedCapabilityIds",
|
|
174
|
+
"allowedAdapters",
|
|
175
|
+
"root",
|
|
176
|
+
],
|
|
177
|
+
"$/providerPolicy",
|
|
178
|
+
);
|
|
179
|
+
if (
|
|
180
|
+
value.schema !== V4_PUBLICATION_REHEARSAL_PROVIDER_POLICY_CONTRACT ||
|
|
181
|
+
value.effectDefault !== "disabled"
|
|
182
|
+
)
|
|
183
|
+
fault(
|
|
184
|
+
"invalid-publication-rehearsal-provider-policy",
|
|
185
|
+
"$/providerPolicy",
|
|
186
|
+
"provider rehearsal effects must default to disabled",
|
|
187
|
+
);
|
|
188
|
+
const capabilityIds = byteSorted(
|
|
189
|
+
value.allowedCapabilityIds,
|
|
190
|
+
"$/providerPolicy/allowedCapabilityIds",
|
|
191
|
+
text,
|
|
192
|
+
);
|
|
193
|
+
const adapters = byteSorted(
|
|
194
|
+
value.allowedAdapters,
|
|
195
|
+
"$/providerPolicy/allowedAdapters",
|
|
196
|
+
token,
|
|
197
|
+
);
|
|
198
|
+
const expectedCapabilityIds = declaration.capabilities
|
|
199
|
+
.map(({ id }) => id)
|
|
200
|
+
.sort((left, right) => Buffer.from(left).compare(Buffer.from(right)));
|
|
201
|
+
const expectedAdapters = [
|
|
202
|
+
...new Set(declaration.capabilities.map(({ adapter }) => adapter)),
|
|
203
|
+
].sort((left, right) => Buffer.from(left).compare(Buffer.from(right)));
|
|
204
|
+
if (
|
|
205
|
+
JSON.stringify(capabilityIds) !== JSON.stringify(expectedCapabilityIds) ||
|
|
206
|
+
JSON.stringify(adapters) !== JSON.stringify(expectedAdapters)
|
|
207
|
+
)
|
|
208
|
+
fault(
|
|
209
|
+
"publication-rehearsal-provider-policy-mismatch",
|
|
210
|
+
"$/providerPolicy",
|
|
211
|
+
"policy must enumerate the exact shared-core capabilities and adapters",
|
|
212
|
+
);
|
|
213
|
+
const normalized = {
|
|
214
|
+
schema: value.schema,
|
|
215
|
+
effectDefault: value.effectDefault,
|
|
216
|
+
allowedCapabilityIds: capabilityIds,
|
|
217
|
+
allowedAdapters: adapters,
|
|
218
|
+
root: root(value.root, "$/providerPolicy/root"),
|
|
219
|
+
};
|
|
220
|
+
if (normalized.root !== releaseTailRoot(policyPayload(normalized)))
|
|
221
|
+
fault(
|
|
222
|
+
"publication-rehearsal-provider-policy-root-mismatch",
|
|
223
|
+
"$/providerPolicy/root",
|
|
224
|
+
"provider policy root drifted",
|
|
225
|
+
);
|
|
226
|
+
return normalized;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function normalizeObservation(value, index, operationIds) {
|
|
230
|
+
const location = `$/expectedObservations/entries/${index}`;
|
|
231
|
+
exactKeys(value, ["operationId", "readbacks", "apply"], location);
|
|
232
|
+
const operationId = root(value.operationId, `${location}/operationId`);
|
|
233
|
+
if (!operationIds.has(operationId))
|
|
234
|
+
fault(
|
|
235
|
+
"publication-rehearsal-observation-operation-mismatch",
|
|
236
|
+
`${location}/operationId`,
|
|
237
|
+
"unknown operation",
|
|
238
|
+
);
|
|
239
|
+
if (!Array.isArray(value.readbacks) || value.readbacks.length === 0)
|
|
240
|
+
fault(
|
|
241
|
+
"invalid-publication-rehearsal-observation",
|
|
242
|
+
`${location}/readbacks`,
|
|
243
|
+
"non-empty readback sequence required",
|
|
244
|
+
);
|
|
245
|
+
for (const [readbackIndex, readback] of value.readbacks.entries()) {
|
|
246
|
+
exactKeys(
|
|
247
|
+
readback,
|
|
248
|
+
["outcome", "subjectRoot", "targetRoot", "evidenceRoots", "providerCode"],
|
|
249
|
+
`${location}/readbacks/${readbackIndex}`,
|
|
250
|
+
);
|
|
251
|
+
if (
|
|
252
|
+
!new Set(["observed", "absent", "transient", "conflict"]).has(
|
|
253
|
+
readback.outcome,
|
|
254
|
+
)
|
|
255
|
+
)
|
|
256
|
+
fault(
|
|
257
|
+
"invalid-publication-rehearsal-observation",
|
|
258
|
+
`${location}/readbacks/${readbackIndex}/outcome`,
|
|
259
|
+
"unsupported outcome",
|
|
260
|
+
);
|
|
261
|
+
if (readback.subjectRoot)
|
|
262
|
+
root(
|
|
263
|
+
readback.subjectRoot,
|
|
264
|
+
`${location}/readbacks/${readbackIndex}/subjectRoot`,
|
|
265
|
+
);
|
|
266
|
+
if (readback.targetRoot)
|
|
267
|
+
root(
|
|
268
|
+
readback.targetRoot,
|
|
269
|
+
`${location}/readbacks/${readbackIndex}/targetRoot`,
|
|
270
|
+
);
|
|
271
|
+
byteSorted(
|
|
272
|
+
readback.evidenceRoots,
|
|
273
|
+
`${location}/readbacks/${readbackIndex}/evidenceRoots`,
|
|
274
|
+
root,
|
|
275
|
+
true,
|
|
276
|
+
);
|
|
277
|
+
text(
|
|
278
|
+
readback.providerCode,
|
|
279
|
+
`${location}/readbacks/${readbackIndex}/providerCode`,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
exactKeys(
|
|
283
|
+
value.apply,
|
|
284
|
+
["outcome", "code", "classification"],
|
|
285
|
+
`${location}/apply`,
|
|
286
|
+
);
|
|
287
|
+
if (!new Set(["applied", "transient", "conflict"]).has(value.apply.outcome))
|
|
288
|
+
fault(
|
|
289
|
+
"invalid-publication-rehearsal-observation",
|
|
290
|
+
`${location}/apply/outcome`,
|
|
291
|
+
"unsupported apply outcome",
|
|
292
|
+
);
|
|
293
|
+
text(value.apply.code, `${location}/apply/code`);
|
|
294
|
+
text(value.apply.classification, `${location}/apply/classification`);
|
|
295
|
+
return structuredClone(value);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function createV4PublicationRehearsalProviderPolicy(declarationInput) {
|
|
299
|
+
const declaration = parseReleaseTailDeclaration(declarationInput);
|
|
300
|
+
const body = {
|
|
301
|
+
schema: V4_PUBLICATION_REHEARSAL_PROVIDER_POLICY_CONTRACT,
|
|
302
|
+
effectDefault: "disabled",
|
|
303
|
+
allowedCapabilityIds: declaration.capabilities
|
|
304
|
+
.map(({ id }) => id)
|
|
305
|
+
.sort((left, right) => Buffer.from(left).compare(Buffer.from(right))),
|
|
306
|
+
allowedAdapters: [
|
|
307
|
+
...new Set(declaration.capabilities.map(({ adapter }) => adapter)),
|
|
308
|
+
].sort((left, right) => Buffer.from(left).compare(Buffer.from(right))),
|
|
309
|
+
};
|
|
310
|
+
return { ...body, root: releaseTailRoot(body) };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function createV4PublicationRehearsalCapsule(input) {
|
|
314
|
+
const declaration = parseReleaseTailDeclaration(input.declaration);
|
|
315
|
+
const transaction =
|
|
316
|
+
input.transaction || createReleaseTailTransaction(declaration);
|
|
317
|
+
const files = structuredClone(input.files || []).sort((left, right) =>
|
|
318
|
+
Buffer.from(left.path).compare(Buffer.from(right.path)),
|
|
319
|
+
);
|
|
320
|
+
const source = {
|
|
321
|
+
repository: text(input.source?.repository, "$/source/repository"),
|
|
322
|
+
revision: text(input.source?.revision, "$/source/revision"),
|
|
323
|
+
};
|
|
324
|
+
const policy =
|
|
325
|
+
input.providerPolicy ||
|
|
326
|
+
createV4PublicationRehearsalProviderPolicy(declaration);
|
|
327
|
+
const observations = structuredClone(input.expectedObservations || []);
|
|
328
|
+
const providerBindings = validateV4PublicationRehearsalProviderBindings(
|
|
329
|
+
input.providerBindings,
|
|
330
|
+
);
|
|
331
|
+
const body = {
|
|
332
|
+
schema: V4_PUBLICATION_REHEARSAL_CAPSULE_CONTRACT,
|
|
333
|
+
coreVersion: V4_PUBLICATION_REHEARSAL_CORE_VERSION,
|
|
334
|
+
source: { ...source, root: sourceRoot(source) },
|
|
335
|
+
candidate: { root: candidateRoot(files) },
|
|
336
|
+
manifest: structuredClone(input.manifest),
|
|
337
|
+
config: structuredClone(input.config),
|
|
338
|
+
providerBindings,
|
|
339
|
+
providerBindingsRoot: releaseTailRoot(providerBindings),
|
|
340
|
+
providerPolicy: structuredClone(policy),
|
|
341
|
+
expectedObservations: {
|
|
342
|
+
entries: observations,
|
|
343
|
+
root: releaseTailRoot(observations),
|
|
344
|
+
},
|
|
345
|
+
declaration,
|
|
346
|
+
transaction: structuredClone(transaction),
|
|
347
|
+
files,
|
|
348
|
+
};
|
|
349
|
+
return validateV4PublicationRehearsalCapsule({
|
|
350
|
+
...body,
|
|
351
|
+
capsuleRoot: releaseTailRoot(body),
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export function validateV4PublicationRehearsalCapsule(value) {
|
|
356
|
+
exactKeys(
|
|
357
|
+
value,
|
|
358
|
+
[
|
|
359
|
+
"schema",
|
|
360
|
+
"coreVersion",
|
|
361
|
+
"source",
|
|
362
|
+
"candidate",
|
|
363
|
+
"manifest",
|
|
364
|
+
"config",
|
|
365
|
+
"providerBindings",
|
|
366
|
+
"providerBindingsRoot",
|
|
367
|
+
"providerPolicy",
|
|
368
|
+
"expectedObservations",
|
|
369
|
+
"declaration",
|
|
370
|
+
"transaction",
|
|
371
|
+
"files",
|
|
372
|
+
"capsuleRoot",
|
|
373
|
+
],
|
|
374
|
+
"$",
|
|
375
|
+
);
|
|
376
|
+
if (
|
|
377
|
+
value.schema !== V4_PUBLICATION_REHEARSAL_CAPSULE_CONTRACT ||
|
|
378
|
+
value.coreVersion !== V4_PUBLICATION_REHEARSAL_CORE_VERSION
|
|
379
|
+
)
|
|
380
|
+
fault(
|
|
381
|
+
"unsupported-publication-rehearsal-core-version",
|
|
382
|
+
"$/coreVersion",
|
|
383
|
+
"capsule must bind the active production release-tail core",
|
|
384
|
+
);
|
|
385
|
+
exactKeys(value.source, ["repository", "revision", "root"], "$/source");
|
|
386
|
+
text(value.source.repository, "$/source/repository");
|
|
387
|
+
if (!SHA.test(value.source.revision))
|
|
388
|
+
fault(
|
|
389
|
+
"invalid-publication-rehearsal-source",
|
|
390
|
+
"$/source/revision",
|
|
391
|
+
"exact lowercase Git SHA required",
|
|
392
|
+
);
|
|
393
|
+
root(value.source.root, "$/source/root");
|
|
394
|
+
if (value.source.root !== sourceRoot(value.source))
|
|
395
|
+
fault(
|
|
396
|
+
"publication-rehearsal-source-root-mismatch",
|
|
397
|
+
"$/source/root",
|
|
398
|
+
"source root drifted",
|
|
399
|
+
);
|
|
400
|
+
const { files, manifest, config, providerBindings } =
|
|
401
|
+
normalizeCandidateInputs(value);
|
|
402
|
+
const declaration = parseReleaseTailDeclaration(value.declaration);
|
|
403
|
+
const plan = compileReleaseTailDeclaration(declaration);
|
|
404
|
+
const transactionValidation = validateReleaseTailTransaction(
|
|
405
|
+
value.transaction,
|
|
406
|
+
);
|
|
407
|
+
const initial = createReleaseTailTransaction(plan);
|
|
408
|
+
if (
|
|
409
|
+
!transactionValidation.valid ||
|
|
410
|
+
value.transaction.declarationRoot !== plan.declarationRoot ||
|
|
411
|
+
value.transaction.planRoot !== plan.planRoot ||
|
|
412
|
+
value.transaction.transactionRoot !== initial.transactionRoot
|
|
413
|
+
)
|
|
414
|
+
fault(
|
|
415
|
+
"publication-rehearsal-core-binding-mismatch",
|
|
416
|
+
"$/transaction",
|
|
417
|
+
"transaction does not belong to the shared production planner",
|
|
418
|
+
);
|
|
419
|
+
const providerPolicy = normalizeProviderPolicy(
|
|
420
|
+
value.providerPolicy,
|
|
421
|
+
declaration,
|
|
422
|
+
);
|
|
423
|
+
exactKeys(
|
|
424
|
+
value.expectedObservations,
|
|
425
|
+
["entries", "root"],
|
|
426
|
+
"$/expectedObservations",
|
|
427
|
+
);
|
|
428
|
+
if (!Array.isArray(value.expectedObservations.entries))
|
|
429
|
+
fault(
|
|
430
|
+
"invalid-publication-rehearsal-observations",
|
|
431
|
+
"$/expectedObservations/entries",
|
|
432
|
+
"array required",
|
|
433
|
+
);
|
|
434
|
+
const operationIds = new Set(value.transaction.operationOrder);
|
|
435
|
+
const expectedObservations = value.expectedObservations.entries.map(
|
|
436
|
+
(entry, index) => normalizeObservation(entry, index, operationIds),
|
|
437
|
+
);
|
|
438
|
+
if (
|
|
439
|
+
new Set(expectedObservations.map(({ operationId }) => operationId)).size !==
|
|
440
|
+
expectedObservations.length ||
|
|
441
|
+
value.expectedObservations.root !== releaseTailRoot(expectedObservations)
|
|
442
|
+
)
|
|
443
|
+
fault(
|
|
444
|
+
"publication-rehearsal-expected-observation-root-mismatch",
|
|
445
|
+
"$/expectedObservations/root",
|
|
446
|
+
"expected observations are duplicated or drifted",
|
|
447
|
+
);
|
|
448
|
+
root(value.capsuleRoot, "$/capsuleRoot");
|
|
449
|
+
if (value.capsuleRoot !== releaseTailRoot(capsulePayload(value)))
|
|
450
|
+
fault(
|
|
451
|
+
"publication-rehearsal-capsule-root-mismatch",
|
|
452
|
+
"$/capsuleRoot",
|
|
453
|
+
"capsule payload drifted",
|
|
454
|
+
);
|
|
455
|
+
return {
|
|
456
|
+
...structuredClone(value),
|
|
457
|
+
manifest,
|
|
458
|
+
config,
|
|
459
|
+
providerBindings,
|
|
460
|
+
providerPolicy,
|
|
461
|
+
expectedObservations: {
|
|
462
|
+
entries: expectedObservations,
|
|
463
|
+
root: value.expectedObservations.root,
|
|
464
|
+
},
|
|
465
|
+
declaration,
|
|
466
|
+
files,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
export class V4PublicationRehearsalFault extends Error {
|
|
2
|
+
constructor(code, location, message) {
|
|
3
|
+
super(`${location}: ${message}`);
|
|
4
|
+
this.name = "V4PublicationRehearsalFault";
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.location = location;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function publicationRehearsalFault(code, location, message) {
|
|
11
|
+
throw new V4PublicationRehearsalFault(code, location, message);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function publicationRehearsalExactKeys(value, expected, location) {
|
|
15
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16
|
+
publicationRehearsalFault(
|
|
17
|
+
"invalid-publication-rehearsal-shape",
|
|
18
|
+
location,
|
|
19
|
+
"object required",
|
|
20
|
+
);
|
|
21
|
+
const actual = Object.keys(value).sort();
|
|
22
|
+
const canonical = [...expected].sort();
|
|
23
|
+
if (
|
|
24
|
+
actual.length !== canonical.length ||
|
|
25
|
+
actual.some((key, index) => key !== canonical[index])
|
|
26
|
+
)
|
|
27
|
+
publicationRehearsalFault(
|
|
28
|
+
"invalid-publication-rehearsal-shape",
|
|
29
|
+
location,
|
|
30
|
+
`keys must be exactly ${canonical.join(", ")}`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function publicationRehearsalRoot(value, location) {
|
|
35
|
+
if (typeof value !== "string" || !/^sha256:[0-9a-f]{64}$/u.test(value))
|
|
36
|
+
publicationRehearsalFault(
|
|
37
|
+
"invalid-publication-rehearsal-root",
|
|
38
|
+
location,
|
|
39
|
+
"SHA-256 root required",
|
|
40
|
+
);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function publicationRehearsalText(value, location) {
|
|
45
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
46
|
+
publicationRehearsalFault(
|
|
47
|
+
"invalid-publication-rehearsal-text",
|
|
48
|
+
location,
|
|
49
|
+
"non-empty text required",
|
|
50
|
+
);
|
|
51
|
+
return value.trim();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function publicationRehearsalToken(value, location) {
|
|
55
|
+
const normalized = publicationRehearsalText(value, location);
|
|
56
|
+
if (!/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/u.test(normalized))
|
|
57
|
+
publicationRehearsalFault(
|
|
58
|
+
"invalid-publication-rehearsal-token",
|
|
59
|
+
location,
|
|
60
|
+
"ASCII token required",
|
|
61
|
+
);
|
|
62
|
+
return normalized;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function publicationRehearsalRelativePath(value, location) {
|
|
66
|
+
const normalized = publicationRehearsalText(value, location);
|
|
67
|
+
if (
|
|
68
|
+
normalized.startsWith("/") ||
|
|
69
|
+
normalized.includes("\\") ||
|
|
70
|
+
normalized.endsWith("/") ||
|
|
71
|
+
normalized.split("/").some((part) => !part || part === "." || part === "..")
|
|
72
|
+
)
|
|
73
|
+
publicationRehearsalFault(
|
|
74
|
+
"invalid-publication-rehearsal-path",
|
|
75
|
+
location,
|
|
76
|
+
"safe POSIX relative file path required",
|
|
77
|
+
);
|
|
78
|
+
return normalized;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function publicationRehearsalByteSorted(
|
|
82
|
+
values,
|
|
83
|
+
location,
|
|
84
|
+
validate = publicationRehearsalToken,
|
|
85
|
+
allowEmpty = false,
|
|
86
|
+
) {
|
|
87
|
+
if (!Array.isArray(values) || (!allowEmpty && values.length === 0))
|
|
88
|
+
publicationRehearsalFault(
|
|
89
|
+
"invalid-publication-rehearsal-shape",
|
|
90
|
+
location,
|
|
91
|
+
"array required",
|
|
92
|
+
);
|
|
93
|
+
const normalized = values.map((value, index) =>
|
|
94
|
+
validate(value, `${location}/${index}`),
|
|
95
|
+
);
|
|
96
|
+
const canonical = [...new Set(normalized)].sort((left, right) =>
|
|
97
|
+
Buffer.from(left).compare(Buffer.from(right)),
|
|
98
|
+
);
|
|
99
|
+
if (JSON.stringify(normalized) !== JSON.stringify(canonical))
|
|
100
|
+
publicationRehearsalFault(
|
|
101
|
+
"unordered-publication-rehearsal-values",
|
|
102
|
+
location,
|
|
103
|
+
"values must be unique and byte-sorted",
|
|
104
|
+
);
|
|
105
|
+
return normalized;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function canonicalObject(value, location, normalize) {
|
|
109
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
110
|
+
publicationRehearsalFault(
|
|
111
|
+
"invalid-publication-rehearsal-shape",
|
|
112
|
+
location,
|
|
113
|
+
"object required",
|
|
114
|
+
);
|
|
115
|
+
const keys = Object.keys(value);
|
|
116
|
+
const sorted = [...keys].sort((left, right) =>
|
|
117
|
+
Buffer.from(left).compare(Buffer.from(right)),
|
|
118
|
+
);
|
|
119
|
+
if (JSON.stringify(keys) !== JSON.stringify(sorted))
|
|
120
|
+
publicationRehearsalFault(
|
|
121
|
+
"unordered-publication-rehearsal-values",
|
|
122
|
+
location,
|
|
123
|
+
"object keys must be byte-sorted",
|
|
124
|
+
);
|
|
125
|
+
return Object.fromEntries(
|
|
126
|
+
keys.map((key) => [
|
|
127
|
+
publicationRehearsalToken(key, `${location}/${key}`),
|
|
128
|
+
normalize(value[key], key),
|
|
129
|
+
]),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function validateV4PublicationRehearsalProviderBindings(value) {
|
|
134
|
+
publicationRehearsalExactKeys(
|
|
135
|
+
value,
|
|
136
|
+
["schema", "artifacts", "documents", "evidence"],
|
|
137
|
+
"$/providerBindings",
|
|
138
|
+
);
|
|
139
|
+
if (value.schema !== "kungfu.buildchain.release-tail.provider-bindings/v1")
|
|
140
|
+
publicationRehearsalFault(
|
|
141
|
+
"invalid-publication-rehearsal-provider-bindings",
|
|
142
|
+
"$/providerBindings/schema",
|
|
143
|
+
"unsupported provider bindings schema",
|
|
144
|
+
);
|
|
145
|
+
const artifacts = canonicalObject(
|
|
146
|
+
value.artifacts,
|
|
147
|
+
"$/providerBindings/artifacts",
|
|
148
|
+
(binding, key) => {
|
|
149
|
+
publicationRehearsalExactKeys(
|
|
150
|
+
binding,
|
|
151
|
+
["path", "name"],
|
|
152
|
+
`$/providerBindings/artifacts/${key}`,
|
|
153
|
+
);
|
|
154
|
+
return {
|
|
155
|
+
path: publicationRehearsalRelativePath(
|
|
156
|
+
binding.path,
|
|
157
|
+
`$/providerBindings/artifacts/${key}/path`,
|
|
158
|
+
),
|
|
159
|
+
name: publicationRehearsalText(
|
|
160
|
+
binding.name,
|
|
161
|
+
`$/providerBindings/artifacts/${key}/name`,
|
|
162
|
+
),
|
|
163
|
+
};
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
const documents = canonicalObject(
|
|
167
|
+
value.documents,
|
|
168
|
+
"$/providerBindings/documents",
|
|
169
|
+
(binding, key) => {
|
|
170
|
+
publicationRehearsalExactKeys(
|
|
171
|
+
binding,
|
|
172
|
+
["path", "method"],
|
|
173
|
+
`$/providerBindings/documents/${key}`,
|
|
174
|
+
);
|
|
175
|
+
if (!new Set(["PUT", "POST"]).has(binding.method))
|
|
176
|
+
publicationRehearsalFault(
|
|
177
|
+
"invalid-publication-rehearsal-provider-bindings",
|
|
178
|
+
`$/providerBindings/documents/${key}/method`,
|
|
179
|
+
"PUT or POST required",
|
|
180
|
+
);
|
|
181
|
+
return {
|
|
182
|
+
path: publicationRehearsalRelativePath(
|
|
183
|
+
binding.path,
|
|
184
|
+
`$/providerBindings/documents/${key}/path`,
|
|
185
|
+
),
|
|
186
|
+
method: binding.method,
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
publicationRehearsalExactKeys(
|
|
191
|
+
value.evidence,
|
|
192
|
+
["inputs", "output"],
|
|
193
|
+
"$/providerBindings/evidence",
|
|
194
|
+
);
|
|
195
|
+
return {
|
|
196
|
+
schema: value.schema,
|
|
197
|
+
artifacts,
|
|
198
|
+
documents,
|
|
199
|
+
evidence: {
|
|
200
|
+
inputs: publicationRehearsalByteSorted(
|
|
201
|
+
value.evidence.inputs,
|
|
202
|
+
"$/providerBindings/evidence/inputs",
|
|
203
|
+
publicationRehearsalRelativePath,
|
|
204
|
+
true,
|
|
205
|
+
),
|
|
206
|
+
output: publicationRehearsalRelativePath(
|
|
207
|
+
value.evidence.output,
|
|
208
|
+
"$/providerBindings/evidence/output",
|
|
209
|
+
),
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|