@kungfu-tech/buildchain 4.0.2-alpha.30 → 4.0.2-alpha.32
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/architecture/agent-change-map.md +4 -1
- package/architecture/maintainability-debt.json +90 -58
- package/architecture/maintainability-policy.json +22 -23
- package/architecture/v4-architecture-constitution.md +23 -20
- package/architecture/v4-partial-mutation-recovery-qualification.json +4 -1
- package/architecture/v4-provider-operation-journal-contract.json +5 -2
- package/architecture/v4-release-activation-shadow-domain.json +5 -2
- package/architecture/v4-release-topology.json +17 -2
- package/architecture/v4-rust-wasm-production-authority.json +57 -0
- package/architecture/v4-stable-publication-fence.json +5 -2
- package/dist/site/buildchain-contract.json +5 -5
- package/dist/site/buildchain-site.json +44 -8
- package/dist/site/capability-registry.json +1 -1
- package/dist/site/kfd-claims.json +17 -5
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +1 -1
- package/dist/site/node-api-registry.json +27 -27
- package/dist/site/page-registry.json +39 -3
- package/dist/site/public-surface-audit.json +7 -3
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +5 -5
- package/dist/site/workflow-registry.json +4 -4
- package/docs/node-api-reference.md +60 -60
- package/docs/v4-rust-wasm-production-authority.md +58 -0
- package/package.json +5 -3
- package/packages/core/buildchain-v4-domain.wasm +0 -0
- package/packages/core/dev-delivery-candidate-identity.js +48 -11
- package/packages/core/release-tail-provider-plane.js +68 -1048
- package/packages/core/v4-canonical-contracts.js +9 -75
- package/packages/core/v4-domain-wasm-artifact.js +7 -0
- package/packages/core/v4-domain-wasm.js +216 -0
- package/packages/core/v4-partial-mutation-recovery-qualification.js +9 -386
- package/packages/core/v4-product-publication.js +18 -384
- package/packages/core/v4-provider-operation-journal.js +18 -487
- package/packages/core/v4-provider-readback-idempotency.js +12 -97
- package/packages/core/v4-release-activation-shadow.js +13 -500
- package/packages/core/v4-release-invocation.js +28 -389
- package/packages/core/v4-stable-publication-fence.js +13 -342
- package/scripts/build-v4-domain-wasm.mjs +189 -0
- package/scripts/check-action-bundles.mjs +12 -2
- package/scripts/check-v4-release-topology.mjs +50 -25
- package/scripts/copy-v4-domain-wasm.mjs +14 -0
- package/scripts/dev-delivery-warrant.mjs +7 -3
- package/scripts/generate-v4-universal-workflow-facades.mjs +8 -3
|
@@ -1,105 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
RELEASE_TAIL_DECLARATION_CONTRACT,
|
|
4
|
-
RELEASE_TAIL_EFFECT_SCHEMA,
|
|
5
|
-
RELEASE_TAIL_OBSERVATION_SCHEMA,
|
|
6
|
-
RELEASE_TAIL_RECEIPT_SCHEMA,
|
|
7
|
-
RELEASE_TAIL_TRANSACTION_POLICY,
|
|
8
|
-
} from "./release-tail-provider-plane.js";
|
|
9
|
-
import { RELEASE_TAIL_PRODUCT_CAPABILITIES } from "./release-tail-product-capabilities.js";
|
|
1
|
+
import { invokeV4DomainWasm } from "./v4-domain-wasm.js";
|
|
10
2
|
|
|
11
3
|
export const V4_PRODUCT_PUBLICATION_INTENT_CONTRACT =
|
|
12
4
|
"kungfu-buildchain-v4-product-publication-intent/v1";
|
|
13
5
|
export const V4_PRODUCT_PUBLICATION_PLAN_CONTRACT =
|
|
14
6
|
"kungfu-buildchain-v4-product-publication-plan/v1";
|
|
15
7
|
|
|
16
|
-
const VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-alpha\.(\d+))?$/u;
|
|
17
|
-
const SHA = /^[0-9a-f]{40}$/u;
|
|
18
|
-
const ROOT = /^sha256:[0-9a-f]{64}$/u;
|
|
19
|
-
const REPOSITORY = /^[^/\s]+\/[^/\s]+$/u;
|
|
20
|
-
|
|
21
|
-
function fail(message) {
|
|
22
|
-
throw new Error(`invalid v4 product publication: ${message}`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function parseVersion(value, label) {
|
|
26
|
-
const normalized = String(value || "").trim();
|
|
27
|
-
const match = normalized.match(VERSION);
|
|
28
|
-
if (!match) fail(`${label} must be an exact stable or alpha version`);
|
|
29
|
-
return {
|
|
30
|
-
value: normalized,
|
|
31
|
-
major: Number(match[1]),
|
|
32
|
-
minor: Number(match[2]),
|
|
33
|
-
patch: Number(match[3]),
|
|
34
|
-
alpha: match[4] === undefined ? null : Number(match[4]),
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function channelName(value) {
|
|
39
|
-
if (value === "alpha") return "alpha";
|
|
40
|
-
if (["release", "stable", "major"].includes(value)) return "stable";
|
|
41
|
-
fail(`unsupported channel '${value}'`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function publicationArtifactKind(value) {
|
|
45
|
-
if (!value || value === "npm") return "npm";
|
|
46
|
-
if (value === "custom") return "custom";
|
|
47
|
-
fail(`unsupported artifactKind '${value}'`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function publicationProductCoordinates({
|
|
51
|
-
artifactKind,
|
|
52
|
-
packageName,
|
|
53
|
-
distTag,
|
|
54
|
-
sealedBundleRoot,
|
|
55
|
-
}) {
|
|
56
|
-
if (artifactKind === "custom") return { artifactKind };
|
|
57
|
-
const normalizedDistTag = requiredString(distTag, "distTag");
|
|
58
|
-
if (!/^[a-z0-9][a-z0-9._-]*$/u.test(normalizedDistTag))
|
|
59
|
-
fail("distTag must be an npm dist-tag");
|
|
60
|
-
return {
|
|
61
|
-
packageName: requiredString(packageName, "packageName"),
|
|
62
|
-
distTag: normalizedDistTag,
|
|
63
|
-
sealedBundleRoot: requiredRoot(sealedBundleRoot, "sealedBundleRoot"),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function assertLane({ channel, targetRef, version }) {
|
|
68
|
-
const expression =
|
|
69
|
-
channel === "alpha"
|
|
70
|
-
? /^alpha\/v(\d+)\/v(\d+)\.(\d+)$/u
|
|
71
|
-
: /^release\/v(\d+)\/v(\d+)\.(\d+)$/u;
|
|
72
|
-
const match = String(targetRef || "").match(expression);
|
|
73
|
-
if (!match) fail(`target ref '${targetRef}' is not a ${channel} lane`);
|
|
74
|
-
if (
|
|
75
|
-
Number(match[1]) !== version.major ||
|
|
76
|
-
Number(match[2]) !== version.major ||
|
|
77
|
-
Number(match[3]) !== version.minor
|
|
78
|
-
)
|
|
79
|
-
fail("target ref does not match the publication version line");
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function observedAlphaNumber(version, expected) {
|
|
83
|
-
const parsed = VERSION.test(version) ? parseVersion(version, "observed") : {};
|
|
84
|
-
return parsed.major === expected.major &&
|
|
85
|
-
parsed.minor === expected.minor &&
|
|
86
|
-
parsed.patch === expected.patch
|
|
87
|
-
? parsed.alpha
|
|
88
|
-
: null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function requiredString(value, label) {
|
|
92
|
-
const normalized = String(value || "").trim();
|
|
93
|
-
if (!normalized) fail(`${label} must be a non-empty string`);
|
|
94
|
-
return normalized;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function requiredRoot(value, label) {
|
|
98
|
-
const normalized = requiredString(value, label).toLowerCase();
|
|
99
|
-
if (!ROOT.test(normalized)) fail(`${label} must be a sha256 content root`);
|
|
100
|
-
return normalized;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
8
|
export function selectV4ProductPublicationIntent({
|
|
104
9
|
channel,
|
|
105
10
|
targetRef,
|
|
@@ -115,109 +20,21 @@ export function selectV4ProductPublicationIntent({
|
|
|
115
20
|
recoveredVersion = "",
|
|
116
21
|
observedVersions = [],
|
|
117
22
|
}) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
fail("sourceSha must be an exact Git SHA");
|
|
121
|
-
if (!REPOSITORY.test(String(repository || "")))
|
|
122
|
-
fail("repository must be owner/repo");
|
|
123
|
-
const normalizedTimestamp = requiredString(
|
|
124
|
-
sourceTimestamp,
|
|
125
|
-
"sourceTimestamp",
|
|
126
|
-
);
|
|
127
|
-
if (Number.isNaN(Date.parse(normalizedTimestamp)))
|
|
128
|
-
fail("sourceTimestamp must be an ISO timestamp");
|
|
129
|
-
const normalizedArtifactKind = publicationArtifactKind(
|
|
130
|
-
String(artifactKind || "").trim(),
|
|
131
|
-
);
|
|
132
|
-
const productCoordinates = publicationProductCoordinates({
|
|
133
|
-
artifactKind: normalizedArtifactKind,
|
|
134
|
-
packageName,
|
|
135
|
-
distTag,
|
|
136
|
-
sealedBundleRoot,
|
|
137
|
-
});
|
|
138
|
-
if (!Array.isArray(observedVersions))
|
|
139
|
-
fail("observedVersions must be an array");
|
|
140
|
-
const candidate = parseVersion(candidateVersion, "candidateVersion");
|
|
141
|
-
assertLane({ channel: normalizedChannel, targetRef, version: candidate });
|
|
142
|
-
const observed = [...new Set(observedVersions.map(String))].sort();
|
|
143
|
-
let version;
|
|
144
|
-
let mode = "fresh";
|
|
145
|
-
if (String(recoveredVersion || "").trim()) {
|
|
146
|
-
const recovered = parseVersion(recoveredVersion, "recoveredVersion");
|
|
147
|
-
if (
|
|
148
|
-
recovered.major !== candidate.major ||
|
|
149
|
-
recovered.minor !== candidate.minor ||
|
|
150
|
-
recovered.patch !== candidate.patch ||
|
|
151
|
-
(normalizedChannel === "alpha" && recovered.alpha === null) ||
|
|
152
|
-
(normalizedChannel === "stable" && recovered.alpha !== null)
|
|
153
|
-
)
|
|
154
|
-
fail("recoveredVersion is incompatible with the candidate release line");
|
|
155
|
-
version = recovered.value;
|
|
156
|
-
mode = "resume";
|
|
157
|
-
} else if (normalizedChannel === "alpha") {
|
|
158
|
-
if (candidate.alpha === null)
|
|
159
|
-
fail("fresh alpha publication requires an alpha candidate version");
|
|
160
|
-
if (normalizedArtifactKind === "custom") {
|
|
161
|
-
version = candidate.value;
|
|
162
|
-
} else {
|
|
163
|
-
const highest = observed.reduce(
|
|
164
|
-
(current, entry) =>
|
|
165
|
-
Math.max(current, observedAlphaNumber(entry, candidate) ?? -1),
|
|
166
|
-
candidate.alpha,
|
|
167
|
-
);
|
|
168
|
-
version = `${candidate.major}.${candidate.minor}.${candidate.patch}-alpha.${highest + 1}`;
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
version = `${candidate.major}.${candidate.minor}.${candidate.patch}`;
|
|
172
|
-
}
|
|
173
|
-
const intent = {
|
|
174
|
-
schema: V4_PRODUCT_PUBLICATION_INTENT_CONTRACT,
|
|
175
|
-
mode,
|
|
176
|
-
channel: normalizedChannel,
|
|
23
|
+
return invokeV4DomainWasm("product-publication-intent", {
|
|
24
|
+
channel,
|
|
177
25
|
targetRef,
|
|
178
26
|
sourceSha,
|
|
179
|
-
sourceTimestamp
|
|
27
|
+
sourceTimestamp,
|
|
180
28
|
repository,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
candidateVersion
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
};
|
|
191
|
-
return {
|
|
192
|
-
...intent,
|
|
193
|
-
intentRoot: v4ContentRoot("v4-product-publication-intent", intent),
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function alphaReferences(intent, version) {
|
|
198
|
-
const line = `v${version.major}.${version.minor}`;
|
|
199
|
-
return [
|
|
200
|
-
{ ref: `refs/tags/${intent.exactTag}`, target: "source" },
|
|
201
|
-
{ ref: `refs/heads/${intent.targetRef}`, target: "version-state" },
|
|
202
|
-
{
|
|
203
|
-
ref: `refs/heads/dev/v${version.major}/${line}`,
|
|
204
|
-
target: "version-state",
|
|
205
|
-
},
|
|
206
|
-
{ ref: `refs/tags/${line}-alpha`, target: "version-state" },
|
|
207
|
-
{ ref: `refs/tags/v${version.major}-alpha`, target: "version-state" },
|
|
208
|
-
];
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function stableReferences(intent, version) {
|
|
212
|
-
return [
|
|
213
|
-
{ ref: `refs/tags/${intent.exactTag}`, target: "source" },
|
|
214
|
-
{ ref: `refs/heads/${intent.targetRef}`, target: "version-state" },
|
|
215
|
-
{
|
|
216
|
-
ref: `refs/tags/v${version.major}.${version.minor}`,
|
|
217
|
-
target: "version-state",
|
|
218
|
-
},
|
|
219
|
-
{ ref: `refs/tags/v${version.major}`, target: "version-state" },
|
|
220
|
-
];
|
|
29
|
+
artifactKind,
|
|
30
|
+
...(packageName === undefined ? {} : { packageName }),
|
|
31
|
+
...(distTag === undefined ? {} : { distTag }),
|
|
32
|
+
...(sealedBundleRoot === undefined ? {} : { sealedBundleRoot }),
|
|
33
|
+
requiredArtifactsRoot,
|
|
34
|
+
candidateVersion,
|
|
35
|
+
recoveredVersion,
|
|
36
|
+
observedVersions,
|
|
37
|
+
});
|
|
221
38
|
}
|
|
222
39
|
|
|
223
40
|
export function createV4ProductPublicationPlan({
|
|
@@ -225,199 +42,16 @@ export function createV4ProductPublicationPlan({
|
|
|
225
42
|
invocationRoot,
|
|
226
43
|
transactionRoot,
|
|
227
44
|
}) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const selected = selectV4ProductPublicationIntent({
|
|
231
|
-
channel: intent.channel,
|
|
232
|
-
targetRef: intent.targetRef,
|
|
233
|
-
sourceSha: intent.sourceSha,
|
|
234
|
-
sourceTimestamp: intent.sourceTimestamp,
|
|
235
|
-
repository: intent.repository,
|
|
236
|
-
artifactKind: intent.artifactKind,
|
|
237
|
-
packageName: intent.packageName,
|
|
238
|
-
distTag: intent.distTag,
|
|
239
|
-
sealedBundleRoot: intent.sealedBundleRoot,
|
|
240
|
-
requiredArtifactsRoot: intent.requiredArtifactsRoot,
|
|
241
|
-
candidateVersion: intent.candidateVersion,
|
|
242
|
-
recoveredVersion: intent.mode === "resume" ? intent.version : "",
|
|
243
|
-
observedVersions: intent.observedVersions,
|
|
244
|
-
});
|
|
245
|
-
if (selected.intentRoot !== intent.intentRoot)
|
|
246
|
-
fail("intentRoot does not match the canonical publication intent");
|
|
247
|
-
const parsed = parseVersion(intent.version, "intent.version");
|
|
248
|
-
const references =
|
|
249
|
-
intent.channel === "alpha"
|
|
250
|
-
? alphaReferences(intent, parsed)
|
|
251
|
-
: stableReferences(intent, parsed);
|
|
252
|
-
const stateRef = `refs/heads/buildchain/v4-product-state/${intent.sourceSha}-${intent.version.replaceAll(".", "-")}`;
|
|
253
|
-
const operations = [
|
|
254
|
-
{
|
|
255
|
-
id: "product.version-state.materialize",
|
|
256
|
-
adapter: "github-version-state",
|
|
257
|
-
authority: "contents-write",
|
|
258
|
-
target: {
|
|
259
|
-
repository: intent.repository,
|
|
260
|
-
version: intent.version,
|
|
261
|
-
sourceSha: intent.sourceSha,
|
|
262
|
-
sourceTimestamp: intent.sourceTimestamp,
|
|
263
|
-
stateRef,
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
...(intent.artifactKind === "custom"
|
|
267
|
-
? []
|
|
268
|
-
: [
|
|
269
|
-
{
|
|
270
|
-
id: "product.package.publish",
|
|
271
|
-
adapter: "npm-trusted-publishing",
|
|
272
|
-
authority: "oidc-provider-mutation",
|
|
273
|
-
target: {
|
|
274
|
-
packageName: intent.packageName,
|
|
275
|
-
version: intent.version,
|
|
276
|
-
distTag: intent.distTag,
|
|
277
|
-
sealedBundleRoot: intent.sealedBundleRoot,
|
|
278
|
-
requiredArtifactsRoot: intent.requiredArtifactsRoot,
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
]),
|
|
282
|
-
{
|
|
283
|
-
id: "product.release-refs.converge",
|
|
284
|
-
adapter: "github-release-refs",
|
|
285
|
-
authority: "contents-write",
|
|
286
|
-
target: {
|
|
287
|
-
repository: intent.repository,
|
|
288
|
-
sourceSha: intent.sourceSha,
|
|
289
|
-
stateRef,
|
|
290
|
-
references,
|
|
291
|
-
},
|
|
292
|
-
},
|
|
293
|
-
].map((operation) => ({
|
|
294
|
-
...operation,
|
|
295
|
-
operationRoot: v4ContentRoot("v4-product-publication-operation", operation),
|
|
296
|
-
}));
|
|
297
|
-
const plan = {
|
|
298
|
-
schema: V4_PRODUCT_PUBLICATION_PLAN_CONTRACT,
|
|
299
|
-
intentRoot: intent.intentRoot,
|
|
45
|
+
return invokeV4DomainWasm("product-publication-plan", {
|
|
46
|
+
intent,
|
|
300
47
|
invocationRoot,
|
|
301
48
|
transactionRoot,
|
|
302
|
-
|
|
303
|
-
operations,
|
|
304
|
-
};
|
|
305
|
-
return {
|
|
306
|
-
...plan,
|
|
307
|
-
planRoot: v4ContentRoot("v4-product-publication-plan", plan),
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const PRODUCT_CAPABILITIES = Object.fromEntries(
|
|
312
|
-
RELEASE_TAIL_PRODUCT_CAPABILITIES.map((capability) => [
|
|
313
|
-
capability.id,
|
|
314
|
-
{
|
|
315
|
-
...capability,
|
|
316
|
-
destinationKind:
|
|
317
|
-
capability.id === "product.package.publish"
|
|
318
|
-
? "npm-package"
|
|
319
|
-
: capability.adapter,
|
|
320
|
-
},
|
|
321
|
-
]),
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
function exactTagPattern(tag) {
|
|
325
|
-
return `^${tag.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}$`;
|
|
49
|
+
});
|
|
326
50
|
}
|
|
327
51
|
|
|
328
52
|
export function createV4ProductPublicationDeclaration({ intent, plan }) {
|
|
329
|
-
|
|
53
|
+
return invokeV4DomainWasm("product-publication-declaration", {
|
|
330
54
|
intent,
|
|
331
|
-
|
|
332
|
-
transactionRoot: plan.transactionRoot,
|
|
55
|
+
plan,
|
|
333
56
|
});
|
|
334
|
-
if (rebuilt.planRoot !== plan.planRoot)
|
|
335
|
-
fail("planRoot does not match the canonical publication plan");
|
|
336
|
-
const operationById = new Map(
|
|
337
|
-
plan.operations.map((operation) => [operation.id, operation]),
|
|
338
|
-
);
|
|
339
|
-
return {
|
|
340
|
-
contract: RELEASE_TAIL_DECLARATION_CONTRACT,
|
|
341
|
-
schemaVersion: 1,
|
|
342
|
-
transactionPolicy: RELEASE_TAIL_TRANSACTION_POLICY,
|
|
343
|
-
subject: {
|
|
344
|
-
repository: intent.repository,
|
|
345
|
-
sourceSha: intent.sourceSha,
|
|
346
|
-
version: intent.version,
|
|
347
|
-
tag: intent.exactTag,
|
|
348
|
-
channel: intent.channel,
|
|
349
|
-
},
|
|
350
|
-
capabilities: plan.operationOrder.map((id) => {
|
|
351
|
-
const operation = operationById.get(id);
|
|
352
|
-
const descriptor = PRODUCT_CAPABILITIES[id];
|
|
353
|
-
if (!operation || !descriptor)
|
|
354
|
-
fail(`unsupported product publication operation '${id}'`);
|
|
355
|
-
return {
|
|
356
|
-
id,
|
|
357
|
-
executor: "provider-adapter",
|
|
358
|
-
adapter: operation.adapter,
|
|
359
|
-
artifactRoles: [
|
|
360
|
-
{ role: "publication-intent", root: intent.intentRoot },
|
|
361
|
-
...(id === "product.package.publish"
|
|
362
|
-
? [
|
|
363
|
-
{ role: "sealed-bundle", root: intent.sealedBundleRoot },
|
|
364
|
-
{
|
|
365
|
-
role: "required-artifacts",
|
|
366
|
-
root: intent.requiredArtifactsRoot,
|
|
367
|
-
},
|
|
368
|
-
]
|
|
369
|
-
: []),
|
|
370
|
-
],
|
|
371
|
-
destination: {
|
|
372
|
-
kind: descriptor.destinationKind,
|
|
373
|
-
locator: `${operation.adapter}:${operation.operationRoot}`,
|
|
374
|
-
},
|
|
375
|
-
channelPolicy: {
|
|
376
|
-
channel: intent.channel,
|
|
377
|
-
tagPattern: exactTagPattern(intent.exactTag),
|
|
378
|
-
authorityMove:
|
|
379
|
-
id === "product.package.publish" ? "none" : "verified-ref",
|
|
380
|
-
},
|
|
381
|
-
activationPolicy: { mode: "none", environment: "none" },
|
|
382
|
-
readbackPredicates: [
|
|
383
|
-
{
|
|
384
|
-
id: `${id}.target-root`,
|
|
385
|
-
kind: "exact-root",
|
|
386
|
-
expected: operation.operationRoot,
|
|
387
|
-
},
|
|
388
|
-
],
|
|
389
|
-
effect: {
|
|
390
|
-
schema: RELEASE_TAIL_EFFECT_SCHEMA,
|
|
391
|
-
kind: descriptor.effectKind,
|
|
392
|
-
},
|
|
393
|
-
observation: {
|
|
394
|
-
schema: RELEASE_TAIL_OBSERVATION_SCHEMA,
|
|
395
|
-
kind: descriptor.observationKind,
|
|
396
|
-
},
|
|
397
|
-
receipt: {
|
|
398
|
-
schema: RELEASE_TAIL_RECEIPT_SCHEMA,
|
|
399
|
-
kind: descriptor.receiptKind,
|
|
400
|
-
},
|
|
401
|
-
operationIdentity: {
|
|
402
|
-
transactionRoot: plan.transactionRoot,
|
|
403
|
-
capabilityId: id,
|
|
404
|
-
subjectRoot: intent.intentRoot,
|
|
405
|
-
targetRoot: operation.operationRoot,
|
|
406
|
-
attemptKey: `${plan.planRoot}:${id}`,
|
|
407
|
-
},
|
|
408
|
-
idempotency: {
|
|
409
|
-
scope: "subject-target",
|
|
410
|
-
duplicate: "readback-before-retry",
|
|
411
|
-
},
|
|
412
|
-
retry: {
|
|
413
|
-
class: "provider-transient",
|
|
414
|
-
localAttempts: 1,
|
|
415
|
-
exhausted: "blocked",
|
|
416
|
-
},
|
|
417
|
-
evidenceRequirements: [
|
|
418
|
-
"provider readback must match the rooted publication operation",
|
|
419
|
-
],
|
|
420
|
-
};
|
|
421
|
-
}),
|
|
422
|
-
};
|
|
423
57
|
}
|