@go-to-k/cdkd 0.295.1 → 0.296.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{asg-provider-CbwOK2TQ.js → asg-provider-AVCcoXnQ.js} +8 -6
  2. package/dist/asg-provider-AVCcoXnQ.js.map +1 -0
  3. package/dist/cli.js +2 -2
  4. package/dist/{deploy-engine-DG-oC9YK.js → deploy-engine-D7204v7Z.js} +775 -216
  5. package/dist/deploy-engine-D7204v7Z.js.map +1 -0
  6. package/dist/{iam-policy-targets-CMSQGQnm.js → iam-policy-targets-DSDSdxXz.js} +145 -4
  7. package/dist/iam-policy-targets-DSDSdxXz.js.map +1 -0
  8. package/dist/{iam-role-provider-DUZtt9lH.js → iam-role-provider-CCPaZ3U4.js} +11 -5
  9. package/dist/iam-role-provider-CCPaZ3U4.js.map +1 -0
  10. package/dist/index.d.ts +28 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -4
  13. package/dist/{logger-B46YMG0h.js → logger-Dvc7ddKe.js} +19 -3
  14. package/dist/{logger-B46YMG0h.js.map → logger-Dvc7ddKe.js.map} +1 -1
  15. package/dist/{neptune-provider-TnGNCeLX.js → neptune-provider-D1t9NgT-.js} +20 -14
  16. package/dist/neptune-provider-D1t9NgT-.js.map +1 -0
  17. package/dist/{program-DfJFegS1.js → program-B0sp_SHG.js} +6187 -5931
  18. package/dist/program-B0sp_SHG.js.map +1 -0
  19. package/dist/{provider-classes-DUw5QAWI.js → provider-classes-DMOnX5s-.js} +754 -208
  20. package/dist/provider-classes-DMOnX5s-.js.map +1 -0
  21. package/dist/{rds-provider-COCDd7bS.js → rds-provider-DltlcDiQ.js} +22 -15
  22. package/dist/rds-provider-DltlcDiQ.js.map +1 -0
  23. package/dist/{version-Bqzsng8Y.js → version-DUHDmEhz.js} +2 -2
  24. package/dist/{version-Bqzsng8Y.js.map → version-DUHDmEhz.js.map} +1 -1
  25. package/package.json +1 -1
  26. package/dist/asg-provider-CbwOK2TQ.js.map +0 -1
  27. package/dist/deploy-engine-DG-oC9YK.js.map +0 -1
  28. package/dist/iam-policy-targets-CMSQGQnm.js.map +0 -1
  29. package/dist/iam-role-provider-DUZtt9lH.js.map +0 -1
  30. package/dist/neptune-provider-TnGNCeLX.js.map +0 -1
  31. package/dist/program-DfJFegS1.js.map +0 -1
  32. package/dist/provider-classes-DUw5QAWI.js.map +0 -1
  33. package/dist/rds-provider-COCDd7bS.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import { r as getAwsClients, s as __exportAll } from "./aws-clients-CnmtbrxD.js";
2
- import { A as displaySafe, E as UNRENDERABLE, F as safeMsg, L as truncateCodePoints, M as isPasteableIdent, O as displayAwsMessage, P as plainIdentOr, S as withoutGeneratedFallbackName, T as STACK_REF_MAX_CODE_POINTS, _ as getCurrentSkipPrefix, b as withSkipPrefix, c as getLiveRenderer, f as applyDefaultNameForFallback, g as generateResourceNameWithFallback, h as generateResourceName, j as displayStackName, k as displayIdent, m as explicitNamePropertyFor, n as getLogger, r as isStdoutReservedForPayload, s as installLogLineMaskerSource, v as getCurrentStackName, w as SECRET_REF_MAX_CODE_POINTS, x as withStackName, y as looksLikeCdkdGeneratedName } from "./logger-B46YMG0h.js";
3
- import { $t as StateError, A as isTerminalDeleteFailure, An as isAmbiguousCcHandlerErrorCode, At as clientDefaultsFor, Bn as isMarkedNonRetryable, Bt as IntrinsicResolutionRefusalError, C as refusalTypeShown, Cn as isNameCollisionErrorFrom, D as ProtectionFlipRegistry, Dt as withPasteableAwsProfile, En as isReplayedNameCollisionFrom, Fn as retryClassificationText, Gt as MalformedProducerRecordRefusalError, H as pasteableAwsCommand, Hn as markNonRetryable, In as describeAwsFailure, It as CrossAccountSecretRefusalError, J as isInterruptedWaitError, Jt as ProvisioningError, Lt as DependencyError, M as observeThenDisableProtection, Mn as isIamPropagationError, Mt as AccountIdUnavailableError, N as protectionFlipKey, Nn as isRetryableTransientError, Nt as AssetError, O as compensateProtectionFlip, On as markReplayMayCollide, Ot as ambientClientDefaults, Pn as isTransientServerError, Pt as CdkdError, Q as canonicalizeRoute53QueryName, R as DELETION_PROTECTION_DOC_POINTER, Rn as safeStringify$1, S as quotedRemedyLogicalId, Sn as hasReplayMayCollide, St as injectiveKey, T as resolveExplicitPhysicalId, Tn as isRecreateRetryableError, Tt as producerRecordKey, U as protectedReplacementAdvice, Un as markRedactedCause, Ut as LockError, Vn as isThrottlingError, Wn as wrapMaskedAwsError, Wt as MacroExpansionError, X as ElapsedBudgetRegistry, Xt as ResourceUpdateNotSupportedError, Y as startInterruptWatch, Yt as ResourceTimeoutError, Z as monotonicNowMs, _n as shellQuote, _t as formatLockOperation, at as segmentAfterAnchor, b as isQuotableImportValue, bt as CUSTOM_RESOURCE_RESPONSE_PREFIX, cn as UNSHOWABLE_VALUE, ct as isSecretDerivedValue, d as prepareRemovalForUpdate, dn as isInertUnquoted, dt as withDerivedNameMasks, en as SynthesisError, et as compositeIdSeparatorRefusal, f as removalWarning, fn as pasteableCommand, ft as UNREPRODUCIBLE_LOCK_CLAUSE, g as assertRegionMatch, gn as shellBoundedDisplay, gt as formatLockExpiry, h as RESOURCE_NOT_FOUND, hn as quotedOrDescribed, i as holdsSecretDerivedEntry, it as resourceTypeShown, jn as isAmbiguousOutcomeError, jt as credentialFingerprint, k as deleteWithProtectionCompensation, kn as formatRetryClassificationSignals, kt as ambientCredentialConfig, l as withUnchangedSecretPrincipalLists, ln as commandHole, lt as maskDeep, m as withoutInjectedRemovals, mn as plainOrDescribed, nt as logicalIdShown, on as SHELL_ACTIVE, ot as createMaskedLogSinks, pn as physicalIdShownBesideCommand, pt as buildForceUnlockCommand, rn as normalizeAwsError, sn as SHELL_ACTIVE_WHY, st as createMaskedRetryLogger, ut as maskerOrIdentity, vn as withheldTargetClause, vt as formatLockOwner, wn as isNameCooldownError, x as normalizeAwsTagsToCfn, xn as isUpdateUnsupportedError, xt as DEFAULT_STATE_PREFIX, yt as sanitizeRecoveryValue, zt as DynamicReferenceRegionAmbiguousError } from "./iam-policy-targets-CMSQGQnm.js";
2
+ import { A as displaySafe, E as UNRENDERABLE, F as safeMsg, L as truncateCodePoints, M as isPasteableIdent, O as displayAwsMessage, P as plainIdentOr, S as withoutGeneratedFallbackName, T as STACK_REF_MAX_CODE_POINTS, _ as getCurrentSkipPrefix, b as withSkipPrefix, c as getLiveRenderer, f as applyDefaultNameForFallback, g as generateResourceNameWithFallback, h as generateResourceName, j as displayStackName, k as displayIdent, m as explicitNamePropertyFor, n as getLogger, r as isStdoutReservedForPayload, s as installLogLineMaskerSource, v as getCurrentStackName, w as SECRET_REF_MAX_CODE_POINTS, x as withStackName, y as looksLikeCdkdGeneratedName } from "./logger-Dvc7ddKe.js";
3
+ import { $n as markRedactedCause, $t as LockError, A as isTerminalDeleteFailure, At as CUSTOM_RESOURCE_RESPONSE_PREFIX, Bn as isAmbiguousCcHandlerErrorCode, Bt as clientDefaultsFor, C as refusalTypeShown, Cn as physicalIdShownBesideCommand, Ct as buildForceUnlockCommand, D as ProtectionFlipRegistry, Dn as shellQuote, Dt as formatLockOperation, En as shellBoundedDisplay, Et as formatLockExpiry, Fn as isRecreateRetryableError, Ft as producerRecordKey, Gn as retryClassificationText, H as pasteableAwsCommand, Hn as isIamPropagationError, Ht as AccountIdUnavailableError, In as isReplayedNameCollisionFrom, J as isInterruptedWaitError, Jn as safeStringify$1, Kn as describeAwsFailure, Kt as CrossAccountSecretRefusalError, Lt as withPasteableAwsProfile, M as observeThenDisableProtection, Mn as hasReplayMayCollide, Mt as injectiveKey, N as protectionFlipKey, Nn as isNameCollisionErrorFrom, O as compensateProtectionFlip, On as withheldTargetClause, Ot as formatLockOwner, Pn as isNameCooldownError, Q as canonicalizeRoute53QueryName, Qn as markNonRetryable, R as DELETION_PROTECTION_DOC_POINTER, Rn as markReplayMayCollide, Rt as ambientClientDefaults, S as quotedRemedyLogicalId, Sn as pasteableCommand, St as UNREPRODUCIBLE_LOCK_CLAUSE, T as resolveExplicitPhysicalId, Tn as quotedOrDescribed, U as protectedReplacementAdvice, Un as isRetryableTransientError, Ut as AssetError, Vn as isAmbiguousOutcomeError, Vt as credentialFingerprint, Wn as isTransientServerError, Wt as CdkdError, X as ElapsedBudgetRegistry, Xn as isMarkedNonRetryable, Xt as IntrinsicResolutionRefusalError, Y as startInterruptWatch, Yt as DynamicReferenceRegionAmbiguousError, Z as monotonicNowMs, Zn as isThrottlingError, _n as SHELL_ACTIVE_WHY, _t as hasCreatedBeforeFailure, an as ResourceTimeoutError, at as segmentAfterAnchor, b as isQuotableImportValue, bt as markAuxiliaryFailure, ct as createMaskedRetryLogger, d as prepareRemovalForUpdate, dt as maskerOrIdentity, en as MacroExpansionError, er as wrapMaskedAwsError, et as compositeIdSeparatorRefusal, f as removalWarning, ft as withDerivedNameMasks, g as assertRegionMatch, gn as SHELL_ACTIVE, gt as createdBeforeFailure, h as RESOURCE_NOT_FOUND, i as holdsSecretDerivedEntry, in as ProvisioningError, it as resourceTypeShown, jn as isUpdateUnsupportedError, jt as DEFAULT_STATE_PREFIX, k as deleteWithProtectionCompensation, kt as sanitizeRecoveryValue, l as withUnchangedSecretPrincipalLists, ln as StateError, lt as isSecretDerivedValue, m as withoutInjectedRemovals, mt as carryCreatedBeforeFailure, nt as logicalIdShown, on as ResourceUpdateNotSupportedError, ot as stateOrphanRecordRemedy, pn as normalizeAwsError, pt as RETRY_AUXILIARY_OWNER, qt as DependencyError, st as createMaskedLogSinks, tn as MalformedProducerRecordRefusalError, un as SynthesisError, ut as maskDeep, vn as UNSHOWABLE_VALUE, vt as isAuxiliaryFailure, wn as plainOrDescribed, x as normalizeAwsTagsToCfn, xn as isInertUnquoted, xt as markCreatedBeforeFailure, yn as commandHole, yt as isAuxiliaryMarkOf, zn as formatRetryClassificationSignals, zt as ambientCredentialConfig } from "./iam-policy-targets-DSDSdxXz.js";
4
4
  import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, s as ambientRegion, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-D0q0z4dG.js";
5
- import { t as getCdkdVersion } from "./version-Bqzsng8Y.js";
5
+ import { t as getCdkdVersion } from "./version-DUHDmEhz.js";
6
6
  import { createHash, randomUUID } from "node:crypto";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
8
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -4976,7 +4976,7 @@ async function rebuildClientForBucketRegion(client, bucket, opts = {}) {
4976
4976
 
4977
4977
  //#endregion
4978
4978
  //#region src/state/s3-state-backend.ts
4979
- function errorDetail$1(error) {
4979
+ function errorDetail$2(error) {
4980
4980
  return displaySafe(error instanceof Error ? error.message : error, { asciiOnly: true }) || "<unrenderable>";
4981
4981
  }
4982
4982
  const LEGACY_KEY_DEPTH = 2;
@@ -5096,7 +5096,7 @@ var S3StateBackend = class {
5096
5096
  } catch (error) {
5097
5097
  if (!isNoSuchKey(error)) {
5098
5098
  if (error instanceof StateError) throw error;
5099
- throw new StateError(`Failed to get state for stack ${shownStackName} (${shownRegionName}): ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
5099
+ throw new StateError(`Failed to get state for stack ${shownStackName} (${shownRegionName}): ${errorDetail$2(error)}`, error instanceof Error ? error : void 0);
5100
5100
  }
5101
5101
  this.logger.debug(`No state at new key for stack: ${shownStackName} (${shownRegionName})`);
5102
5102
  }
@@ -5143,7 +5143,7 @@ var S3StateBackend = class {
5143
5143
  }));
5144
5144
  this.logger.info(`Migrated state for stack ${this.displayName(stackName)} to region-scoped layout (${displayIdent(region)})`);
5145
5145
  } catch (deleteError) {
5146
- this.logger.warn(`Migrated stack ${this.displayName(stackName)} to new key, but failed to delete legacy key: ${errorDetail$1(deleteError)}`);
5146
+ this.logger.warn(`Migrated stack ${this.displayName(stackName)} to new key, but failed to delete legacy key: ${errorDetail$2(deleteError)}`);
5147
5147
  }
5148
5148
  await notifyStateSaved(stackName, region);
5149
5149
  return response.ETag;
@@ -5153,7 +5153,7 @@ var S3StateBackend = class {
5153
5153
  bucket: this.config.bucket,
5154
5154
  operation: "PutObject"
5155
5155
  });
5156
- throw new StateError(`Failed to save state for stack ${this.stackRef(stackName, region)}: ${errorDetail$1(normalized)}`, normalized);
5156
+ throw new StateError(`Failed to save state for stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}`, normalized);
5157
5157
  }
5158
5158
  }
5159
5159
  async deleteState(stackName, region) {
@@ -5185,7 +5185,7 @@ var S3StateBackend = class {
5185
5185
  bucket: this.config.bucket,
5186
5186
  operation: "DeleteObject"
5187
5187
  });
5188
- throw new StateError(`Failed to delete state for stack ${this.stackRef(stackName, region)}: ${errorDetail$1(normalized)}`, normalized);
5188
+ throw new StateError(`Failed to delete state for stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}`, normalized);
5189
5189
  } finally {
5190
5190
  await this.deleteRollbackJournal(stackName, region);
5191
5191
  }
@@ -5207,7 +5207,7 @@ var S3StateBackend = class {
5207
5207
  bucket: this.config.bucket,
5208
5208
  operation: "DeleteObject"
5209
5209
  });
5210
- throw new StateError(`Failed to delete legacy state for stack ${displayStackName(stackName)}: ${errorDetail$1(normalized)}`, normalized);
5210
+ throw new StateError(`Failed to delete legacy state for stack ${displayStackName(stackName)}: ${errorDetail$2(normalized)}`, normalized);
5211
5211
  }
5212
5212
  }
5213
5213
  async listStacks() {
@@ -5378,7 +5378,7 @@ var S3StateBackend = class {
5378
5378
  });
5379
5379
  } catch (error) {
5380
5380
  const describing = options.objectDescription ? ` (${options.objectDescription})` : "";
5381
- this.logger.warn(`Could not purge noncurrent versions of ${keys.length} key(s) in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId${describing}. Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key(s) by hand. Underlying error: ${errorDetail$1(error)}`);
5381
+ this.logger.warn(`Could not purge noncurrent versions of ${keys.length} key(s) in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId${describing}. Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key(s) by hand. Underlying error: ${errorDetail$2(error)}`);
5382
5382
  }
5383
5383
  }
5384
5384
  async purgeNoncurrentVersionsUnderPrefix(keyPrefix, options = {}) {
@@ -5392,7 +5392,7 @@ var S3StateBackend = class {
5392
5392
  } catch (error) {
5393
5393
  const prefixShown = displayIdent(keyPrefix, { maxCodePoints: STACK_REF_MAX_CODE_POINTS });
5394
5394
  const describing = options.objectDescription ? ` (${options.objectDescription})` : "";
5395
- this.logger.warn(safeMsg`Could not purge noncurrent versions under the prefix ${prefixShown} in bucket ${this.config.bucket}: the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId${describing}. Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the prefix by hand. Underlying error: ${errorDetail$1(error)}`);
5395
+ this.logger.warn(safeMsg`Could not purge noncurrent versions under the prefix ${prefixShown} in bucket ${this.config.bucket}: the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId${describing}. Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the prefix by hand. Underlying error: ${errorDetail$2(error)}`);
5396
5396
  return {
5397
5397
  deletedBodies: 0,
5398
5398
  complete: false
@@ -5418,7 +5418,7 @@ var S3StateBackend = class {
5418
5418
  await this.saveCreateTokenLedger(stackName, region, ledger);
5419
5419
  } catch (error) {
5420
5420
  const normalized = normalizeAwsError(error, { bucket: this.config.bucket });
5421
- throw new StateError(`Failed to renew the create-token ledger of stack ${this.stackRef(stackName, region)}: ${errorDetail$1(normalized)}. The state record was left in place; re-run once the ledger can be written.`, normalized);
5421
+ throw new StateError(`Failed to renew the create-token ledger of stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}. The state record was left in place; re-run once the ledger can be written.`, normalized);
5422
5422
  }
5423
5423
  }
5424
5424
  async deleteCreateTokenLedger(stackName, region) {
@@ -5435,7 +5435,7 @@ var S3StateBackend = class {
5435
5435
  bucket: this.config.bucket,
5436
5436
  operation: "DeleteObject"
5437
5437
  });
5438
- throw new StateError(`Failed to delete the create-token ledger for stack ${this.stackRef(stackName, region)}: ${errorDetail$1(normalized)}. The state record was left in place; re-run once the ledger can be deleted.`, normalized);
5438
+ throw new StateError(`Failed to delete the create-token ledger for stack ${this.stackRef(stackName, region)}: ${errorDetail$2(normalized)}. The state record was left in place; re-run once the ledger can be deleted.`, normalized);
5439
5439
  }
5440
5440
  }
5441
5441
  async loadRollbackJournal(stackName, region) {
@@ -5461,6 +5461,58 @@ var S3StateBackend = class {
5461
5461
  else newest.failedOperations = remaining;
5462
5462
  await this.putRawObject(this.getRollbackJournalKey(stackName, region), JSON.stringify(journal, null, 2));
5463
5463
  }
5464
+ async dropRollbackJournalFailedOperations(stackName, region, drop) {
5465
+ const journal = await this.loadRollbackJournal(stackName, region);
5466
+ if (!journal) return 0;
5467
+ let removed = 0;
5468
+ for (const segment of journal.segments) {
5469
+ if (!segment.failedOperations) continue;
5470
+ const kept = segment.failedOperations.filter((op) => !drop(op, segment));
5471
+ removed += segment.failedOperations.length - kept.length;
5472
+ if (kept.length === 0) delete segment.failedOperations;
5473
+ else segment.failedOperations = kept;
5474
+ }
5475
+ if (removed === 0) return 0;
5476
+ await this.putRawObject(this.getRollbackJournalKey(stackName, region), JSON.stringify(journal, null, 2));
5477
+ return removed;
5478
+ }
5479
+ async reduceRollbackJournalToFailedOperations(stackName, region, keep, supersededLogicalIds = [], demote = () => false) {
5480
+ const journal = await this.loadRollbackJournal(stackName, region);
5481
+ if (!journal) return 0;
5482
+ const carried = new Set(supersededLogicalIds);
5483
+ const kept = [];
5484
+ let count = 0;
5485
+ const keptBySegment = journal.segments.map((segment) => (segment.failedOperations ?? []).filter((op) => keep(op, segment)).map((op) => op.physicalIdRecoveredFromError === true && demote(op, segment) ? {
5486
+ ...op,
5487
+ physicalIdRecoveredFromError: false
5488
+ } : op));
5489
+ const keptIds = new Set(keptBySegment.flat().map((op) => op.logicalId));
5490
+ for (let s = journal.segments.length - 1; s >= 0; s--) {
5491
+ const segment = journal.segments[s];
5492
+ for (const op of segment.operations) carried.add(op.logicalId);
5493
+ for (const id of segment.supersededLogicalIds ?? []) carried.add(id);
5494
+ const failed = keptBySegment[s];
5495
+ if (failed.length === 0) continue;
5496
+ const reduced = {
5497
+ ...segment,
5498
+ initialDeploy: false,
5499
+ operations: [],
5500
+ failedOperations: failed
5501
+ };
5502
+ delete reduced.previousOutputs;
5503
+ delete reduced.previousCrossStackReads;
5504
+ addSupersededIds(reduced, [...carried].filter((id) => !keptIds.has(id) || segment.supersededLogicalIds?.includes(id)));
5505
+ kept.unshift(reduced);
5506
+ count += failed.length;
5507
+ }
5508
+ if (kept.length === 0) {
5509
+ await this.deleteRollbackJournal(stackName, region);
5510
+ return 0;
5511
+ }
5512
+ journal.segments = kept;
5513
+ await this.putRawObject(this.getRollbackJournalKey(stackName, region), JSON.stringify(journal, null, 2));
5514
+ return count;
5515
+ }
5464
5516
  async popRollbackJournalSegment(stackName, region) {
5465
5517
  const journal = await this.loadRollbackJournal(stackName, region);
5466
5518
  if (!journal || journal.segments.length === 0) {
@@ -5529,7 +5581,7 @@ var S3StateBackend = class {
5529
5581
  } catch (error) {
5530
5582
  if (!isNoSuchKey(error) && error.name !== "NotFound") {
5531
5583
  gone = false;
5532
- this.logger.warn(`Failed to delete rollback journal for ${this.stackRef(stackName, region)}: ${errorDetail$1(error)}`);
5584
+ this.logger.warn(`Failed to delete rollback journal for ${this.stackRef(stackName, region)}: ${errorDetail$2(error)}`);
5533
5585
  }
5534
5586
  }
5535
5587
  await this.purgeNoncurrentVersions([key], { objectDescription: "the rollback journal, whose `failedOperations[].attemptedProperties` records the properties of the failed write verbatim" });
@@ -5647,7 +5699,7 @@ var S3StateBackend = class {
5647
5699
  };
5648
5700
  } catch (error) {
5649
5701
  if (isNoSuchKey(error)) return null;
5650
- throw new StateError(`Failed to get legacy state for stack ${this.displayName(stackName)}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
5702
+ throw new StateError(`Failed to get legacy state for stack ${this.displayName(stackName)}: ${errorDetail$2(error)}`, error instanceof Error ? error : void 0);
5651
5703
  }
5652
5704
  }
