@kungfu-tech/buildchain 4.0.2-alpha.0 → 4.0.2-alpha.11
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 +52 -5
- package/architecture/ci-lane-change-budget.json +408 -8
- package/architecture/internal-capabilities.json +44 -1
- package/architecture/maintainability-debt.json +65 -133
- package/architecture/maintainability-policy.json +20 -15
- package/architecture/release-tail-contract-inventory.json +4 -4
- package/architecture/v3-core-mechanism-inventory.json +1 -0
- package/architecture/v3-v4-live-capability-inventory.json +17 -17
- package/architecture/v4-delivery-warrant-shadow-fixtures.json +5 -5
- package/architecture/v4-release-invocation-fixtures.json +139 -0
- package/architecture/v4-release-topology.json +317 -0
- package/architecture/v4-runtime-semantic-closure.json +4 -1
- package/architecture/v4-universal-workflow-bootstrap.json +181 -0
- package/architecture/v4-universal-workflow-fault-campaign.json +72 -0
- package/architecture/v4-universal-workflow-train-admission.json +40 -0
- package/contracts/buildchain-v2-residuals-v1.json +0 -9
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
- package/contracts/v4-release-invocation-v1.schema.json +134 -0
- package/dist/site/buildchain-contract.json +87 -42
- package/dist/site/buildchain-site.json +15 -10
- package/dist/site/capability-registry.json +1 -1
- package/dist/site/controller-registry.json +46 -10
- package/dist/site/kfd-claims.json +176 -69
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +2 -2
- package/dist/site/node-api-registry.json +97 -22
- package/dist/site/page-registry.json +9 -4
- package/dist/site/public-surface-audit.json +190 -71
- package/dist/site/publication-authority-registry.json +68 -3
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +6 -6
- package/dist/site/workflow-registry.json +221 -72
- package/docs/node-api-reference.md +28 -25
- package/docs/reusable-build-surface.md +16 -0
- package/package.json +2 -2
- package/packages/core/buildchain-publication-authority.js +3 -0
- package/packages/core/ci-lane-change-budget.js +14 -1
- package/packages/core/dev-delivery-candidate-identity.js +45 -17
- package/packages/core/dev-delivery-execution-transfer.js +6 -7
- package/packages/core/dev-delivery-provider-heartbeat.js +22 -6
- package/packages/core/dev-delivery-warrant-legacy-recovery.js +4 -2
- package/packages/core/dev-delivery-warrant-native-compatibility.js +33 -0
- package/packages/core/dev-delivery-warrant-state.js +54 -54
- package/packages/core/dev-delivery-warrant.js +8 -0
- package/packages/core/dev-delivery-writer-protocol-transition.js +72 -0
- package/packages/core/release-tail-product-capabilities.js +29 -0
- package/packages/core/release-tail-provider-plane.js +3 -3
- package/packages/core/v4-canonical-contracts.js +14 -0
- package/packages/core/v4-floating-consumer-policy.js +4 -1
- package/packages/core/v4-product-publication.js +387 -0
- package/packages/core/v4-protected-publication-source.js +93 -0
- package/packages/core/v4-publication-qualification.js +1 -0
- package/packages/core/v4-release-invocation.js +425 -0
- package/packages/core/v4-universal-workflow-bootstrap.js +596 -0
- package/scripts/audit-publication-control-plane.mjs +0 -1
- package/scripts/check-inventory.mjs +27 -59
- package/scripts/check-maintainability.mjs +29 -118
- package/scripts/check-v3-v4-capability-inventory.mjs +3 -61
- package/scripts/check-v4-floating-consumer-policy-contract.mjs +10 -20
- package/scripts/check-v4-release-topology.mjs +493 -0
- package/scripts/check-v4-universal-workflow-bootstrap.mjs +257 -0
- package/scripts/dev-delivery-warrant.mjs +26 -5
- package/scripts/generate-channel-build-workflow.mjs +5 -1
- package/scripts/generate-channel-promotion-workflow.mjs +17 -57
- package/scripts/generate-v4-universal-workflow-facades.mjs +415 -0
- package/scripts/maintainability-public-surface.mjs +115 -0
- package/scripts/release-candidate-resolver.mjs +23 -24
- package/scripts/resume-from-candidate-run.mjs +16 -17
- package/scripts/universal-facade-maintainability.mjs +82 -0
- package/scripts/v3-v4-capability-catalog.mjs +107 -0
- package/scripts/v4-declarative-promotion-admission.mjs +4 -1
- package/scripts/v4-product-publication-intent.mjs +114 -0
- package/scripts/v4-release-candidate-adapter.mjs +41 -0
- package/scripts/v4-universal-workflow-backflow.mjs +212 -0
- package/scripts/v4-universal-workflow-engine.mjs +586 -0
- package/scripts/v4-universal-workflow-self-dogfood.mjs +205 -0
- package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
- package/templates/universal-buildchain-bootstrap.yml +28 -0
- package/scripts/capture-package-release-propagation.mjs +0 -263
- package/scripts/publication-commit-evidence.mjs +0 -444
- package/scripts/publish-github-artifact-attestation-evidence.mjs +0 -201
- package/scripts/stage-github-artifact-attestation-inputs.mjs +0 -65
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function lacksExactNativeExecutionContract(
|
|
2
|
+
candidate,
|
|
3
|
+
allowLegacyV3Readback = false,
|
|
4
|
+
) {
|
|
5
|
+
const native =
|
|
6
|
+
candidate.deliveryClass !== "non-native-fast" ||
|
|
7
|
+
candidate.environmentRoot ||
|
|
8
|
+
candidate.nativeCommandContract;
|
|
9
|
+
return Boolean(
|
|
10
|
+
native &&
|
|
11
|
+
(!candidate.environmentRoot ||
|
|
12
|
+
(!candidate.nativeCommandContract && !allowLegacyV3Readback)),
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function lacksLiveNativeProof(
|
|
17
|
+
candidate,
|
|
18
|
+
status,
|
|
19
|
+
{ allowLegacyV3Readback = false, allowLegacyQueuedReadback = false } = {},
|
|
20
|
+
) {
|
|
21
|
+
return (
|
|
22
|
+
lacksExactNativeExecutionContract(candidate, allowLegacyV3Readback) &&
|
|
23
|
+
!(status === "queued" && allowLegacyQueuedReadback) &&
|
|
24
|
+
!TERMINAL_STATES.has(status)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const TERMINAL_STATES = new Set([
|
|
28
|
+
"merged",
|
|
29
|
+
"terminal-failure",
|
|
30
|
+
"dequeued",
|
|
31
|
+
"cancelled",
|
|
32
|
+
"superseded",
|
|
33
|
+
]);
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
chainedDevDeliveryAttemptInput,
|
|
14
14
|
createDevDeliveryCandidateIdentity,
|
|
15
|
+
EXACT_DEV_DELIVERY_PROOF_FIELDS,
|
|
16
|
+
matchesExactDevDeliveryCandidate,
|
|
15
17
|
validateDevDeliveryCandidateChain,
|
|
16
18
|
} from "./dev-delivery-candidate-identity.js";
|
|
17
19
|
import {
|
|
@@ -19,6 +21,10 @@ import {
|
|
|
19
21
|
normalizeNativeCommandContract,
|
|
20
22
|
validateActiveDevDeliveryWarrant,
|
|
21
23
|
} from "./dev-delivery-native-proof.js";
|
|
24
|
+
import {
|
|
25
|
+
lacksExactNativeExecutionContract,
|
|
26
|
+
lacksLiveNativeProof,
|
|
27
|
+
} from "./dev-delivery-warrant-native-compatibility.js";
|
|
22
28
|
import {
|
|
23
29
|
normalizeProviderFailureAuthorityBinding,
|
|
24
30
|
normalizeTerminalEvidenceCorrection,
|
|
@@ -34,6 +40,8 @@ export const DEV_DELIVERY_WARRANT_SCHEMA =
|
|
|
34
40
|
"kungfu.buildchain.dev-delivery-warrant/v1";
|
|
35
41
|
export const DEV_DELIVERY_SUBMISSION_RECEIPT_SCHEMA =
|
|
36
42
|
"kungfu.buildchain.dev-delivery-submission-receipt/v1";
|
|
43
|
+
export const DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT =
|
|
44
|
+
"sha256:54a203cadf0b14d4e3c198a3cc3c177c42813aa1c0cca03e900df714b6ae5563";
|
|
37
45
|
export const DEV_DELIVERY_SELECTION_RECEIPT_SCHEMA =
|
|
38
46
|
"kungfu.buildchain.dev-delivery-selection-receipt/v1";
|
|
39
47
|
export const DEV_DELIVERY_LEASE_RECEIPT_SCHEMA =
|
|
@@ -146,7 +154,7 @@ function exactRoots(values, label) {
|
|
|
146
154
|
return [...new Set(values.map((value) => exactRoot(value, label)))].sort();
|
|
147
155
|
}
|
|
148
156
|
function normalizePolicy(policy = {}) {
|
|
149
|
-
|
|
157
|
+
const normalized = {
|
|
150
158
|
agingSeconds: positiveInteger(
|
|
151
159
|
policy.agingSeconds,
|
|
152
160
|
"policy agingSeconds",
|
|
@@ -160,22 +168,17 @@ function normalizePolicy(policy = {}) {
|
|
|
160
168
|
),
|
|
161
169
|
emergencyPolicy: text(policy.emergencyPolicy || "reviewed-explicit-only"),
|
|
162
170
|
};
|
|
171
|
+
if (Object.hasOwn(policy, "minimumWriterProtocolRoot")) {
|
|
172
|
+
const root = exactRoot(
|
|
173
|
+
policy.minimumWriterProtocolRoot,
|
|
174
|
+
"policy minimumWriterProtocolRoot",
|
|
175
|
+
);
|
|
176
|
+
if (root !== DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT)
|
|
177
|
+
throw new Error("unsupported dev delivery minimum writer protocol");
|
|
178
|
+
normalized.minimumWriterProtocolRoot = root;
|
|
179
|
+
}
|
|
180
|
+
return normalized;
|
|
163
181
|
}
|
|
164
|
-
|
|
165
|
-
function lacksLiveNativeProof(candidate, status, allowLegacyV3Readback) {
|
|
166
|
-
const { environmentRoot, nativeCommandContract } = candidate;
|
|
167
|
-
const native =
|
|
168
|
-
candidate.deliveryClass !== "non-native-fast" ||
|
|
169
|
-
environmentRoot ||
|
|
170
|
-
nativeCommandContract;
|
|
171
|
-
return (
|
|
172
|
-
native &&
|
|
173
|
-
(!environmentRoot ||
|
|
174
|
-
(!nativeCommandContract && allowLegacyV3Readback !== true)) &&
|
|
175
|
-
!TERMINAL_STATES.has(status)
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
182
|
function normalizeCandidate(input, expected) {
|
|
180
183
|
const identity = createDevDeliveryCandidateIdentity(
|
|
181
184
|
input,
|
|
@@ -274,7 +277,12 @@ function normalizeCandidate(input, expected) {
|
|
|
274
277
|
"candidate shardEvidenceRoots",
|
|
275
278
|
);
|
|
276
279
|
}
|
|
277
|
-
if (
|
|
280
|
+
if (
|
|
281
|
+
lacksLiveNativeProof(candidate, status, {
|
|
282
|
+
allowLegacyV3Readback: expected.allowLegacyV3Readback,
|
|
283
|
+
allowLegacyQueuedReadback: expected.allowLegacyQueuedNativeReadback,
|
|
284
|
+
})
|
|
285
|
+
)
|
|
278
286
|
throw new Error("live native candidate requires exact native proof");
|
|
279
287
|
if (Object.hasOwn(input, "releaseBlockerPriority"))
|
|
280
288
|
candidate.releaseBlockerPriority = normalizeReleaseBlockerPriorityClaim(
|
|
@@ -308,7 +316,10 @@ export function createDevDeliveryQueue({
|
|
|
308
316
|
protectedBase: protectedBase(protectedBaseInput),
|
|
309
317
|
generation: 0,
|
|
310
318
|
fencingCounter: 0,
|
|
311
|
-
policy:
|
|
319
|
+
policy: {
|
|
320
|
+
...normalizePolicy(policy),
|
|
321
|
+
minimumWriterProtocolRoot: DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT,
|
|
322
|
+
},
|
|
312
323
|
activeWarrant: null,
|
|
313
324
|
candidates: [],
|
|
314
325
|
updatedAt: timestamp(now, "now"),
|
|
@@ -344,16 +355,19 @@ export function normalizeDevDeliveryQueue(input, expected = {}) {
|
|
|
344
355
|
"queue fencingCounter",
|
|
345
356
|
);
|
|
346
357
|
queue.policy = normalizePolicy(queue.policy);
|
|
358
|
+
const hasExecutionReceipt = !!queue.activeWarrant?.nativeExecutionReceiptRoot;
|
|
359
|
+
const hasQualificationReceipt =
|
|
360
|
+
!!queue.activeWarrant?.qualificationReceiptRoot;
|
|
347
361
|
const allowLegacyV3Readback =
|
|
348
362
|
expected.allowLegacyV3Readback === true &&
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
363
|
+
hasExecutionReceipt === hasQualificationReceipt;
|
|
364
|
+
const candidateExpected = {
|
|
365
|
+
...queue,
|
|
366
|
+
allowLegacyV3Readback,
|
|
367
|
+
allowLegacyQueuedNativeReadback: true,
|
|
368
|
+
};
|
|
355
369
|
queue.candidates = (queue.candidates || []).map((candidate) =>
|
|
356
|
-
normalizeCandidate(candidate,
|
|
370
|
+
normalizeCandidate(candidate, candidateExpected),
|
|
357
371
|
);
|
|
358
372
|
validateDevDeliveryCandidateChain(queue.candidates, TERMINAL_STATES);
|
|
359
373
|
queue.updatedAt = timestamp(queue.updatedAt, "queue updatedAt");
|
|
@@ -380,6 +394,8 @@ export function transitionDevDeliveryQueue(queueInput, mutate, nowInput) {
|
|
|
380
394
|
delete queue.stateRoot;
|
|
381
395
|
const now = timestamp(nowInput, "now");
|
|
382
396
|
const result = mutate(queue, before, now);
|
|
397
|
+
if (result.preserveState)
|
|
398
|
+
return { before, after: before, expectedOldStateRoot, result };
|
|
383
399
|
queue.generation += 1;
|
|
384
400
|
queue.updatedAt = now;
|
|
385
401
|
const after = withQueueRoot(queue);
|
|
@@ -478,34 +494,14 @@ export function submitDevDeliveryCandidate(
|
|
|
478
494
|
`candidate ${attemptedCandidate.candidateId} is terminal and cannot be resubmitted`,
|
|
479
495
|
);
|
|
480
496
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
"dependencyRoot",
|
|
487
|
-
"toolchainRoot",
|
|
488
|
-
"environmentRoot",
|
|
489
|
-
"sourceWorkflowRunId",
|
|
490
|
-
];
|
|
491
|
-
const exactProofMatches =
|
|
492
|
-
exactProofFields.every(
|
|
493
|
-
(field) => existing[field] === attemptedCandidate[field],
|
|
494
|
-
) &&
|
|
495
|
-
JSON.stringify(existing.affectedPaths || []) ===
|
|
496
|
-
JSON.stringify(attemptedCandidate.affectedPaths || []) &&
|
|
497
|
-
JSON.stringify(existing.shardEvidenceRoots || []) ===
|
|
498
|
-
JSON.stringify(attemptedCandidate.shardEvidenceRoots || []) &&
|
|
499
|
-
existing.nativeCommandContract?.commandRoot ===
|
|
500
|
-
attemptedCandidate.nativeCommandContract?.commandRoot &&
|
|
501
|
-
existing.releaseBlockerPriority?.claimRoot ===
|
|
502
|
-
attemptedCandidate.releaseBlockerPriority?.claimRoot;
|
|
503
|
-
if (
|
|
504
|
-
existing.sourceHead === attemptedCandidate.sourceHead &&
|
|
505
|
-
exactProofMatches
|
|
506
|
-
) {
|
|
507
|
-
action = "duplicate-noop";
|
|
497
|
+
if (matchesExactDevDeliveryCandidate(existing, attemptedCandidate)) {
|
|
498
|
+
action =
|
|
499
|
+
before.activeWarrant?.candidateId === existing.candidateId
|
|
500
|
+
? "active-warrant-noop"
|
|
501
|
+
: "duplicate-noop";
|
|
508
502
|
selected = existing;
|
|
503
|
+
if (action === "active-warrant-noop")
|
|
504
|
+
return { candidate: selected, action, preserveState: true };
|
|
509
505
|
} else {
|
|
510
506
|
if (before.activeWarrant?.candidateId === existing.candidateId) {
|
|
511
507
|
throw new Error(
|
|
@@ -515,7 +511,7 @@ export function submitDevDeliveryCandidate(
|
|
|
515
511
|
const headChanged =
|
|
516
512
|
existing.sourceHead !== attemptedCandidate.sourceHead;
|
|
517
513
|
existing.sourceHead = attemptedCandidate.sourceHead;
|
|
518
|
-
for (const field of
|
|
514
|
+
for (const field of EXACT_DEV_DELIVERY_PROOF_FIELDS)
|
|
519
515
|
existing[field] = attemptedCandidate[field];
|
|
520
516
|
if (attemptedCandidate.nativeCommandContract)
|
|
521
517
|
existing.nativeCommandContract =
|
|
@@ -585,7 +581,11 @@ export function rankDevDeliveryCandidates(
|
|
|
585
581
|
});
|
|
586
582
|
const currentTime = timestamp(now, "now");
|
|
587
583
|
return queue.candidates
|
|
588
|
-
.filter(
|
|
584
|
+
.filter(
|
|
585
|
+
(candidate) =>
|
|
586
|
+
candidate.status === "queued" &&
|
|
587
|
+
!lacksExactNativeExecutionContract(candidate),
|
|
588
|
+
)
|
|
589
589
|
.map((candidate) => ({
|
|
590
590
|
candidate,
|
|
591
591
|
priority: effectivePriority(candidate, queue.policy, currentTime),
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
DEV_DELIVERY_QUEUE_CONTRACT,
|
|
30
30
|
DEV_DELIVERY_SELECTION_RECEIPT_SCHEMA,
|
|
31
31
|
DEV_DELIVERY_SUBMISSION_RECEIPT_SCHEMA,
|
|
32
|
+
DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT,
|
|
32
33
|
DEV_DELIVERY_WARRANT_SCHEMA,
|
|
33
34
|
TERMINAL_STATES,
|
|
34
35
|
createDevDeliveryQueue,
|
|
@@ -38,6 +39,10 @@ import {
|
|
|
38
39
|
submitDevDeliveryCandidate,
|
|
39
40
|
transitionDevDeliveryQueue as transition,
|
|
40
41
|
} from "./dev-delivery-warrant-state.js";
|
|
42
|
+
import {
|
|
43
|
+
DEV_DELIVERY_WRITER_PROTOCOL_FENCE_RECEIPT_SCHEMA,
|
|
44
|
+
fenceDevDeliveryWriterProtocol,
|
|
45
|
+
} from "./dev-delivery-writer-protocol-transition.js";
|
|
41
46
|
|
|
42
47
|
export { devDeliveryContentRoot } from "./dev-delivery-common.js";
|
|
43
48
|
export {
|
|
@@ -85,8 +90,11 @@ export {
|
|
|
85
90
|
DEV_DELIVERY_QUEUE_CONTRACT,
|
|
86
91
|
DEV_DELIVERY_SELECTION_RECEIPT_SCHEMA,
|
|
87
92
|
DEV_DELIVERY_SUBMISSION_RECEIPT_SCHEMA,
|
|
93
|
+
DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT,
|
|
94
|
+
DEV_DELIVERY_WRITER_PROTOCOL_FENCE_RECEIPT_SCHEMA,
|
|
88
95
|
DEV_DELIVERY_WARRANT_SCHEMA,
|
|
89
96
|
createDevDeliveryQueue,
|
|
97
|
+
fenceDevDeliveryWriterProtocol,
|
|
90
98
|
normalizeDevDeliveryQueue,
|
|
91
99
|
rankDevDeliveryCandidates,
|
|
92
100
|
submitDevDeliveryCandidate,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { devDeliveryContentRoot } from "./dev-delivery-common.js";
|
|
2
|
+
import {
|
|
3
|
+
DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT,
|
|
4
|
+
TERMINAL_STATES,
|
|
5
|
+
transitionDevDeliveryQueue,
|
|
6
|
+
} from "./dev-delivery-warrant-state.js";
|
|
7
|
+
|
|
8
|
+
export const DEV_DELIVERY_WRITER_PROTOCOL = Object.freeze({
|
|
9
|
+
schema: "kungfu.buildchain.dev-delivery-writer-protocol/v1",
|
|
10
|
+
requiredCandidateCapabilities: [
|
|
11
|
+
"environment-root-v1",
|
|
12
|
+
"native-command-contract-v1",
|
|
13
|
+
],
|
|
14
|
+
});
|
|
15
|
+
export const DEV_DELIVERY_WRITER_PROTOCOL_FENCE_RECEIPT_SCHEMA =
|
|
16
|
+
"kungfu.buildchain.dev-delivery-writer-protocol-fence-receipt/v1";
|
|
17
|
+
if (
|
|
18
|
+
devDeliveryContentRoot(DEV_DELIVERY_WRITER_PROTOCOL) !==
|
|
19
|
+
DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT
|
|
20
|
+
) {
|
|
21
|
+
throw new Error("dev delivery writer protocol root drift");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function fenceDevDeliveryWriterProtocol(
|
|
25
|
+
queueInput,
|
|
26
|
+
{ now = new Date().toISOString() } = {},
|
|
27
|
+
) {
|
|
28
|
+
const transaction = transitionDevDeliveryQueue(
|
|
29
|
+
queueInput,
|
|
30
|
+
(queue) => {
|
|
31
|
+
if (
|
|
32
|
+
queue.policy.minimumWriterProtocolRoot ===
|
|
33
|
+
DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT
|
|
34
|
+
) {
|
|
35
|
+
return {
|
|
36
|
+
action: "minimum-writer-protocol-already-fenced",
|
|
37
|
+
preserveState: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (
|
|
41
|
+
queue.activeWarrant ||
|
|
42
|
+
queue.candidates.some(
|
|
43
|
+
(candidate) => !TERMINAL_STATES.has(candidate.status),
|
|
44
|
+
)
|
|
45
|
+
) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
"minimum writer protocol can be fenced only while the queue is idle",
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
queue.policy.minimumWriterProtocolRoot =
|
|
51
|
+
DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT;
|
|
52
|
+
return { action: "minimum-writer-protocol-fenced" };
|
|
53
|
+
},
|
|
54
|
+
now,
|
|
55
|
+
);
|
|
56
|
+
const receipt = {
|
|
57
|
+
schema: DEV_DELIVERY_WRITER_PROTOCOL_FENCE_RECEIPT_SCHEMA,
|
|
58
|
+
action: transaction.result.action,
|
|
59
|
+
repository: transaction.after.repository,
|
|
60
|
+
protectedBase: transaction.after.protectedBase,
|
|
61
|
+
minimumWriterProtocolRoot: DEV_DELIVERY_MINIMUM_WRITER_PROTOCOL_ROOT,
|
|
62
|
+
expectedOldStateRoot: transaction.expectedOldStateRoot,
|
|
63
|
+
nextStateRoot: transaction.after.stateRoot,
|
|
64
|
+
nextAction:
|
|
65
|
+
"Use only a Buildchain runtime that preserves the rooted minimum writer protocol.",
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
queue: transaction.after,
|
|
69
|
+
receipt,
|
|
70
|
+
receiptRoot: devDeliveryContentRoot(receipt),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const RELEASE_TAIL_PRODUCT_CAPABILITIES = Object.freeze([
|
|
2
|
+
Object.freeze({
|
|
3
|
+
id: "product.version-state.materialize",
|
|
4
|
+
executor: "provider-adapter",
|
|
5
|
+
adapter: "github-version-state",
|
|
6
|
+
effectKind: "product-version-state-materialization",
|
|
7
|
+
observationKind: "product-version-state-readback",
|
|
8
|
+
receiptKind: "product-version-state",
|
|
9
|
+
transactionState: "preparing",
|
|
10
|
+
}),
|
|
11
|
+
Object.freeze({
|
|
12
|
+
id: "product.package.publish",
|
|
13
|
+
executor: "provider-adapter",
|
|
14
|
+
adapter: "npm-trusted-publishing",
|
|
15
|
+
effectKind: "product-package-publication",
|
|
16
|
+
observationKind: "product-package-readback",
|
|
17
|
+
receiptKind: "product-package-publication",
|
|
18
|
+
transactionState: "publishing",
|
|
19
|
+
}),
|
|
20
|
+
Object.freeze({
|
|
21
|
+
id: "product.release-refs.converge",
|
|
22
|
+
executor: "provider-adapter",
|
|
23
|
+
adapter: "github-release-refs",
|
|
24
|
+
effectKind: "product-release-ref-convergence",
|
|
25
|
+
observationKind: "product-release-ref-readback",
|
|
26
|
+
receiptKind: "product-release-ref-convergence",
|
|
27
|
+
transactionState: "committing",
|
|
28
|
+
}),
|
|
29
|
+
]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
|
|
4
|
+
import { RELEASE_TAIL_PRODUCT_CAPABILITIES } from "./release-tail-product-capabilities.js";
|
|
5
5
|
export const RELEASE_TAIL_DECLARATION_CONTRACT =
|
|
6
6
|
"kungfu-buildchain-release-tail-capabilities";
|
|
7
7
|
export const RELEASE_TAIL_TRANSACTION_POLICY = "buildchain.release-tail/v1";
|
|
@@ -27,8 +27,8 @@ export const RELEASE_TAIL_STATES = Object.freeze([
|
|
|
27
27
|
"repair-required",
|
|
28
28
|
"terminal-failure",
|
|
29
29
|
]);
|
|
30
|
-
|
|
31
30
|
export const RELEASE_TAIL_CAPABILITY_REGISTRY = Object.freeze([
|
|
31
|
+
...RELEASE_TAIL_PRODUCT_CAPABILITIES,
|
|
32
32
|
Object.freeze({
|
|
33
33
|
id: "artifact.publish",
|
|
34
34
|
executor: "provider-adapter",
|
|
@@ -1102,7 +1102,7 @@ export async function executeReleaseTailTransaction(
|
|
|
1102
1102
|
if (cycle + 1 < maxCycles) continue;
|
|
1103
1103
|
break;
|
|
1104
1104
|
}
|
|
1105
|
-
if (applied
|
|
1105
|
+
if (applied) continue;
|
|
1106
1106
|
|
|
1107
1107
|
operation = current.operations.find(
|
|
1108
1108
|
(entry) => entry.operationId === pending.operationId,
|
|
@@ -56,11 +56,25 @@ const ROOT_DOMAINS = new Set([
|
|
|
56
56
|
"stable-publication-fence",
|
|
57
57
|
"partial-mutation-recovery-checkpoint",
|
|
58
58
|
"partial-mutation-recovery-plan",
|
|
59
|
+
"v4-product-required-artifacts",
|
|
60
|
+
"v4-product-publication-intent",
|
|
61
|
+
"v4-product-publication-operation",
|
|
62
|
+
"v4-product-publication-plan",
|
|
59
63
|
"tail-reseal-plan",
|
|
60
64
|
"tail-reseal-admission",
|
|
61
65
|
"tail-reseal-artifact-files",
|
|
62
66
|
"tail-reseal-receipt",
|
|
63
67
|
"release-candidate-passport",
|
|
68
|
+
"release-invocation-publisher",
|
|
69
|
+
"release-invocation-runtime",
|
|
70
|
+
"release-invocation-candidate",
|
|
71
|
+
"release-invocation-target",
|
|
72
|
+
"release-invocation-authority",
|
|
73
|
+
"release-invocation-provider",
|
|
74
|
+
"release-invocation-parent",
|
|
75
|
+
"release-invocation",
|
|
76
|
+
"release-transaction",
|
|
77
|
+
"release-receipt",
|
|
64
78
|
]);
|
|
65
79
|
const FAULT_CLASSES = new Set([
|
|
66
80
|
"validation",
|
|
@@ -302,8 +302,11 @@ function classifyBuildchainUses(records, failures, { repository } = {}) {
|
|
|
302
302
|
parsed.selector === ALPHA_RECOVERY_BOOTSTRAP.selector;
|
|
303
303
|
const protectedBootstrap =
|
|
304
304
|
repository === BUILDCHAIN_REPOSITORY && bootstrapShape;
|
|
305
|
+
const unauthorizedBootstrap =
|
|
306
|
+
repository !== BUILDCHAIN_REPOSITORY && bootstrapShape;
|
|
305
307
|
const channel =
|
|
306
|
-
|
|
308
|
+
!unauthorizedBootstrap &&
|
|
309
|
+
(CHANNELS[parsed.selector] || (protectedBootstrap ? "alpha" : ""));
|
|
307
310
|
uses.push({
|
|
308
311
|
...record,
|
|
309
312
|
...parsed,
|