@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.
Files changed (82) hide show
  1. package/architecture/agent-change-map.md +52 -5
  2. package/architecture/ci-lane-change-budget.json +408 -8
  3. package/architecture/internal-capabilities.json +44 -1
  4. package/architecture/maintainability-debt.json +65 -133
  5. package/architecture/maintainability-policy.json +20 -15
  6. package/architecture/release-tail-contract-inventory.json +4 -4
  7. package/architecture/v3-core-mechanism-inventory.json +1 -0
  8. package/architecture/v3-v4-live-capability-inventory.json +17 -17
  9. package/architecture/v4-delivery-warrant-shadow-fixtures.json +5 -5
  10. package/architecture/v4-release-invocation-fixtures.json +139 -0
  11. package/architecture/v4-release-topology.json +317 -0
  12. package/architecture/v4-runtime-semantic-closure.json +4 -1
  13. package/architecture/v4-universal-workflow-bootstrap.json +181 -0
  14. package/architecture/v4-universal-workflow-fault-campaign.json +72 -0
  15. package/architecture/v4-universal-workflow-train-admission.json +40 -0
  16. package/contracts/buildchain-v2-residuals-v1.json +0 -9
  17. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  18. package/contracts/v4-release-invocation-v1.schema.json +134 -0
  19. package/dist/site/buildchain-contract.json +87 -42
  20. package/dist/site/buildchain-site.json +15 -10
  21. package/dist/site/capability-registry.json +1 -1
  22. package/dist/site/controller-registry.json +46 -10
  23. package/dist/site/kfd-claims.json +176 -69
  24. package/dist/site/kfd-upstream-aggregate.json +1 -1
  25. package/dist/site/manual-registry.json +2 -2
  26. package/dist/site/node-api-registry.json +97 -22
  27. package/dist/site/page-registry.json +9 -4
  28. package/dist/site/public-surface-audit.json +190 -71
  29. package/dist/site/publication-authority-registry.json +68 -3
  30. package/dist/site/publication-registry.json +4 -4
  31. package/dist/site/site-manifest.json +6 -6
  32. package/dist/site/workflow-registry.json +221 -72
  33. package/docs/node-api-reference.md +28 -25
  34. package/docs/reusable-build-surface.md +16 -0
  35. package/package.json +2 -2
  36. package/packages/core/buildchain-publication-authority.js +3 -0
  37. package/packages/core/ci-lane-change-budget.js +14 -1
  38. package/packages/core/dev-delivery-candidate-identity.js +45 -17
  39. package/packages/core/dev-delivery-execution-transfer.js +6 -7
  40. package/packages/core/dev-delivery-provider-heartbeat.js +22 -6
  41. package/packages/core/dev-delivery-warrant-legacy-recovery.js +4 -2
  42. package/packages/core/dev-delivery-warrant-native-compatibility.js +33 -0
  43. package/packages/core/dev-delivery-warrant-state.js +54 -54
  44. package/packages/core/dev-delivery-warrant.js +8 -0
  45. package/packages/core/dev-delivery-writer-protocol-transition.js +72 -0
  46. package/packages/core/release-tail-product-capabilities.js +29 -0
  47. package/packages/core/release-tail-provider-plane.js +3 -3
  48. package/packages/core/v4-canonical-contracts.js +14 -0
  49. package/packages/core/v4-floating-consumer-policy.js +4 -1
  50. package/packages/core/v4-product-publication.js +387 -0
  51. package/packages/core/v4-protected-publication-source.js +93 -0
  52. package/packages/core/v4-publication-qualification.js +1 -0
  53. package/packages/core/v4-release-invocation.js +425 -0
  54. package/packages/core/v4-universal-workflow-bootstrap.js +596 -0
  55. package/scripts/audit-publication-control-plane.mjs +0 -1
  56. package/scripts/check-inventory.mjs +27 -59
  57. package/scripts/check-maintainability.mjs +29 -118
  58. package/scripts/check-v3-v4-capability-inventory.mjs +3 -61
  59. package/scripts/check-v4-floating-consumer-policy-contract.mjs +10 -20
  60. package/scripts/check-v4-release-topology.mjs +493 -0
  61. package/scripts/check-v4-universal-workflow-bootstrap.mjs +257 -0
  62. package/scripts/dev-delivery-warrant.mjs +26 -5
  63. package/scripts/generate-channel-build-workflow.mjs +5 -1
  64. package/scripts/generate-channel-promotion-workflow.mjs +17 -57
  65. package/scripts/generate-v4-universal-workflow-facades.mjs +415 -0
  66. package/scripts/maintainability-public-surface.mjs +115 -0
  67. package/scripts/release-candidate-resolver.mjs +23 -24
  68. package/scripts/resume-from-candidate-run.mjs +16 -17
  69. package/scripts/universal-facade-maintainability.mjs +82 -0
  70. package/scripts/v3-v4-capability-catalog.mjs +107 -0
  71. package/scripts/v4-declarative-promotion-admission.mjs +4 -1
  72. package/scripts/v4-product-publication-intent.mjs +114 -0
  73. package/scripts/v4-release-candidate-adapter.mjs +41 -0
  74. package/scripts/v4-universal-workflow-backflow.mjs +212 -0
  75. package/scripts/v4-universal-workflow-engine.mjs +586 -0
  76. package/scripts/v4-universal-workflow-self-dogfood.mjs +205 -0
  77. package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
  78. package/templates/universal-buildchain-bootstrap.yml +28 -0
  79. package/scripts/capture-package-release-propagation.mjs +0 -263
  80. package/scripts/publication-commit-evidence.mjs +0 -444
  81. package/scripts/publish-github-artifact-attestation-evidence.mjs +0 -201
  82. 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
- return {
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 (lacksLiveNativeProof(candidate, status, expected.allowLegacyV3Readback))
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: normalizePolicy(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
- !(queue.candidates || []).some(
350
- (candidate) => candidate?.nativeCommandContract,
351
- ) &&
352
- !queue.activeWarrant?.nativeCommandContract &&
353
- !queue.activeWarrant?.nativeExecutionReceiptRoot &&
354
- !queue.activeWarrant?.qualificationReceiptRoot;
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, { ...queue, allowLegacyV3Readback }),
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
- const exactProofFields = [
482
- "sourcePatchRoot",
483
- "sourceProofRoot",
484
- "planRoot",
485
- "closureRoot",
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 exactProofFields)
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((candidate) => candidate.status === "queued")
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 && policy.class !== "provider-transient") continue;
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
- CHANNELS[parsed.selector] || (protectedBootstrap ? "alpha" : "");
308
+ !unauthorizedBootstrap &&
309
+ (CHANNELS[parsed.selector] || (protectedBootstrap ? "alpha" : ""));
307
310
  uses.push({
308
311
  ...record,
309
312
  ...parsed,