5653
5705
  parseStateBody(bodyString, stackName) {
@@ -5699,7 +5751,7 @@ function safeSegment(value) {
5699
5751
  function stackRef(stackName, region) {
5700
5752
  return region === void 0 ? safeSegment(stackName) : `${safeSegment(stackName)} (${safeSegment(region)})`;
5701
5753
  }
5702
- function errorDetail(error) {
5754
+ function errorDetail$1(error) {
5703
5755
  return displaySafe(error instanceof Error ? error.message : error, { asciiOnly: true }) || "<unrenderable>";
5704
5756
  }
5705
5757
  function isLockInfoExpired(lockInfo) {
@@ -5835,7 +5887,7 @@ var LockManager = class {
5835
5887
  }
5836
5888
  return false;
5837
5889
  }
5838
- throw new LockError(`Failed to acquire lock for stack ${safeSegment(stackName)} (${safeSegment(region)}): ` + errorDetail(error), error instanceof Error ? error : void 0);
5890
+ throw new LockError(`Failed to acquire lock for stack ${safeSegment(stackName)} (${safeSegment(region)}): ` + errorDetail$1(error), error instanceof Error ? error : void 0);
5839
5891
  }
5840
5892
  }
5841
5893
  async putLockObject(key, lockInfo, condition = { IfNoneMatch: "*" }) {
@@ -5890,7 +5942,7 @@ var LockManager = class {
5890
5942
  return null;
5891
5943
  }
5892
5944
  if (error instanceof LockError) throw error;
5893
- throw new LockError(`Failed to get lock info for stack ${shownStack}: ${errorDetail(error)}`, error instanceof Error ? error : void 0);
5945
+ throw new LockError(`Failed to get lock info for stack ${shownStack}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
5894
5946
  }
5895
5947
  }
5896
5948
  async isLocked(stackName, region) {
@@ -5938,16 +5990,16 @@ var LockManager = class {
5938
5990
  this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: the conditional delete could not be evaluated here, and this process could not confirm the lock is still its own. Leaving it in place rather than risk deleting another process's lock. It expires on its own, or clear it with cdkd force-unlock. If this repeats, grant s3:GetObject on the lock key -- a delete conditioned on an ETag requires it.`);
5939
5991
  return;
5940
5992
  }
5941
- this.logger.debug(`Conditional lock release for stack ${stackRef(stackName, region)} is not supported here (${errorDetail(error)}); retrying unconditionally`);
5993
+ this.logger.debug(`Conditional lock release for stack ${stackRef(stackName, region)} is not supported here (${errorDetail$1(error)}); retrying unconditionally`);
5942
5994
  try {
5943
5995
  await this.deleteLock(stackName, region);
5944
5996
  this.logger.debug(`Lock released for stack: ${stackRef(stackName, region)}`);
5945
5997
  return;
5946
5998
  } catch (fallbackError) {
5947
- throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail(fallbackError)}`, fallbackError instanceof Error ? fallbackError : void 0);
5999
+ throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail$1(fallbackError)}`, fallbackError instanceof Error ? fallbackError : void 0);
5948
6000
  }
5949
6001
  }
5950
- throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail(error)}`, error instanceof Error ? error : void 0);
6002
+ throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
5951
6003
  } finally {
5952
6004
  await this.purgeLockVersions(this.getLockKey(stackName, region), "release");
5953
6005
  }
@@ -6006,7 +6058,7 @@ var LockManager = class {
6006
6058
  objectDescription: LOCK_OBJECT_DESCRIPTION
6007
6059
  });
6008
6060
  } catch (error) {
6009
- report(`Could not purge noncurrent versions of the lock key ${displayIdent(key, { maxCodePoints: STACK_REF_MAX_CODE_POINTS })} in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId (${LOCK_OBJECT_DESCRIPTION}). Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key by hand. Underlying error: ${errorDetail(error)}`);
6061
+ report(`Could not purge noncurrent versions of the lock key ${displayIdent(key, { maxCodePoints: STACK_REF_MAX_CODE_POINTS })} in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId (${LOCK_OBJECT_DESCRIPTION}). Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key by hand. Underlying error: ${errorDetail$1(error)}`);
6010
6062
  }
6011
6063
  }
6012
6064
  trackHeldLock(args) {
@@ -6086,7 +6138,7 @@ var LockManager = class {
6086
6138
  this.logger.warn(`Lost the lock for stack ${stackRef(held.stackName, held.region)} while the operation was still running: the lock object has been replaced or removed. Another cdkd process may now be writing to this stack concurrently. This process will not delete the current lock when it finishes.`);
6087
6139
  return;
6088
6140
  }
6089
- this.logger.debug(`Lock renewal for stack ${stackRef(held.stackName, held.region)} failed, will retry: ${errorDetail(error)}`);
6141
+ this.logger.debug(`Lock renewal for stack ${stackRef(held.stackName, held.region)} failed, will retry: ${errorDetail$1(error)}`);
6090
6142
  if (!held.warnedPastExpiry && Date.now() >= held.info.expiresAt) {
6091
6143
  held.warnedPastExpiry = true;
6092
6144
  this.logger.warn(`Lock renewal for stack ${stackRef(held.stackName, held.region)} has been failing long enough that the lock expired at ${new Date(held.info.expiresAt).toISOString()}. Another cdkd process can now take it while this operation is still running. Renewal keeps retrying.`);
@@ -9107,129 +9159,6 @@ var ReplacementRulesRegistry = class {
9107
9159
  }
9108
9160
  };
9109
9161
 
9110
- //#endregion
9111
- //#region src/provisioning/auxiliary-failure.ts
9112
- const AUXILIARY_LOGICAL_ID_SUFFIX = "/auxiliary";
9113
- const MAX_DEPTH = 5;
9114
- function auxiliaryLogicalId(ownerLogicalId) {
9115
- return `${ownerLogicalId}${AUXILIARY_LOGICAL_ID_SUFFIX}`;
9116
- }
9117
- const RETRY_AUXILIARY_OWNER = "withRetry";
9118
- function isAuxiliaryMarkOf(link, ownerLogicalId) {
9119
- try {
9120
- if (typeof link !== "object" && typeof link !== "function" || link === null) return false;
9121
- const own = Object.getOwnPropertyDescriptor(link, "logicalId");
9122
- return isAuxiliaryMark(own) && own?.value === auxiliaryLogicalId(ownerLogicalId);
9123
- } catch {
9124
- return false;
9125
- }
9126
- }
9127
- function isAuxiliaryMark(descriptor) {
9128
- return descriptor !== void 0 && descriptor.enumerable === false && descriptor.writable === false && typeof descriptor.value === "string" && descriptor.value.endsWith(AUXILIARY_LOGICAL_ID_SUFFIX);
9129
- }
9130
- function isAuxiliaryFailure(error) {
9131
- try {
9132
- let current = error;
9133
- for (let depth = 0; depth < MAX_DEPTH && typeof current === "object" && current !== null; depth++) {
9134
- if (isAuxiliaryMark(Object.getOwnPropertyDescriptor(current, "logicalId"))) return true;
9135
- current = current.cause;
9136
- }
9137
- } catch {}
9138
- return false;
9139
- }
9140
- const CREATED_BEFORE_FAILURE = Symbol.for("cdkd.createdBeforeFailure");
9141
- function markCreatedBeforeFailure(error, ownerLogicalId, resourceType, physicalId) {
9142
- try {
9143
- if (typeof error !== "object" || error === null || !Object.isExtensible(error)) return error;
9144
- if (physicalId === "") return error;
9145
- Object.defineProperty(error, CREATED_BEFORE_FAILURE, {
9146
- value: Object.freeze({
9147
- logicalId: ownerLogicalId,
9148
- resourceType,
9149
- physicalId
9150
- }),
9151
- enumerable: false,
9152
- writable: false,
9153
- configurable: true
9154
- });
9155
- } catch {}
9156
- return error;
9157
- }
9158
- function createdMarkOn(link) {
9159
- const value = link[CREATED_BEFORE_FAILURE];
9160
- if (typeof value !== "object" || value === null) return void 0;
9161
- const { logicalId, resourceType, physicalId } = value;
9162
- if (typeof logicalId !== "string" || typeof resourceType !== "string" || typeof physicalId !== "string" || physicalId === "") return;
9163
- return {
9164
- logicalId,
9165
- resourceType,
9166
- physicalId
9167
- };
9168
- }
9169
- function createdBeforeFailure(error, logicalId, resourceType) {
9170
- try {
9171
- let current = error;
9172
- for (let depth = 0; depth < 10 && typeof current === "object" && current !== null; depth++) {
9173
- const mark = createdMarkOn(current);
9174
- if (mark) return mark.logicalId === logicalId && mark.resourceType === resourceType ? mark.physicalId : void 0;
9175
- const own = Object.getOwnPropertyDescriptor(current, "logicalId");
9176
- if (typeof own?.value === "string" && own.value !== logicalId && !isAuxiliaryMarkOf(current, logicalId)) return;
9177
- current = current.cause;
9178
- }
9179
- } catch {}
9180
- }
9181
- function hasCreatedBeforeFailure(error) {
9182
- try {
9183
- let current = error;
9184
- for (let depth = 0; depth < 10 && typeof current === "object" && current !== null; depth++) {
9185
- if (createdMarkOn(current)) return true;
9186
- current = current.cause;
9187
- }
9188
- } catch {}
9189
- return false;
9190
- }
9191
- function carryCreatedBeforeFailure(from, to) {
9192
- try {
9193
- if (typeof to !== "object" || to === null) return to;
9194
- let current = from;
9195
- let mark;
9196
- for (let depth = 0; depth < 10 && typeof current === "object" && current !== null && !mark; depth++) {
9197
- mark = createdMarkOn(current);
9198
- current = current.cause;
9199
- }
9200
- if (!mark) return to;
9201
- let probe = to;
9202
- for (let depth = 0; depth < 10 && typeof probe === "object" && probe !== null; depth++) {
9203
- if (createdMarkOn(probe)) return to;
9204
- probe = probe.cause;
9205
- }
9206
- return markCreatedBeforeFailure(to, mark.logicalId, mark.resourceType, mark.physicalId);
9207
- } catch {
9208
- return to;
9209
- }
9210
- }
9211
- function markAuxiliaryFailure(error, ownerLogicalId) {
9212
- try {
9213
- let current = error;
9214
- for (let depth = 0; depth < MAX_DEPTH && typeof current === "object" && current !== null; depth++) {
9215
- const own = Object.getOwnPropertyDescriptor(current, "logicalId");
9216
- if (typeof own?.value === "string") {
9217
- if (isAuxiliaryMark(own)) return error;
9218
- } else {
9219
- if (Object.isExtensible(current) && own?.configurable !== false) Object.defineProperty(current, "logicalId", {
9220
- value: auxiliaryLogicalId(ownerLogicalId),
9221
- enumerable: false,
9222
- writable: false,
9223
- configurable: true
9224
- });
9225
- return error;
9226
- }
9227
- current = current.cause;
9228
- }
9229
- } catch {}
9230
- return error;
9231
- }
9232
-
9233
9162
  //#endregion
9234
9163
  //#region src/deployment/retry.ts
9235
9164
  const IAM_PROPAGATION_INITIAL_DELAY_MS = 250;
@@ -15291,10 +15220,10 @@ function refuseMalformedResourcesForDestroy(state, stackName, region, recovery)
15291
15220
  throw markNonRetryable(new CdkdError(malformedDestroyResourcesRefusalMessage(stackName, region, recovery), STATE_RESOURCES_MALFORMED));
15292
15221
  }
15293
15222
  const STATE_REGION_DIVERGED = "STATE_REGION_DIVERGED";
15294
- function divergentRecordRegionRefusalMessage(stackName, keyRegion, divergentBodyRegion, resourceCount, recovery) {
15223
+ function divergentRecordRegionRefusalMessage(stackName, keyRegion, divergentBodyRegion, resourceCount, recovery, provenOrphans = 0) {
15295
15224
  const cap = STACK_REF_MAX_CODE_POINTS;
15296
15225
  const exact = rendersExactly(stackName, cap) && rendersExactly(keyRegion, cap) && isPasteableIdent(stackName) && isPasteableIdent(keyRegion);
15297
- const lists = resourceCount === void 0 ? "its resources map cannot be read" : `it still lists ${resourceCount} resource${resourceCount === 1 ? "" : "s"}`;
15226
+ const lists = resourceCount === void 0 ? "its resources map cannot be read" : resourceCount === 0 && provenOrphans > 0 ? `its rollback journal holds ${provenOrphans} failed create${provenOrphans === 1 ? "" : "s"} whose resource the destroy would delete` : `it still lists ${resourceCount} resource${resourceCount === 1 ? "" : "s"}`;
15298
15227
  const kind = describeRegionValueKind(divergentBodyRegion);
15299
15228
  const opening = exact ? `cdkd will not destroy stack ${shellQuote(safeIdentifier(stackName, cap))} (${shellQuote(safeIdentifier(keyRegion, cap))}): the state record read from that region's key carries a 'region' of its own (${kind}) that is not the key's, and ${lists}` : `cdkd will not destroy the state record this command loaded: it carries a 'region' of its own (${kind}) that is not the region of the key it was read from, and ${lists}`;
15300
15229
  const listing = withheldListingPointer(recovery);
@@ -15302,11 +15231,11 @@ function divergentRecordRegionRefusalMessage(stackName, keyRegion, divergentBody
15302
15231
  const remedy = exact ? "Re-run with --verbose to see what the record's region field holds, then either destroy against the region the resources are really in, or repair that field to match the key it is stored under and re-run. " + withheldAccountClause(withheldAccounts, "the command at the end of this message prints") + "To drop the record and leave the live resources standing, spelled out rather than pasteable because that command DELETES a record: " + dropRecordTemplate(recovery) : "This record's stack name or region does NOT render exactly — what any surrounding output shows is a sanitized form, and another record may render identically — so this message names no target and offers no command against one. List the records with " + (listing.line === void 0 ? `${WITHHELD_LISTING_POINTER}. Inspect it with: ${inspectCommand(void 0, void 0)}` : `${listing.pointer}.` + destroyAccountClause(recovery) + `\n${listing.line}\nInspect it with: ${inspectCommand(void 0, void 0, recovery)}`);
15303
15232
  return `${opening} ${resourceCount === void 0 ? `— so cdkd can neither count what it would delete nor tell which region it is in` : `— so cdkd cannot tell which region those resources are in`}. cdkd stamps the key's region into every record it writes, so this record was not written by cdkd. Destroying against the key's region would issue every delete there; if the record's own region is the honest half, each delete comes back not-found, which this command reads as ALREADY DELETED — it would report success, remove the record, and leave every resource standing in the other region with nothing naming it. ${remedy}`;
15304
15233
  }
15305
- function refuseDivergentRecordRegionForDestroy(state, stackName, keyRegion, divergentBodyRegion, recovery) {
15234
+ function refuseDivergentRecordRegionForDestroy(state, stackName, keyRegion, divergentBodyRegion, recovery, provenOrphans = 0) {
15306
15235
  if (divergentBodyRegion === void 0) return;
15307
15236
  const resourceCount = isReadableBag(state.resources) ? Object.keys(state.resources).length : void 0;
15308
- if (resourceCount === 0) return;
15309
- throw markNonRetryable(new CdkdError(divergentRecordRegionRefusalMessage(stackName, keyRegion, divergentBodyRegion, resourceCount, recovery), STATE_REGION_DIVERGED));
15237
+ if (resourceCount === 0 && provenOrphans === 0) return;
15238
+ throw markNonRetryable(new CdkdError(divergentRecordRegionRefusalMessage(stackName, keyRegion, divergentBodyRegion, resourceCount, recovery, provenOrphans), STATE_REGION_DIVERGED));
15310
15239
  }
15311
15240
  function malformedDeployResourcesRefusalMessage(rawStackName, rawRegion) {
15312
15241
  const stackName = absentIfEmpty(rawStackName);
@@ -15994,7 +15923,7 @@ function isPlainObject$2(value) {
15994
15923
  return value !== null && typeof value === "object" && !Array.isArray(value);
15995
15924
  }
15996
15925
  const DYNAMIC_REFERENCE_OPEN = "{{resolve:";
15997
- const NESTED_STACK_TYPE$2 = "AWS::CloudFormation::Stack";
15926
+ const NESTED_STACK_TYPE$3 = "AWS::CloudFormation::Stack";
15998
15927
  const NESTED_OUTPUT_PREFIX = "Outputs.";
15999
15928
  function carriesSecretValue(value, corpora) {
16000
15929
  if (carriesSecretMask(value)) return true;
@@ -16069,7 +15998,7 @@ function intrinsicKey(value) {
16069
15998
  const key = keys[0];
16070
15999
  return key === "Ref" || key.startsWith("Fn::") ? key : void 0;
16071
16000
  }
16072
- const OPAQUE_ATTRIBUTE_TYPES = /* @__PURE__ */ new Set(["AWS::CloudFormation::CustomResource", NESTED_STACK_TYPE$2]);
16001
+ const OPAQUE_ATTRIBUTE_TYPES = /* @__PURE__ */ new Set(["AWS::CloudFormation::CustomResource", NESTED_STACK_TYPE$3]);
16073
16002
  function hasOpaqueAttributes(logicalId, walk) {
16074
16003
  const definition = walk.resources[logicalId];
16075
16004
  const type = isPlainObject$2(definition) ? definition["Type"] : void 0;
@@ -16426,7 +16355,7 @@ function passedKey(passed) {
16426
16355
  function isNestedStackRow(logicalId, walk) {
16427
16356
  if (!Object.hasOwn(walk.resources, logicalId)) return false;
16428
16357
  const definition = walk.resources[logicalId];
16429
- return isPlainObject$2(definition) && definition["Type"] === NESTED_STACK_TYPE$2;
16358
+ return isPlainObject$2(definition) && definition["Type"] === NESTED_STACK_TYPE$3;
16430
16359
  }
16431
16360
  function getAttAttribute(operand, target) {
16432
16361
  if (Array.isArray(operand)) return operand.length === 2 && typeof operand[1] === "string" ? operand[1] : void 0;
@@ -22068,7 +21997,7 @@ var CloudControlProvider = class {
22068
21997
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
22069
21998
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
22070
21999
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
22071
- const { ASGProvider } = await import("./asg-provider-CbwOK2TQ.js");
22000
+ const { ASGProvider } = await import("./asg-provider-AVCcoXnQ.js");
22072
22001
  const delegateRegion = ambientRegion();
22073
22002
  let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
22074
22003
  if (asgProvider === void 0) {
@@ -22174,7 +22103,7 @@ var CloudControlProvider = class {
22174
22103
  const family = SDK_DELETE_FAMILIES.get(resourceType);
22175
22104
  const cached = this.sdkDeleteDelegates.get(family);
22176
22105
  if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
22177
- const provider = family === "rds" ? new (await (import("./rds-provider-COCDd7bS.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-TnGNCeLX.js"))).NeptuneProvider({ region: ccRegion });
22106
+ const provider = family === "rds" ? new (await (import("./rds-provider-DltlcDiQ.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-D1t9NgT-.js"))).NeptuneProvider({ region: ccRegion });
22178
22107
  this.sdkDeleteDelegates.set(family, {
22179
22108
  region: ccRegion,
22180
22109
  provider
@@ -23073,8 +23002,34 @@ const CR_MASKED_SERVICE_TOKEN_SKIP_REASON = "masked ServiceToken in state — De
23073
23002
  const CR_REFERENCE_SERVICE_TOKEN_SKIP_REASON = "dynamic reference as ServiceToken in state — handler not invoked";
23074
23003
  const CR_DELETE_INVOKE_FAILED_SKIP_REASON = "Delete request to the handler did not complete — resource unproven";
23075
23004
  const CR_DELETE_HANDLER_FAILED_SKIP_REASON = "Delete handler reported FAILED — resource unproven";
23076
- const CR_SKIP_NOT_A_RETRY_CAVEAT = "NOTE this record is a POINTER, not a retry: the same destroy run deletes the backing Lambda, so the next 'cdkd destroy' finds the handler gone and DROPS this record (issue 804 pre-check). Tear the resource down by hand, then clear the stack's records with 'cdkd state orphan <stack> --stack-region <region>' — that command drops EVERY record for the stack in that region, not just this one.";
23005
+ const CR_BACKING_LAMBDA_GONE_SKIP_REASON = "backing Lambda function is gone — Delete handler not invoked";
23006
+ function crSkipNotARetryCaveat(context, logicalId) {
23007
+ return `NOTE this record is a POINTER, not a retry: the same destroy run deletes the backing Lambda, so the next 'cdkd destroy' cannot reach the handler either: it skips this resource again and keeps the record (issue 2115). Tear the resource down by hand, then drop the record with ${stateOrphanRecordRemedy(context, logicalId)}.`;
23008
+ }
23077
23009
  const DEPLOY_SKIP_CAVEAT = "NOTE this arm is ALSO reached from cdkd deploy. Since issue 1762 the DELETE of a resource removed from the template behaves like destroy — the record is KEPT and the next deploy re-attempts it — but a REPLACEMENT / rollback delete FAILS the resource instead (https://github.com/go-to-k/cdkd/issues/1762), leaving the old one untracked; there, tear the resource down by hand.";
23010
+ function crDeployNoStateOrphan(logicalId) {
23011
+ return `For a resource removed from the template, to give up on the delete and stop tracking it, drop the record with ${stateOrphanRecordRemedy(void 0, logicalId)}.`;
23012
+ }
23013
+ function crDeploySkipTail(logicalId) {
23014
+ return "Meanwhile 'cdkd deploy --allow-unaddressed' exits 0 (a deploy-only flag; 'cdkd rollback' has none); the record stays and each deploy re-attempts the delete. A delete-first REPLACEMENT or a rollback delete usually FAILS the resource and keeps the record (https://github.com/go-to-k/cdkd/issues/1762). Where the other copy already exists (a replacement that created the new resource first, or a rollback that re-created the old one first), the skip only warns and the surviving copy is no longer tracked, so tear it down by hand. " + crDeployNoStateOrphan(logicalId);
23015
+ }
23016
+ const CR_DEPLOY_HANDLER_SKIP_HEAD = "This delete is not part of a stack destroy (a 'cdkd deploy' template removal, replacement or rollback, or a 'cdkd rollback'). For a resource removed from the template the record is KEPT and the next 'cdkd deploy' re-sends the Delete: fix what made it fail (the handler's Delete logic, or what stopped the invoke) and re-deploy. That reaches the handler only while its function exists: if this deploy also deleted the backing Lambda, the next deploy finds it gone and DROPS the record with a warning, so tear down what the handler manages by hand. ";
23017
+ const CR_DEPLOY_UNADDRESSABLE_HEAD = "This delete is not part of a stack destroy (a 'cdkd deploy' template removal, replacement or rollback, or a 'cdkd rollback'). For a resource removed from the template the record is KEPT and every 'cdkd deploy' skips it again until ServiceToken is restored: put the provider's Lambda function or SNS topic ARN back in state.json and re-deploy, which sends the Delete while that handler exists. If its Lambda function is gone, that deploy DROPS the record with a warning instead, so tear down what the handler manages by hand. ";
23018
+ function crDestroyUnaddressableRemedy(context, logicalId) {
23019
+ return `Tear the resource down by hand, then drop the record with ${stateOrphanRecordRemedy(context, logicalId)}. Restoring ServiceToken (the provider's Lambda function or SNS topic ARN) in state.json and re-running helps only while that handler still exists: a destroy goes on to delete its backing Lambda.`;
23020
+ }
23021
+ function handlerSkipRemedy(context, logicalId) {
23022
+ return context?.stackDestroy === true ? ` — cdkd is KEEPING the state record and the run exits non-zero. ${crSkipNotARetryCaveat(context, logicalId)}` : `. ${CR_DEPLOY_HANDLER_SKIP_HEAD}${crDeploySkipTail(logicalId)}`;
23023
+ }
23024
+ function crUnresolvedTokenUpdateRemedy() {
23025
+ return "This indicates an unresolved value in the template, or, on a rollback, in the resource's recorded state. Check that the template resolves ServiceToken to the provider's Lambda function or SNS topic ARN and re-deploy; a rollback replays the recorded value, so restore the template and re-deploy instead. Do not drop this record with 'cdkd state orphan', with or without --resource: the template still declares the resource, so the next deploy would send the handler a fresh Create and leave what it already manages untracked.";
23026
+ }
23027
+ function unresolvedTokenDeleteRemedy(context, logicalId) {
23028
+ return context?.stackDestroy === true ? `re-run 'cdkd import', or drop the record with ${stateOrphanRecordRemedy(context, logicalId)}, to recover.` : `put the provider's Lambda function or SNS topic ARN back as ServiceToken in state.json and re-run to recover. ${crDeployNoStateOrphan(logicalId)}`;
23029
+ }
23030
+ function unaddressableServiceTokenRemedy(context, logicalId) {
23031
+ return context?.stackDestroy === true ? crDestroyUnaddressableRemedy(context, logicalId) : `${CR_DEPLOY_UNADDRESSABLE_HEAD}${crDeploySkipTail(logicalId)}`;
23032
+ }
23078
23033
  function isCustomResourceResponsePayload(value) {
23079
23034
  if (typeof value !== "object" || value === null) return false;
23080
23035
  const payload = value;
@@ -23417,7 +23372,7 @@ var CustomResourceProvider = class CustomResourceProvider {
23417
23372
  this.logger.debug(`Creating custom resource ${logicalId} (${resourceType})`);
23418
23373
  const serviceToken = properties["ServiceToken"];
23419
23374
  if (!serviceToken) throw new ProvisioningError(`ServiceToken is required for custom resource ${logicalId}`, resourceType, logicalId);
23420
- if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). This usually indicates state was written by a pre-fix cdkd import; re-run 'cdkd import' or 'cdkd state orphan <stack> --stack-region <region>' to recover.`, resourceType, logicalId);
23375
+ if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). This indicates an unresolved value in the template, or, on a rollback, in the resource's recorded state. Check that the template resolves ServiceToken to the provider's Lambda function or SNS topic ARN; a rollback replays the recorded value, so restore the template and re-deploy instead.`, resourceType, logicalId);
23421
23376
  this.refuseResolvedSecret(logicalId, resourceType, properties);
23422
23377
  try {
23423
23378
  const cfnResponse = await this.invokeCustomResourceWithRetry(serviceToken, logicalId, "Create", (invocation) => ({
@@ -23448,7 +23403,7 @@ var CustomResourceProvider = class CustomResourceProvider {
23448
23403
  this.logger.debug(`Updating custom resource ${logicalId}: ${physicalId} (${resourceType})`);
23449
23404
  const serviceToken = properties["ServiceToken"];
23450
23405
  if (!serviceToken) throw new ProvisioningError(`ServiceToken is required for custom resource ${logicalId}`, resourceType, logicalId, physicalId);
23451
- if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). This usually indicates state was written by a pre-fix cdkd import; re-run 'cdkd import' or 'cdkd state orphan <stack> --stack-region <region>' to recover.`, resourceType, logicalId, physicalId);
23406
+ if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). ` + crUnresolvedTokenUpdateRemedy(), resourceType, logicalId, physicalId);
23452
23407
  this.refuseResolvedSecret(logicalId, resourceType, properties, physicalId, previousProperties);
23453
23408
  try {
23454
23409
  const cfnResponse = await this.invokeCustomResourceWithRetry(serviceToken, logicalId, "Update", (invocation) => ({
@@ -23478,7 +23433,7 @@ var CustomResourceProvider = class CustomResourceProvider {
23478
23433
  throw new ProvisioningError(`Failed to update custom resource ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
23479
23434
  }
23480
23435
  }
23481
- async delete(logicalId, physicalId, resourceType, properties, _context) {
23436
+ async delete(logicalId, physicalId, resourceType, properties, context) {
23482
23437
  this.logger.debug(`Deleting custom resource ${logicalId}: ${physicalId} (${resourceType})`);
23483
23438
  if (!properties) {
23484
23439
  this.logger.warn(`No properties available for custom resource ${logicalId}, skipping deletion — the handler is never invoked, so anything this custom resource manages is LEFT IN PLACE. Restore the record's properties in state.json and re-run, or tear the resource down by hand. ${DEPLOY_SKIP_CAVEAT}`);
@@ -23495,23 +23450,30 @@ var CustomResourceProvider = class CustomResourceProvider {
23495
23450
  reason: CR_NO_SERVICE_TOKEN_SKIP_REASON
23496
23451
  };
23497
23452
  }
23498
- if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). This usually indicates state was written by a pre-fix cdkd import; re-run 'cdkd import' or 'cdkd state orphan <stack> --stack-region <region>' to recover.`, resourceType, logicalId, physicalId);
23453
+ if (typeof serviceToken !== "string") throw new ProvisioningError(`Custom Resource ${logicalId}: ServiceToken is not a resolved string ARN (got ${typeof serviceToken}). This usually indicates state was written by a pre-fix cdkd import; ` + unresolvedTokenDeleteRemedy(context, logicalId), resourceType, logicalId, physicalId);
23499
23454
  if (carriesSecretMask(serviceToken)) {
23500
- this.logger.warn(safeMsg`ServiceToken for custom resource ${logicalId} is recorded in state as the redaction ` + safeMsg`mask '${"***"}' (a NoEcho value this resource reads equals, or is contained ` + "in, its ServiceToken), so cdkd cannot address the handler; skipping deletion — anything this custom resource manages is LEFT IN PLACE. Re-deploying does not repair the record while that attribute still carries the value. Tear the resource down by hand, then clear the stack's records with 'cdkd state orphan <stack> --stack-region <region>' — that command drops EVERY record for the stack in that region, not just this one. Restoring ServiceToken (the provider's Lambda function or SNS topic ARN) in state.json and re-running helps only while that handler still exists: a destroy goes on to delete its backing Lambda. " + safeMsg`${DEPLOY_SKIP_CAVEAT}`);
23455
+ this.logger.warn(safeMsg`ServiceToken for custom resource ${logicalId} is recorded in state as the redaction ` + safeMsg`mask '${"***"}' (a NoEcho value this resource reads equals, or is contained ` + "in, its ServiceToken), so cdkd cannot address the handler; skipping deletion — anything this custom resource manages is LEFT IN PLACE. Re-deploying does not repair the record while that attribute still carries the value. " + safeMsg`${unaddressableServiceTokenRemedy(context, logicalId)}`);
23501
23456
  return {
23502
23457
  outcome: "skipped",
23503
23458
  reason: CR_MASKED_SERVICE_TOKEN_SKIP_REASON
23504
23459
  };
23505
23460
  }
23506
23461
  if (dynamicReferenceTokens(serviceToken).length > 0) {
23507
- this.logger.warn(safeMsg`ServiceToken for custom resource ${logicalId} is recorded in state as a ` + "'{{resolve:...}}' dynamic reference, which cdkd does not resolve on delete, so it cannot address the handler; skipping deletion — anything this custom resource manages is LEFT IN PLACE. CloudFormation does not support secure (secretsmanager / ssm-secure) dynamic references in custom resources, and cdkd now refuses such a template at deploy time. Tear the resource down by hand, then clear the stack's records with 'cdkd state orphan <stack> --stack-region <region>' — that command drops EVERY record for the stack in that region, not just this one. Restoring ServiceToken (the provider's Lambda function or SNS topic ARN) in state.json and re-running helps only while that handler still exists: a destroy goes on to delete its backing Lambda. " + safeMsg`${DEPLOY_SKIP_CAVEAT}`);
23462
+ this.logger.warn(safeMsg`ServiceToken for custom resource ${logicalId} is recorded in state as a ` + "'{{resolve:...}}' dynamic reference, which cdkd does not resolve on delete, so it cannot address the handler; skipping deletion — anything this custom resource manages is LEFT IN PLACE. CloudFormation does not support secure (secretsmanager / ssm-secure) dynamic references in custom resources, and cdkd now refuses such a template at deploy time. " + safeMsg`${unaddressableServiceTokenRemedy(context, logicalId)}`);
23508
23463
  return {
23509
23464
  outcome: "skipped",
23510
23465
  reason: CR_REFERENCE_SERVICE_TOKEN_SKIP_REASON
23511
23466
  };
23512
23467
  }
23513
23468
  if (!this.isSnsServiceToken(serviceToken) && await this.isBackingLambdaGone(serviceToken)) {
23514
- this.logger.warn(`Backing Lambda for custom resource ${logicalId} no longer exists (${serviceToken}); treating the custom resource as already deleted and DROPPING its state record. The handler can never run again, so if its teardown was never PROVEN — e.g. an earlier run reported this resource as skipped (issue 2054) — whatever it manages is still LIVE and is now untracked by cdkd. Check for leftovers before treating the stack as gone.`);
23469
+ if (context?.stackDestroy === true) {
23470
+ this.logger.warn(safeMsg`Backing Lambda for custom resource ${logicalId} no longer exists (${serviceToken}), so ` + "its Delete handler cannot be invoked and cdkd cannot confirm the resource was deleted; skipping deletion — anything this custom resource manages may still be LIVE. cdkd is KEEPING the state record and the run exits non-zero, as CloudFormation leaves such a stack DELETE_FAILED. A re-run skips it again unless a function with that exact ARN exists again (e.g. a shared provider stack destroyed before this one, then redeployed). Otherwise confirm by hand that whatever it manages is gone (or tear it down), then drop the record with " + safeMsg`${stateOrphanRecordRemedy(context, logicalId)}.`);
23471
+ return {
23472
+ outcome: "skipped",
23473
+ reason: CR_BACKING_LAMBDA_GONE_SKIP_REASON
23474
+ };
23475
+ }
23476
+ this.logger.warn(safeMsg`Backing Lambda for custom resource ${logicalId} no longer exists (${serviceToken}); ` + "treating the custom resource as already deleted and DROPPING its state record, as CloudFormation ignores a delete failure in an update's cleanup phase. The handler can never run again, so if its teardown was never PROVEN, whatever it manages may still be LIVE and is now untracked by cdkd. Check for leftovers by hand.");
23515
23477
  return;
23516
23478
  }
23517
23479
  try {
@@ -23526,7 +23488,7 @@ var CustomResourceProvider = class CustomResourceProvider {
23526
23488
  ResourceProperties: this.stringifyProperties(properties)
23527
23489
  }), DELETE_PATH_UNMASKED);
23528
23490
  if (cfnResponse.Status === "FAILED") {
23529
- this.logger.warn(`Custom resource delete handler returned FAILED for ${logicalId}: ${cfnResponse.Reason || "Unknown reason"}. The handler reported that it did NOT delete, so anything this custom resource manages is LEFT IN PLACE — cdkd is KEEPING the state record and the run exits non-zero. ${CR_SKIP_NOT_A_RETRY_CAVEAT} ('cdkd deploy' also accepts --allow-unaddressed, which forces exit 0; 'cdkd destroy' has no such flag.) ${DEPLOY_SKIP_CAVEAT}`);
23491
+ this.logger.warn(`Custom resource delete handler returned FAILED for ${logicalId}: ${cfnResponse.Reason || "Unknown reason"}. The handler reported that it did NOT delete, so anything this custom resource manages is LEFT IN PLACE${handlerSkipRemedy(context, logicalId)}`);
23530
23492
  return {
23531
23493
  outcome: "skipped",
23532
23494
  reason: CR_DELETE_HANDLER_FAILED_SKIP_REASON
@@ -23534,7 +23496,7 @@ var CustomResourceProvider = class CustomResourceProvider {
23534
23496
  }
23535
23497
  this.logger.debug(`Successfully deleted custom resource ${logicalId}`);
23536
23498
  } catch (error) {
23537
- this.logger.warn(`Failed to delete custom resource ${logicalId}, but continuing: ${describeAwsFailure(error).detail}. The Delete handler did not complete, so anything this custom resource manages may still be LIVE — cdkd is KEEPING the state record and the run exits non-zero. ${CR_SKIP_NOT_A_RETRY_CAVEAT} ${DEPLOY_SKIP_CAVEAT}`);
23499
+ this.logger.warn(`Failed to delete custom resource ${logicalId}, but continuing: ${describeAwsFailure(error).detail}. The Delete handler did not complete, so anything this custom resource manages may still be LIVE${handlerSkipRemedy(context, logicalId)}`);
23538
23500
  return {
23539
23501
  outcome: "skipped",
23540
23502
  reason: CR_DELETE_INVOKE_FAILED_SKIP_REASON
@@ -26482,6 +26444,81 @@ function ownPoliciesChange(change) {
26482
26444
  return (change?.propertyChanges ?? []).some((c) => c.path === "Policies" && c.inPlacePropagated !== true && c.replacementPropagated !== true);
26483
26445
  }
26484
26446
 
26447
+ //#endregion
26448
+ //#region src/analyzer/destructive-changes.ts
26449
+ const IGNORED_RESOURCE_TYPES = /* @__PURE__ */ new Set(["AWS::CDK::Metadata"]);
26450
+ const PATH_METADATA_KEY = "aws:cdk:path";
26451
+ function findDestructiveChanges(stackName, changes, records, template, recreateTargets = /* @__PURE__ */ new Set()) {
26452
+ const found = [];
26453
+ for (const change of changes) {
26454
+ const record = Object.hasOwn(records, change.logicalId) ? records[change.logicalId] : void 0;
26455
+ const resourceType = record?.resourceType ?? change.resourceType;
26456
+ if (IGNORED_RESOURCE_TYPES.has(resourceType) || IGNORED_RESOURCE_TYPES.has(change.resourceType)) continue;
26457
+ const impact = change.changeType === "UPDATE" && recreateTargets.has(change.logicalId) ? "WILL_REPLACE" : destructiveImpactOf(change, record);
26458
+ if (impact === void 0) continue;
26459
+ const recorded = typeof record?.constructPath === "string" ? record.constructPath : void 0;
26460
+ const constructPath = constructPathOf(template, change.logicalId) ?? recorded;
26461
+ found.push({
26462
+ stackName,
26463
+ logicalId: change.logicalId,
26464
+ resourceType,
26465
+ ...constructPath !== void 0 && { constructPath },
26466
+ impact
26467
+ });
26468
+ }
26469
+ return found;
26470
+ }
26471
+ function destructiveImpactOf(change, record) {
26472
+ switch (change.changeType) {
26473
+ case "DELETE": return shouldRetainResource(record?.deletionPolicy) ? "WILL_ORPHAN" : "WILL_DESTROY";
26474
+ case "UPDATE": {
26475
+ if (record !== void 0 && record.resourceType !== change.resourceType) return "WILL_REPLACE";
26476
+ let mayReplace = false;
26477
+ for (const pc of change.propertyChanges ?? []) {
26478
+ if (!pc.requiresReplacement) continue;
26479
+ if (pc.inPlacePropagated === true || pc.replacementPropagated === true) mayReplace = true;
26480
+ else return "WILL_REPLACE";
26481
+ }
26482
+ return mayReplace ? "MAY_REPLACE" : void 0;
26483
+ }
26484
+ default: return;
26485
+ }
26486
+ }
26487
+ function constructPathOf(template, logicalId) {
26488
+ const resources = template?.Resources;
26489
+ if (resources === void 0 || !Object.hasOwn(resources, logicalId)) return void 0;
26490
+ const path = resources[logicalId]?.Metadata?.[PATH_METADATA_KEY];
26491
+ return typeof path === "string" && path !== "" ? path : void 0;
26492
+ }
26493
+ function describeDestructiveImpact(impact) {
26494
+ switch (impact) {
26495
+ case "WILL_REPLACE": return "will be replaced";
26496
+ case "MAY_REPLACE": return "may be replaced";
26497
+ case "WILL_DESTROY": return "will be destroyed";
26498
+ case "WILL_ORPHAN": return "will be orphaned";
26499
+ }
26500
+ }
26501
+ function formatDestructiveChange(change) {
26502
+ const path = change.constructPath !== void 0 ? `${displaySafe(displayPath(change.constructPath))} ` : "";
26503
+ return `${displayIdent(change.stackName)}: ${displaySafe(change.resourceType)} ${path}${displayIdent(change.logicalId)} ${describeDestructiveImpact(change.impact)}`;
26504
+ }
26505
+ function displayPath(constructPath) {
26506
+ let parts = constructPath.replace(/^\//, "").split("/");
26507
+ if (parts.length > 1) {
26508
+ parts = parts.slice(1);
26509
+ const last = parts[parts.length - 1];
26510
+ if (parts.length > 1 && (last === "Resource" || last === "Default")) parts = parts.slice(0, -1);
26511
+ }
26512
+ return parts.join("/");
26513
+ }
26514
+ function withConstructPath(record, path) {
26515
+ if (path === void 0 || record.constructPath === path) return record;
26516
+ return {
26517
+ ...record,
26518
+ constructPath: path
26519
+ };
26520
+ }
26521
+
26485
26522
  //#endregion
26486
26523
  //#region src/deployment/masking-retry-logger.ts
26487
26524
  function maskingRetryLogger(logger, secrets) {
@@ -27377,9 +27414,9 @@ const REDACTED_DELETE_ADDRESS_SKIP_REASON = "redacted address property in state
27377
27414
  function redactedDeleteAddressFields(fields) {
27378
27415
  return Object.keys(fields).filter((key) => isRedactedRecordedValue(fields[key]));
27379
27416
  }
27380
- function redactedDeleteAddressSkip(logger, logicalId, what, redactedFields) {
27417
+ function redactedDeleteAddressSkip(logger, logicalId, what, redactedFields, context) {
27381
27418
  if (redactedFields.length === 0) return void 0;
27382
- logger.warn(safeMsg`${what} ${logicalId} is recorded in state with ${redactedFields.join(", ")} ` + "redacted (the '***' mask of a NoEcho value it read, or a secret '{{resolve:...}}' reference), which names nothing in AWS; skipping deletion — no AWS call is issued, so the resource is LEFT IN PLACE unless a parent resource this run also deletes removes it (then only the record is stale). Re-deploying records the same redaction again. The state record is KEPT and the run reports the skip: on 'cdkd destroy' / 'cdkd state destroy' (which exits non-zero) and, since issue 1762, on the plain DELETE of a resource removed from the template during cdkd deploy. Remove the resource by hand, then clear the stack's records with 'cdkd state orphan <stack>' — that command drops EVERY record for the stack, not just this one. NOTE a deploy-side REPLACEMENT or rollback delete instead FAILS the resource (https://github.com/go-to-k/cdkd/issues/1762) — the old resource is left untracked there, so remove it by hand.");
27419
+ logger.warn(safeMsg`${what} ${logicalId} is recorded in state with ${redactedFields.join(", ")} ` + "redacted (the '***' mask of a NoEcho value it read, or a secret '{{resolve:...}}' reference), which names nothing in AWS; skipping deletion — no AWS call is issued, so the resource is LEFT IN PLACE unless a parent resource this run also deletes removes it (then only the record is stale). Re-deploying records the same redaction again. The state record is KEPT and the run reports the skip: on 'cdkd destroy' / 'cdkd state destroy' (which exits non-zero) and, since issue 1762, on the plain DELETE of a resource removed from the template during cdkd deploy. Remove the resource by hand, " + safeMsg`then drop the record with ${stateOrphanRecordRemedy(context, logicalId)}. ` + "NOTE a deploy-side REPLACEMENT or rollback delete instead FAILS the resource (https://github.com/go-to-k/cdkd/issues/1762) — the old resource is left untracked there, so remove it by hand.");
27383
27420
  return {
27384
27421
  outcome: "skipped",
27385
27422
  reason: REDACTED_DELETE_ADDRESS_SKIP_REASON
@@ -28395,6 +28432,9 @@ function mayOwn(o, orphan, completed) {
28395
28432
  if (o.physicalId === orphan.physicalId) return true;
28396
28433
  return o.previousState?.physicalId === orphan.physicalId;
28397
28434
  }
28435
+ function isJournaledOrphan(op) {
28436
+ return op.changeType === "CREATE" && typeof op.physicalIdRecoveredFromError === "boolean";
28437
+ }
28398
28438
  function planFailedOps(failedOps, stateResources) {
28399
28439
  return failedOps.map((op) => ({
28400
28440
  op,
@@ -29278,7 +29318,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
29278
29318
  const takeFinalSnapshot = snapshotPolicy && ctx.skipFinalSnapshot !== true;
29279
29319
  let finalSnapshotIdentifier;
29280
29320
  if (takeFinalSnapshot) finalSnapshotIdentifier = await prepareCreateRollbackFinalSnapshot(op, deleteProvisionedBy, ctx, mask);
29281
- logger.info(` Rollback: deleting partially-created ${safe(op.logicalId)} (${safe(op.resourceType)}) (--revert-failed)` + (takeFinalSnapshot ? " — DeletionPolicy: Snapshot" : "") + (snapshotPolicy && !takeFinalSnapshot ? " — DeletionPolicy: Snapshot NOT taken (--skip-final-snapshot)" : ""));
29321
+ logger.info(` Rollback: deleting partially-created ${safe(op.logicalId)} (${safe(op.resourceType)})` + (takeFinalSnapshot ? " — DeletionPolicy: Snapshot" : "") + (snapshotPolicy && !takeFinalSnapshot ? " — DeletionPolicy: Snapshot NOT taken (--skip-final-snapshot)" : ""));
29282
29322
  const { provider, provisionedBy: deleteRoutedVia } = ctx.providerRegistry.getProviderFor({
29283
29323
  resourceType: op.resourceType,
29284
29324
  provisionedBy: deleteProvisionedBy
@@ -29292,7 +29332,7 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
29292
29332
  deletionPolicy: snapshotPolicy ? "Snapshot" : "Delete",
29293
29333
  recordedAttributes: stateResources[op.logicalId]?.attributes
29294
29334
  });
29295
- throwIfDeleteSkipped(failedCreateDelete, op.logicalId, op.physicalId, "while deleting the partially-created resource (--revert-failed)", {
29335
+ throwIfDeleteSkipped(failedCreateDelete, op.logicalId, op.physicalId, "while deleting the partially-created resource", {
29296
29336
  ctx,
29297
29337
  stackName,
29298
29338
  resourceType: op.resourceType,
@@ -29444,7 +29484,7 @@ async function collectNestedChildUnaddressed(fn) {
29444
29484
  //#endregion
29445
29485
  //#region src/deployment/nested-child-journal.ts
29446
29486
  const NESTED_PENDING_PARENT_REASON = "nested-pending-parent";
29447
- const NESTED_STACK_TYPE$1 = "AWS::CloudFormation::Stack";
29487
+ const NESTED_STACK_TYPE$2 = "AWS::CloudFormation::Stack";
29448
29488
  const MAX_NESTED_WALK_DEPTH = 32;
29449
29489
  function nestedChildStackName(parentStackName, logicalId) {
29450
29490
  return `${parentStackName}~${logicalId}`;
@@ -29500,7 +29540,7 @@ function recordDisplacedSkips(recordEvent, stackName, ops) {
29500
29540
  });
29501
29541
  }
29502
29542
  function revertedNestedRowIds(ops) {
29503
- return ops.filter((op) => op.resourceType === NESTED_STACK_TYPE$1 && op.changeType === "UPDATE").map((op) => op.logicalId);
29543
+ return ops.filter((op) => op.resourceType === NESTED_STACK_TYPE$2 && op.changeType === "UPDATE").map((op) => op.logicalId);
29504
29544
  }
29505
29545
  const revertRunStorage = new AsyncLocalStorage();
29506
29546
  function withNestedRevertRun(runId, fn) {
@@ -29526,7 +29566,7 @@ async function dropNestedChildJournals(args) {
29526
29566
  if (!isPlainRecord(resources)) return;
29527
29567
  if (depthExceeded(depth, parentStackName, logger)) return;
29528
29568
  for (const [logicalId, record] of Object.entries(resources)) {
29529
- if (!isPlainRecord(record) || record["resourceType"] !== NESTED_STACK_TYPE$1) continue;
29569
+ if (!isPlainRecord(record) || record["resourceType"] !== NESTED_STACK_TYPE$2) continue;
29530
29570
  const child = nestedChildStackName(parentStackName, logicalId);
29531
29571
  try {
29532
29572
  const data = await stateBackend.getState(child, region);
@@ -29540,13 +29580,34 @@ async function dropNestedChildJournals(args) {
29540
29580
  warnUncleared(logger, child, error);
29541
29581
  }
29542
29582
  try {
29543
- await withChildLock(args.lockManager, child, region, logger, () => stateBackend.deleteRollbackJournal(child, region));
29544
- logger.debug(safeMsg`Deleted the rollback journal of nested stack ${displaySafe(child)}`);
29583
+ if (await withChildLock(args.lockManager, child, region, logger, async () => {
29584
+ if (args.beforeDelete) {
29585
+ if (!await args.beforeDelete(child, await readOwnRecord(stateBackend, child, region))) return false;
29586
+ }
29587
+ let gone;
29588
+ try {
29589
+ gone = await stateBackend.deleteRollbackJournal(child, region);
29590
+ } catch (error) {
29591
+ await args.onDeleteFailed?.(child);
29592
+ throw error;
29593
+ }
29594
+ if (gone === false) {
29595
+ await args.onDeleteFailed?.(child);
29596
+ return false;
29597
+ }
29598
+ return true;
29599
+ })) logger.debug(safeMsg`Deleted the rollback journal of nested stack ${displaySafe(child)}`);
29545
29600
  } catch (error) {
29546
29601
  warnUncleared(logger, child, error);
29547
29602
  }
29548
29603
  }
29549
29604
  }
29605
+ async function readOwnRecord(stateBackend, child, region) {
29606
+ try {
29607
+ const data = await stateBackend.getState(child, region);
29608
+ if (data && isPlainRecord(data.state) && isPlainRecord(data.state.resources) && (data.state.stackName === void 0 || data.state.stackName === child)) return data.state;
29609
+ } catch {}
29610
+ }
29550
29611
  async function dropSettledNestedJournals(args) {
29551
29612
  const { stateBackend, parentStackName, region, runId, logger } = args;
29552
29613
  const depth = args.depth ?? 0;
@@ -29856,6 +29917,306 @@ function makeSiblingClaimReader(params) {
29856
29917
  };
29857
29918
  }
29858
29919
 
29920
+ //#endregion
29921
+ //#region src/deployment/rollback-executor/journaled-orphans.ts
29922
+ const NONE = {
29923
+ segments: [],
29924
+ count: 0
29925
+ };
29926
+ async function loadJournaledOrphans(stateBackend, stackName, region, rollbackOrphans, logger, options = {}) {
29927
+ let segments;
29928
+ try {
29929
+ const journal = await stateBackend.loadRollbackJournal(stackName, region);
29930
+ if (!journal) return NONE;
29931
+ segments = journal.segments;
29932
+ } catch (err) {
29933
+ const detail = err instanceof Error ? err.message : String(err);
29934
+ logger.warn(safeMsg`Could not read the stack's rollback journal (${displaySafe(detail)}); ` + safeMsg`no resource it records for a failed CREATE is deleted, and ${options.unreadableOutcome ?? "a destroy that proceeds removes the journal with the state"}.`);
29935
+ return {
29936
+ ...NONE,
29937
+ unreadable: true
29938
+ };
29939
+ }
29940
+ const physicalIdOnly = (ops) => ops.filter((op) => op.changeType !== "CREATE");
29941
+ const evidence = segments.map((segment) => options.deployRunId !== void 0 && segment.reason === "nested-pending-parent" && segment.runId === options.deployRunId ? {
29942
+ ...segment,
29943
+ operations: physicalIdOnly(segment.operations)
29944
+ } : segment);
29945
+ const newer = options.newerOperations ?? [];
29946
+ if (newer.length > 0) evidence.push({ operations: physicalIdOnly(newer) });
29947
+ demoteSupersededOrphans(evidence, Array.isArray(rollbackOrphans) ? rollbackOrphans : []);
29948
+ const deployLogicalIds = new Set(newer.map((op) => op.logicalId));
29949
+ for (const segment of segments) if (options.deployRunId !== void 0 && segment.reason === "nested-pending-parent" && segment.runId === options.deployRunId) for (const op of segment.operations) deployLogicalIds.add(op.logicalId);
29950
+ const out = [];
29951
+ let count = 0;
29952
+ for (let s = segments.length - 1; s >= 0; s--) {
29953
+ const segment = segments[s];
29954
+ if (segment.reason === "nested-pending-parent") continue;
29955
+ const ops = splitImportedOps(segment.failedOperations ?? [], segment).replay.filter(isJournaledOrphan);
29956
+ if (ops.length === 0) continue;
29957
+ out.push({
29958
+ segment,
29959
+ ops
29960
+ });
29961
+ count += ops.length;
29962
+ }
29963
+ return {
29964
+ segments: out,
29965
+ count,
29966
+ deployLogicalIds
29967
+ };
29968
+ }
29969
+ function journaledOrphanLines(orphans, logger) {
29970
+ return orphans.segments.flatMap(({ ops }) => ops.map((op) => ` - ${logicalIdShown(op.logicalId)} (${resourceTypeShown(op.resourceType)}) ${displacedPhysicalIdShown(op, logger) ?? "a physical id"}`));
29971
+ }
29972
+ async function deleteJournaledOrphans(orphans, stateResources, stackName, ctx, options = {}) {
29973
+ const total = {
29974
+ failures: 0,
29975
+ warnings: 0,
29976
+ interrupted: false,
29977
+ handled: []
29978
+ };
29979
+ const inlinePolicyWriters = new RollbackInlinePolicyWriters();
29980
+ for (const { segment, ops } of orphans.segments) {
29981
+ if (options.isInterrupted?.()) {
29982
+ total.interrupted = true;
29983
+ break;
29984
+ }
29985
+ const replay = () => withStackName(stackName, () => replayFailedOperations(ops, stateResources, stackName, ctx, {
29986
+ emitEnvelope: false,
29987
+ inlinePolicyWriters,
29988
+ ...options.isInterrupted && { isInterrupted: options.isInterrupted }
29989
+ }));
29990
+ const result = segment.skipPrefix === void 0 ? await replay() : await withSkipPrefix(segment.skipPrefix, replay);
29991
+ total.failures += result.failures;
29992
+ total.warnings += result.warnings;
29993
+ const pending = new Set(result.remainingFailedOps);
29994
+ for (const op of ops) if (!pending.has(op)) total.handled.push({
29995
+ segment,
29996
+ op
29997
+ });
29998
+ if (result.interrupted) {
29999
+ total.interrupted = true;
30000
+ break;
30001
+ }
30002
+ }
30003
+ return total;
30004
+ }
30005
+ async function settleJournaledOrphansOnSuccess(args) {
30006
+ const { stateBackend, stackName, region, stateResources, newerOperations, ctx, logger } = args;
30007
+ const stack = displayIdent(stackName);
30008
+ const newerIds = newerOperations.map((op) => op.logicalId);
30009
+ let orphans;
30010
+ try {
30011
+ orphans = await loadJournaledOrphans(stateBackend, stackName, region, args.rollbackOrphans, logger, {
30012
+ newerOperations,
30013
+ ...args.deployRunId !== void 0 && { deployRunId: args.deployRunId },
30014
+ unreadableOutcome: "the successful deploy removes the journal"
30015
+ });
30016
+ } catch (err) {
30017
+ logger.warn(safeMsg`Could not act on the rollback journal of stack ${stack}: ${errorDetail(err)}. It is kept.`);
30018
+ await markSuperseded(stateBackend, stackName, region, newerIds);
30019
+ return {
30020
+ unaddressed: 1,
30021
+ keepJournal: true
30022
+ };
30023
+ }
30024
+ if (orphans.count === 0) return {
30025
+ unaddressed: 0,
30026
+ keepJournal: false
30027
+ };
30028
+ const all = orphans.segments.flatMap(({ segment, ops }) => ops.map((op) => ({
30029
+ segment,
30030
+ op
30031
+ })));
30032
+ let kept = all;
30033
+ if (stateResources === void 0) logger.warn(safeMsg`The rollback journal of stack ${stack} records ${all.length} resource(s) a failed deploy ` + `created, but the stack's state cannot be read, so whether a record now owns them is unknown: none is deleted.`);
30034
+ else {
30035
+ logger.info(safeMsg`The rollback journal of stack ${stack} records ${all.length} resource(s) a failed deploy ` + `created that no state record holds; acting on them per their DeletionPolicy before the journal is removed:`);
30036
+ for (const line of journaledOrphanLines(orphans, logger)) logger.info(line);
30037
+ try {
30038
+ const { unreadable, tracked } = await applySuccessRule(orphans, stateResources, orphans.deployLogicalIds ?? /* @__PURE__ */ new Set(), args.foreignHolder, stack, logger, args.isInterrupted);
30039
+ const outcome = await deleteJournaledOrphans({
30040
+ segments: orphans.segments.map(({ segment, ops }) => ({
30041
+ segment,
30042
+ ops: ops.filter((op) => !unreadable.has(op) && !tracked.has(op))
30043
+ })).filter(({ ops }) => ops.length > 0),
30044
+ count: orphans.count - unreadable.size - tracked.size
30045
+ }, { ...stateResources }, stackName, ctx, args.isInterrupted ? { isInterrupted: args.isInterrupted } : {});
30046
+ kept = all.filter(({ segment, op }) => unreadable.has(op) || !tracked.has(op) && !isHandledOrphan(outcome.handled, segment, op));
30047
+ } catch (err) {
30048
+ logger.warn(safeMsg`Acting on the journaled resources of stack ${stack} failed: ${errorDetail(err)}`);
30049
+ }
30050
+ }
30051
+ const keptOps = new Set(kept.map(({ op }) => op));
30052
+ const skipped = all.filter(({ op }) => !keptOps.has(op) && op.physicalIdRecoveredFromError === false).length;
30053
+ const cleared = all.filter(({ op }) => !keptOps.has(op));
30054
+ const stripCleared = cleared.length === 0 ? void 0 : async () => {
30055
+ try {
30056
+ await stateBackend.dropRollbackJournalFailedOperations(stackName, region, (op, segment) => isHandledOrphan(cleared, segment, op));
30057
+ } catch (err) {
30058
+ logger.warn(safeMsg`Failed to remove the settled entries from the rollback journal of stack ${stack}: ` + safeMsg`${errorDetail(err)}. A cdkd rollback or cdkd destroy could act on them again; run a ` + "successful cdkd deploy of the stack first, which settles them again.");
30059
+ }
30060
+ };
30061
+ if (kept.length === 0) return {
30062
+ unaddressed: skipped,
30063
+ keepJournal: false,
30064
+ ...stripCleared && { stripCleared }
30065
+ };
30066
+ const keptIds = new Set(kept.map(({ op }) => op.logicalId));
30067
+ const supersededIds = newerIds.filter((id) => !keptIds.has(id));
30068
+ const demoted = kept.filter(({ op }) => op.physicalIdRecoveredFromError === false);
30069
+ const reduce = () => stateBackend.reduceRollbackJournalToFailedOperations(stackName, region, (op, segment) => isHandledOrphan(kept, segment, op), supersededIds, (op, segment) => isHandledOrphan(demoted, segment, op));
30070
+ let reduced = false;
30071
+ for (let attempt = 0; attempt < 2 && !reduced; attempt++) try {
30072
+ await reduce();
30073
+ reduced = true;
30074
+ } catch (err) {
30075
+ if (attempt === 1) logger.warn(safeMsg`Failed to reduce the rollback journal of stack ${stack} to its undeleted resources: ` + safeMsg`${errorDetail(err)}. The whole journal is kept.`);
30076
+ }
30077
+ if (!reduced) {
30078
+ await markSuperseded(stateBackend, stackName, region, supersededIds);
30079
+ await stripCleared?.();
30080
+ }
30081
+ logger.warn(safeMsg`${kept.length} resource(s) a failed deploy of stack ${stack} created were not deleted ` + (reduced ? "(see above). The rollback journal, their only record, is kept with just them; the next " : "(see above). The rollback journal, their only record, is kept; the next ") + "successful deploy retries.");
30082
+ return {
30083
+ unaddressed: kept.length + skipped,
30084
+ keepJournal: true
30085
+ };
30086
+ }
30087
+ async function applySuccessRule(orphans, stateResources, deployLogicalIds, foreignHolder, stack, logger, isInterrupted) {
30088
+ const unreadable = /* @__PURE__ */ new Set();
30089
+ const tracked = /* @__PURE__ */ new Set();
30090
+ let interrupted = false;
30091
+ for (const { ops } of orphans.segments) for (const op of ops) {
30092
+ if (op.physicalIdRecoveredFromError !== true || !op.physicalId) continue;
30093
+ if (interrupted || isInterrupted?.()) {
30094
+ interrupted = true;
30095
+ unreadable.add(op);
30096
+ continue;
30097
+ }
30098
+ if (Object.values(stateResources).some((r) => r?.resourceType === op.resourceType && r.physicalId === op.physicalId)) {
30099
+ tracked.add(op);
30100
+ continue;
30101
+ }
30102
+ if (Object.prototype.hasOwnProperty.call(stateResources, op.logicalId) || deployLogicalIds.has(op.logicalId)) {
30103
+ op.physicalIdRecoveredFromError = false;
30104
+ continue;
30105
+ }
30106
+ const holding = await foreignHolder(op.resourceType, op.physicalId);
30107
+ if (holding === void 0) continue;
30108
+ if (holding.kind === "held") {
30109
+ logger.warn(safeMsg`${logicalIdShown(op.logicalId)} (${resourceTypeShown(op.resourceType)}), which a failed deploy ` + safeMsg`of stack ${stack} created, is not deleted: ${holding.by} holds a resource of that type under ` + "the same physical id.");
30110
+ op.physicalIdRecoveredFromError = false;
30111
+ continue;
30112
+ }
30113
+ logger.warn(safeMsg`${logicalIdShown(op.logicalId)} (${resourceTypeShown(op.resourceType)}), which a failed deploy ` + safeMsg`of stack ${stack} created, is not deleted: ${holding.what}, so whether another stack holds it is unknown.`);
30114
+ unreadable.add(op);
30115
+ }
30116
+ return {
30117
+ unreadable,
30118
+ tracked
30119
+ };
30120
+ }
30121
+ function makeForeignHolderScan(stateBackend) {
30122
+ let scan;
30123
+ const key = (type, id) => JSON.stringify([type, id]);
30124
+ const run = async () => {
30125
+ const holders = /* @__PURE__ */ new Map();
30126
+ let refs;
30127
+ try {
30128
+ refs = await stateBackend.listStacks();
30129
+ } catch {
30130
+ return {
30131
+ holders,
30132
+ unreadable: "the state bucket listing (it could not be read)"
30133
+ };
30134
+ }
30135
+ let unreadable;
30136
+ await Promise.all(refs.map(async (ref) => {
30137
+ const named = (why) => safeMsg`the state record of stack ${displayIdent(ref.stackName)} (${why})`;
30138
+ if (ref.region === void 0) {
30139
+ unreadable ??= named("its region cannot be read");
30140
+ return;
30141
+ }
30142
+ const region = ref.region;
30143
+ let state;
30144
+ try {
30145
+ state = (await stateBackend.getState(ref.stackName, region))?.state;
30146
+ } catch {
30147
+ unreadable ??= named("it could not be read");
30148
+ return;
30149
+ }
30150
+ if (state === void 0) return;
30151
+ const resources = state.resources;
30152
+ if (resources !== void 0 && (typeof resources !== "object" || resources === null || Array.isArray(resources))) {
30153
+ unreadable ??= named("its resources cannot be read");
30154
+ return;
30155
+ }
30156
+ if (!hasReadableOrphans(state) || unreadableOrphanRecords(state).length > 0) {
30157
+ unreadable ??= named("its rollback-orphan records cannot be read");
30158
+ return;
30159
+ }
30160
+ const held = [...Object.values(resources ?? {}), ...(state.orphans ?? []).map((record) => record.state)];
30161
+ for (const record of held) {
30162
+ const r = record;
30163
+ if (typeof r?.resourceType !== "string" || typeof r.physicalId !== "string") continue;
30164
+ const k = key(r.resourceType, r.physicalId);
30165
+ const list = holders.get(k) ?? [];
30166
+ list.push({
30167
+ stackName: ref.stackName,
30168
+ region
30169
+ });
30170
+ holders.set(k, list);
30171
+ }
30172
+ }));
30173
+ return {
30174
+ holders,
30175
+ ...unreadable !== void 0 && { unreadable }
30176
+ };
30177
+ };
30178
+ return (self) => async (resourceType, physicalId) => {
30179
+ scan ??= run();
30180
+ const { holders, unreadable } = await scan;
30181
+ const other = (holders.get(key(resourceType, physicalId)) ?? []).find((h) => !(h.stackName === self.stackName && h.region === self.region));
30182
+ if (other) return {
30183
+ kind: "held",
30184
+ by: safeMsg`the state record of stack ${displayIdent(other.stackName)} (${displaySafe(other.region)})`
30185
+ };
30186
+ return unreadable === void 0 ? void 0 : {
30187
+ kind: "unreadable",
30188
+ what: unreadable
30189
+ };
30190
+ };
30191
+ }
30192
+ async function markSuperseded(stateBackend, stackName, region, ids) {
30193
+ try {
30194
+ await stateBackend.markRollbackJournalSuperseded(stackName, region, ids);
30195
+ } catch {}
30196
+ }
30197
+ function errorDetail(err) {
30198
+ return displaySafe(err instanceof Error ? err.message : String(err));
30199
+ }
30200
+ function isHandledOrphan(handled, segment, op) {
30201
+ return handled.some((h) => h.segment.timestamp === segment.timestamp && h.segment.runId === segment.runId && h.op.logicalId === op.logicalId && h.op.changeType === op.changeType && h.op.resourceType === op.resourceType && h.op.physicalId === op.physicalId);
30202
+ }
30203
+ function orphanKey(segment, op) {
30204
+ return JSON.stringify([
30205
+ segment.timestamp,
30206
+ segment.runId ?? null,
30207
+ op.logicalId,
30208
+ op.changeType,
30209
+ op.resourceType,
30210
+ op.physicalId ?? null
30211
+ ]);
30212
+ }
30213
+ function sameJournaledOrphans(a, b) {
30214
+ const keys = (o) => o.segments.flatMap(({ segment, ops }) => ops.map((op) => orphanKey(segment, op))).sort();
30215
+ const ka = keys(a);
30216
+ const kb = keys(b);
30217
+ return ka.length === kb.length && ka.every((k, i) => k === kb[i]);
30218
+ }
30219
+
29859
30220
  //#endregion
29860
30221
  //#region src/deployment/deploy-engine/rollback.ts
29861
30222
  function redactOperationsForJournal(operations) {
@@ -29904,33 +30265,109 @@ async function adoptRollbackOrphans(currentState, effectiveTemplate) {
29904
30265
  if (records.length > 0) currentState.orphans = plan.remaining;
29905
30266
  return plan;
29906
30267
  }
29907
- async function performRollback(completedOperations, stateResources, stackName, previousState) {
30268
+ async function performRollback(completedOperations, stateResources, stackName, previousState, failedOperations = [], priorOrphans = []) {
30269
+ const orphanIndexes = [];
30270
+ const orphanOps = [];
30271
+ failedOperations.forEach((op, i) => {
30272
+ if (!isJournaledOrphan(op)) return;
30273
+ orphanIndexes.push(i);
30274
+ orphanOps.push({ ...op });
30275
+ });
30276
+ demoteSupersededOrphans([{
30277
+ operations: completedOperations,
30278
+ failedOperations: orphanOps
30279
+ }], priorOrphans);
30280
+ const ctx = this.rollbackExecutorContext(previousState, stackName);
30281
+ const inlinePolicyWriters = new RollbackInlinePolicyWriters();
29908
30282
  const runId = this.options.eventRecorder?.runId;
29909
- const { result, run } = await withNestedRevertRun(runId, async (scope) => ({
29910
- result: await replayRollback(completedOperations, stateResources, stackName, this.rollbackExecutorContext(previousState, stackName)),
29911
- run: scope
29912
- }));
30283
+ const { result, failed, run } = await withNestedRevertRun(runId, async (scope) => {
30284
+ return {
30285
+ failed: orphanOps.length > 0 ? await replayFailedOperations(orphanOps, stateResources, stackName, ctx, {
30286
+ emitEnvelope: completedOperations.length === 0,
30287
+ inlinePolicyWriters
30288
+ }) : void 0,
30289
+ result: await replayRollback(completedOperations, stateResources, stackName, ctx, { inlinePolicyWriters }),
30290
+ run: scope
30291
+ };
30292
+ });
30293
+ const pendingOrphans = new Set(failed?.remainingFailedOps ?? []);
30294
+ const handled = new Set(orphanIndexes.filter((_, k) => !pendingOrphans.has(orphanOps[k])));
29913
30295
  return {
29914
- failures: result.failures,
29915
- warnings: result.warnings + run.warnings,
29916
- skipped: result.skipped,
29917
- orphaned: result.orphaned,
29918
- settledNested: run.settled
30296
+ failures: result.failures + (failed?.failures ?? 0),
30297
+ warnings: result.warnings + run.warnings + (failed?.warnings ?? 0),
30298
+ skipped: result.skipped + (failed?.skipped ?? 0),
30299
+ orphaned: [...failed?.orphaned ?? [], ...result.orphaned],
30300
+ settledNested: run.settled,
30301
+ remainingFailedOps: failedOperations.filter((_, i) => !handled.has(i))
29919
30302
  };
29920
30303
  }
29921
30304
  async function settleJournalAfterSuccess(stackName, completedOperations, previousState, finalResources, initialDeploy) {
29922
30305
  if (this.options.parentStackInfo) {
29923
30306
  await this.writeRollbackJournalSegment(stackName, completedOperations, [], NESTED_PENDING_PARENT_REASON, initialDeploy, nestedPendingSnapshot(previousState));
29924
- return;
29925
- }
29926
- await Promise.all([this.deleteRollbackJournalBestEffort(stackName, completedOperations.map((op) => op.logicalId)), dropNestedChildJournals({
30307
+ return 0;
30308
+ }
30309
+ let nestedLeft = 0;
30310
+ const foreignHolderFor = makeForeignHolderScan(this.stateBackend);
30311
+ const deployRunId = this.options.eventRecorder?.runId;
30312
+ const stripOnFailure = /* @__PURE__ */ new Map();
30313
+ const [ownLeft] = await Promise.all([(async () => {
30314
+ const own = await settleJournaledOrphansOnSuccess({
30315
+ stateBackend: this.stateBackend,
30316
+ stackName,
30317
+ region: this.stackRegion,
30318
+ stateResources: finalResources,
30319
+ rollbackOrphans: previousState.orphans,
30320
+ newerOperations: completedOperations,
30321
+ ...deployRunId !== void 0 && { deployRunId },
30322
+ foreignHolder: foreignHolderFor({
30323
+ stackName,
30324
+ region: this.stackRegion
30325
+ }),
30326
+ ctx: this.rollbackExecutorContext(previousState, stackName),
30327
+ isInterrupted: () => this.interrupted,
30328
+ logger: this.logger
30329
+ });
30330
+ if (own.keepJournal) return own.unaddressed;
30331
+ if (!await this.deleteRollbackJournalBestEffort(stackName, completedOperations.map((op) => op.logicalId))) await own.stripCleared?.();
30332
+ return own.unaddressed;
30333
+ })(), dropNestedChildJournals({
29927
30334
  stateBackend: this.stateBackend,
29928
30335
  lockManager: this.lockManager,
29929
30336
  parentStackName: stackName,
29930
30337
  region: this.stackRegion,
29931
30338
  resources: finalResources,
29932
- logger: this.logger
30339
+ logger: this.logger,
30340
+ beforeDelete: async (child, childRecord) => {
30341
+ const childState = childRecord !== void 0 && hasReadableOrphans(childRecord) ? childRecord : void 0;
30342
+ const settled = await settleJournaledOrphansOnSuccess({
30343
+ stateBackend: this.stateBackend,
30344
+ stackName: child,
30345
+ region: this.stackRegion,
30346
+ stateResources: childState?.resources,
30347
+ rollbackOrphans: childState?.orphans,
30348
+ newerOperations: [],
30349
+ ...deployRunId !== void 0 && { deployRunId },
30350
+ foreignHolder: foreignHolderFor({
30351
+ stackName: child,
30352
+ region: this.stackRegion
30353
+ }),
30354
+ isInterrupted: () => this.interrupted,
30355
+ ctx: {
30356
+ ...this.rollbackExecutorContext(childState ?? previousState, child),
30357
+ producerRegionsIncomplete: true,
30358
+ nestedChildStack: child
30359
+ },
30360
+ logger: this.logger
30361
+ });
30362
+ nestedLeft += settled.unaddressed;
30363
+ if (settled.stripCleared) stripOnFailure.set(child, settled.stripCleared);
30364
+ return !settled.keepJournal;
30365
+ },
30366
+ onDeleteFailed: async (child) => {
30367
+ await stripOnFailure.get(child)?.();
30368
+ }
29933
30369
  })]);
30370
+ return ownLeft + nestedLeft;
29934
30371
  }
29935
30372
  async function deleteRollbackJournalBestEffort(stackName, supersededLogicalIds = []) {
29936
30373
  let deleted;
@@ -29940,12 +30377,14 @@ async function deleteRollbackJournalBestEffort(stackName, supersededLogicalIds =
29940
30377
  this.logger.debug(safeMsg`Failed to delete rollback journal for ${stackName}: ${err instanceof Error ? err.message : String(err)}`);
29941
30378
  deleted = false;
29942
30379
  }
29943
- if (deleted !== false || supersededLogicalIds.length === 0) return;
30380
+ if (deleted !== false) return true;
30381
+ if (supersededLogicalIds.length === 0) return false;
29944
30382
  try {
29945
30383
  await this.stateBackend.markRollbackJournalSuperseded(stackName, this.stackRegion, supersededLogicalIds);
29946
30384
  } catch (markErr) {
29947
30385
  this.logger.debug(safeMsg`Failed to record superseded logical ids on the rollback journal for ${stackName}: ${markErr instanceof Error ? markErr.message : String(markErr)}`);
29948
30386
  }
30387
+ return false;
29949
30388
  }
29950
30389
  async function settleJournalAfterCleanRollback(stackName, failedOperations, initialDeploy) {
29951
30390
  if (failedOperations.length === 0) {
@@ -31737,6 +32176,7 @@ var DynamoDBGlobalTableProvider = class {
31737
32176
  };
31738
32177
  } catch (wiringError) {
31739
32178
  warn(`Wiring failed after CreateTable for ${tableName}; attempting best-effort cleanup`);
32179
+ let tableLeftBehind = false;
31740
32180
  try {
31741
32181
  const replicasForCleanup = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }))).Table?.Replicas ?? [];
31742
32182
  for (const replica of replicasForCleanup) {
@@ -31755,12 +32195,15 @@ var DynamoDBGlobalTableProvider = class {
31755
32195
  }
31756
32196
  await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: tableName }));
31757
32197
  } catch (cleanupErr) {
32198
+ tableLeftBehind = true;
31758
32199
  const cleanupMsg = describeAwsFailure(cleanupErr).detail;
31759
32200
  warn(`Partial-create cleanup failed for ${tableName}: ${cleanupMsg}. To remove the orphaned AWS-side table, run: ` + pasteableAwsCommand(maskSecrets)`aws dynamodb delete-table --table-name ${tableName}`.render());
31760
32201
  }
31761
32202
  markAuxiliaryFailure(wiringError, logicalId);
31762
32203
  const cause = wiringError instanceof Error ? wiringError : void 0;
31763
- throw this.wrapMaskedError(log, wiringError, (text) => new ProvisioningError(`Failed to create DynamoDB GlobalTable ${logicalId}: ${text}`, resourceType, logicalId, tableName, cause));
32204
+ const thrown = this.wrapMaskedError(log, wiringError, (text) => new ProvisioningError(`Failed to create DynamoDB GlobalTable ${logicalId}: ${text}`, resourceType, logicalId, tableName, cause));
32205
+ if (tableLeftBehind) markCreatedBeforeFailure(thrown, logicalId, resourceType, tableName);
32206
+ throw thrown;
31764
32207
  }
31765
32208
  }
31766
32209
  reportThroughputDiagnostics(diagnostics, logicalId, physicalId, maskSecrets = (text) => text) {
@@ -34782,31 +35225,61 @@ function validateOptions(opts) {
34782
35225
  }
34783
35226
  async function withResourceDeadline(operation, opts) {
34784
35227
  validateOptions(opts);
34785
- const startedAt = Date.now();
34786
35228
  return new Promise((resolve, reject) => {
34787
35229
  let settled = false;
35230
+ let timedOut = false;
35231
+ let warned = false;
34788
35232
  let warnTimer;
34789
35233
  let timeoutTimer;
35234
+ let elapsedBeforePause = 0;
35235
+ let runningSince = Date.now();
35236
+ let pauses = 0;
35237
+ const elapsed = () => elapsedBeforePause + (pauses > 0 ? 0 : Date.now() - runningSince);
34790
35238
  const cleanup = () => {
34791
35239
  if (warnTimer !== void 0) clearTimeout(warnTimer);
34792
35240
  if (timeoutTimer !== void 0) clearTimeout(timeoutTimer);
34793
35241
  warnTimer = void 0;
34794
35242
  timeoutTimer = void 0;
34795
35243
  };
34796
- if (opts.onWarn) warnTimer = setTimeout(() => {
34797
- if (settled) return;
34798
- try {
34799
- opts.onWarn(Date.now() - startedAt);
34800
- } catch {}
34801
- }, opts.warnAfterMs);
34802
- timeoutTimer = setTimeout(() => {
34803
- if (settled) return;
34804
- settled = true;
34805
- cleanup();
34806
- const elapsed = Date.now() - startedAt;
34807
- reject(opts.onTimeout(elapsed));
34808
- }, opts.timeoutMs);
34809
- Promise.resolve().then(() => operation()).then((value) => {
35244
+ const arm = () => {
35245
+ if (opts.onWarn && !warned) warnTimer = setTimeout(() => {
35246
+ if (settled) return;
35247
+ warned = true;
35248
+ try {
35249
+ opts.onWarn(elapsed());
35250
+ } catch {}
35251
+ }, Math.max(0, opts.warnAfterMs - elapsed()));
35252
+ timeoutTimer = setTimeout(() => {
35253
+ if (settled) return;
35254
+ settled = true;
35255
+ timedOut = true;
35256
+ cleanup();
35257
+ reject(opts.onTimeout(elapsed()));
35258
+ }, Math.max(0, opts.timeoutMs - elapsed()));
35259
+ };
35260
+ arm();
35261
+ const outer = deadlineScope.getStore();
35262
+ const control = {
35263
+ pause: () => {
35264
+ pauses += 1;
35265
+ if (pauses === 1) {
35266
+ elapsedBeforePause += Date.now() - runningSince;
35267
+ cleanup();
35268
+ }
35269
+ outer?.pause();
35270
+ },
35271
+ resume: () => {
35272
+ if (pauses === 0) return;
35273
+ pauses -= 1;
35274
+ if (pauses === 0) {
35275
+ runningSince = Date.now();
35276
+ if (!settled) arm();
35277
+ }
35278
+ outer?.resume();
35279
+ },
35280
+ expired: () => timedOut || (outer?.expired() ?? false)
35281
+ };
35282
+ Promise.resolve().then(() => deadlineScope.run(control, operation)).then((value) => {
34810
35283
  if (settled) return;
34811
35284
  settled = true;
34812
35285
  cleanup();
@@ -34819,6 +35292,20 @@ async function withResourceDeadline(operation, opts) {
34819
35292
  });
34820
35293
  });
34821
35294
  }
35295
+ const deadlineScope = new AsyncLocalStorage();
35296
+ async function whileEnclosingDeadlinesPaused(fn) {
35297
+ const control = deadlineScope.getStore();
35298
+ if (control === void 0) return fn();
35299
+ control.pause();
35300
+ try {
35301
+ return await fn();
35302
+ } finally {
35303
+ control.resume();
35304
+ }
35305
+ }
35306
+ function enclosingDeadlineExpired() {
35307
+ return deadlineScope.getStore()?.expired() ?? false;
35308
+ }
34822
35309
 
34823
35310
  //#endregion
34824
35311
  //#region src/deployment/deploy-engine/provision.ts
@@ -35381,6 +35868,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
35381
35868
  let autoRollbackJournaled = false;
35382
35869
  let rollbackOrphans = [];
35383
35870
  let rollbackSettledNested = /* @__PURE__ */ new Map();
35871
+ let rollbackRemainingFailedOps = failedOperations;
35384
35872
  if (error instanceof InterruptedError || isInterruptedWaitError(error) || this.interruptCause === "user") {
35385
35873
  await this.writeRollbackJournalSegment(stackName, completedOperations, failedOperations, "interrupted", initialDeploy);
35386
35874
  this.logger.info(`Partial state saved (${Object.keys(newResources).length} resources). Run deploy again to resume, 'cdkd rollback' to revert, or destroy to clean up.`);
@@ -35392,7 +35880,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
35392
35880
  this.logger.warn(safeMsg`Partial state has been saved. ${this.recoveryHint("Run 'cdkd deploy' to resume, 'cdkd rollback' to revert, or destroy to clean up.")}`);
35393
35881
  } else {
35394
35882
  autoRollbackJournaled = await this.writeRollbackJournalSegment(stackName, completedOperations, failedOperations, "auto-rollback-started", initialDeploy);
35395
- const rollbackResult = await this.performRollback(completedOperations, newResources, stackName, currentState);
35883
+ const rollbackResult = await this.performRollback(completedOperations, newResources, stackName, currentState, failedOperations, currentState.orphans ?? []);
35396
35884
  autoRollbackClean = autoRollbackJournaled && rollbackResult.failures === 0 && rollbackResult.skipped === 0;
35397
35885
  if (rollbackResult.failures === 0 && rollbackResult.skipped > 0) {
35398
35886
  this.logger.warn(safeMsg`The automatic rollback could not revert ${rollbackResult.skipped} operation(s) ` + `(see the warnings above; each is recorded as a ROLLBACK_RESOURCE_SKIPPED event).` + (autoRollbackJournaled ? ` The rollback journal keeps them.` : ""));
@@ -35403,6 +35891,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
35403
35891
  }
35404
35892
  rollbackOrphans = rollbackResult.orphaned;
35405
35893
  rollbackSettledNested = rollbackResult.settledNested;
35894
+ rollbackRemainingFailedOps = rollbackResult.remainingFailedOps;
35406
35895
  }
35407
35896
  try {
35408
35897
  const postRollbackState = {
@@ -35419,7 +35908,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
35419
35908
  };
35420
35909
  await this.stateBackend.saveState(stackName, this.stackRegion, this.withParentInfo(postRollbackState), { ...currentEtag !== void 0 && { expectedEtag: currentEtag } });
35421
35910
  this.logger.debug("State saved after deployment failure");
35422
- if (autoRollbackClean) await this.settleNestedChildrenAfterCleanRollback(stackName, rollbackSettledNested, await this.settleJournalAfterCleanRollback(stackName, failedOperations, initialDeploy));
35911
+ if (autoRollbackClean) await this.settleNestedChildrenAfterCleanRollback(stackName, rollbackSettledNested, await this.settleJournalAfterCleanRollback(stackName, rollbackRemainingFailedOps, initialDeploy));
35423
35912
  } catch (saveError) {
35424
35913
  this.logger.debug(`Retrying state save after rollback (ETag mismatch): ${saveError instanceof Error ? saveError.message : String(saveError)}`);
35425
35914
  try {
@@ -35438,7 +35927,7 @@ async function executeDeployment(template, currentState, changes, dag, execution
35438
35927
  };
35439
35928
  await this.stateBackend.saveState(stackName, this.stackRegion, this.withParentInfo(postRollbackState), { ...freshEtag !== void 0 && { expectedEtag: freshEtag } });
35440
35929
  this.logger.debug("State saved after deployment failure (retry succeeded)");
35441
- if (autoRollbackClean) await this.settleNestedChildrenAfterCleanRollback(stackName, rollbackSettledNested, await this.settleJournalAfterCleanRollback(stackName, failedOperations, initialDeploy));
35930
+ if (autoRollbackClean) await this.settleNestedChildrenAfterCleanRollback(stackName, rollbackSettledNested, await this.settleJournalAfterCleanRollback(stackName, rollbackRemainingFailedOps, initialDeploy));
35442
35931
  } catch (retryError) {
35443
35932
  this.logger.warn(`Failed to save state after rollback: ${retryError instanceof Error ? retryError.message : String(retryError)}`);
35444
35933
  }
@@ -35610,6 +36099,62 @@ function refuseNoValueOutputs(outputs, conditions) {
35610
36099
  throw markNonRetryable(/* @__PURE__ */ new Error(`Output ${offending.join(", ")} evaluates to AWS::NoValue, and CloudFormation rejects the template for it ("The Value field of every Outputs member must evaluate to a String") before creating anything. To publish an Output only sometimes, give it a Condition instead of selecting AWS::NoValue in its Value.`));
35611
36100
  }
35612
36101
 
36102
+ //#endregion
36103
+ //#region src/deployment/deployment-approval.ts
36104
+ const NESTED_STACK_TYPE$1 = "AWS::CloudFormation::Stack";
36105
+ async function requireDeploymentApproval(args) {
36106
+ const level = args.options.requireApproval ?? "never";
36107
+ const approve = args.options.approveDeployment;
36108
+ if (level === "never" || approve === void 0) return;
36109
+ const changes = [...args.changes].filter((c) => c.changeType !== "NO_CHANGE");
36110
+ const destructiveChanges = findDestructiveChanges(args.stackName, changes, args.records, args.template, new Set(args.recreateTargetIds ?? []));
36111
+ const onlyNestedUpdates = changes.every((c) => c.changeType === "UPDATE" && c.resourceType === NESTED_STACK_TYPE$1);
36112
+ if (!(level === "destructive" ? destructiveChanges.length > 0 : changes.length > 0 && !onlyNestedUpdates)) return;
36113
+ const count = (type) => changes.filter((c) => c.changeType === type).length;
36114
+ if (enclosingDeadlineExpired()) throw approvalAfterTimeout(args.stackName);
36115
+ let approved;
36116
+ try {
36117
+ approved = await whileEnclosingDeadlinesPaused(() => approve({
36118
+ stackName: args.stackName,
36119
+ level,
36120
+ counts: {
36121
+ create: count("CREATE"),
36122
+ update: count("UPDATE"),
36123
+ delete: count("DELETE")
36124
+ },
36125
+ destructiveChanges
36126
+ }));
36127
+ } catch (error) {
36128
+ throw error instanceof Error ? markNonRetryable(error) : error;
36129
+ }
36130
+ if (!approved) throw markNonRetryable(new CdkdError(safeMsg`Deployment of stack ${args.stackName} was not approved (--require-approval=${level}). Nothing was changed.`, "DEPLOY_NOT_APPROVED"));
36131
+ }
36132
+ function approvalAfterTimeout(stackName) {
36133
+ return markNonRetryable(new CdkdError(safeMsg`Deployment of stack ${stackName} was not started: its parent's nested-stack row already timed out (--resource-timeout). Nothing was changed.`, "DEPLOY_APPROVAL_AFTER_TIMEOUT"));
36134
+ }
36135
+ async function requireOutputsOnlyApproval(args) {
36136
+ const approve = args.options.approveDeployment;
36137
+ if (args.options.requireApproval !== "any-change" || approve === void 0) return;
36138
+ if (enclosingDeadlineExpired()) throw approvalAfterTimeout(args.stackName);
36139
+ let approved;
36140
+ try {
36141
+ approved = await whileEnclosingDeadlinesPaused(() => approve({
36142
+ stackName: args.stackName,
36143
+ level: "any-change",
36144
+ counts: {
36145
+ create: 0,
36146
+ update: 0,
36147
+ delete: 0
36148
+ },
36149
+ destructiveChanges: [],
36150
+ outputsOnly: true
36151
+ }));
36152
+ } catch (error) {
36153
+ throw error instanceof Error ? markNonRetryable(error) : error;
36154
+ }
36155
+ if (!approved) throw markNonRetryable(new CdkdError(safeMsg`Deployment of stack ${args.stackName} was not approved (--require-approval=any-change). Nothing was changed.`, "DEPLOY_NOT_APPROVED"));
36156
+ }
36157
+
35613
36158
  //#endregion
35614
36159
  //#region src/deployment/condition-verdicts.ts
35615
36160
  function conditionInputsFrom(args) {
@@ -36137,6 +36682,7 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
36137
36682
  }));
36138
36683
  }
36139
36684
  const effectiveTemplate = this.templateParser.filterResourcesByCondition(template, conditions);
36685
+ this.constructPathTemplate = effectiveTemplate;
36140
36686
  const orphanCountBeforeAdoption = (currentState.orphans ?? []).length;
36141
36687
  const orphanPlan = await this.adoptRollbackOrphans(currentState, effectiveTemplate);
36142
36688
  if (Object.keys(orphanPlan.adopted).length > 0) {
@@ -36230,6 +36776,10 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
36230
36776
  const skippedOutputsChanged = !skippedOutputsEqual(currentState.skippedOutputs, this.skippedOutputs);
36231
36777
  const healedAttributesPending = this.hasUnpersistedHeals(currentState.resources);
36232
36778
  const conditionVerdictsChanged = !conditionVerdictRecordsEqual(readRecordedConditionVerdicts(currentState), conditionVerdicts);
36779
+ if (outputsChanged || exportSetChanged && currentState.exportNames !== void 0) await requireOutputsOnlyApproval({
36780
+ options: this.options,
36781
+ stackName
36782
+ });
36233
36783
  if (observedRefresh || maskedFingerprintsBackfilled || conditionVerdictsChanged || outputsChanged || exportSetChanged || skippedOutputsChanged || orphansChanged || healedAttributesPending) try {
36234
36784
  const refreshedState = {
36235
36785
  version: 10,
@@ -36263,13 +36813,12 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
36263
36813
  this.logger.warn(`Failed to persist no-change state update: ${saveError instanceof Error ? saveError.message : String(saveError)} — drift baseline / outputs will be re-resolved on next deploy.`);
36264
36814
  }
36265
36815
  }
36266
- if (!this.options.dryRun) await this.settleJournalAfterSuccess(stackName, [], currentState, currentState.resources, currentEtag === void 0);
36267
36816
  return {
36268
36817
  stackName,
36269
36818
  created: 0,
36270
36819
  updated: 0,
36271
36820
  deleted: 0,
36272
- deleteSkipped: 0,
36821
+ deleteSkipped: this.options.dryRun ? 0 : await this.settleJournalAfterSuccess(stackName, [], currentState, currentState.resources, currentEtag === void 0),
36273
36822
  updatePartial: 0,
36274
36823
  unchanged: Object.keys(currentState.resources).length,
36275
36824
  durationMs: Date.now() - startTime,
@@ -36295,6 +36844,14 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
36295
36844
  attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
36296
36845
  };
36297
36846
  }
36847
+ await requireDeploymentApproval({
36848
+ options: this.options,
36849
+ stackName,
36850
+ changes: changes.values(),
36851
+ records: currentState.resources,
36852
+ template: effectiveTemplate,
36853
+ recreateTargetIds: recreateTargetIdsFor(this.options.recreateTargets, stackName)
36854
+ });
36298
36855
  this.resolver.resetPhysicalIdFallbackCount();
36299
36856
  const progress = {
36300
36857
  current: 0,
@@ -36308,7 +36865,7 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
36308
36865
  } : newState));
36309
36866
  this.logger.debug(`State saved (ETag: ${newEtag})`);
36310
36867
  await forgetRecordedCreateTokens(Object.keys(newState.resources));
36311
- await Promise.all([this.settleJournalAfterSuccess(stackName, completedOperations, currentState, newState.resources, currentEtag === void 0), this.exportIndexStore ? this.exportIndexStore.updateForStack(stackName, this.stackRegion, importableOutputs({
36868
+ const [journaledOrphansLeft] = await Promise.all([this.settleJournalAfterSuccess(stackName, completedOperations, currentState, newState.resources, currentEtag === void 0), this.exportIndexStore ? this.exportIndexStore.updateForStack(stackName, this.stackRegion, importableOutputs({
36312
36869
  ...newState,
36313
36870
  outputs: this.redactOutputs(newState.outputs)
36314
36871
  })) : Promise.resolve()]);
@@ -36319,7 +36876,7 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
36319
36876
  created: actualCounts.created,
36320
36877
  updated: actualCounts.updated,
36321
36878
  deleted: actualCounts.deleted,
36322
- deleteSkipped: actualCounts.deleteSkipped,
36879
+ deleteSkipped: actualCounts.deleteSkipped + journaledOrphansLeft,
36323
36880
  updatePartial: actualCounts.updatePartial,
36324
36881
  nestedUpdatePartial: actualCounts.nestedUpdatePartial,
36325
36882
  unchanged: unchangedCount,
@@ -36644,6 +37201,7 @@ var DeployEngine = class {
36644
37201
  outputsTemplateSource = Object.create(null);
36645
37202
  resolvedExportNames = [];
36646
37203
  skippedOutputs;
37204
+ constructPathTemplate;
36647
37205
  outputsSourceUsable = true;
36648
37206
  attemptedResolvedProps = /* @__PURE__ */ new Map();
36649
37207
  liveTaskLabels = /* @__PURE__ */ new Map();
@@ -36685,6 +37243,7 @@ var DeployEngine = class {
36685
37243
  this.perResourceSecrets = /* @__PURE__ */ new Map();
36686
37244
  this.noEchoAttributeResources = /* @__PURE__ */ new Map();
36687
37245
  this.perResourceTemplateProps = /* @__PURE__ */ new Map();
37246
+ this.constructPathTemplate = void 0;
36688
37247
  this.perResourceResolvedType = /* @__PURE__ */ new Map();
36689
37248
  this.fingerprintNoEchoValues = void 0;
36690
37249
  this.fingerprintParameters = void 0;
@@ -36717,7 +37276,7 @@ var DeployEngine = class {
36717
37276
  const secrets = this.perResourceSecrets.get(logicalId);
36718
37277
  const templateProps = this.perResourceTemplateProps.get(logicalId);
36719
37278
  const scrubbed = scrubResourceRecord(this.withHealedAttributes(logicalId, record), secrets ?? /* @__PURE__ */ new Map(), templateProps);
36720
- resources[logicalId] = withMaskedPropertyFingerprints(scrubbed, record.properties, templateProps, secrets, this.fingerprintNoEchoValues, this.perResourceInputFingerprints.get(logicalId));
37279
+ resources[logicalId] = withConstructPath(withMaskedPropertyFingerprints(scrubbed, record.properties, templateProps, secrets, this.fingerprintNoEchoValues, this.perResourceInputFingerprints.get(logicalId)), constructPathOf(this.constructPathTemplate, logicalId));
36721
37280
  }
36722
37281
  const orphans = state.orphans?.map((entry) => {
36723
37282
  const sameResource = this.perResourceResolvedType.get(entry.logicalId) === entry.state.resourceType;
@@ -36898,5 +37457,5 @@ DeployEngine.prototype.replacementNameOrigin = replacementNameOrigin;
36898
37457
  DeployEngine.prototype.orphanedNameCollisionAdvice = orphanedNameCollisionAdvice;
36899
37458
 
36900
37459
  //#endregion
36901
- export { resourcesNamingDeclaredParameter as $, recordMaskOnlyValuesIn as $a, WARM_THROUGHPUT_MEMBERS as $i, assertSendableRoleArn as $n, getDockerCmd as $o, malformedOutputsRefusalMessage as $r, isWholeDynamicReferenceValue as $t, resolveDynamoDbDeleteBudgetClock as A, hasMaskableValues as Aa, refuseMalformedResourcesForExport as Ai, slowCcOperationTimeoutMs as An, buildAssetRedirectMap as Ao, JSON_LISTING_HOLE_VALUE as Ar, uploadCfnTemplate as As, buildFinalSnapshotIdentifier as At, getPriorAttempts as B, maskSecretsInText as Ba, unreadableResourceEntries as Bi, ec2InstanceProtectionSite as Bn, parseBootstrapMarker as Bo, isReadableOrphanRecord as Br, defineOwnKey as Bs, redactedDeleteAddressSkip as Bt, perType as C, DagBuilder as Ca, refuseMalformedResourceEntriesForOrphan as Ci, CC_BROKEN_REASON as Cn, orphansAfterRollback as Co, cfnRefValueFromPhysicalId as Cr, stateBucketExistenceConfirmed as Cs, planRollback as Ct, beginDeleteWait as D, recordNestedStackParameterExpressions as Da, refuseMalformedResourcePropertiesForOrphan as Di, isCustomResourceType as Dn, isSensitiveAttributeName as Do, withSharedDrainBudget as Dr, CFN_TEMPLATE_URL_LIMIT as Ds, inheritProducerRegions as Dt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as E, inheritNestedStackParameterAssociations as Ea, refuseMalformedResourcePropertiesForExport as Ei, wouldReturnToSdkProvider as En, AssetPublisher as Eo, parseWebACLArn as Er, CFN_TEMPLATE_BODY_LIMIT as Es, getCurrentProducerRegions as Et, waitForIndexesSettled as F, recordLogOnlyValue as Fa, repairMalformedResourceEntriesForReadOnly as Fi, deleteSkipReason as Fn, BOOTSTRAP_MARKER_PREFIX as Fo, deployRefusesOrphanRowsReason as Fr, canonicalizeRegion as Fs, refusesFinalSnapshot as Ft, cyan as G, DYNAMIC_REFERENCE_TOKEN_SCAN as Ga, NO_CC_HANDLERS_REASON as Gi, DiffCalculator as Gn, buildDockerImage as Go, malformedLocalOutputsWarning as Gr, absoluteAssemblyPathEscape as Gs, extractDeploymentEventError as Gt, formatResourceLine as H, redactSecretsForState as Ha, findSilentDropProperties as Hi, observeThenDisableInstanceApiTermination as Hn, validateAssetBucketName as Ho, malformedDriftResourcePropertiesWarning as Hr, hasPlainPrototype$1 as Hs, updatePartialReason as Ht, ECR_AUTO_DELETE_IMAGES_TAG as I, shareLogOnlyValues as Ia, repairMalformedResourcePropertiesForReadOnly as Ii, withIndeterminateGuard as In, assertAssetBucketRegion as Io, displayLogicalId as Ir, derivePartitionAndUrlSuffix as Is, unsupportedFinalSnapshotError as It, red as J, pathCrossesDottedKey as Ja, shownType as Ji, classifyReplaySecretRegion as Jn, describeDockerExecFailure as Jo, malformedOrphanRecordsRefusalMessage as Jr, renderAssemblyPathEscape as Js, exportAliasCollisionScrubWarning as Jt, gray as K, dynamicReferenceTokens as Ka, hasNoCloudControlHandlers as Ki, INTRINSIC_KEYS as Kn, resolveDockerContextDirectory as Ko, malformedLocalResourceEntriesWarning as Kr, describeFileReadFailure as Ks, WITHHELD_NAME_DISPLAY as Kt, S3_AUTO_DELETE_OBJECTS_TAG as L, createSecretMasker as La, repairMalformedResourcesForReadOnly as Li, isWaitAbandonedError as Ln, ensureAssetStorage as Lo, hasReadableOrphans as Lr, AssemblyReader as Ls, REDACTED_DELETE_ADDRESS_SKIP_REASON as Lt, DELETE_INDEX_WAIT_PROCEED_NOTE as M, logOnlyValueCount as Ma, repairMalformedOrphanRecordsForReadOnly as Mi, unchangedBehindSecretReference as Mn, loadPublishableAssetManifest as Mo, STATE_RESOURCES_MALFORMED as Mr, decodeListingKey as Ms, createPreDeleteFinalSnapshot as Mt, INDEX_SETTLE_POLL_INTERVAL_MS as N, printingCorpusOf as Na, repairMalformedOrphansForReadOnly as Ni, UNSPECIFIED_SKIP_REASON as Nn, rewriteTemplateAssetReferences as No, UNREADABLE_ORPHANS_CONTAINER_ROW as Nr, expectedOwnerParam as Ns, effectiveDeletionPolicy as Nt, compensateRemovedDeletionProtection as O, carryLogOnlyValues as Oa, refuseMalformedResourcesForDeploy as Oi, getCurrentResourceSecrets as On, stringifyValue as Oo, parameterInputsFor as Or, MIGRATE_TMP_PREFIX as Os, ATOMIC_FINAL_SNAPSHOT_TYPES as Ot, deleteTableWithIndexBusyRetry as P, recordLogOnlyParameterValue as Pa, repairMalformedOutputsForReadOnly as Pi, deleteIndeterminateGuards as Pn, AssetModeResolver as Po, UNREADABLE_RESOURCES_MAP_ROW as Pr, PARTITION_TABLE as Ps, isFinalSnapshotError as Pt, reachableDivergentParameters as Q, recordMaskOnlyValue as Qa, renderStatefulReason as Qi, assertFlagRoleArn as Qn, formatDockerLoginError as Qo, malformedOrphansWarning as Qr, exportNameSecretExposure as Qt, hasCdkAutoDeleteTag as R, errorCauseChain as Ra, unpreviewableOrphanRecords as Ri, markWaitAbandoned as Rn, getBootstrapMarkerKey as Ro, hasReadableOutputs as Rr, StageLoadError as Rs, isRedactedRecordedValue as Rt, isProtectionValueActive as S, sameLambdaFunctionAddress as Sa, refuseMalformedResourceEntriesForImportSave as Si, stringifyIfAssigned as Sn, isReadableBag as So, AWS_NO_VALUE as Sr, resolveUseCdkBootstrapAssets as Ss, planFailedOps as St, DynamoDBGlobalTableProvider as T, liveMatchesUnresolvedTokenFrame as Ta, refuseMalformedResourcePropertiesForDrift as Ti, ccBrokenReason as Tn, shouldRetainResource as To, refStateLookupFromResource as Tr, ssmResolvedValueType as Ts, findNestedStackTypeChanges as Tt, createReadOnlyAttributeHealerFactory as U, scrubResourceRecord as Ua, unwrittenCreateOnlyReplacement as Ui, reDisableInstanceApiTermination as Un, validateContainerRepoName as Uo, malformedExportNamesWarning as Ur, nullPrototypeRecord as Us, DeploymentEventsReader as Ut, markRefusedBeforeApplying as V, markSameGenerationBag as Va, findActionableSilentDrops as Vi, isTerminationProtectionPropagationError as Vn, readBootstrapMarkerBody as Vo, isReadableResourceEntry as Vr, hasOwnKey as Vs, updatePartialMessage as Vt, bold as W, recoverMaskedOutput as Wa, withoutSilentDropProperties as Wi, reEnableInstanceApiTermination as Wn, buildDenyExternalAccessPolicy as Wo, malformedExportSourceWarning as Wr, ownValue as Ws, DeploymentEventsStore as Wt, computeParameterTaint as X, carriesSecretMask as Xa, isStatefulRecreateTargetForReplace as Xi, regionLessSecretName as Xn, dockerSpawnEnvWithSensitive as Xo, malformedOrphanRowsKeptWarning as Xr, clearBucketRegionCache as Xs, secretBearingStateKeyWarning as Xt, yellow as Y, identityKeyFor as Ya, MULTI_REGION_RECREATE_BLOCKED_TYPES as Yi, producerRegionsFromState as Yn, describeDockerFailure as Yo, malformedOrphanRecordsWarning as Yr, resolveAssemblyPath as Ys, secretBearing as Yt, namesAnyDeclaredParameter as Z, provenPublicValue as Za, isStatefulRecreateTargetSync as Zi, applyRoleArnIfSet as Zn, finchSecretArgvRefusal as Zo, malformedOrphansRefusalMessage as Zr, resolveBucketRegion as Zs, secretSafeKeyDisplay as Zt, makeCanonicalizePropertiesFn as _, withRetry as _a, refuseMalformedResourceAttributesForOrphan as _i, readTagList as _n, hasReadableExportSet as _o, isImpossibleEmptyStoredAttribute as _r, resolveAutoAssetStorage as _s, destroyStackRecordsView as _t, findNestedTemplateTreeDefect as a, coerceCfnInteger as aa, malformedScrubResourceEntriesRefusalMessage as ai, DEFAULT_RESOURCE_TIMEOUT_MS as an, STATE_SOURCED_READBACK_RULES as ao, callerEnvCredentials as ar, runDockerForeground as as, dropSettledNestedJournals as at, recordedProtectionNote as b, canonicalLambdaFunctionName as ba, refuseMalformedResourceEntriesForDestroy as bi, tagPlanWarning as bn, importableOutputKeys as bo, isNamelessDynamicReferenceError as br, resolveStateBucketWithDefault as bs, recordAfterRollbackUpdate as bt, renderNestedTemplateTreeDefect as c, configStringRefusal as ca, refuseDivergentRecordRegionForDestroy as ci, RollbackInlinePolicyWriters as cn, isSingleDynamicReferenceToken as co, s3BucketArn as cr, escapeRegExp$3 as cs, recordDisplacedSkips as ct, conditionInputsFrom as d, requireConfigArray as da, refuseMalformedOrphanRecordsForDestroy as di, reserveStackCreateToken as dn, S3StateBackend as do, s3BucketRegionalDomainName as dr, getDockerImageBySourceHash as ds, withNestedRevertRun as dt, coerceWarmThroughput as ea, malformedOutputsWarning as ei, noEchoParameterValueSeed as en, recordNoEchoAttributeValues as eo, explicitRoleArnOrThrow as er, isDockerClientEnvKey as es, makeSiblingClaimReader as et, parentSuppliedValues as f, requireConfigObject as fa, refuseMalformedOrphans as fi, withCreateTokenLedger as fn, rebuildClientForBucketRegion as fo, s3BucketWebsiteUrl as fr, Synthesizer as fs, getCurrentNestedStackContext as ft, mergeNoChangeOutputs as g, describeTypeWithThrottleRetry as ga, refuseMalformedOutputsForDestroy as gi, planTagDiff as gn, exportNamesCarriedFrom as go, getAccountInfo as gr, resolveApp as gs, awaitInFlightSibling as gt, keptWholeReasonText as h, templateResourceTypes as ha, refuseMalformedOutputs as hi, DBPROXY_TAG_OPTIONS as hn, describeRegionValueKind as ho, parameterTypeMayLoseSecretIdentity as hr, getLegacyStateBucketName as hs, replayRollback as ht, childTemplateLoader as i, coerceCfnBoolean as ia, malformedResourcesWarning as ii, bindingSkippedOutputs as in, STATE_SOURCED_CROSS_GENERATION_RULES as io, applyCallerIdentityCredentials as ir, redactedDockerCause as is, displacedPhysicalIdShown as it, resolveDynamoDbDeleteBudgetMs as j, literalSplitDelimitersOf as ja, refuseMalformedState as ji, ccProtectionRegistryTypes as jn, createAssetRedirectResolver as jo, STATE_REGION_DIVERGED as jr, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as js, ccRoutedFinalSnapshotError as jt, deleteBudgetKey as k, createUnionSecretMasker as ka, refuseMalformedResourcesForDestroy as ki, CloudControlProvider as kn, WorkGraph as ko, passedParameterClassesOf as kr, findLargeInlineResources as ks, PRE_DELETE_SNAPSHOT_TYPES as kt, templateIdentity as l, readConfigString as la, refuseMalformedNestedChildOutputs as li, earliestDefined as ln, LockManager as lo, s3BucketDomainName as lr, stripControlChars as ls, revertNestedChildFromJournal as lt, isSecretBearingReferenceString as m, prefetchCreateOnlyPropertyPaths as ma, refuseMalformedOrphansForOrphan as mi, DBPROXY_TAGS_WHAT as mn, acceptedCreateOnlyDropsOf as mo, isUnboundTemplateParameter as mr, getDefaultStateBucketName as ms, replayFailedOperations as mt, IMPLICIT_DELETE_DEPENDENCIES as n, toCfnInteger as na, malformedResourceEntriesWarning as ni, collectPublishedOutputNames as nn, wholeStringLeavesOf as no, sendableAssumeRoleCommand as nr, partitionSensitiveEnv as ns, NESTED_PENDING_PARENT_REASON as nt, isAbsoluteAssetPath as o, configBooleanRefusal as oa, malformedStateRefusalMessage as oi, DEFAULT_RESOURCE_WARN_AFTER_MS as on, TEMPLATE_SOURCED_RULES as oo, envCredentialsAreAssumedRole as or, runDockerStreaming as os, getNestedRevertRun as ot, readRecordedConditionVerdicts as p, requireConfigString as pa, refuseMalformedOrphansForDestroy as pi, acquireIdempotencyToken as pn, splitImportedOps as po, coerceParameterTypedValue as pr, synthesisStatusMessage as ps, withNestedStackContext as pt, green as q, isUncertifiedBaselineMaskPosition as qa, findReplacedReadersOfRecreateTargets as qi, IntrinsicFunctionResolver as qn, describeDockerCapturedOutput as qo, malformedLocalResourcesWarning as qr, displayAssemblyPath as qs, displayTextOrWithheld as qt, computeImplicitDeleteEdges as r, toFiniteNumber as ra, malformedResourcePropertiesWarning as ri, isExportAliasCollision as rn, STATE_SOURCED_BASELINE_RULES as ro, AWS_CREDENTIAL_ENV_KEYS as rr, redactDockerArgvValues as rs, displacedOpClause as rt, listNestedTemplateRows as s, configIntegerRefusal as sa, previewableOrphanRecords as si, maskingRetryLogger as sn, WHOLE_DYNAMIC_REFERENCE_PATTERN as so, isSettledInstanceState as sr, warnFinchArgvExposure as ss, nestedChildStackName as st, DeployEngine as t, isWarmThroughputDecrease as ta, malformedRenderedContainersWarning as ti, collectDeclaredOutputNames as tn, recordProvenPublicExpression as to, isIamRoleArn as tr, isMalformedEnvKey as ts, planOrphanAdoption as tt, conditionFingerprint as u, replayWarn as ua, refuseMalformedOrphanRecords as ui, ledgerForStack as un, isLockInfoExpired as uo, s3BucketDualStackDomainName as ur, AssetManifestLoader as us, revertedNestedRowIds as ut, withResourceDeadline as v, markAuxiliaryFailure as va, refuseMalformedResourceEntries as vi, refuseMalformedDesiredTags as vn, hasReasonlessBaselineRefusal as vo, carriesDynamicReference as vr, resolveCaptureObservedState as vs, getStackRecords as vt, readProtection as w, TemplateParser as wa, refuseMalformedResourcePropertiesForDestroy as wi, ProviderRegistry as wn, orphansCarriedFrom as wo, isStalePlaceholderArnAttribute as wr, warnDeprecatedNoPrefixCliFlag as ws, resolveReplacementOldType as wt, PROTECTION_PROPERTY_BY_TYPE as x, lambdaFunctionNameForMask as xa, refuseMalformedResourceEntriesForImport as xi, definedAttributes as xn, importableOutputs as xo, keepsSecretReferenceToken as xr, resolveStateBucketWithDefaultAndSource as xs, demoteSupersededOrphans as xt, recordedProtectionEvidence as y, markCreatedBeforeFailure as ya, refuseMalformedResourceEntriesForDeploy as yi, tagMapAsList as yn, hasUnverifiableParameterRefusal as yo, carriesFetchableDynamicReference as yr, resolveSkipPrefix as ys, withStackRecords as yt, isTruthyCfnBoolean as z, maskSecretsInError as za, unreadableOrphanRecords as zi, disableInstanceApiTermination as zn, isCrossRegionRedirect as zo, hasReadableResources as zr, processStackMessages as zs, redactedDeleteAddressFields as zt };
36902
- //# sourceMappingURL=deploy-engine-DG-oC9YK.js.map
37460
+ export { resourcesNamingDeclaredParameter as $, dynamicReferenceTokens as $a, withoutSilentDropProperties as $i, reEnableInstanceApiTermination as $n, resolveDockerContextDirectory as $o, malformedExportSourceWarning as $r, absoluteAssemblyPathEscape as $s, displayTextOrWithheld as $t, resolveDynamoDbDeleteBudgetClock as A, DagBuilder as Aa, refuseMalformedResourceEntriesForImport as Ai, definedAttributes as An, orphansAfterRollback as Ao, keepsSecretReferenceToken as Ar, resolveUseCdkBootstrapAssets as As, resolveReplacementOldType as At, getPriorAttempts as B, printingCorpusOf as Ba, refuseMalformedState as Bi, ccProtectionRegistryTypes as Bn, rewriteTemplateAssetReferences as Bo, STATE_REGION_DIVERGED as Br, decodeListingKey as Bs, isFinalSnapshotError as Bt, perType as C, prefetchCreateOnlyPropertyPaths as Ca, refuseMalformedOrphansForOrphan as Ci, DBPROXY_TAGS_WHAT as Cn, exportNamesCarriedFrom as Co, isUnboundTemplateParameter as Cr, loadCdkJson as Cs, getStackRecords as Ct, beginDeleteWait as D, canonicalLambdaFunctionName as Da, refuseMalformedResourceEntries as Di, refuseMalformedDesiredTags as Dn, importableOutputKeys as Do, carriesDynamicReference as Dr, resolveSkipPrefix as Ds, isJournaledOrphan as Dt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as E, withRetry as Ea, refuseMalformedResourceAttributesForOrphan as Ei, readTagList as En, hasUnverifiableParameterRefusal as Eo, isImpossibleEmptyStoredAttribute as Er, resolveCaptureObservedState as Es, demoteSupersededOrphans as Et, waitForIndexesSettled as F, carryLogOnlyValues as Fa, refuseMalformedResourcePropertiesForExport as Fi, wouldReturnToSdkProvider as Fn, stringifyValue as Fo, parseWebACLArn as Fr, CFN_TEMPLATE_URL_LIMIT as Fs, PRE_DELETE_SNAPSHOT_TYPES as Ft, cyan as G, errorCauseChain as Ga, repairMalformedResourcePropertiesForReadOnly as Gi, withIndeterminateGuard as Gn, getBootstrapMarkerKey as Go, displayLogicalId as Gr, AssemblyReader as Gs, redactedDeleteAddressFields as Gt, formatResourceLine as H, recordLogOnlyValue as Ha, repairMalformedOrphansForReadOnly as Hi, UNSPECIFIED_SKIP_REASON as Hn, BOOTSTRAP_MARKER_PREFIX as Ho, UNREADABLE_ORPHANS_CONTAINER_ROW as Hr, PARTITION_TABLE as Hs, unsupportedFinalSnapshotError as Ht, ECR_AUTO_DELETE_IMAGES_TAG as I, createUnionSecretMasker as Ia, refuseMalformedResourcePropertiesForOrphan as Ii, isCustomResourceType as In, WorkGraph as Io, withSharedDrainBudget as Ir, MIGRATE_TMP_PREFIX as Is, buildFinalSnapshotIdentifier as It, red as J, markSameGenerationBag as Ja, unreadableOrphanRecords as Ji, disableInstanceApiTermination as Jn, readBootstrapMarkerBody as Jo, hasReadableResources as Jr, defineOwnKey as Js, updatePartialReason as Jt, gray as K, maskSecretsInError as Ka, repairMalformedResourcesForReadOnly as Ki, isWaitAbandonedError as Kn, isCrossRegionRedirect as Ko, hasReadableOrphans as Kr, StageLoadError as Ks, redactedDeleteAddressSkip as Kt, S3_AUTO_DELETE_OBJECTS_TAG as L, hasMaskableValues as La, refuseMalformedResourcesForDeploy as Li, getCurrentResourceSecrets as Ln, buildAssetRedirectMap as Lo, parameterInputsFor as Lr, findLargeInlineResources as Ls, ccRoutedFinalSnapshotError as Lt, DELETE_INDEX_WAIT_PROCEED_NOTE as M, liveMatchesUnresolvedTokenFrame as Ma, refuseMalformedResourceEntriesForOrphan as Mi, CC_BROKEN_REASON as Mn, shouldRetainResource as Mo, cfnRefValueFromPhysicalId as Mr, warnDeprecatedNoPrefixCliFlag as Ms, getCurrentProducerRegions as Mt, INDEX_SETTLE_POLL_INTERVAL_MS as N, inheritNestedStackParameterAssociations as Na, refuseMalformedResourcePropertiesForDestroy as Ni, ProviderRegistry as Nn, AssetPublisher as No, isStalePlaceholderArnAttribute as Nr, ssmResolvedValueType as Ns, inheritProducerRegions as Nt, compensateRemovedDeletionProtection as O, lambdaFunctionNameForMask as Oa, refuseMalformedResourceEntriesForDeploy as Oi, tagMapAsList as On, importableOutputs as Oo, carriesFetchableDynamicReference as Or, resolveStateBucketWithDefault as Os, planFailedOps as Ot, deleteTableWithIndexBusyRetry as P, recordNestedStackParameterExpressions as Pa, refuseMalformedResourcePropertiesForDrift as Pi, ccBrokenReason as Pn, isSensitiveAttributeName as Po, refStateLookupFromResource as Pr, CFN_TEMPLATE_BODY_LIMIT as Ps, ATOMIC_FINAL_SNAPSHOT_TYPES as Pt, reachableDivergentParameters as Q, DYNAMIC_REFERENCE_TOKEN_SCAN as Qa, unwrittenCreateOnlyReplacement as Qi, reDisableInstanceApiTermination as Qn, buildDockerImage as Qo, malformedExportNamesWarning as Qr, ownValue as Qs, WITHHELD_NAME_DISPLAY as Qt, hasCdkAutoDeleteTag as R, literalSplitDelimitersOf as Ra, refuseMalformedResourcesForDestroy as Ri, CloudControlProvider as Rn, createAssetRedirectResolver as Ro, passedParameterClassesOf as Rr, uploadCfnTemplate as Rs, createPreDeleteFinalSnapshot as Rt, isProtectionValueActive as S, requireConfigString as Sa, refuseMalformedOrphansForDestroy as Si, acquireIdempotencyToken as Sn, describeRegionValueKind as So, coerceParameterTypedValue as Sr, getLegacyStateBucketName as Ss, destroyStackRecordsView as St, DynamoDBGlobalTableProvider as T, describeTypeWithThrottleRetry as Ta, refuseMalformedOutputsForDestroy as Ti, planTagDiff as Tn, hasReasonlessBaselineRefusal as To, getAccountInfo as Tr, resolveAutoAssetStorage as Ts, recordAfterRollbackUpdate as Tt, createReadOnlyAttributeHealerFactory as U, shareLogOnlyValues as Ua, repairMalformedOutputsForReadOnly as Ui, deleteIndeterminateGuards as Un, assertAssetBucketRegion as Uo, UNREADABLE_RESOURCES_MAP_ROW as Ur, canonicalizeRegion as Us, REDACTED_DELETE_ADDRESS_SKIP_REASON as Ut, markRefusedBeforeApplying as V, recordLogOnlyParameterValue as Va, repairMalformedOrphanRecordsForReadOnly as Vi, unchangedBehindSecretReference as Vn, AssetModeResolver as Vo, STATE_RESOURCES_MALFORMED as Vr, expectedOwnerParam as Vs, refusesFinalSnapshot as Vt, bold as W, createSecretMasker as Wa, repairMalformedResourceEntriesForReadOnly as Wi, deleteSkipReason as Wn, ensureAssetStorage as Wo, deployRefusesOrphanRowsReason as Wr, derivePartitionAndUrlSuffix as Ws, isRedactedRecordedValue as Wt, computeParameterTaint as X, scrubResourceRecord as Xa, findActionableSilentDrops as Xi, isTerminationProtectionPropagationError as Xn, validateContainerRepoName as Xo, isReadableResourceEntry as Xr, hasPlainPrototype$1 as Xs, DeploymentEventsStore as Xt, yellow as Y, redactSecretsForState as Ya, unreadableResourceEntries as Yi, ec2InstanceProtectionSite as Yn, validateAssetBucketName as Yo, isReadableOrphanRecord as Yr, hasOwnKey as Ys, DeploymentEventsReader as Yt, namesAnyDeclaredParameter as Z, recoverMaskedOutput as Za, findSilentDropProperties as Zi, observeThenDisableInstanceApiTermination as Zn, buildDenyExternalAccessPolicy as Zo, malformedDriftResourcePropertiesWarning as Zr, nullPrototypeRecord as Zs, extractDeploymentEventError as Zt, makeCanonicalizePropertiesFn as _, configStringRefusal as _a, refuseDivergentRecordRegionForDestroy as _i, RollbackInlinePolicyWriters as _n, isLockInfoExpired as _o, s3BucketArn as _r, AssetManifestLoader as _s, getCurrentNestedStackContext as _t, findNestedTemplateTreeDefect as a, isStatefulRecreateTargetForReplace as aa, resolveBucketRegion as ac, malformedOrphanRowsKeptWarning as ai, isWholeDynamicReferenceValue as an, recordMaskOnlyValue as ao, regionLessSecretName as ar, formatDockerLoginError as as, makeSiblingClaimReader as at, recordedProtectionNote as b, requireConfigArray as ba, refuseMalformedOrphanRecordsForDestroy as bi, reserveStackCreateToken as bn, splitImportedOps as bo, s3BucketRegionalDomainName as br, synthesisStatusMessage as bs, replayRollback as bt, renderNestedTemplateTreeDefect as c, WARM_THROUGHPUT_MEMBERS as ca, malformedOutputsRefusalMessage as ci, collectPublishedOutputNames as cn, recordProvenPublicExpression as co, assertSendableRoleArn as cr, isMalformedEnvKey as cs, displacedOpClause as ct, conditionInputsFrom as d, toCfnInteger as da, malformedResourceEntriesWarning as di, DEFAULT_RESOURCE_TIMEOUT_MS as dn, STATE_SOURCED_CROSS_GENERATION_RULES as do, sendableAssumeRoleCommand as dr, redactedDockerCause as ds, getNestedRevertRun as dt, NO_CC_HANDLERS_REASON as ea, describeFileReadFailure as ec, malformedLocalOutputsWarning as ei, exportAliasCollisionScrubWarning as en, isUncertifiedBaselineMaskPosition as eo, DiffCalculator as er, describeDockerCapturedOutput as es, deleteJournaledOrphans as et, parentSuppliedValues as f, toFiniteNumber as fa, malformedResourcePropertiesWarning as fi, DEFAULT_RESOURCE_WARN_AFTER_MS as fn, STATE_SOURCED_READBACK_RULES as fo, AWS_CREDENTIAL_ENV_KEYS as fr, runDockerForeground as fs, nestedChildStackName as ft, mergeNoChangeOutputs as g, configIntegerRefusal as ga, previewableOrphanRecords as gi, formatDestructiveChange as gn, LockManager as go, isSettledInstanceState as gr, stripControlChars as gs, withNestedRevertRun as gt, keptWholeReasonText as h, configBooleanRefusal as ha, malformedStateRefusalMessage as hi, findDestructiveChanges as hn, isSingleDynamicReferenceToken as ho, envCredentialsAreAssumedRole as hr, escapeRegExp$3 as hs, revertedNestedRowIds as ht, childTemplateLoader as i, MULTI_REGION_RECREATE_BLOCKED_TYPES as ia, clearBucketRegionCache as ic, malformedOrphanRecordsWarning as ii, exportNameSecretExposure as in, provenPublicValue as io, producerRegionsFromState as ir, finchSecretArgvRefusal as is, sameJournaledOrphans as it, resolveDynamoDbDeleteBudgetMs as j, TemplateParser as ja, refuseMalformedResourceEntriesForImportSave as ji, stringifyIfAssigned as jn, orphansCarriedFrom as jo, AWS_NO_VALUE as jr, stateBucketExistenceConfirmed as js, findNestedStackTypeChanges as jt, deleteBudgetKey as k, sameLambdaFunctionAddress as ka, refuseMalformedResourceEntriesForDestroy as ki, tagPlanWarning as kn, isReadableBag as ko, isNamelessDynamicReferenceError as kr, resolveStateBucketWithDefaultAndSource as ks, planRollback as kt, templateIdentity as l, coerceWarmThroughput as la, malformedOutputsWarning as li, isExportAliasCollision as ln, wholeStringLeavesOf as lo, explicitRoleArnOrThrow as lr, partitionSensitiveEnv as ls, displacedPhysicalIdShown as lt, isSecretBearingReferenceString as m, coerceCfnInteger as ma, malformedScrubResourceEntriesRefusalMessage as mi, constructPathOf as mn, WHOLE_DYNAMIC_REFERENCE_PATTERN as mo, callerEnvCredentials as mr, warnFinchArgvExposure as ms, revertNestedChildFromJournal as mt, IMPLICIT_DELETE_DEPENDENCIES as n, findReplacedReadersOfRecreateTargets as na, renderAssemblyPathEscape as nc, malformedLocalResourcesWarning as ni, secretBearingStateKeyWarning as nn, identityKeyFor as no, IntrinsicFunctionResolver as nr, describeDockerFailure as ns, journaledOrphanLines as nt, isAbsoluteAssetPath as o, isStatefulRecreateTargetSync as oa, malformedOrphansRefusalMessage as oi, noEchoParameterValueSeed as on, recordMaskOnlyValuesIn as oo, applyRoleArnIfSet as or, getDockerCmd as os, planOrphanAdoption as ot, readRecordedConditionVerdicts as p, coerceCfnBoolean as pa, malformedResourcesWarning as pi, maskingRetryLogger as pn, TEMPLATE_SOURCED_RULES as po, applyCallerIdentityCredentials as pr, runDockerStreaming as ps, recordDisplacedSkips as pt, green as q, maskSecretsInText as qa, unpreviewableOrphanRecords as qi, markWaitAbandoned as qn, parseBootstrapMarker as qo, hasReadableOutputs as qr, processStackMessages as qs, updatePartialMessage as qt, computeImplicitDeleteEdges as r, shownType as ra, resolveAssemblyPath as rc, malformedOrphanRecordsRefusalMessage as ri, secretSafeKeyDisplay as rn, carriesSecretMask as ro, classifyReplaySecretRegion as rr, dockerSpawnEnvWithSensitive as rs, loadJournaledOrphans as rt, listNestedTemplateRows as s, renderStatefulReason as sa, malformedOrphansWarning as si, collectDeclaredOutputNames as sn, recordNoEchoAttributeValues as so, assertFlagRoleArn as sr, isDockerClientEnvKey as ss, NESTED_PENDING_PARENT_REASON as st, DeployEngine as t, hasNoCloudControlHandlers as ta, displayAssemblyPath as tc, malformedLocalResourceEntriesWarning as ti, secretBearing as tn, pathCrossesDottedKey as to, INTRINSIC_KEYS as tr, describeDockerExecFailure as ts, isHandledOrphan as tt, conditionFingerprint as u, isWarmThroughputDecrease as ua, malformedRenderedContainersWarning as ui, bindingSkippedOutputs as un, STATE_SOURCED_BASELINE_RULES as uo, isIamRoleArn as ur, redactDockerArgvValues as us, dropSettledNestedJournals as ut, withResourceDeadline as v, readConfigString as va, refuseMalformedNestedChildOutputs as vi, earliestDefined as vn, S3StateBackend as vo, s3BucketDomainName as vr, getDockerImageBySourceHash as vs, withNestedStackContext as vt, readProtection as w, templateResourceTypes as wa, refuseMalformedOutputs as wi, DBPROXY_TAG_OPTIONS as wn, hasReadableExportSet as wo, parameterTypeMayLoseSecretIdentity as wr, resolveApp as ws, withStackRecords as wt, PROTECTION_PROPERTY_BY_TYPE as x, requireConfigObject as xa, refuseMalformedOrphans as xi, withCreateTokenLedger as xn, acceptedCreateOnlyDropsOf as xo, s3BucketWebsiteUrl as xr, getDefaultStateBucketName as xs, awaitInFlightSibling as xt, recordedProtectionEvidence as y, replayWarn as ya, refuseMalformedOrphanRecords as yi, ledgerForStack as yn, rebuildClientForBucketRegion as yo, s3BucketDualStackDomainName as yr, Synthesizer as ys, replayFailedOperations as yt, isTruthyCfnBoolean as z, logOnlyValueCount as za, refuseMalformedResourcesForExport as zi, slowCcOperationTimeoutMs as zn, loadPublishableAssetManifest as zo, JSON_LISTING_HOLE_VALUE as zr, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as zs, effectiveDeletionPolicy as zt };
37461
+ //# sourceMappingURL=deploy-engine-D7204v7Z.js.map