@go-to-k/cdkd 0.296.28 → 0.296.29

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 (26) hide show
  1. package/dist/{asg-provider-B3zcS87C.js → asg-provider-UKRukGI_.js} +3 -3
  2. package/dist/{asg-provider-B3zcS87C.js.map → asg-provider-UKRukGI_.js.map} +1 -1
  3. package/dist/cli.js +2 -2
  4. package/dist/{deploy-engine-D4FdwPCi.js → deploy-engine-Bt-8KvUj.js} +1913 -57
  5. package/dist/deploy-engine-Bt-8KvUj.js.map +1 -0
  6. package/dist/{iam-policy-targets-B61e5_Sk.js → iam-policy-targets-Cz2tPxXk.js} +2 -2
  7. package/dist/{iam-policy-targets-B61e5_Sk.js.map → iam-policy-targets-Cz2tPxXk.js.map} +1 -1
  8. package/dist/{iam-role-provider-0U4kMuzh.js → iam-role-provider-BBFYFBLx.js} +3 -3
  9. package/dist/{iam-role-provider-0U4kMuzh.js.map → iam-role-provider-BBFYFBLx.js.map} +1 -1
  10. package/dist/index.d.ts +121 -55
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -3
  13. package/dist/{neptune-provider-DF6Eh4Tl.js → neptune-provider-B9InVgs6.js} +3 -3
  14. package/dist/{neptune-provider-DF6Eh4Tl.js.map → neptune-provider-B9InVgs6.js.map} +1 -1
  15. package/dist/{program-v_QNBjtZ.js → program-CN7Dqb3j.js} +513 -30
  16. package/dist/program-CN7Dqb3j.js.map +1 -0
  17. package/dist/{provider-classes-wbKBBEol.js → provider-classes-eEgFT-Vt.js} +196 -22
  18. package/dist/provider-classes-eEgFT-Vt.js.map +1 -0
  19. package/dist/{rds-provider-BfQsw4hw.js → rds-provider-DgbVxaPP.js} +3 -3
  20. package/dist/{rds-provider-BfQsw4hw.js.map → rds-provider-DgbVxaPP.js.map} +1 -1
  21. package/dist/{version-B0JEGOLV.js → version-DyV_xwRX.js} +2 -2
  22. package/dist/{version-B0JEGOLV.js.map → version-DyV_xwRX.js.map} +1 -1
  23. package/package.json +1 -1
  24. package/dist/deploy-engine-D4FdwPCi.js.map +0 -1
  25. package/dist/program-v_QNBjtZ.js.map +0 -1
  26. package/dist/provider-classes-wbKBBEol.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import { r as getAwsClients, s as __exportAll } from "./aws-clients-CnmtbrxD.js";
2
2
  import { A as UNRENDERABLE, C as looksLikeCdkdGeneratedName, E as withoutGeneratedFallbackName, F as displayStackName, I as isPasteableIdent, M as displayAwsMessage, N as displayIdent, O as SECRET_REF_MAX_CODE_POINTS, P as displaySafe, R as plainIdentOr, S as getCurrentStackName, T as withStackName, V as truncateCodePoints, a as getLogger, b as generateResourceNameWithFallback, d as installLogLineMaskerSource, f as getLiveRenderer, g as applyDefaultNameForFallback, k as STACK_REF_MAX_CODE_POINTS, o as isStdoutReservedForPayload, r as safeStringify$1, t as describeAwsFailure, u as currentLogLineMasker, v as explicitNamePropertyFor, w as withSkipPrefix, x as getCurrentSkipPrefix, y as generateResourceName, z as safeMsg } from "./aws-failure-text-BaWeCWRz.js";
3
- import { $ as protectedReplacementAdvice, $n as isIamPropagationError, $t as AccountIdUnavailableError, A as isQuotableImportValue, An as commandHole, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bt as sanitizeRecoveryValue, Ct as RETRY_AUXILIARY_OWNER, Dn as SHELL_ACTIVE, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as plainOrDescribed, G as runDeleteAttempt, Gn as isNameCooldownError, H as observeThenDisableProtection, Hn as isUpdateUnsupportedError, Ht as DEFAULT_STATE_PREFIX, In as quotedOrDescribed, J as DELETION_PROTECTION_DOC_POINTER, Jt as withPasteableAwsProfile, Kn as isRecreateRetryableError, Kt as producerRecordKey, L as ProtectionFlipRegistry, Ln as shellBoundedDisplay, Lt as formatLockExpiry, M as quotedRemedyLogicalId, Mn as isInertUnquoted, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as pasteableCommand, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE_WHY, Ot as hasCreatedBeforeFailure, Pn as physicalIdShownBesideCommand, Pt as buildForceUnlockCommand, Q as pasteableAwsCommand, Qn as isAmbiguousOutcomeError, Qt as credentialFingerprint, R as compensateProtectionFlip, Rn as shellQuote, Rt as formatLockOperation, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, U as protectionFlipKey, Un as hasReplayMayCollide, Ut as injectiveKey, Vt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Wn as isNameCollisionErrorFrom, Xn as formatRetryClassificationSignals, Xt as ambientCredentialConfig, Yn as markReplayMayCollide, Yt as ambientClientDefaults, Zn as isAmbiguousCcHandlerErrorCode, Zt as clientDefaultsFor, _n as ResourceUpdateNotSupportedError, _t as createMaskedLogSinks, ar as isThrottlingError, at as startInterruptWatch, bn as StateError, bt as maskDeep, cr as wrapMaskedAwsError, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as MacroExpansionError, en as AssetError, er as isRetryableTransientError, f as removalWarning, fn as MalformedProducerRecordRefusalError, ft as logicalIdShown, gn as ResourceTimeoutError, gt as stateOrphanRecordRemedy, hn as ProvisioningError, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as DependencyError, ir as isMarkedNonRetryable, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jt as markAuxiliaryFailure, kn as UNSHOWABLE_VALUE, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, m as withoutInjectedRemovals, mt as resourceTypeShown, nr as retryClassificationText, on as DynamicReferenceRegionAmbiguousError, or as markNonRetryable, ot as ElapsedBudgetRegistry, qn as isReplayedNameCollisionFrom, rn as CrossAccountSecretRefusalError, sn as IntrinsicResolutionRefusalError, sr as markRedactedCause, st as monotonicNowMs, tn as CdkdError, tr as isTransientServerError, un as LockError, ut as compositeIdSeparatorRefusal, vt as createMaskedRetryLogger, w as withoutServerErrorRetries, wn as normalizeAwsError, wt as carryCreatedBeforeFailure, xn as SynthesisError, xt as maskerOrIdentity, yt as isSecretDerivedValue, z as deleteWithProtectionCompensation, zn as withheldTargetClause, zt as formatLockOwner } from "./iam-policy-targets-B61e5_Sk.js";
3
+ import { $ as protectedReplacementAdvice, $n as isAmbiguousOutcomeError, $t as credentialFingerprint, A as isQuotableImportValue, An as UNSHOWABLE_VALUE, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bn as withheldTargetClause, Bt as recoveryCommandFlags, Ct as RETRY_AUXILIARY_OWNER, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as physicalIdShownBesideCommand, G as runDeleteAttempt, Gn as isNameCollisionErrorFrom, H as observeThenDisableProtection, Ht as CUSTOM_RESOURCE_RESPONSE_PREFIX, In as plainOrDescribed, J as DELETION_PROTECTION_DOC_POINTER, Jn as isReplayedNameCollisionFrom, Kn as isNameCooldownError, L as ProtectionFlipRegistry, Ln as quotedOrDescribed, Lt as formatLockExpiry, M as quotedRemedyLogicalId, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as isInertUnquoted, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE, Ot as hasCreatedBeforeFailure, Pn as pasteableCommand, Pt as buildForceUnlockCommand, Q as pasteableAwsCommand, Qn as isAmbiguousCcHandlerErrorCode, Qt as clientDefaultsFor, R as compensateProtectionFlip, Rn as shellBoundedDisplay, Rt as formatLockOperation, Sn as SynthesisError, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, Tn as normalizeAwsError, U as protectionFlipKey, Un as isUpdateUnsupportedError, Ut as DEFAULT_STATE_PREFIX, Vt as sanitizeRecoveryValue, Wn as hasReplayMayCollide, Wt as injectiveKey, Xn as markReplayMayCollide, Xt as ambientClientDefaults, Yt as withPasteableAwsProfile, Zn as formatRetryClassificationSignals, Zt as ambientCredentialConfig, _n as ResourceTimeoutError, _t as createMaskedLogSinks, an as DependencyError, ar as isMarkedNonRetryable, at as startInterruptWatch, bt as maskDeep, cn as IntrinsicResolutionRefusalError, cr as markRedactedCause, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as LockError, en as AccountIdUnavailableError, er as isIamPropagationError, f as removalWarning, fn as MacroExpansionError, ft as logicalIdShown, gn as ProvisioningError, gt as stateOrphanRecordRemedy, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as CrossAccountSecretRefusalError, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jn as commandHole, jt as markAuxiliaryFailure, kn as SHELL_ACTIVE_WHY, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, lr as wrapMaskedAwsError, m as withoutInjectedRemovals, mt as resourceTypeShown, nn as CdkdError, nr as isTransientServerError, or as isThrottlingError, ot as ElapsedBudgetRegistry, pn as MalformedProducerRecordRefusalError, qn as isRecreateRetryableError, qt as producerRecordKey, rr as retryClassificationText, sn as DynamicReferenceRegionAmbiguousError, sr as markNonRetryable, st as monotonicNowMs, tn as AssetError, tr as isRetryableTransientError, ut as compositeIdSeparatorRefusal, vn as ResourceUpdateNotSupportedError, vt as createMaskedRetryLogger, w as withoutServerErrorRetries, wt as carryCreatedBeforeFailure, xn as StateError, xt as maskerOrIdentity, yt as isSecretDerivedValue, z as deleteWithProtectionCompensation, zn as shellQuote, zt as formatLockOwner } from "./iam-policy-targets-Cz2tPxXk.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-B0JEGOLV.js";
5
+ import { t as getCdkdVersion } from "./version-DyV_xwRX.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";
@@ -4937,14 +4937,16 @@ function parseCreateTokenLedger(body) {
4937
4937
  for (const [logicalId, entry] of Object.entries(rawSent)) if (isSent(entry)) sent[logicalId] = {
4938
4938
  base: entry.base,
4939
4939
  token: entry.token,
4940
- firstSentAt: entry.firstSentAt
4940
+ firstSentAt: entry.firstSentAt,
4941
+ ...typeof entry.failedAt === "number" && Number.isFinite(entry.failedAt) && { failedAt: entry.failedAt }
4941
4942
  };
4942
4943
  }
4943
4944
  return {
4944
4945
  ledgerVersion: 1,
4945
4946
  nonce: doc["nonce"],
4946
4947
  sent,
4947
- ...doc["stateRecorded"] === true && { stateRecorded: true }
4948
+ ...doc["stateRecorded"] === true && { stateRecorded: true },
4949
+ ...typeof doc["abandonedAt"] === "number" && Number.isFinite(doc["abandonedAt"]) && { abandonedAt: doc["abandonedAt"] }
4948
4950
  };
4949
4951
  }
4950
4952
  const stateSavedObserver = new AsyncLocalStorage();
@@ -4955,6 +4957,409 @@ async function notifyStateSaved(stackName, region) {
4955
4957
  await stateSavedObserver.getStore()?.(stackName, region);
4956
4958
  }
4957
4959
 
4960
+ //#endregion
4961
+ //#region src/state/cross-prefix-stack-scan.ts
4962
+ function journalCanOwnResources(journal) {
4963
+ return recordCanOwnResources({ resources: {} }, journal);
4964
+ }
4965
+ function recordCanOwnResources(record, journal) {
4966
+ const resources = record.resources;
4967
+ if (resources === null || typeof resources !== "object" || Array.isArray(resources)) return true;
4968
+ if (Object.keys(resources).length > 0) return true;
4969
+ const orphans = record.orphans;
4970
+ if (orphans !== void 0 && (!Array.isArray(orphans) || orphans.length > 0)) return true;
4971
+ if (journal === null) return false;
4972
+ const segments = journal.segments;
4973
+ if (!Array.isArray(segments)) return true;
4974
+ return segments.some((seg) => {
4975
+ if (seg === null || typeof seg !== "object" || Array.isArray(seg)) return true;
4976
+ const ops = seg.operations;
4977
+ if (ops !== void 0 && (!Array.isArray(ops) || ops.length > 0)) return true;
4978
+ const failed = seg.failedOperations;
4979
+ if (failed === void 0) return false;
4980
+ if (!Array.isArray(failed)) return true;
4981
+ return failed.some((op) => op === null || typeof op !== "object" || op.physicalId !== void 0);
4982
+ });
4983
+ }
4984
+ var CrossPrefixReadError = class extends Error {
4985
+ key;
4986
+ cause;
4987
+ constructor(key, cause) {
4988
+ super(`reading ${displayIdent(key, { maxCodePoints: 1024 })} failed (${errorName$1(cause, "an unknown error")})`);
4989
+ this.name = "CrossPrefixReadError";
4990
+ this.key = key;
4991
+ this.cause = cause;
4992
+ }
4993
+ };
4994
+ const PROBE_CONCURRENCY = 50;
4995
+ function unwrapCause(error) {
4996
+ return error instanceof CrossPrefixReadError ? error.cause : error;
4997
+ }
4998
+ function isNotImplemented(error) {
4999
+ const name = error?.name;
5000
+ const status = error?.$metadata?.httpStatusCode;
5001
+ return name === "NotImplemented" || status === 501;
5002
+ }
5003
+ function isAccessDenied(error) {
5004
+ let current = error;
5005
+ for (let depth = 0; depth < 5 && current !== null && typeof current === "object"; depth++) {
5006
+ const name = current.name;
5007
+ if (name === "AccessDenied" || name === "Forbidden" || name === "AllAccessDisabled") return true;
5008
+ if (current.$metadata?.httpStatusCode === 403) return true;
5009
+ current = current.cause;
5010
+ }
5011
+ return false;
5012
+ }
5013
+ function candidatePrefixPasses(segments, own) {
5014
+ const seen = /* @__PURE__ */ new Set([own]);
5015
+ const pass = (names) => {
5016
+ const out = [];
5017
+ for (const name of names) {
5018
+ if (seen.has(name)) continue;
5019
+ seen.add(name);
5020
+ out.push(name);
5021
+ }
5022
+ return out;
5023
+ };
5024
+ return [pass(segments), pass(segments.map((p) => `${p}/`))];
5025
+ }
5026
+ async function scanOtherPrefixesForStack(target, stackName, region) {
5027
+ let segments;
5028
+ try {
5029
+ segments = await target.listTopLevelPrefixes();
5030
+ } catch (error) {
5031
+ return isAccessDenied(error) ? {
5032
+ kind: "denied",
5033
+ error,
5034
+ stage: "list"
5035
+ } : {
5036
+ kind: "failed",
5037
+ error
5038
+ };
5039
+ }
5040
+ const found = [];
5041
+ const stale = [];
5042
+ let denied;
5043
+ let failed;
5044
+ const probeAll = async (candidates) => {
5045
+ let next = 0;
5046
+ const worker = async () => {
5047
+ while (found.length === 0 && next < candidates.length) {
5048
+ const prefix = candidates[next++];
5049
+ try {
5050
+ const held = await target.recordUnderPrefix(prefix, stackName, region);
5051
+ if (held === "holder") found.push(prefix);
5052
+ else if (held === "empty") stale.push(prefix);
5053
+ } catch (error) {
5054
+ if (isAccessDenied(error)) denied ??= error;
5055
+ else failed ??= error;
5056
+ }
5057
+ }
5058
+ };
5059
+ await Promise.all(Array.from({ length: Math.min(50, candidates.length) }, () => worker()));
5060
+ };
5061
+ const [segmentsThemselves, twins] = candidatePrefixPasses(segments, target.prefix);
5062
+ await probeAll([...segmentsThemselves, ...twins]);
5063
+ const extra = stale.length > 0 ? { stale } : {};
5064
+ if (found.length > 0) return {
5065
+ kind: "found",
5066
+ prefixes: found,
5067
+ ...extra
5068
+ };
5069
+ if (failed !== void 0) return {
5070
+ kind: "failed",
5071
+ error: failed,
5072
+ ...extra
5073
+ };
5074
+ if (denied !== void 0) return {
5075
+ kind: "denied",
5076
+ error: denied,
5077
+ stage: "probe",
5078
+ ...extra
5079
+ };
5080
+ return {
5081
+ kind: "clear",
5082
+ ...extra
5083
+ };
5084
+ }
5085
+ function withSharedListing(target) {
5086
+ let listing;
5087
+ let inFlight = 0;
5088
+ let seq = 0;
5089
+ let prestarted = 0;
5090
+ const keyOf = (stackName, region) => JSON.stringify([stackName, region]);
5091
+ const ranks = /* @__PURE__ */ new Map();
5092
+ const rankOf = (stackName, region) => ranks.get(keyOf(stackName, region)) ?? Number.MAX_SAFE_INTEGER;
5093
+ const heap = [];
5094
+ const before = (a, b) => a.rank < b.rank || a.rank === b.rank && a.seq < b.seq;
5095
+ const swap = (i, j) => {
5096
+ const t = heap[i];
5097
+ heap[i] = heap[j];
5098
+ heap[j] = t;
5099
+ };
5100
+ const siftUp = (i) => {
5101
+ while (i > 0) {
5102
+ const parent = i - 1 >> 1;
5103
+ if (!before(heap[i], heap[parent])) return;
5104
+ swap(i, parent);
5105
+ i = parent;
5106
+ }
5107
+ };
5108
+ const siftDown = (i) => {
5109
+ for (;;) {
5110
+ const l = 2 * i + 1;
5111
+ const r = l + 1;
5112
+ let best = i;
5113
+ if (l < heap.length && before(heap[l], heap[best])) best = l;
5114
+ if (r < heap.length && before(heap[r], heap[best])) best = r;
5115
+ if (best === i) return;
5116
+ swap(i, best);
5117
+ i = best;
5118
+ }
5119
+ };
5120
+ const popBest = () => {
5121
+ const top = heap[0];
5122
+ const last = heap.pop();
5123
+ if (heap.length > 0) {
5124
+ heap[0] = last;
5125
+ siftDown(0);
5126
+ }
5127
+ return top;
5128
+ };
5129
+ const admitBest = () => {
5130
+ while (inFlight < 50 && heap.length > 0) {
5131
+ inFlight++;
5132
+ popBest().resolve();
5133
+ }
5134
+ };
5135
+ const acquire = async (stackName, region) => {
5136
+ const rank = rankOf(stackName, region);
5137
+ if (inFlight < 50 && (heap.length === 0 || heap[0].rank >= rank)) {
5138
+ inFlight++;
5139
+ return;
5140
+ }
5141
+ const key = keyOf(stackName, region);
5142
+ await new Promise((resolve) => {
5143
+ heap.push({
5144
+ key,
5145
+ rank,
5146
+ seq: seq++,
5147
+ resolve
5148
+ });
5149
+ siftUp(heap.length - 1);
5150
+ });
5151
+ };
5152
+ const release = () => {
5153
+ inFlight--;
5154
+ admitBest();
5155
+ };
5156
+ return {
5157
+ prefix: target.prefix,
5158
+ rank: (stackName, region, when) => {
5159
+ const key = keyOf(stackName, region);
5160
+ if (when === "prestart") {
5161
+ if (!ranks.has(key)) ranks.set(key, prestarted++);
5162
+ return;
5163
+ }
5164
+ if (ranks.get(key) === -1) return;
5165
+ ranks.set(key, -1);
5166
+ let moved = false;
5167
+ for (const w of heap) if (w.key === key) {
5168
+ w.rank = -1;
5169
+ moved = true;
5170
+ }
5171
+ if (moved) for (let i = (heap.length >> 1) - 1; i >= 0; i--) siftDown(i);
5172
+ },
5173
+ listTopLevelPrefixes: () => listing ??= target.listTopLevelPrefixes(),
5174
+ recordUnderPrefix: async (prefix, stackName, region) => {
5175
+ await acquire(stackName, region);
5176
+ try {
5177
+ return await target.recordUnderPrefix(prefix, stackName, region);
5178
+ } finally {
5179
+ release();
5180
+ }
5181
+ }
5182
+ };
5183
+ }
5184
+ var CrossPrefixScanCache = class {
5185
+ target;
5186
+ scans = /* @__PURE__ */ new Map();
5187
+ constructor(target) {
5188
+ this.target = withSharedListing(target);
5189
+ }
5190
+ full(stackName, region, when = "now") {
5191
+ this.target.rank(stackName, region, when);
5192
+ const key = JSON.stringify([stackName, region]);
5193
+ let scan = this.scans.get(key);
5194
+ if (scan === void 0) {
5195
+ scan = scanOtherPrefixesForStack(this.target, stackName, region);
5196
+ this.scans.set(key, scan);
5197
+ }
5198
+ return scan;
5199
+ }
5200
+ };
5201
+ const STACK_UNDER_OTHER_PREFIX = "STACK_UNDER_OTHER_STATE_PREFIX";
5202
+ const UNSUPPORTED_SENTENCE = "A stack name is unique per account and region, as in CloudFormation: deploying one stack name under two state prefixes is unsupported, because both deployments use the same cdkd-generated resource names, and a failed deploy, a destroy, or a deploy that deletes or replaces of either one deletes resources the other's record also names.";
5203
+ function subjectText(s) {
5204
+ return `${displayStackName(s.stackName)} (${displayIdent(s.region)})`;
5205
+ }
5206
+ const LISTED_PREFIXES = 5;
5207
+ function prefixesText(prefixes) {
5208
+ const shown = prefixes.slice(0, LISTED_PREFIXES).map((p) => displayIdent(p, { listMember: true })).join(", ");
5209
+ const more = prefixes.length - LISTED_PREFIXES;
5210
+ return more > 0 ? `${shown} and ${more} more` : shown;
5211
+ }
5212
+ function stateCommand(verb, s, prefix) {
5213
+ const account = recoveryCommandFlags({
5214
+ profile: s.recovery?.profile,
5215
+ stateBucket: s.recovery?.stateBucket ?? s.bucket
5216
+ });
5217
+ return pasteableCommand(`cdkd state ${verb}`, [
5218
+ {
5219
+ value: s.stackName,
5220
+ hole: "stack"
5221
+ },
5222
+ {
5223
+ flag: "--stack-region",
5224
+ value: s.region,
5225
+ hole: "region"
5226
+ },
5227
+ {
5228
+ flag: "--state-prefix",
5229
+ value: prefix,
5230
+ hole: "prefix"
5231
+ }
5232
+ ], account.flags).command;
5233
+ }
5234
+ function releaseRemedy(s, prefixes, destroyToo) {
5235
+ const first = prefixes[0];
5236
+ if (prefixes.length === 1 && destroyToo) return `\`${stateCommand("destroy", s, first)}\` deletes its resources and its record, \`${stateCommand("orphan", s, first)}\` drops only its record.`;
5237
+ if (prefixes.length === 1) return `drop the other record with \`cdkd state orphan\` (it removes only the record, never a resource): \`${stateCommand("orphan", s, first)}\`.`;
5238
+ return `release each other record with \`cdkd state orphan\` (it removes only the record, never a resource; a destroy under one of them is refused while another still records the stack, and the check stops at the first ones it finds, so re-run it until none is named), e.g. \`${stateCommand("orphan", s, first)}\`, then the same with each other prefix.`;
5239
+ }
5240
+ const VERB = {
5241
+ deploy: "deploy",
5242
+ destroy: "destroy",
5243
+ rollback: "roll back",
5244
+ "deploy-destructive": "deploy",
5245
+ "deploy-late-replace": "replace a resource of"
5246
+ };
5247
+ const NOTHING = {
5248
+ deploy: "No resource of this stack was created.",
5249
+ destroy: "Nothing was deleted.",
5250
+ rollback: "Nothing was reverted or deleted.",
5251
+ "deploy-destructive": "No resource of this stack was changed.",
5252
+ "deploy-late-replace": "That resource is kept, so the new value is not applied; the rest of the deploy goes on."
5253
+ };
5254
+ function deployUnderOtherPrefixMessage(s, prefixes) {
5255
+ return `Refusing to deploy stack ${subjectText(s)}: it is already recorded under another state prefix of bucket ${displayIdent(s.bucket)} (${prefixesText(prefixes)}). ${UNSUPPORTED_SENTENCE} ${NOTHING.deploy} Either deploy it under that prefix (pass the same --state-prefix it was deployed with), give this stack another name, or, if the other deployment is no longer wanted, ${prefixes.length === 1 ? "remove it first: " : ""}` + releaseRemedy(s, prefixes, true);
5256
+ }
5257
+ function destroyUnderOtherPrefixMessage(s, prefixes, action = "destroy") {
5258
+ return `Refusing to ${VERB[action]} stack ${subjectText(s)}: it is also recorded under another state prefix of bucket ${displayIdent(s.bucket)} (${prefixesText(prefixes)}). ${UNSUPPORTED_SENTENCE} ${NOTHING[action]} Keep one record per stack name and region: once you have confirmed which record describes the deployment you want to keep, ${releaseRemedy(s, prefixes, false)} Then re-run.`;
5259
+ }
5260
+ function destructiveDeployUnderOtherPrefixMessage(s, prefixes, action = "deploy-destructive") {
5261
+ return `${action === "deploy-late-replace" ? `Refusing to replace a resource of stack ${subjectText(s)} (a replacement this deploy found only on reading the resource back)` : `Refusing to deploy stack ${subjectText(s)}: this deploy deletes or replaces resources`}, and the stack is also recorded under another state prefix of bucket ${displayIdent(s.bucket)} (${prefixesText(prefixes)}). ${UNSUPPORTED_SENTENCE} ${NOTHING[action]} Keep one record per stack name and region: once you have confirmed which record describes the deployment you want to keep, ${releaseRemedy(s, prefixes, false)} Then re-run.`;
5262
+ }
5263
+ function staleRecordNotice(s, prefixes) {
5264
+ return `Note: bucket ${displayIdent(s.bucket)} also holds a record of stack ${subjectText(s)} under another state prefix (${prefixesText(prefixes)}) that owns no resource -- the leftover of a failed first deploy. It does not block this command; remove it with \`${stateCommand("orphan", s, prefixes[0])}\`${prefixes.length > 1 ? ", and the same with each other prefix" : ""}.`;
5265
+ }
5266
+ function errorName$1(error, fallback) {
5267
+ const subject = error instanceof CrossPrefixReadError ? error.cause : error;
5268
+ return subject !== null && typeof subject === "object" && typeof subject.name === "string" ? displaySafe(subject.name, { asciiOnly: true }) : fallback;
5269
+ }
5270
+ function failedKeyText(error) {
5271
+ return error instanceof CrossPrefixReadError ? ` reading s3 object ${displayIdent(error.key, { maxCodePoints: 1024 })}` : "";
5272
+ }
5273
+ function crossPrefixDeniedWarning(s, error, stage = "probe") {
5274
+ if (stage === "registry" && isNotImplemented(unwrapCause(error))) return `Could not use the stack registry for stack ${subjectText(s)}: the state bucket's endpoint does not implement a conditional write${failedKeyText(error)} (${errorName$1(error, "NotImplemented")}), so the bucket's other state prefixes were scanned instead, which is slower. Continuing.`;
5275
+ if (stage === "registry") return `Could not use the stack registry for stack ${subjectText(s)}: S3 refused${failedKeyText(error)} (${errorName$1(error, "AccessDenied")}), so the bucket's other state prefixes were scanned instead, which is slower. Grant s3:GetObject, s3:PutObject and s3:DeleteObject on ${displayIdent(s.bucket)}/_cdkd-registry/* to use it. Continuing.`;
5276
+ const what = stage === "list" ? `S3 refused to list bucket ${displayIdent(s.bucket)}` : `S3 refused a read under another state prefix of bucket ${displayIdent(s.bucket)}`;
5277
+ return `Could not check the other state prefixes for stack ${subjectText(s)}: ${what} (${errorName$1(error, "AccessDenied")}). Continuing. Deploying one stack name under two state prefixes in one account and region is unsupported.`;
5278
+ }
5279
+ function inProgressUnderOtherPrefixMessage(s, action, prefix) {
5280
+ const account = recoveryCommandFlags({
5281
+ profile: s.recovery?.profile,
5282
+ stateBucket: s.recovery?.stateBucket ?? s.bucket
5283
+ });
5284
+ const unlock = pasteableCommand("cdkd force-unlock", [
5285
+ {
5286
+ value: s.stackName,
5287
+ hole: "stack"
5288
+ },
5289
+ {
5290
+ flag: "--stack-region",
5291
+ value: s.region,
5292
+ hole: "region"
5293
+ },
5294
+ {
5295
+ flag: "--state-prefix",
5296
+ value: prefix,
5297
+ hole: "prefix"
5298
+ }
5299
+ ], account.flags).command;
5300
+ return `Refusing to ${VERB[action]} stack ${subjectText(s)}: bucket ${displayIdent(s.bucket)} assigns it to state prefix ${displayIdent(prefix)}, which records nothing for it yet but holds its lock, so a deploy there may be in progress. ${UNSUPPORTED_SENTENCE} ${NOTHING[action]} Re-run once that deploy has finished; if none is running, remove its lock with \`${unlock}\` and re-run.`;
5301
+ }
5302
+ function crossPrefixFailedMessage(s, action, error) {
5303
+ return `Refusing to ${VERB[action]} stack ${subjectText(s)}: cdkd could not check whether the bucket ${displayIdent(s.bucket)} records it under another state prefix (${errorName$1(error, "an unknown error")}${failedKeyText(error)}). ${UNSUPPORTED_SENTENCE} ${NOTHING[action]} Re-run once the check can succeed.`;
5304
+ }
5305
+ function applyCrossPrefixScan(result, s, action, warn, info) {
5306
+ if (result.kind !== "in-progress" && result.stale !== void 0 && result.stale.length > 0) info?.(staleRecordNotice(s, result.stale));
5307
+ switch (result.kind) {
5308
+ case "clear": return;
5309
+ case "denied":
5310
+ warn(crossPrefixDeniedWarning(s, result.error, result.stage));
5311
+ return;
5312
+ case "found": {
5313
+ const message = action === "deploy" ? deployUnderOtherPrefixMessage(s, result.prefixes) : action === "deploy-destructive" || action === "deploy-late-replace" ? destructiveDeployUnderOtherPrefixMessage(s, result.prefixes, action) : destroyUnderOtherPrefixMessage(s, result.prefixes, action);
5314
+ throw new CdkdError(message, STACK_UNDER_OTHER_PREFIX);
5315
+ }
5316
+ case "failed": throw new CdkdError(crossPrefixFailedMessage(s, action, result.error), STACK_UNDER_OTHER_PREFIX);
5317
+ case "in-progress": throw new CdkdError(inProgressUnderOtherPrefixMessage(s, action, result.prefix), STACK_UNDER_OTHER_PREFIX);
5318
+ }
5319
+ }
5320
+
5321
+ //#endregion
5322
+ //#region src/state/earlier-state-versions.ts
5323
+ async function readEarlierStateResources(s3, bucket, owner, key, max) {
5324
+ const versions = ((await s3.send(new ListObjectVersionsCommand({
5325
+ Bucket: bucket,
5326
+ ...owner,
5327
+ Prefix: key,
5328
+ EncodingType: "url",
5329
+ MaxKeys: max + 1
5330
+ }))).Versions ?? []).filter((v) => decodeListingKey(v.Key) === key && typeof v.VersionId === "string").sort((a, b) => (b.LastModified?.getTime() ?? 0) - (a.LastModified?.getTime() ?? 0)).slice(0, max);
5331
+ return (await Promise.all(versions.map(async (v) => {
5332
+ const body = await (await s3.send(new GetObjectCommand({
5333
+ Bucket: bucket,
5334
+ ...owner,
5335
+ Key: key,
5336
+ VersionId: v.VersionId
5337
+ }))).Body?.transformToString();
5338
+ if (body === void 0) return void 0;
5339
+ try {
5340
+ const parsed = JSON.parse(body);
5341
+ if (parsed === null || typeof parsed.resources !== "object" || parsed.resources === null) return;
5342
+ return {
5343
+ resources: parsed.resources,
5344
+ ...v.LastModified instanceof Date && { writtenAt: v.LastModified.getTime() }
5345
+ };
5346
+ } catch {
5347
+ return;
5348
+ }
5349
+ }))).filter((r) => r !== void 0);
5350
+ }
5351
+
5352
+ //#endregion
5353
+ //#region src/state/retained-time.ts
5354
+ var RetainedTimeUnconfirmedError = class extends Error {
5355
+ cause;
5356
+ constructor(cause) {
5357
+ super("the kept-resource record was written, but its time could not be confirmed from S3");
5358
+ this.name = "RetainedTimeUnconfirmedError";
5359
+ this.cause = cause;
5360
+ }
5361
+ };
5362
+
4958
5363
  //#endregion
4959
5364
  //#region src/utils/bucket-region-client.ts
4960
5365
  async function rebuildClientForBucketRegion(client, bucket, opts = {}) {
@@ -5014,12 +5419,14 @@ function legacyProbeBelongsTo(probe, region) {
5014
5419
  case "unreadable": return false;
5015
5420
  }
5016
5421
  }
5017
- var S3StateBackend = class {
5422
+ const KEPT_AT_CLOCK_TOLERANCE_MS = 2e3;
5423
+ var S3StateBackend = class S3StateBackend {
5018
5424
  logger = getLogger().child("S3StateBackend");
5019
5425
  s3Client;
5020
5426
  config;
5021
5427
  clientOpts;
5022
5428
  clientResolved = false;
5429
+ scanClient;
5023
5430
  resolveInFlight = null;
5024
5431
  constructor(s3Client, config, clientOpts = {}) {
5025
5432
  this.s3Client = s3Client;
@@ -5028,6 +5435,19 @@ var S3StateBackend = class {
5028
5435
  }
5029
5436
  destroyClient() {
5030
5437
  this.s3Client.destroy();
5438
+ this.scanClient?.destroy();
5439
+ }
5440
+ async clientForScan() {
5441
+ await this.ensureClientForBucket();
5442
+ if (this.scanClient !== void 0) return this.scanClient;
5443
+ if (!(this.s3Client instanceof S3Client)) return this.s3Client;
5444
+ const region = await this.s3Client.config.region();
5445
+ this.scanClient = new S3Client({
5446
+ ...awsClientDefaults(this.clientOpts.profile ? { profile: this.clientOpts.profile } : {}),
5447
+ region,
5448
+ credentials: this.s3Client.config.credentials
5449
+ });
5450
+ return this.scanClient;
5031
5451
  }
5032
5452
  get prefix() {
5033
5453
  return this.config.prefix;
@@ -5295,6 +5715,87 @@ var S3StateBackend = class {
5295
5715
  throw new StateError(`Failed to list stacks: ${normalized.message}`, normalized);
5296
5716
  }
5297
5717
  }
5718
+ async listTopLevelPrefixes() {
5719
+ const client = await this.clientForScan();
5720
+ const out = [];
5721
+ let continuationToken;
5722
+ do {
5723
+ const response = await client.send(new ListObjectsV2Command({
5724
+ Bucket: this.config.bucket,
5725
+ ...await this.ownerParam(),
5726
+ Delimiter: "/",
5727
+ EncodingType: "url",
5728
+ ...continuationToken && { ContinuationToken: continuationToken }
5729
+ }));
5730
+ for (const cp of response.CommonPrefixes ?? []) {
5731
+ let decoded;
5732
+ try {
5733
+ decoded = decodeListingKey(cp.Prefix);
5734
+ } catch {
5735
+ this.logger.debug(safeMsg`Skipping a top-level prefix of bucket ${this.config.bucket} that is not valid URL encoding: ${cp.Prefix ?? ""}`);
5736
+ continue;
5737
+ }
5738
+ if (decoded === void 0 || !decoded.endsWith("/")) continue;
5739
+ if (decoded === `${"_cdkd-registry"}/`) continue;
5740
+ out.push(decoded.slice(0, -1));
5741
+ }
5742
+ continuationToken = response.IsTruncated ? response.NextContinuationToken : void 0;
5743
+ } while (continuationToken);
5744
+ return out;
5745
+ }
5746
+ async recordUnderPrefix(prefix, stackName, region) {
5747
+ const client = await this.clientForScan();
5748
+ const sibling = new S3StateBackend(client, {
5749
+ ...this.config,
5750
+ prefix
5751
+ }, this.clientOpts);
5752
+ sibling.clientResolved = true;
5753
+ const stackDir = `${prefix}/${stackName}/`;
5754
+ let listed;
5755
+ try {
5756
+ listed = await client.send(new ListObjectsV2Command({
5757
+ Bucket: this.config.bucket,
5758
+ ...await this.ownerParam(),
5759
+ Prefix: stackDir,
5760
+ MaxKeys: 1,
5761
+ EncodingType: "url"
5762
+ }));
5763
+ } catch (error) {
5764
+ throw new CrossPrefixReadError(stackDir, error);
5765
+ }
5766
+ if ((listed.KeyCount ?? listed.Contents?.length ?? 0) === 0) return "absent";
5767
+ const read = async (key) => {
5768
+ let body;
5769
+ try {
5770
+ body = await sibling.getRawObject(key);
5771
+ } catch (error) {
5772
+ throw new CrossPrefixReadError(key, error);
5773
+ }
5774
+ if (body === null) return null;
5775
+ if (body.trim() === "") throw new CrossPrefixReadError(key, Object.assign(/* @__PURE__ */ new Error("empty object"), { name: "EmptyObject" }));
5776
+ let value;
5777
+ try {
5778
+ value = JSON.parse(body);
5779
+ } catch (error) {
5780
+ throw new CrossPrefixReadError(key, error);
5781
+ }
5782
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new CrossPrefixReadError(key, /* @__PURE__ */ new TypeError("not a JSON object"));
5783
+ return value;
5784
+ };
5785
+ const [scoped, legacy, journal] = await Promise.all([
5786
+ read(sibling.getStateKey(stackName, region)),
5787
+ read(sibling.getLegacyStateKey(stackName)),
5788
+ read(sibling.getRollbackJournalKey(stackName, region))
5789
+ ]);
5790
+ let record;
5791
+ if (scoped !== null) record = scoped;
5792
+ else if (legacy !== null) {
5793
+ const bodyRegion = legacy["region"];
5794
+ if (!bodyRegion || bodyRegion === region) record = legacy;
5795
+ }
5796
+ if (record === void 0 && journal === null) return "absent";
5797
+ return recordCanOwnResources(record ?? { resources: {} }, journal) ? "holder" : "empty";
5798
+ }
5298
5799
  async putRawObject(key, body, contentType = "application/json") {
5299
5800
  await this.ensureClientForBucket();
5300
5801
  await this.s3Client.send(new PutObjectCommand({
@@ -5306,6 +5807,176 @@ var S3StateBackend = class {
5306
5807
  ContentType: contentType
5307
5808
  }));
5308
5809
  }
5810
+ async earlierStateResources(stackName, region, max = 10) {
5811
+ await this.ensureClientForBucket();
5812
+ return readEarlierStateResources(this.s3Client, this.config.bucket, await this.ownerParam(), this.getStateKey(stackName, region), max);
5813
+ }
5814
+ getRetainedKey(stackName, region) {
5815
+ return `${this.config.prefix}/${stackName}/${region}/retained.json`;
5816
+ }
5817
+ async loadRetainedResources(stackName, region) {
5818
+ return await this.loadRetainedRecord(stackName, region) ?? [];
5819
+ }
5820
+ async loadRetainedRecord(stackName, region) {
5821
+ const key = this.getRetainedKey(stackName, region);
5822
+ let body;
5823
+ try {
5824
+ body = await this.getRawObject(key);
5825
+ } catch (error) {
5826
+ throw new CrossPrefixReadError(key, error);
5827
+ }
5828
+ if (body === null) return null;
5829
+ const entries = parseRetainedResources(body);
5830
+ if (entries === void 0) throw new CrossPrefixReadError(key, Object.assign(/* @__PURE__ */ new Error("not a retained-resource record"), { name: "MalformedRecord" }));
5831
+ return entries;
5832
+ }
5833
+ async ensureRetainedTombstone(stackName, region) {
5834
+ await this.ensureClientForBucket();
5835
+ const key = this.getRetainedKey(stackName, region);
5836
+ const put = async () => this.s3Client.send(new PutObjectCommand({
5837
+ Bucket: this.config.bucket,
5838
+ ...await this.ownerParam(),
5839
+ Key: key,
5840
+ Body: JSON.stringify({
5841
+ retainedVersion: 1,
5842
+ resources: []
5843
+ }),
5844
+ ContentType: "application/json",
5845
+ IfNoneMatch: "*"
5846
+ }));
5847
+ try {
5848
+ try {
5849
+ await put();
5850
+ } catch (error) {
5851
+ if (!isConditionalConflict(error)) throw error;
5852
+ await put();
5853
+ }
5854
+ } catch (error) {
5855
+ if (isConditionFailure(error) && !isConditionalConflict(error)) return;
5856
+ if (!isNotImplemented(error)) throw error;
5857
+ if (await this.loadRetainedRecord(stackName, region) === null) await this.saveRetainedResources(stackName, region, []);
5858
+ }
5859
+ }
5860
+ async saveRetainedResources(stackName, region, entries) {
5861
+ await this.ensureClientForBucket();
5862
+ const key = this.getRetainedKey(stackName, region);
5863
+ const put = (resources) => this.ownerParam().then((owner) => this.s3Client.send(new PutObjectCommand({
5864
+ Bucket: this.config.bucket,
5865
+ ...owner,
5866
+ Key: key,
5867
+ Body: JSON.stringify({
5868
+ retainedVersion: 1,
5869
+ resources
5870
+ }),
5871
+ ContentType: "application/json"
5872
+ })));
5873
+ const fresh = new Set(entries.filter((e) => e.keptAt === void 0));
5874
+ const provisional = Date.now();
5875
+ await put(entries.map((e) => fresh.has(e) ? {
5876
+ ...e,
5877
+ keptAt: provisional
5878
+ } : e));
5879
+ if (fresh.size === 0) return;
5880
+ try {
5881
+ const head = await this.s3Client.send(new HeadObjectCommand({
5882
+ Bucket: this.config.bucket,
5883
+ ...await this.ownerParam(),
5884
+ Key: key
5885
+ }));
5886
+ const keptAt = head.LastModified instanceof Date ? head.LastModified.getTime() : void 0;
5887
+ if (keptAt === void 0) throw new Error("S3 reported no LastModified");
5888
+ if (Math.abs(keptAt - provisional) <= KEPT_AT_CLOCK_TOLERANCE_MS) return;
5889
+ await put(entries.map((e) => fresh.has(e) ? {
5890
+ ...e,
5891
+ keptAt
5892
+ } : e));
5893
+ } catch (error) {
5894
+ throw new RetainedTimeUnconfirmedError(error);
5895
+ }
5896
+ }
5897
+ registryMarkerKey(stackName, region) {
5898
+ return `${REGISTRY_ROOT}/${region}/${stackName}.json`;
5899
+ }
5900
+ async getRegistryMarker(stackName, region) {
5901
+ await this.ensureClientForBucket();
5902
+ const key = this.registryMarkerKey(stackName, region);
5903
+ let body;
5904
+ let etag;
5905
+ try {
5906
+ const response = await this.s3Client.send(new GetObjectCommand({
5907
+ Bucket: this.config.bucket,
5908
+ ...await this.ownerParam(),
5909
+ Key: key
5910
+ }));
5911
+ body = await response.Body?.transformToString();
5912
+ etag = response.ETag;
5913
+ } catch (error) {
5914
+ if (isNoSuchKey(error) || error.name === "NotFound") return null;
5915
+ throw new CrossPrefixReadError(key, error);
5916
+ }
5917
+ const prefix = registryMarkerPrefix(body);
5918
+ if (prefix === void 0 || etag === void 0) throw new CrossPrefixReadError(key, Object.assign(/* @__PURE__ */ new Error("not a registry marker"), { name: "MalformedMarker" }));
5919
+ return {
5920
+ prefix,
5921
+ etag
5922
+ };
5923
+ }
5924
+ async claimRegistryMarker(stackName, region, ifMatch) {
5925
+ await this.ensureClientForBucket();
5926
+ const key = this.registryMarkerKey(stackName, region);
5927
+ try {
5928
+ await this.s3Client.send(new PutObjectCommand({
5929
+ Bucket: this.config.bucket,
5930
+ ...await this.ownerParam(),
5931
+ Key: key,
5932
+ Body: JSON.stringify({ prefix: this.config.prefix }),
5933
+ ContentType: "application/json",
5934
+ ...ifMatch === void 0 ? { IfNoneMatch: "*" } : { IfMatch: ifMatch }
5935
+ }));
5936
+ return "claimed";
5937
+ } catch (error) {
5938
+ if (isConditionFailure(error)) return "conflict";
5939
+ throw new CrossPrefixReadError(key, error);
5940
+ }
5941
+ }
5942
+ async releaseRegistryMarker(stackName, region, known) {
5943
+ const marker = known !== void 0 && (known === null || known.etag !== "") ? known : await this.getRegistryMarker(stackName, region);
5944
+ if (marker === null) return "absent";
5945
+ if (marker.prefix !== this.config.prefix) return "elsewhere";
5946
+ const key = this.registryMarkerKey(stackName, region);
5947
+ try {
5948
+ await this.s3Client.send(new DeleteObjectCommand({
5949
+ Bucket: this.config.bucket,
5950
+ ...await this.ownerParam(),
5951
+ Key: key,
5952
+ IfMatch: marker.etag
5953
+ }));
5954
+ return "released";
5955
+ } catch (error) {
5956
+ if (isConditionFailure(error)) return "elsewhere";
5957
+ if (!isNotImplemented(error)) throw error;
5958
+ }
5959
+ const again = await this.getRegistryMarker(stackName, region);
5960
+ if (again === null) return "absent";
5961
+ if (again.prefix !== this.config.prefix || again.etag !== marker.etag) return "elsewhere";
5962
+ await this.s3Client.send(new DeleteObjectCommand({
5963
+ Bucket: this.config.bucket,
5964
+ ...await this.ownerParam(),
5965
+ Key: key
5966
+ }));
5967
+ return "released";
5968
+ }
5969
+ async lockUnderPrefix(prefix, stackName, region) {
5970
+ await this.ensureClientForBucket();
5971
+ const keys = [`${prefix}/${stackName}/${region}/lock.json`, `${prefix}/${stackName}/lock.json`];
5972
+ return (await Promise.all(keys.map(async (key) => {
5973
+ try {
5974
+ return await this.headObject(key);
5975
+ } catch (error) {
5976
+ throw new CrossPrefixReadError(key, error);
5977
+ }
5978
+ }))).some(Boolean);
5979
+ }
5309
5980
  async getRawObject(key) {
5310
5981
  await this.ensureClientForBucket();
5311
5982
  try {
@@ -5750,6 +6421,53 @@ var S3StateBackend = class {
5750
6421
  return parsed;
5751
6422
  }
5752
6423
  };
6424
+ function parseRetainedResources(body) {
6425
+ let value;
6426
+ try {
6427
+ value = JSON.parse(body);
6428
+ } catch {
6429
+ return;
6430
+ }
6431
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
6432
+ const doc = value;
6433
+ if (doc.retainedVersion !== 1 || !Array.isArray(doc.resources)) return void 0;
6434
+ const out = [];
6435
+ for (const entry of doc.resources) {
6436
+ const e = entry;
6437
+ if (typeof e?.logicalId === "string" && typeof e.resourceType === "string" && typeof e.physicalId === "string" && e.physicalId !== "") out.push({
6438
+ logicalId: e.logicalId,
6439
+ resourceType: e.resourceType,
6440
+ physicalId: e.physicalId,
6441
+ ...typeof e.keptAt === "number" && Number.isFinite(e.keptAt) && { keptAt: e.keptAt }
6442
+ });
6443
+ }
6444
+ return out;
6445
+ }
6446
+ const REGISTRY_ROOT = "_cdkd-registry";
6447
+ function registryMarkerPrefix(body) {
6448
+ if (body === void 0) return void 0;
6449
+ let value;
6450
+ try {
6451
+ value = JSON.parse(body);
6452
+ } catch {
6453
+ return;
6454
+ }
6455
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
6456
+ const prefix = value.prefix;
6457
+ if (typeof prefix !== "string" || prefix.length > 1024) return void 0;
6458
+ if (/[\u0000-\u001f\u007f<>]/.test(prefix)) return void 0;
6459
+ return prefix;
6460
+ }
6461
+ function isConditionalConflict(error) {
6462
+ const name = error?.name;
6463
+ const status = error?.$metadata?.httpStatusCode;
6464
+ return name === "ConditionalRequestConflict" || status === 409 && name !== "PreconditionFailed";
6465
+ }
6466
+ function isConditionFailure(error) {
6467
+ const name = error?.name;
6468
+ const status = error?.$metadata?.httpStatusCode;
6469
+ return name === "PreconditionFailed" || name === "ConditionalRequestConflict" || status === 412 || status === 409;
6470
+ }
5753
6471
  function isNoSuchKey(error) {
5754
6472
  if (error instanceof NoSuchKey) return true;
5755
6473
  return error?.name === "NoSuchKey";
@@ -5768,6 +6486,15 @@ function addSupersededIds(segment, ids) {
5768
6486
  const MAX_RENEWAL_INTERVAL_MS = 12e4;
5769
6487
  const RENEWAL_TTL_FRACTION = 4;
5770
6488
  const MIN_RENEWAL_INTERVAL_MS = 1e3;
6489
+ function renewalIntervalFor(ttlMs) {
6490
+ return Math.max(MIN_RENEWAL_INTERVAL_MS, Math.min(MAX_RENEWAL_INTERVAL_MS, Math.floor(ttlMs / RENEWAL_TTL_FRACTION)));
6491
+ }
6492
+ function abandonedRunHorizon(record) {
6493
+ if (record.lastModified === void 0) return void 0;
6494
+ const ttlMs = Number(record.info.expiresAt) - record.lastModified;
6495
+ const interval = Number.isFinite(ttlMs) && ttlMs > 0 ? renewalIntervalFor(ttlMs) : MAX_RENEWAL_INTERVAL_MS;
6496
+ return record.lastModified + interval;
6497
+ }
5771
6498
  const RELEASED_LOCK_REACQUIRE_LIMIT = 3;
5772
6499
  const LOCK_OBJECT_DESCRIPTION = "a stack lock heartbeat, which records the lock owner, its acquisition timestamp, its deadline and the operation name — no secret, but one row per renewal";
5773
6500
  function safeSegment(value) {
@@ -5791,6 +6518,7 @@ var LockManager = class {
5791
6518
  renewalIntervalMs;
5792
6519
  renewalDisabled;
5793
6520
  heldLocks = /* @__PURE__ */ new Map();
6521
+ abandonedLocks = /* @__PURE__ */ new Map();
5794
6522
  clientResolved = false;
5795
6523
  resolveInFlight = null;
5796
6524
  constructor(s3Client, config, options) {
@@ -5800,7 +6528,7 @@ var LockManager = class {
5800
6528
  if (!(ttlMinutes > 0) || !Number.isFinite(ttlMinutes)) throw new LockError(`Lock TTL must be a positive number of minutes (got ${String(ttlMinutes)}). A non-positive TTL makes every lock born expired, and the renewal interval clamps to its floor, so the heartbeat would spin one request per second for the life of the process.`);
5801
6529
  this.ttlMs = ttlMinutes * 60 * 1e3;
5802
6530
  this.renewalDisabled = options?.disableRenewal === true;
5803
- this.renewalIntervalMs = Math.max(MIN_RENEWAL_INTERVAL_MS, Math.min(MAX_RENEWAL_INTERVAL_MS, Math.floor(this.ttlMs / RENEWAL_TTL_FRACTION)));
6531
+ this.renewalIntervalMs = renewalIntervalFor(this.ttlMs);
5804
6532
  }
5805
6533
  async ownerParam() {
5806
6534
  return expectedOwnerParam(this.s3Client);
@@ -5889,6 +6617,8 @@ var LockManager = class {
5889
6617
  }
5890
6618
  const why = Number.isFinite(existing.info.expiresAt) ? "A live cdkd process renews its lock well inside the TTL, so this normally means the previous owner crashed or was suspended" : `Its expiresAt is not a finite number, which cdkd treats as already expired`;
5891
6619
  this.logger.warn(`Took over an EXPIRED lock for stack: ${safeSegment(stackName)} (${safeSegment(region)}, owner: ${formatLockOwner(existing.info.owner)}, ${formatLockExpiry(existing.info.expiresAt)}). ${why} -- if it is in fact still running, both processes are now writing to the same stack.`);
6620
+ const abandonedAt = abandonedRunHorizon(existing);
6621
+ if (abandonedAt !== void 0) this.abandonedLocks.set(key, abandonedAt);
5892
6622
  try {
5893
6623
  const retryEtag = await this.putLockObject(key, lockInfo);
5894
6624
  this.logger.debug(`Lock acquired for stack: ${stackRef(stackName, region)} after expired lock cleanup, owner: ${displaySafe(lockOwner)}`);
@@ -5959,7 +6689,8 @@ var LockManager = class {
5959
6689
  this.logger.debug(`Lock info for stack: ${shownStack}:`, lockInfo);
5960
6690
  return {
5961
6691
  info: lockInfo,
5962
- etag: response.ETag
6692
+ etag: response.ETag,
6693
+ ...response.LastModified instanceof Date && { lastModified: response.LastModified.getTime() }
5963
6694
  };
5964
6695
  } catch (error) {
5965
6696
  if (error instanceof NoSuchKey) {
@@ -6042,9 +6773,13 @@ var LockManager = class {
6042
6773
  sameLockIdentity(a, b) {
6043
6774
  return displaySafe(a.owner) === displaySafe(b.owner) && a.timestamp === b.timestamp;
6044
6775
  }
6045
- async forceReleaseLock(stackName, region) {
6776
+ abandonedRunEndedBy(stackName, region) {
6777
+ return this.abandonedLocks.get(this.getLockKey(stackName, region));
6778
+ }
6779
+ async forceReleaseLock(stackName, region, beforeDelete) {
6046
6780
  const where = stackRef(stackName, region);
6047
- const lockInfo = await this.getLockInfo(stackName, region).catch(() => null);
6781
+ const record = await this.getLockRecord(stackName, region).catch(() => null);
6782
+ const lockInfo = record?.info ?? null;
6048
6783
  this.logger.warn(lockInfo ? `Force releasing lock for stack: ${where}, owner: ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? `, operation: ${formatLockOperation(lockInfo.operation)}` : ""}, expired: ${this.isLockExpired(lockInfo)}` : `Force releasing lock for stack: ${where} (no lock body read — absent or unparseable; deleting the object either way, since a lock cdkd cannot read is a lock nothing else can clear)`);
6049
6784
  const key = this.getLockKey(stackName, region);
6050
6785
  const held = this.heldLocks.get(key);
@@ -6052,11 +6787,14 @@ var LockManager = class {
6052
6787
  this.stopRenewal(held);
6053
6788
  held.releasing = Promise.resolve();
6054
6789
  }
6790
+ const horizon = record ? abandonedRunHorizon(record) : void 0;
6791
+ if (horizon !== void 0 && beforeDelete !== void 0) await beforeDelete(horizon).catch(() => void 0);
6055
6792
  try {
6056
6793
  await this.deleteLock(stackName, region);
6057
6794
  } finally {
6058
6795
  await this.purgeLockVersions(key, "reap");
6059
6796
  }
6797
+ return horizon;
6060
6798
  }
6061
6799
  async deleteLock(stackName, region, etag) {
6062
6800
  await this.ensureClientForBucket();
@@ -11311,7 +12049,7 @@ const DERIVED_GENERATED_NAMES = {
11311
12049
  },
11312
12050
  "AWS::S3::Bucket": {
11313
12051
  file: "s3-bucket-provider.ts",
11314
- source: "generateResourceName(logicalId, {\n maxLength: 63,\n lowercase: true,\n allowedPattern: /[^a-z0-9.-]/g,\n })",
12052
+ source: "generateResourceName(logicalId, {\n maxLength: 63,\n lowercase: true,\n allowedPattern: /[^a-z0-9.-]/g,\n })",
11315
12053
  derive: (id) => generateResourceName(id, {
11316
12054
  maxLength: 63,
11317
12055
  lowercase: true,
@@ -22972,7 +23710,7 @@ var CloudControlProvider = class {
22972
23710
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
22973
23711
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
22974
23712
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
22975
- const { ASGProvider } = await import("./asg-provider-B3zcS87C.js");
23713
+ const { ASGProvider } = await import("./asg-provider-UKRukGI_.js");
22976
23714
  const delegateRegion = ambientRegion();
22977
23715
  let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
22978
23716
  if (asgProvider === void 0) {
@@ -23078,7 +23816,7 @@ var CloudControlProvider = class {
23078
23816
  const family = SDK_DELETE_FAMILIES.get(resourceType);
23079
23817
  const cached = this.sdkDeleteDelegates.get(family);
23080
23818
  if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
23081
- const provider = family === "rds" ? new (await (import("./rds-provider-BfQsw4hw.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-DF6Eh4Tl.js"))).NeptuneProvider({ region: ccRegion });
23819
+ const provider = family === "rds" ? new (await (import("./rds-provider-DgbVxaPP.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-B9InVgs6.js"))).NeptuneProvider({ region: ccRegion });
23082
23820
  this.sdkDeleteDelegates.set(family, {
23083
23821
  region: ccRegion,
23084
23822
  provider
@@ -25661,7 +26399,7 @@ const NESTED_REQUIRED = /* @__PURE__ */ new Map([
25661
26399
  ["ContainerDefinitions.LinuxParameters.Tmpfs", ["Size"]],
25662
26400
  ["ContainerDefinitions.LogConfiguration", ["LogDriver"]],
25663
26401
  ["ContainerDefinitions.LogConfiguration.SecretOptions", ["Name", "ValueFrom"]],
25664
- ["ContainerDefinitions.ResourceRequirements", ["Type", "Value"]],
26402
+ ["ContainerDefinitions.ResourceRequirements", ["Type"]],
25665
26403
  ["ContainerDefinitions.Secrets", ["Name", "ValueFrom"]],
25666
26404
  ["ContainerDefinitions.Ulimits", [
25667
26405
  "HardLimit",
@@ -27003,9 +27741,12 @@ var ProviderRegistry = class {
27003
27741
  this.providers.delete(resourceType);
27004
27742
  }
27005
27743
  getProviderFor(input) {
27744
+ const debug = (message) => {
27745
+ if (input.quiet !== true) this.logger.debug(message);
27746
+ };
27006
27747
  const { resourceType, properties, provisionedBy } = input;
27007
27748
  if (isCustomResource(resourceType)) {
27008
- this.logger.debug(`Using Custom Resource provider for ${resourceType}`);
27749
+ debug(`Using Custom Resource provider for ${resourceType}`);
27009
27750
  return {
27010
27751
  provider: this.customResourceProvider,
27011
27752
  provisionedBy: "sdk"
@@ -27020,7 +27761,7 @@ var ProviderRegistry = class {
27020
27761
  allowedUnsupportedProperties: this.allowedUnsupportedProperties,
27021
27762
  forceCcApi: input.forceCcApi === true
27022
27763
  })) {
27023
- this.logger.debug(`Routing ${resourceType} via Cloud Control (state-recorded provisionedBy=cc-api)`);
27764
+ debug(`Routing ${resourceType} via Cloud Control (state-recorded provisionedBy=cc-api)`);
27024
27765
  return {
27025
27766
  provider: this.cloudControlProvider,
27026
27767
  provisionedBy: "cc-api"
@@ -27032,9 +27773,9 @@ var ProviderRegistry = class {
27032
27773
  if (specificProvider) {
27033
27774
  const actionableDrops = findActionableSilentDrops(resourceType, properties, this.allowedUnsupportedProperties, input.previousProperties);
27034
27775
  if (actionableDrops.length === 0) {
27035
- this.logger.debug(`Using specific SDK provider for ${resourceType}`);
27776
+ debug(`Using specific SDK provider for ${resourceType}`);
27036
27777
  if (returningToSdk) {
27037
- this.logger.debug(`${resourceType} is returning to its SDK provider from a state-recorded cc-api route; physical id is preserved`);
27778
+ debug(`${resourceType} is returning to its SDK provider from a state-recorded cc-api route; physical id is preserved`);
27038
27779
  return {
27039
27780
  provider: specificProvider,
27040
27781
  provisionedBy: "sdk",
@@ -27048,7 +27789,7 @@ var ProviderRegistry = class {
27048
27789
  }
27049
27790
  const unroutable = this.ccRouteUnavailableReason(resourceType);
27050
27791
  if (unroutable !== void 0) throw new Error(this.buildUnroutableSilentDropMessage(resourceType, actionableDrops, unroutable));
27051
- this.logger.debug(`Auto-routing ${resourceType} via Cloud Control (silent-drop properties: ${actionableDrops.map((d) => d.property).join(", ")})`);
27792
+ debug(`Auto-routing ${resourceType} via Cloud Control (silent-drop properties: ${actionableDrops.map((d) => d.property).join(", ")})`);
27052
27793
  return {
27053
27794
  provider: this.cloudControlProvider,
27054
27795
  provisionedBy: "cc-api",
@@ -27056,14 +27797,14 @@ var ProviderRegistry = class {
27056
27797
  };
27057
27798
  }
27058
27799
  if (CloudControlProvider.isSupportedResourceType(resourceType)) {
27059
- this.logger.debug(`Using Cloud Control API provider for ${resourceType}`);
27800
+ debug(`Using Cloud Control API provider for ${resourceType}`);
27060
27801
  return {
27061
27802
  provider: this.cloudControlProvider,
27062
27803
  provisionedBy: "cc-api"
27063
27804
  };
27064
27805
  }
27065
27806
  if (this.allowedUnsupportedTypes.has(resourceType)) {
27066
- this.logger.debug(`Routing escape-hatch-allowed type ${resourceType} through Cloud Control API`);
27807
+ debug(`Routing escape-hatch-allowed type ${resourceType} through Cloud Control API`);
27067
27808
  return {
27068
27809
  provider: this.cloudControlProvider,
27069
27810
  provisionedBy: "cc-api"
@@ -27336,7 +28077,7 @@ function recordedTagsUnreadableWarning(resourceType, id, applied) {
27336
28077
  //#endregion
27337
28078
  //#region src/provisioning/providers/idempotency-token.ts
27338
28079
  const PROCESS_NONCE = randomUUID();
27339
- const inFlight = /* @__PURE__ */ new Map();
28080
+ const inFlight$1 = /* @__PURE__ */ new Map();
27340
28081
  const generations = /* @__PURE__ */ new Map();
27341
28082
  const MAX_TRACKED_GENERATIONS = 1e5;
27342
28083
  const tokenKey = (scope, logicalId, maxLength, charset) => injectiveKey(scope, ambientRegion() ?? "", getCurrentStackName() ?? "", logicalId, maxLength, charset);
@@ -27347,14 +28088,14 @@ const derive = (key, generation, maxLength, charset) => {
27347
28088
  function acquireIdempotencyToken(options) {
27348
28089
  const { scope, logicalId, maxLength = 64, charset = "default" } = options;
27349
28090
  const key = tokenKey(scope, logicalId, maxLength, charset);
27350
- const existing = inFlight.get(key);
28091
+ const existing = inFlight$1.get(key);
27351
28092
  const value = existing ?? derive(key, generations.get(key) ?? 0, maxLength, charset);
27352
- if (existing === void 0) inFlight.set(key, value);
28093
+ if (existing === void 0) inFlight$1.set(key, value);
27353
28094
  return {
27354
28095
  value,
27355
28096
  release: () => {
27356
- if (!inFlight.has(key)) return;
27357
- inFlight.delete(key);
28097
+ if (!inFlight$1.has(key)) return;
28098
+ inFlight$1.delete(key);
27358
28099
  const generation = (generations.get(key) ?? 0) + 1;
27359
28100
  if (!generations.has(key) && generations.size >= MAX_TRACKED_GENERATIONS) {
27360
28101
  const oldest = generations.keys().next();
@@ -27379,6 +28120,7 @@ function stackScopedCreateToken(options) {
27379
28120
  //#region src/provisioning/providers/create-token-ledger.ts
27380
28121
  var CreateTokenLedger = class {
27381
28122
  doc;
28123
+ loadedAbsent = false;
27382
28124
  stale = false;
27383
28125
  startedThisDeploy = false;
27384
28126
  replaceRecordedLedger = false;
@@ -27404,8 +28146,10 @@ var CreateTokenLedger = class {
27404
28146
  }
27405
28147
  async current() {
27406
28148
  if (this.doc !== void 0 && !this.stale) return this.doc;
28149
+ if (this.loadedAbsent && !this.stale) return null;
27407
28150
  const loaded = await this.store.load();
27408
28151
  this.stale = false;
28152
+ this.loadedAbsent = loaded === null;
27409
28153
  if (loaded !== null && this.replaceRecordedLedger && loaded.stateRecorded === true) {
27410
28154
  this.logger.info("This stack has no state record but its create-token ledger outlived an earlier one; starting a fresh ledger, so this deploy does not take over resources that deployment left.");
27411
28155
  this.doc = emptyCreateTokenLedger(randomUUID());
@@ -27492,6 +28236,85 @@ var CreateTokenLedger = class {
27492
28236
  }
27493
28237
  });
27494
28238
  }
28239
+ sentEntries() {
28240
+ return this.serialized(async () => {
28241
+ try {
28242
+ return { ...(await this.current())?.sent ?? {} };
28243
+ } catch (error) {
28244
+ this.stale = true;
28245
+ throw error;
28246
+ }
28247
+ });
28248
+ }
28249
+ recordSent(entries, firstSentAt) {
28250
+ return this.serialized(async () => {
28251
+ try {
28252
+ let doc = await this.current();
28253
+ if (doc === null) {
28254
+ doc = emptyCreateTokenLedger(randomUUID());
28255
+ this.doc = doc;
28256
+ this.startedThisDeploy = true;
28257
+ }
28258
+ let changed = false;
28259
+ for (const entry of entries) {
28260
+ const recorded = doc.sent[entry.logicalId];
28261
+ if (recorded?.base === entry.base && recorded.token === entry.token) continue;
28262
+ doc.sent[entry.logicalId] = {
28263
+ base: entry.base,
28264
+ token: entry.token,
28265
+ firstSentAt
28266
+ };
28267
+ changed = true;
28268
+ }
28269
+ if (changed) await this.persist(doc);
28270
+ } catch (error) {
28271
+ this.stale = true;
28272
+ throw error;
28273
+ }
28274
+ });
28275
+ }
28276
+ abandonedAt() {
28277
+ return this.serialized(async () => (await this.current())?.abandonedAt);
28278
+ }
28279
+ noteAbandoned(at) {
28280
+ return this.serialized(async () => {
28281
+ try {
28282
+ const doc = await this.current();
28283
+ if (doc === null) return;
28284
+ if (!Object.values(doc.sent).some((e) => e.base.startsWith("adopt-by-name:")) || doc.abandonedAt !== void 0 && doc.abandonedAt >= at) return;
28285
+ doc.abandonedAt = at;
28286
+ await this.persist(doc);
28287
+ } catch (error) {
28288
+ this.stale = true;
28289
+ throw error;
28290
+ }
28291
+ });
28292
+ }
28293
+ settleAdoptingCreates(drop, failedAt) {
28294
+ return this.serialized(async () => {
28295
+ try {
28296
+ const doc = await this.current();
28297
+ if (doc === null) return;
28298
+ const adopting = (id) => doc.sent[id]?.base.startsWith(ADOPTING_CREATE_BASE) === true;
28299
+ let changed = false;
28300
+ for (const id of drop) {
28301
+ if (!adopting(id)) continue;
28302
+ delete doc.sent[id];
28303
+ changed = true;
28304
+ }
28305
+ for (const [id, at] of failedAt) {
28306
+ const entry = adopting(id) ? doc.sent[id] : void 0;
28307
+ if (entry === void 0 || entry.failedAt !== void 0) continue;
28308
+ entry.failedAt = at;
28309
+ changed = true;
28310
+ }
28311
+ if (changed) await this.persist(doc);
28312
+ } catch (error) {
28313
+ this.stale = true;
28314
+ throw error;
28315
+ }
28316
+ });
28317
+ }
27495
28318
  forget(logicalIds) {
27496
28319
  return this.serialized(async () => {
27497
28320
  try {
@@ -27537,6 +28360,39 @@ function ledgerForStack(backend, stackName, region) {
27537
28360
  });
27538
28361
  }
27539
28362
  const ledgerStore = new AsyncLocalStorage();
28363
+ const ADOPTING_CREATE_BASE = "adopt-by-name:";
28364
+ async function recordedAdoptingCreates() {
28365
+ const ledger = ledgerStore.getStore();
28366
+ if (ledger === void 0) return void 0;
28367
+ const out = /* @__PURE__ */ new Map();
28368
+ for (const [logicalId, entry] of Object.entries(await ledger.sentEntries())) if (entry.base.startsWith("adopt-by-name:")) out.set(logicalId, {
28369
+ resourceType: entry.base.slice(14),
28370
+ name: entry.token,
28371
+ firstSentAt: entry.firstSentAt,
28372
+ ...entry.failedAt !== void 0 && { failedAt: entry.failedAt }
28373
+ });
28374
+ return out;
28375
+ }
28376
+ async function recordAdoptingCreates(creates) {
28377
+ const ledger = ledgerStore.getStore();
28378
+ if (ledger === void 0 || creates.length === 0) return;
28379
+ await ledger.recordSent(creates.map((c) => ({
28380
+ logicalId: c.logicalId,
28381
+ base: `${ADOPTING_CREATE_BASE}${c.resourceType}`,
28382
+ token: c.name
28383
+ })), Date.now());
28384
+ }
28385
+ async function noteAbandonedRun(at) {
28386
+ const ledger = ledgerStore.getStore();
28387
+ if (ledger === void 0) return true;
28388
+ return ledger.noteAbandoned(at).then(() => true, () => false);
28389
+ }
28390
+ async function ledgerAbandonedAt() {
28391
+ return ledgerStore.getStore()?.abandonedAt();
28392
+ }
28393
+ async function settleAdoptingCreates(drop, failedAt = /* @__PURE__ */ new Map()) {
28394
+ await ledgerStore.getStore()?.settleAdoptingCreates(drop, failedAt);
28395
+ }
27540
28396
  function withCreateTokenLedger(ledger, fn) {
27541
28397
  return ledgerStore.run(ledger, () => withStateSavedObserver((stackName, region) => ledger.noteStateSaved(stackName, region), fn));
27542
28398
  }
@@ -28280,6 +29136,25 @@ function skipUnaddressableReplay(scope, logger, op, what, source = "record") {
28280
29136
  logger.warn(safeMsg` Rollback: Cannot ${what} ${shownLogicalId(op.logicalId)} (${refusalResourceType(op.resourceType)}) ` + "— its state record has no non-empty string 'physicalId', so cdkd cannot address it in AWS and sent nothing for it. The resource and its state record are left exactly as they are. Repair the record's 'physicalId' (inspect it with `cdkd state show`), then re-converge it with `cdkd deploy`.");
28281
29137
  recordRollbackSkip(scope, op, UNADDRESSABLE_SKIP_CAUSE);
28282
29138
  }
29139
+ async function keptForAnotherHolder(scope, logger, op, physicalId) {
29140
+ const ask = scope.ctx.createdResourceHolder;
29141
+ if (ask === void 0) return false;
29142
+ let holding;
29143
+ try {
29144
+ holding = await ask(op.resourceType, physicalId);
29145
+ } catch {
29146
+ holding = {
29147
+ kind: "unreadable",
29148
+ what: "the other stacks' state records (the check failed)"
29149
+ };
29150
+ }
29151
+ if (holding === void 0) return false;
29152
+ const why = holding.kind === "held" ? `${holding.by} holds it` : `${holding.what}, so it is not known whether another deployment owns it`;
29153
+ const retry = holding.kind === "unreadable" && holding.retryable === true ? scope.ctx.createdResourceRetryCommand : void 0;
29154
+ logger.warn(safeMsg` Rollback: Keeping created resource ${shownLogicalId(op.logicalId)} (${refusalResourceType(op.resourceType)}) ` + safeMsg`\u2014 ${why}. The failed deploy may have adopted a resource that existed under its name, so the rollback does not delete it; the rollback journal keeps it.` + (retry === void 0 ? "" : safeMsg` Once S3 can be read, finish the rollback with: ${retry}`));
29155
+ recordRollbackSkip(scope, op, "Another state record holds this resource, or it could not be checked, so the rollback did not delete it.");
29156
+ return true;
29157
+ }
28283
29158
  function effectiveProvisionedBy(record, fallbackProvisionedBy) {
28284
29159
  return record?.provisionedBy ?? fallbackProvisionedBy;
28285
29160
  }
@@ -30644,6 +31519,7 @@ async function replayDelete(s) {
30644
31519
  skipUnaddressableReplay(s, logger, op, "delete created resource");
30645
31520
  return;
30646
31521
  }
31522
+ if (await keptForAnotherHolder(s, logger, op, op.physicalId)) return;
30647
31523
  s.createRollbackRoute = deleteProvisionedBy;
30648
31524
  const snapshotPolicy = action === "delete-with-final-snapshot";
30649
31525
  const takeFinalSnapshot = snapshotPolicy && ctx.skipFinalSnapshot !== true;
@@ -31440,6 +32316,10 @@ async function replayFailedOperationsUnbound(failedOps, stateResources, stackNam
31440
32316
  skipUnaddressableReplay(skipScope, logger, op, "delete partially-created resource", failedCreateRecord ? "record" : "journal");
31441
32317
  break;
31442
32318
  }
32319
+ if (await keptForAnotherHolder(skipScope, logger, op, op.physicalId)) {
32320
+ pending.add(op);
32321
+ break;
32322
+ }
31443
32323
  const orphanDeleteChecked = op.physicalIdRecoveredFromError === true && ctx.foreignHolder !== void 0 && ctx.orphanDeleteProven?.has(op) !== true;
31444
32324
  if (orphanDeleteChecked) {
31445
32325
  const verdict = await journaledOrphanKeepReason({
@@ -32636,7 +33516,16 @@ async function performRollback(completedOperations, stateResources, stackName, p
32636
33516
  operations: completedOperations,
32637
33517
  failedOperations: orphanOps
32638
33518
  }], priorOrphans);
32639
- const ctx = this.rollbackExecutorContext(previousState, stackName);
33519
+ const crossPrefixHolder = this.options.crossPrefixHolder;
33520
+ let crossPrefixAnswer;
33521
+ const ctx = {
33522
+ ...this.rollbackExecutorContext(previousState, stackName),
33523
+ createdResourceRetryCommand: pasteableCommand("cdkd rollback", [{
33524
+ value: (this.options.parentStackInfo?.parentStack ?? stackName).split("~")[0],
33525
+ hole: "stack"
33526
+ }], recoveryCommandFlags(this.options.refusalRecovery).flags).command,
33527
+ createdResourceHolder: crossPrefixHolder === void 0 ? void 0 : () => crossPrefixAnswer ??= crossPrefixHolder(stackName)
33528
+ };
32640
33529
  const inlinePolicyWriters = new RollbackInlinePolicyWriters();
32641
33530
  const runId = this.options.eventRecorder?.runId;
32642
33531
  const { result, failed, run } = await withNestedRevertRun(runId, async (scope) => {
@@ -32666,6 +33555,21 @@ async function performRollback(completedOperations, stateResources, stackName, p
32666
33555
  remainingFailedOps: failedOperations.filter((_, i) => !handled.has(i))
32667
33556
  };
32668
33557
  }
33558
+ function foreignHolderResolver(engine) {
33559
+ const sameBucketHolderFor = makeForeignHolderScan(engine.stateBackend);
33560
+ const crossPrefixHolder = engine.options.crossPrefixHolder;
33561
+ const crossPrefixAnswers = /* @__PURE__ */ new Map();
33562
+ return (self) => async (resourceType, physicalId) => {
33563
+ const held = await sameBucketHolderFor(self)(resourceType, physicalId);
33564
+ if (held !== void 0 || crossPrefixHolder === void 0) return held;
33565
+ let answer = crossPrefixAnswers.get(self.stackName);
33566
+ if (answer === void 0) {
33567
+ answer = crossPrefixHolder(self.stackName);
33568
+ crossPrefixAnswers.set(self.stackName, answer);
33569
+ }
33570
+ return answer;
33571
+ };
33572
+ }
32669
33573
  async function settleJournalAfterSuccess(stackName, completedOperations, previousState, finalResources, initialDeploy) {
32670
33574
  if (this.options.parentStackInfo) {
32671
33575
  await this.writeRollbackJournalSegment(stackName, completedOperations, [], NESTED_PENDING_PARENT_REASON, initialDeploy, nestedPendingSnapshot(previousState, (name) => {
@@ -32677,7 +33581,7 @@ async function settleJournalAfterSuccess(stackName, completedOperations, previou
32677
33581
  return 0;
32678
33582
  }
32679
33583
  let nestedLeft = 0;
32680
- const foreignHolderFor = makeForeignHolderScan(this.stateBackend);
33584
+ const foreignHolderFor = foreignHolderResolver(this);
32681
33585
  const deployRunId = this.options.eventRecorder?.runId;
32682
33586
  const stripOnFailure = /* @__PURE__ */ new Map();
32683
33587
  const [ownLeft] = await Promise.all([(async () => {
@@ -34197,6 +35101,13 @@ async function provisionCreate(logicalId, change, stateResources, stackName, tem
34197
35101
  });
34198
35102
  const createProvider = createDecision.provider;
34199
35103
  const createProps = createDecision.provisionedBy === "cc-api" ? this.preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) : resolvedProps;
35104
+ await refuseUnlicensedGeneratedName.call(this, {
35105
+ logicalId,
35106
+ resourceType,
35107
+ stackName,
35108
+ createdVia: createDecision.provisionedBy,
35109
+ resolvedProps
35110
+ });
34200
35111
  await refuseTakenCreateName.call(this, {
34201
35112
  logicalId,
34202
35113
  resourceType,
@@ -34207,7 +35118,15 @@ async function provisionCreate(logicalId, change, stateResources, stackName, tem
34207
35118
  secrets: createSecrets,
34208
35119
  stateResources
34209
35120
  });
34210
- const result = await this.withRetry(() => withCurrentResourceSecrets(createSecrets, () => createProvider.create(logicalId, resourceType, createProps, { maskSecrets: createSecretMasker(createSecrets) })), logicalId, void 0, void 0, createProvider);
35121
+ this.generatedNameGuard?.noteSent(logicalId);
35122
+ let result;
35123
+ try {
35124
+ result = await this.withRetry(() => withCurrentResourceSecrets(createSecrets, () => createProvider.create(logicalId, resourceType, createProps, { maskSecrets: createSecretMasker(createSecrets) })), logicalId, void 0, void 0, createProvider);
35125
+ } catch (error) {
35126
+ this.generatedNameGuard?.noteFailed(logicalId, error);
35127
+ throw error;
35128
+ }
35129
+ this.generatedNameGuard?.noteReturned(logicalId);
34211
35130
  this.registerNoEchoAttributes(logicalId, result, createSecrets, resolvedProps);
34212
35131
  const dependencies = this.extractAllDependencies(template, logicalId);
34213
35132
  const templateAttrs = this.extractTemplateAttributes(template, logicalId);
@@ -34235,6 +35154,46 @@ async function provisionCreate(logicalId, change, stateResources, stackName, tem
34235
35154
  renderer.removeTask(logicalId);
34236
35155
  this.logger.info(`${createPrefix}${formatResourceLine("created", logicalId, resourceType)}`);
34237
35156
  }
35157
+ async function refuseUnlicensedGeneratedName(input) {
35158
+ const { logicalId, resourceType } = input;
35159
+ const asked = this.generatedNameGuard?.candidate(logicalId);
35160
+ if (asked === void 0 || input.createdVia === "cc-api") return;
35161
+ const verdict = await this.generatedNameGuard.admit(logicalId, input.resolvedProps);
35162
+ if (verdict === void 0) return;
35163
+ const subject = `${displaySafe(logicalId)} (${displaySafe(resourceType)})`;
35164
+ const named = `the cdkd-generated ${asked.property ?? "name"} ${displaySafe(asked.name)}`;
35165
+ const adoptsText = "its create API hands back or overwrites an existing resource of that name instead of refusing it";
35166
+ const refuse = (message) => {
35167
+ throw markNonRetryable(markRefusedBeforeApplying(new CdkdError(message, "GENERATED_NAME_HELD")));
35168
+ };
35169
+ switch (verdict.kind) {
35170
+ case "free":
35171
+ case "licensed": return;
35172
+ case "unchecked":
35173
+ this.logger.warn(safeMsg`${subject} is created with ${named} without checking whether another resource already ` + safeMsg`holds it: the lookup was refused (${describeAwsFailure(verdict.error).summary}). ` + "Grant this identity the type's Describe / List permission to have cdkd refuse taking over another deployment's resource.");
35174
+ return;
35175
+ case "failed":
35176
+ if (isInterruptedWaitError(verdict.error)) throw verdict.error;
35177
+ return refuse(`${subject} is created with ${named}, and ${adoptsText}, but cdkd could not check whether another resource already holds it (${describeAwsFailure(verdict.error).summary}). ${displaySafe(logicalId)} was not created. Re-run the deploy once the check can succeed.`);
35178
+ case "held": {
35179
+ const nested = input.stackName.includes("~");
35180
+ const top = input.stackName.split("~")[0];
35181
+ const importLine = nested ? `adopt it through the top-level stack ${quotedOrDescribed(top, "stack name")} with \`cdkd import\`` : `adopt it with \`${pasteableCommand("cdkd import", [{
35182
+ value: input.stackName,
35183
+ hole: "stack"
35184
+ }, {
35185
+ flag: "--resource",
35186
+ value: `${logicalId}=${verdict.holder}`,
35187
+ hole: "logicalId=physicalId"
35188
+ }], recoveryCommandFlags(this.options.refusalRecovery).flags).command}\``;
35189
+ if (verdict.ownIntent !== void 0) {
35190
+ const why = verdict.ownIntent === "abandoned" ? "a deploy of this stack that was killed or force-unlocked" : "a create of this stack that came back failed (a timeout or a server error)";
35191
+ return refuse(`${subject} would be created with ${named}, which an existing resource (${displaySafe(verdict.holder)}) already holds. This stack's create-token ledger records that ${why} sent this name, but this type reports no creation time, so cdkd cannot tell that resource is the one it made rather than another deployment's created since. Since ${adoptsText}, creating it would take that resource over. ${displaySafe(logicalId)} was not created. The likely cause: the resource is this stack's own, from that deploy. If it is, ${importLine} and re-run; if it is not, this stack is also deployed under another state backend (go-to-k/cdkd#4705).`);
35192
+ }
35193
+ return refuse(`${subject} would be created with ${named}, which an existing resource (${displaySafe(verdict.holder)}) already holds, and nothing this stack records names that resource: not its state, its rollback journal or create-token ledger, nor what a destroy of it under this state prefix kept. Since ${adoptsText}, creating it would take that resource over, as CloudFormation refuses with "already exists". ${displaySafe(logicalId)} was not created. The likely cause: this stack is also deployed under another state backend (another --state-prefix, --state-bucket or account), where cdkd generates the same names. One stack name per account and region is supported (go-to-k/cdkd#4705): deploy it under one backend only, or give this stack another name. If the resource is this stack's own, ${importLine} and re-run.`);
35194
+ }
35195
+ }
35196
+ }
34238
35197
  async function refuseTakenCreateName(input) {
34239
35198
  const { logicalId, resourceType, secrets } = input;
34240
35199
  const question = createNameQuestion({
@@ -37450,11 +38409,11 @@ const NESTED_STACK_TYPE$1 = "AWS::CloudFormation::Stack";
37450
38409
  async function requireDeploymentApproval(args) {
37451
38410
  const level = args.options.requireApproval ?? "never";
37452
38411
  const approve = args.options.approveDeployment;
37453
- if (level === "never" || approve === void 0) return;
38412
+ if (level === "never" || approve === void 0) return false;
37454
38413
  const changes = [...args.changes].filter((c) => c.changeType !== "NO_CHANGE" && !isNoEchoPromotionOnly(c));
37455
38414
  const destructiveChanges = findDestructiveChanges(args.stackName, changes, args.records, args.template, new Set(args.recreateTargetIds ?? []));
37456
38415
  const onlyNestedUpdates = changes.every((c) => c.changeType === "UPDATE" && c.resourceType === NESTED_STACK_TYPE$1);
37457
- if (!(level === "destructive" ? destructiveChanges.length > 0 : changes.length > 0 && !onlyNestedUpdates)) return;
38416
+ if (!(level === "destructive" ? destructiveChanges.length > 0 : changes.length > 0 && !onlyNestedUpdates)) return false;
37458
38417
  const count = (type) => changes.filter((c) => c.changeType === type).length;
37459
38418
  if (enclosingDeadlineExpired()) throw approvalAfterTimeout(args.stackName);
37460
38419
  let approved;
@@ -37473,6 +38432,16 @@ async function requireDeploymentApproval(args) {
37473
38432
  throw error instanceof Error ? markNonRetryable(error) : error;
37474
38433
  }
37475
38434
  if (!approved) throw markNonRetryable(new CdkdError(safeMsg`Deployment of stack ${args.stackName} was not approved (--require-approval=${level}). Nothing was changed.`, "DEPLOY_NOT_APPROVED"));
38435
+ return approve.autoApproves !== true;
38436
+ }
38437
+ async function checkDestructivePlan(args) {
38438
+ const hook = args.options.onDestructivePlan;
38439
+ if (hook === void 0) return;
38440
+ const changes = [...args.changes].filter((c) => c.changeType !== "NO_CHANGE" && !isNoEchoPromotionOnly(c));
38441
+ const destroying = findDestructiveChanges(args.stackName, changes, args.records, args.template, new Set(args.recreateTargetIds ?? [])).filter((c) => c.impact !== "WILL_ORPHAN");
38442
+ const nestedRowChanges = changes.some((c) => c.resourceType === NESTED_STACK_TYPE$1 && (c.changeType === "CREATE" || c.changeType === "UPDATE"));
38443
+ if (destroying.length === 0 && !nestedRowChanges) return;
38444
+ await hook(args.stackName, destroying);
37476
38445
  }
37477
38446
  async function approveLateReplacement(args) {
37478
38447
  const level = args.options.requireApproval ?? "never";
@@ -37480,7 +38449,7 @@ async function approveLateReplacement(args) {
37480
38449
  if (level === "never" || approve === void 0) return true;
37481
38450
  if (enclosingDeadlineExpired()) return false;
37482
38451
  try {
37483
- return await whileEnclosingDeadlinesPaused(() => approve({
38452
+ const approved = await whileEnclosingDeadlinesPaused(() => approve({
37484
38453
  stackName: args.stackName,
37485
38454
  level,
37486
38455
  counts: {
@@ -37490,6 +38459,8 @@ async function approveLateReplacement(args) {
37490
38459
  },
37491
38460
  destructiveChanges: findDestructiveChanges(args.stackName, [args.change], args.records, args.template)
37492
38461
  }));
38462
+ if (approve.autoApproves !== true) args.onAsked?.();
38463
+ return approved;
37493
38464
  } catch {
37494
38465
  return false;
37495
38466
  }
@@ -37836,27 +38807,42 @@ async function provisionUpdate(logicalId, change, stateResources, stackName, tem
37836
38807
  };
37837
38808
  let replacedAnyway = false;
37838
38809
  let lateApproval;
38810
+ let lateCrossPrefixRefused = false;
37839
38811
  const approveReplacementOf = (pc) => {
37840
38812
  if (replacedAnyway) return Promise.resolve(true);
37841
38813
  const { noEchoPromoted: _promoted, ...asReplacement } = pc;
37842
- lateApproval ??= approveLateReplacement({
37843
- options: this.options,
37844
- stackName,
37845
- change: {
37846
- ...change,
37847
- changeType: "UPDATE",
37848
- propertyChanges: [{
37849
- ...asReplacement,
37850
- requiresReplacement: true
37851
- }]
37852
- },
37853
- records: stateResources,
37854
- template
37855
- });
38814
+ const asChange = {
38815
+ ...change,
38816
+ changeType: "UPDATE",
38817
+ propertyChanges: [{
38818
+ ...asReplacement,
38819
+ requiresReplacement: true
38820
+ }]
38821
+ };
38822
+ lateApproval ??= (async () => {
38823
+ const crossPrefixGate = this.options.onDestructivePlan;
38824
+ if (crossPrefixGate !== void 0) try {
38825
+ await crossPrefixGate(stackName, findDestructiveChanges(stackName, [asChange], stateResources, template), "late");
38826
+ } catch (error) {
38827
+ if (!(error instanceof CdkdError) || error.code !== "STACK_UNDER_OTHER_STATE_PREFIX") throw error;
38828
+ lateCrossPrefixRefused = true;
38829
+ if (counts) counts.crossPrefixKept = (counts.crossPrefixKept ?? 0) + 1;
38830
+ this.logger.warn(error.message);
38831
+ return false;
38832
+ }
38833
+ return approveLateReplacement({
38834
+ options: this.options,
38835
+ stackName,
38836
+ change: asChange,
38837
+ records: stateResources,
38838
+ template,
38839
+ onAsked: () => this.generatedNameGuard?.noteApprovalPrompted()
38840
+ });
38841
+ })();
37856
38842
  return lateApproval;
37857
38843
  };
37858
38844
  const lateReplacementDeclined = /* @__PURE__ */ new Set();
37859
- const differsWhy = (key) => lateReplacementDeclined.has(key) ? `differs; the replacement was not approved (--require-approval=${this.options.requireApproval ?? "never"})` : "differs; the provider is not known to report this property exactly, so the difference may be its normalization";
38845
+ const differsWhy = (key) => !lateReplacementDeclined.has(key) ? "differs; the provider is not known to report this property exactly, so the difference may be its normalization" : lateCrossPrefixRefused ? "differs; the replacement was refused: see the state-prefix warning above" : `differs; the replacement was not approved (--require-approval=${this.options.requireApproval ?? "never"})`;
37860
38846
  if (unmarkedRecord && !typeChanged && echoCandidates.length > 0 && hasAddressablePhysicalId(currentResource)) await readOnce();
37861
38847
  if (!typeChanged && !suppliesFreshMaskOnlyValue && lostChild === void 0 && this.recreateDirectionFor(stackName, logicalId) === void 0 && recordMatchesDesired) {
37862
38848
  if (change.attributeChanges && change.attributeChanges.length > 0) {
@@ -38649,8 +39635,83 @@ async function updateInPlace({ conditions, counts, currentProps, currentPropsAsW
38649
39635
  this.logger.info(`${updatePrefix}${formatResourceLine("updated", logicalId, resourceType)}`);
38650
39636
  }
38651
39637
 
39638
+ //#endregion
39639
+ //#region src/deployment/retained-readoption.ts
39640
+ function keptForReadoption(resource) {
39641
+ if (!replacementCreateAdoptsName(resource.resourceType, resource.provisionedBy)) return false;
39642
+ if (typeof resource.physicalId !== "string" || resource.physicalId === "") return false;
39643
+ const property = explicitNamePropertyFor(resource.resourceType);
39644
+ const properties = resource.properties;
39645
+ return property === void 0 || !properties?.[property];
39646
+ }
39647
+ async function recordRetainedForReadoption(backend, stackName, region, kept, logger, earlier) {
39648
+ if (kept.length === 0) {
39649
+ try {
39650
+ await backend.ensureRetainedTombstone(stackName, region);
39651
+ } catch (error) {
39652
+ logger.warn(safeMsg`Could not write the empty kept-resource record of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}). Until one exists, a later deploy here may ` + `take back a resource an older cdkd kept; 'cdkd state orphan' writes it.`);
39653
+ }
39654
+ return;
39655
+ }
39656
+ try {
39657
+ const keptIds = new Set(kept.map((k) => k.logicalId));
39658
+ const before = await (earlier ?? backend.loadRetainedRecord(stackName, region)) ?? [];
39659
+ await backend.saveRetainedResources(stackName, region, [...before.filter((e) => !keptIds.has(e.logicalId)), ...kept]);
39660
+ } catch (error) {
39661
+ if (error instanceof RetainedTimeUnconfirmedError) {
39662
+ logger.warn(safeMsg`Recorded the ${String(kept.length)} kept resource(s) of ${displayStackName(stackName)} ` + safeMsg`a later deploy takes back by name, but their time could not be confirmed from S3 ` + safeMsg`(${describeAwsFailure(error.cause).summary}); they carry this machine's clock instead.`);
39663
+ return;
39664
+ }
39665
+ logger.warn(safeMsg`Could not record the ${String(kept.length)} kept resource(s) of ${displayStackName(stackName)} ` + safeMsg`a later deploy takes back by name (${describeAwsFailure(error).summary}). That deploy ` + `refuses to create them over the kept ones; adopt them with 'cdkd import' then.`);
39666
+ }
39667
+ }
39668
+ var KeptForReadoption = class {
39669
+ entries = [];
39670
+ earlier;
39671
+ inFlight;
39672
+ backend;
39673
+ stackName;
39674
+ region;
39675
+ logger;
39676
+ constructor(backend, stackName, region, logger) {
39677
+ this.backend = backend;
39678
+ this.stackName = stackName;
39679
+ this.region = region;
39680
+ this.logger = logger;
39681
+ }
39682
+ get size() {
39683
+ return this.entries.length;
39684
+ }
39685
+ add(entry) {
39686
+ this.entries.push(entry);
39687
+ if (this.earlier === void 0) {
39688
+ this.earlier = Promise.resolve().then(() => this.backend.loadRetainedRecord(this.stackName, this.region));
39689
+ this.earlier.catch(() => void 0);
39690
+ }
39691
+ }
39692
+ async flush() {
39693
+ if (this.inFlight !== void 0) await this.inFlight;
39694
+ if (this.entries.length === 0) return;
39695
+ const kept = this.entries;
39696
+ const earlier = this.earlier;
39697
+ this.entries = [];
39698
+ this.earlier = void 0;
39699
+ const write = recordRetainedForReadoption(this.backend, this.stackName, this.region, kept, this.logger, earlier);
39700
+ this.inFlight = write;
39701
+ try {
39702
+ await write;
39703
+ } finally {
39704
+ if (this.inFlight === write) this.inFlight = void 0;
39705
+ }
39706
+ }
39707
+ };
39708
+
38652
39709
  //#endregion
38653
39710
  //#region src/deployment/deploy-engine/delete.ts
39711
+ const keptByEngine = /* @__PURE__ */ new WeakMap();
39712
+ async function flushKeptForReadoption(engine) {
39713
+ await keptByEngine.get(engine)?.flush();
39714
+ }
38654
39715
  async function provisionDelete(logicalId, change, stateResources, stackName, template, counts, progress) {
38655
39716
  const resourceType = change.resourceType;
38656
39717
  const existingState = stateResources[logicalId];
@@ -38662,6 +39723,18 @@ async function provisionDelete(logicalId, change, stateResources, stackName, tem
38662
39723
  this.logger.info(`Retaining ${logicalId} (${resourceType}) - DeletionPolicy: ${deletionPolicy}`);
38663
39724
  delete stateResources[logicalId];
38664
39725
  await noteRetainedResource(resourceType, logicalId);
39726
+ if (keptForReadoption(currentResource)) {
39727
+ let kept = keptByEngine.get(this);
39728
+ if (kept === void 0) {
39729
+ kept = new KeptForReadoption(this.stateBackend, stackName, this.stackRegion, this.logger);
39730
+ keptByEngine.set(this, kept);
39731
+ }
39732
+ kept.add({
39733
+ logicalId,
39734
+ resourceType,
39735
+ physicalId: currentResource.physicalId
39736
+ });
39737
+ }
38665
39738
  return;
38666
39739
  }
38667
39740
  if (!(currentResource.resourceType === "AWS::CloudFormation::Stack" && currentResource.provisionedBy !== "cc-api") && !hasAddressablePhysicalId(currentResource)) {
@@ -39548,6 +40621,707 @@ function journaledOrphanPolicy(policy) {
39548
40621
  return policy === "Delete" || policy === "Retain" || policy === "Snapshot" || policy === "RetainExceptOnCreate" ? policy : "Retain";
39549
40622
  }
39550
40623
 
40624
+ //#endregion
40625
+ //#region src/provisioning/name-lookup.ts
40626
+ const inFlight = /* @__PURE__ */ new Map();
40627
+ const waiting = /* @__PURE__ */ new Map();
40628
+ async function withApiLimit(api, max, fn) {
40629
+ if ((inFlight.get(api) ?? 0) >= max) await new Promise((resolve) => {
40630
+ const queue = waiting.get(api) ?? [];
40631
+ queue.push(resolve);
40632
+ waiting.set(api, queue);
40633
+ });
40634
+ else inFlight.set(api, (inFlight.get(api) ?? 0) + 1);
40635
+ try {
40636
+ return await fn();
40637
+ } finally {
40638
+ const next = waiting.get(api)?.shift();
40639
+ if (next) next();
40640
+ else inFlight.set(api, (inFlight.get(api) ?? 1) - 1);
40641
+ }
40642
+ }
40643
+ function chunks(items, size) {
40644
+ const out = [];
40645
+ for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
40646
+ return out;
40647
+ }
40648
+ async function lookupEachName(names, api, concurrency, lookupOne) {
40649
+ const found = /* @__PURE__ */ new Map();
40650
+ await Promise.all(names.map((name) => withApiLimit(api, concurrency, async () => {
40651
+ const holder = await lookupOne(name);
40652
+ if (holder !== void 0) found.set(name, holder);
40653
+ })));
40654
+ return found;
40655
+ }
40656
+ function isAccessDeniedError(error) {
40657
+ const name = error?.name;
40658
+ const status = error?.$metadata?.httpStatusCode;
40659
+ return name === "AccessDenied" || name === "AccessDeniedException" || name === "AuthorizationError" || name === "UnauthorizedOperation" || status === 403;
40660
+ }
40661
+
40662
+ //#endregion
40663
+ //#region src/deployment/generated-name-guard.ts
40664
+ const GROUP_WINDOW_MS = 15;
40665
+ const DEFAULT_TIMING = {
40666
+ now: () => Date.now(),
40667
+ sleep: (ms) => new Promise((resolve) => {
40668
+ setTimeout(resolve, ms).unref?.();
40669
+ }),
40670
+ cooldownMs: 65e3,
40671
+ cooldownStepMs: 1e4
40672
+ };
40673
+ const STILL_LISTED_WHILE_DELETING = /* @__PURE__ */ new Set(["AWS::SQS::Queue", "AWS::S3::Bucket"]);
40674
+ const PER_NAME_CONCURRENCY = { "AWS::SNS::Topic": 4 };
40675
+ const DEFAULT_PER_NAME_CONCURRENCY = 10;
40676
+ const KEPT_AT_SKEW_MS = 6e4;
40677
+ function provenNothingCreated(error, logicalId, resourceType) {
40678
+ if (createdBeforeFailure(error, logicalId, resourceType) !== void 0) return false;
40679
+ if (isAmbiguousOutcomeError(error) || isThrottlingError(error)) return false;
40680
+ let current = error;
40681
+ for (let depth = 0; depth < 8 && current !== null && typeof current === "object"; depth++) {
40682
+ const status = current.$metadata?.httpStatusCode;
40683
+ if (typeof status === "number") return status >= 400 && status < 500 && status !== 408 && status !== 429;
40684
+ current = current.cause;
40685
+ }
40686
+ return false;
40687
+ }
40688
+ var GeneratedNameGuard = class GeneratedNameGuard {
40689
+ verdicts = /* @__PURE__ */ new Map();
40690
+ decidedAt = /* @__PURE__ */ new Map();
40691
+ candidates = /* @__PURE__ */ new Map();
40692
+ recorded = /* @__PURE__ */ new Set();
40693
+ sent = /* @__PURE__ */ new Set();
40694
+ returned = /* @__PURE__ */ new Set();
40695
+ rejected = /* @__PURE__ */ new Set();
40696
+ failedAt = /* @__PURE__ */ new Map();
40697
+ firstVerdicts = /* @__PURE__ */ new Map();
40698
+ plannedWrites;
40699
+ plannedIds = /* @__PURE__ */ new Set();
40700
+ groupPending = [];
40701
+ groupNext;
40702
+ groupInFlight = Promise.resolve();
40703
+ queued = [];
40704
+ flushing;
40705
+ writes = /* @__PURE__ */ new Set();
40706
+ evidenceRead;
40707
+ abandonedRead;
40708
+ historyRead;
40709
+ recordedRead;
40710
+ input;
40711
+ timing;
40712
+ constructor(input) {
40713
+ this.input = input;
40714
+ this.timing = {
40715
+ ...DEFAULT_TIMING,
40716
+ ...input.timing
40717
+ };
40718
+ }
40719
+ static start(input) {
40720
+ const candidates = [];
40721
+ for (const change of input.changes) {
40722
+ if (change.changeType !== "CREATE") continue;
40723
+ const properties = change.desiredProperties ?? {};
40724
+ let decision;
40725
+ let name;
40726
+ let deferred = false;
40727
+ try {
40728
+ decision = input.providerFor({
40729
+ resourceType: change.resourceType,
40730
+ properties
40731
+ });
40732
+ if (!replacementCreateAdoptsName(change.resourceType, decision.provisionedBy)) continue;
40733
+ name = decision.provider.generatedCreateName?.(change.resourceType, change.logicalId, properties);
40734
+ deferred = decision.provider.lookupNeedsResolvedProperties?.(change.resourceType, properties) === true;
40735
+ } catch {
40736
+ continue;
40737
+ }
40738
+ if (typeof name !== "string" || name === "") continue;
40739
+ candidates.push({
40740
+ logicalId: change.logicalId,
40741
+ resourceType: change.resourceType,
40742
+ name,
40743
+ property: explicitNamePropertyFor(change.resourceType),
40744
+ provider: decision.provider,
40745
+ properties,
40746
+ deferred
40747
+ });
40748
+ }
40749
+ if (candidates.length === 0) return void 0;
40750
+ const guard = new GeneratedNameGuard(input);
40751
+ for (const c of candidates) guard.candidates.set(c.logicalId, c);
40752
+ guard.ask(candidates.filter((c) => !c.deferred));
40753
+ return guard;
40754
+ }
40755
+ ask(candidates) {
40756
+ const { verdicts, first } = this.resolve(candidates);
40757
+ for (const [logicalId, verdict] of verdicts) this.verdicts.set(logicalId, verdict);
40758
+ for (const [logicalId, verdict] of first) this.firstVerdicts.set(logicalId, verdict);
40759
+ }
40760
+ resolve(candidates) {
40761
+ const out = /* @__PURE__ */ new Map();
40762
+ const first = /* @__PURE__ */ new Map();
40763
+ const byType = /* @__PURE__ */ new Map();
40764
+ for (const c of candidates) byType.set(c.resourceType, [...byType.get(c.resourceType) ?? [], c]);
40765
+ for (const group of byType.values()) {
40766
+ const decided = this.run(group).catch((error) => ({
40767
+ verdicts: new Map(group.map((c) => [c.logicalId, {
40768
+ kind: "failed",
40769
+ error
40770
+ }])),
40771
+ deleting: []
40772
+ }));
40773
+ let waited;
40774
+ for (const c of group) {
40775
+ first.set(c.logicalId, decided.then(({ verdicts }) => verdicts.get(c.logicalId) ?? { kind: "free" }));
40776
+ out.set(c.logicalId, decided.then(async ({ verdicts, deleting }) => {
40777
+ let verdict = verdicts.get(c.logicalId) ?? { kind: "free" };
40778
+ if (deleting.includes(c)) {
40779
+ waited ??= this.waitOutDeletion(deleting);
40780
+ verdict = (await waited).get(c.logicalId) ?? verdict;
40781
+ }
40782
+ this.decidedAt.set(c.logicalId, this.timing.now());
40783
+ return verdict;
40784
+ }));
40785
+ }
40786
+ }
40787
+ return {
40788
+ verdicts: out,
40789
+ first
40790
+ };
40791
+ }
40792
+ noteApprovalPrompted() {
40793
+ const stale = [...this.decidedAt.keys()].map((id) => this.candidates.get(id)).filter((c) => !c.deferred && !this.sent.has(c.logicalId));
40794
+ if (stale.length === 0) return;
40795
+ const previous = new Map(stale.map((c) => [c.logicalId, this.verdicts.get(c.logicalId)]));
40796
+ const { verdicts, first } = this.resolve(stale);
40797
+ const keepEarlier = (id, fresh, warn) => fresh.then(async (v) => {
40798
+ if (v.kind !== "failed" && v.kind !== "unchecked") return v;
40799
+ const earlier = await previous.get(id);
40800
+ if (earlier.kind !== "free" && earlier.kind !== "licensed") return v;
40801
+ if (warn) this.input.warn?.(`${displaySafe(id)}: could not re-read whether a resource holds its generated name after the approval prompt; acting on the earlier lookup.`);
40802
+ return earlier;
40803
+ });
40804
+ for (const [id, fresh] of verdicts) this.verdicts.set(id, keepEarlier(id, fresh, true));
40805
+ for (const [id, fresh] of first) this.firstVerdicts.set(id, keepEarlier(id, fresh, false));
40806
+ }
40807
+ recordPlannedIntents() {
40808
+ if (this.plannedWrites !== void 0) return;
40809
+ this.plannedWrites = /* @__PURE__ */ new Map();
40810
+ const byType = /* @__PURE__ */ new Map();
40811
+ for (const c of this.candidates.values()) {
40812
+ if (c.deferred) continue;
40813
+ byType.set(c.resourceType, [...byType.get(c.resourceType) ?? [], c]);
40814
+ }
40815
+ let typesWaiting = byType.size;
40816
+ let allArrived;
40817
+ const arrived = new Promise((resolve) => allArrived = resolve);
40818
+ const window = new Promise((resolve) => {
40819
+ setTimeout(resolve, GROUP_WINDOW_MS).unref?.();
40820
+ });
40821
+ this.groupInFlight = Promise.race([arrived, window]);
40822
+ const arrive = () => {
40823
+ typesWaiting--;
40824
+ if (typesWaiting === 0) allArrived();
40825
+ };
40826
+ for (const [resourceType, group] of byType) {
40827
+ const write = (async () => {
40828
+ let verdicts;
40829
+ try {
40830
+ verdicts = await Promise.all(group.map((c) => this.firstVerdicts.get(c.logicalId) ?? this.verdicts.get(c.logicalId)));
40831
+ } finally {
40832
+ arrive();
40833
+ }
40834
+ const batch = group.filter((_c, i) => verdicts[i].kind === "free" || verdicts[i].kind === "licensed");
40835
+ if (batch.length === 0) return;
40836
+ for (const c of batch) this.plannedIds.add(c.logicalId);
40837
+ await this.commitPlanned(batch);
40838
+ })();
40839
+ this.plannedWrites.set(resourceType, write);
40840
+ this.writes.add(write);
40841
+ write.catch(() => void 0);
40842
+ }
40843
+ }
40844
+ get size() {
40845
+ return this.candidates.size;
40846
+ }
40847
+ verdict(logicalId) {
40848
+ return this.verdicts.get(logicalId);
40849
+ }
40850
+ candidate(logicalId) {
40851
+ const c = this.candidates.get(logicalId);
40852
+ return c === void 0 ? void 0 : {
40853
+ name: c.name,
40854
+ property: c.property
40855
+ };
40856
+ }
40857
+ async admit(logicalId, resolvedProperties) {
40858
+ const c = this.candidates.get(logicalId);
40859
+ if (c === void 0) return void 0;
40860
+ if (c.deferred && !this.verdicts.has(logicalId)) this.ask([{
40861
+ ...c,
40862
+ properties: resolvedProperties,
40863
+ deferred: false
40864
+ }]);
40865
+ const verdict = await this.verdicts.get(logicalId);
40866
+ if (verdict.kind !== "free" && verdict.kind !== "licensed") return verdict;
40867
+ try {
40868
+ const planned = this.plannedWrites?.get(c.resourceType);
40869
+ if (planned !== void 0) try {
40870
+ await planned;
40871
+ } catch (error) {
40872
+ if (this.plannedIds.has(logicalId)) throw error;
40873
+ }
40874
+ await this.recordIntent(c);
40875
+ } catch (error) {
40876
+ return {
40877
+ kind: "failed",
40878
+ error
40879
+ };
40880
+ }
40881
+ return verdict;
40882
+ }
40883
+ noteSent(logicalId) {
40884
+ if (this.candidates.has(logicalId)) this.sent.add(logicalId);
40885
+ }
40886
+ noteReturned(logicalId) {
40887
+ if (this.candidates.has(logicalId)) this.returned.add(logicalId);
40888
+ }
40889
+ noteFailed(logicalId, error) {
40890
+ const c = this.candidates.get(logicalId);
40891
+ if (c === void 0) return;
40892
+ if (provenNothingCreated(error, logicalId, c.resourceType)) this.rejected.add(logicalId);
40893
+ else if (!this.failedAt.has(logicalId)) this.failedAt.set(logicalId, this.timing.now());
40894
+ }
40895
+ async settle() {
40896
+ await Promise.all([...this.writes].map((w) => w.catch(() => void 0)));
40897
+ const drop = [...this.recorded].filter((id) => !this.sent.has(id) || this.returned.has(id) || this.rejected.has(id));
40898
+ const failedAt = new Map([...this.failedAt].filter(([id]) => this.recorded.has(id) && !drop.includes(id)));
40899
+ if (drop.length === 0 && failedAt.size === 0) return;
40900
+ let lastError;
40901
+ for (let attempt = 0; attempt < 2; attempt++) try {
40902
+ await settleAdoptingCreates(drop, failedAt);
40903
+ return;
40904
+ } catch (error) {
40905
+ lastError = error;
40906
+ }
40907
+ const bounded = await noteAbandonedRun(this.timing.now());
40908
+ this.input.warn?.(safeMsg`Could not clear this deploy's unsent name-adopting creates from the stack's create-token ledger (${describeAwsFailure(lastError).summary}). ` + (bounded ? "They license only what existed by now; a later deploy may refuse a resource of those names, which `cdkd import` adopts." : "Nor could the ledger record when this deploy ended: a later deploy may take back a resource of those names that another deployment creates. They are cleared by the next successful deploy."));
40909
+ }
40910
+ async readoptedFromRetained() {
40911
+ const out = [];
40912
+ for (const [logicalId, verdict] of this.verdicts) {
40913
+ if (!this.returned.has(logicalId)) continue;
40914
+ const v = await verdict;
40915
+ if (v.kind === "licensed" && (v.via === "retained" || v.via === "history")) out.push(logicalId);
40916
+ }
40917
+ return out;
40918
+ }
40919
+ recordIntent(c) {
40920
+ if (this.recorded.has(c.logicalId)) return Promise.resolve();
40921
+ this.queued.push(c);
40922
+ if (this.flushing === void 0) {
40923
+ const flush = new Promise((resolve) => setImmediate(resolve)).then(async () => {
40924
+ const batch = this.queued;
40925
+ this.queued = [];
40926
+ if (this.flushing === flush) this.flushing = void 0;
40927
+ await this.writeIntents(batch);
40928
+ });
40929
+ this.flushing = flush;
40930
+ this.writes.add(flush);
40931
+ }
40932
+ return this.flushing;
40933
+ }
40934
+ commitPlanned(batch) {
40935
+ this.groupPending.push(...batch);
40936
+ if (this.groupNext === void 0) {
40937
+ const next = this.groupInFlight.then(() => void 0, () => void 0).then(async () => {
40938
+ const carried = this.groupPending;
40939
+ this.groupPending = [];
40940
+ this.groupNext = void 0;
40941
+ await this.writeIntents(carried);
40942
+ });
40943
+ this.groupNext = next;
40944
+ this.groupInFlight = next;
40945
+ }
40946
+ return this.groupNext;
40947
+ }
40948
+ async writeIntents(batch) {
40949
+ await recordAdoptingCreates(batch.map((b) => ({
40950
+ logicalId: b.logicalId,
40951
+ resourceType: b.resourceType,
40952
+ name: b.name
40953
+ })));
40954
+ for (const b of batch) this.recorded.add(b.logicalId);
40955
+ }
40956
+ recordedIntents() {
40957
+ this.recordedRead ??= recordedAdoptingCreates();
40958
+ return this.recordedRead;
40959
+ }
40960
+ async run(candidates) {
40961
+ const input = this.input;
40962
+ const out = /* @__PURE__ */ new Map();
40963
+ const recorded = this.recordedIntents().then((r) => ({
40964
+ ok: true,
40965
+ value: r
40966
+ }), (error) => ({
40967
+ ok: false,
40968
+ error
40969
+ }));
40970
+ const { found, typeFailures } = await lookupAll(input, candidates);
40971
+ let evidence;
40972
+ if (found.size > 0) {
40973
+ this.evidenceRead ??= loadEvidence(input);
40974
+ evidence = await this.evidenceRead.catch((error) => ({ error }));
40975
+ }
40976
+ const recordedResult = await recorded;
40977
+ const unlicensed = [];
40978
+ for (const c of candidates) {
40979
+ const failure = typeFailures.get(c.resourceType);
40980
+ if (failure !== void 0) {
40981
+ out.set(c.logicalId, isAccessDeniedError(failure) ? {
40982
+ kind: "unchecked",
40983
+ error: failure
40984
+ } : {
40985
+ kind: "failed",
40986
+ error: failure
40987
+ });
40988
+ continue;
40989
+ }
40990
+ const holder = found.get(c.logicalId);
40991
+ if (holder === void 0) {
40992
+ out.set(c.logicalId, { kind: "free" });
40993
+ continue;
40994
+ }
40995
+ if (!recordedResult.ok) {
40996
+ out.set(c.logicalId, {
40997
+ kind: "failed",
40998
+ error: recordedResult.error
40999
+ });
41000
+ continue;
41001
+ }
41002
+ const intent = recordedResult.value?.get(c.logicalId);
41003
+ let ownIntent;
41004
+ if (intent !== void 0 && intent.resourceType === c.resourceType && intent.name === c.name) {
41005
+ const abandonedAt = await this.abandonedRunAt();
41006
+ const byIntent = await this.licenseIfCreatedAfterIntent(c, holder, intent, abandonedAt !== void 0 && intent.firstSentAt <= abandonedAt ? abandonedAt : void 0);
41007
+ if (byIntent.kind !== "held") {
41008
+ out.set(c.logicalId, byIntent);
41009
+ continue;
41010
+ }
41011
+ ownIntent = byIntent.ownIntent;
41012
+ }
41013
+ if (evidence === void 0 || "error" in evidence) {
41014
+ out.set(c.logicalId, {
41015
+ kind: "failed",
41016
+ error: evidence !== void 0 && "error" in evidence ? evidence.error : /* @__PURE__ */ new Error("no evidence")
41017
+ });
41018
+ continue;
41019
+ }
41020
+ const named = evidence.namedBy(c.resourceType, holder);
41021
+ if (named !== void 0) {
41022
+ out.set(c.logicalId, await this.licenseIfKeptBefore(c, holder, named));
41023
+ if (out.get(c.logicalId).kind === "held") unlicensed.push(c);
41024
+ continue;
41025
+ }
41026
+ out.set(c.logicalId, {
41027
+ kind: "held",
41028
+ holder,
41029
+ ...ownIntent && { ownIntent }
41030
+ });
41031
+ unlicensed.push(c);
41032
+ }
41033
+ if (unlicensed.length > 0 && input.loadKeptInHistory !== void 0 && evidence !== void 0 && !("error" in evidence) && evidence.retainedAbsent) {
41034
+ let kept;
41035
+ try {
41036
+ this.historyRead ??= input.loadKeptInHistory();
41037
+ kept = await this.historyRead;
41038
+ } catch {
41039
+ kept = [];
41040
+ }
41041
+ for (const c of [...unlicensed]) {
41042
+ const holder = found.get(c.logicalId);
41043
+ const match = kept.find((k) => k.logicalId === c.logicalId && k.resourceType === c.resourceType && probeFoundSameId(c.resourceType, k.physicalId, holder));
41044
+ if (match === void 0) continue;
41045
+ const verdict = await this.licenseIfKeptBefore(c, holder, {
41046
+ via: "history",
41047
+ ...match.keptAt !== void 0 && { keptAt: match.keptAt }
41048
+ });
41049
+ out.set(c.logicalId, verdict);
41050
+ if (verdict.kind !== "held") unlicensed.splice(unlicensed.indexOf(c), 1);
41051
+ }
41052
+ }
41053
+ return {
41054
+ verdicts: out,
41055
+ deleting: unlicensed.filter((c) => STILL_LISTED_WHILE_DELETING.has(c.resourceType))
41056
+ };
41057
+ }
41058
+ async licenseIfKeptBefore(c, holder, named) {
41059
+ const licensed = {
41060
+ kind: "licensed",
41061
+ holder,
41062
+ via: named.via
41063
+ };
41064
+ if (named.via !== "retained" && named.via !== "history" || named.keptAt === void 0) return licensed;
41065
+ if (c.provider.holderCreatedAt === void 0) return licensed;
41066
+ let createdAt;
41067
+ try {
41068
+ createdAt = await withSkipPrefix(true, () => c.provider.holderCreatedAt(c.resourceType, holder));
41069
+ } catch (error) {
41070
+ if (!isAccessDeniedError(error)) return {
41071
+ kind: "failed",
41072
+ error
41073
+ };
41074
+ this.creationTimeDenied(c, holder, error);
41075
+ return licensed;
41076
+ }
41077
+ if (createdAt === void 0 || createdAt <= named.keptAt + KEPT_AT_SKEW_MS) return licensed;
41078
+ return {
41079
+ kind: "held",
41080
+ holder
41081
+ };
41082
+ }
41083
+ async licenseIfCreatedAfterIntent(c, holder, intent, abandonedAt) {
41084
+ const licensed = {
41085
+ kind: "licensed",
41086
+ holder,
41087
+ via: "ledger"
41088
+ };
41089
+ const held = {
41090
+ kind: "held",
41091
+ holder
41092
+ };
41093
+ const byName = abandonedAt !== void 0 ? {
41094
+ kind: "held",
41095
+ holder,
41096
+ ownIntent: "abandoned"
41097
+ } : intent.failedAt !== void 0 ? {
41098
+ kind: "held",
41099
+ holder,
41100
+ ownIntent: "failed"
41101
+ } : licensed;
41102
+ if (c.provider.holderCreatedAt === void 0) return byName;
41103
+ let createdAt;
41104
+ try {
41105
+ createdAt = await withSkipPrefix(true, () => c.provider.holderCreatedAt(c.resourceType, holder));
41106
+ } catch (error) {
41107
+ if (!isAccessDeniedError(error)) return {
41108
+ kind: "failed",
41109
+ error
41110
+ };
41111
+ this.creationTimeDenied(c, holder, error);
41112
+ return byName;
41113
+ }
41114
+ if (createdAt === void 0) return byName;
41115
+ const { firstSentAt, failedAt } = intent;
41116
+ if (Number.isFinite(firstSentAt) && createdAt < firstSentAt - KEPT_AT_SKEW_MS) return held;
41117
+ for (const until of [abandonedAt, failedAt]) if (until !== void 0 && createdAt > until + KEPT_AT_SKEW_MS) return held;
41118
+ return licensed;
41119
+ }
41120
+ creationTimeDenied(c, holder, error) {
41121
+ this.input.warn?.(safeMsg`${c.logicalId}: could not read when ${holder} was created (${describeAwsFailure(error).summary}); ` + "deciding by its name alone, as for a type that reports no creation time. Grant the type's Describe permission to narrow that.");
41122
+ }
41123
+ async abandonedRunAt() {
41124
+ this.abandonedRead ??= ledgerAbandonedAt().catch(() => void 0).then((fromLedger) => {
41125
+ const at = [fromLedger, this.input.abandonedRunAt].filter((v) => typeof v === "number" && Number.isFinite(v));
41126
+ return at.length > 0 ? Math.max(...at) : void 0;
41127
+ });
41128
+ return this.abandonedRead;
41129
+ }
41130
+ async waitOutDeletion(candidates) {
41131
+ const out = /* @__PURE__ */ new Map();
41132
+ let pending = [...candidates];
41133
+ const until = this.timing.now() + this.timing.cooldownMs;
41134
+ const watch = startInterruptWatch("generated-name deletion cooldown");
41135
+ try {
41136
+ while (pending.length > 0 && this.timing.now() < until) {
41137
+ await this.sleepUnlessInterrupted(this.timing.cooldownStepMs, watch);
41138
+ if (watch.isInterrupted()) {
41139
+ for (const c of pending) out.set(c.logicalId, {
41140
+ kind: "failed",
41141
+ error: watch.onInterrupted()
41142
+ });
41143
+ return out;
41144
+ }
41145
+ const { found, typeFailures } = await lookupAll(this.input, pending);
41146
+ pending = pending.filter((c) => {
41147
+ if (typeFailures.has(c.resourceType)) return true;
41148
+ if (found.has(c.logicalId)) return true;
41149
+ out.set(c.logicalId, { kind: "free" });
41150
+ return false;
41151
+ });
41152
+ }
41153
+ return out;
41154
+ } finally {
41155
+ watch.dispose();
41156
+ }
41157
+ }
41158
+ sleepUnlessInterrupted(ms, watch) {
41159
+ if (watch.isInterrupted()) return Promise.resolve();
41160
+ let timer;
41161
+ const interrupted = new Promise((resolve) => {
41162
+ timer = setInterval(() => {
41163
+ if (watch.isInterrupted()) resolve();
41164
+ }, 200);
41165
+ timer.unref?.();
41166
+ });
41167
+ return Promise.race([this.timing.sleep(ms), interrupted]).finally(() => clearInterval(timer));
41168
+ }
41169
+ };
41170
+ function isPermanentRedirect(error) {
41171
+ const e = error;
41172
+ return e?.name === "PermanentRedirect" || e?.$metadata?.httpStatusCode === 301 || e?.$response?.statusCode === 301;
41173
+ }
41174
+ async function lookupAll(input, candidates) {
41175
+ const byType = /* @__PURE__ */ new Map();
41176
+ for (const c of candidates) byType.set(c.resourceType, [...byType.get(c.resourceType) ?? [], c]);
41177
+ const found = /* @__PURE__ */ new Map();
41178
+ const typeFailures = /* @__PURE__ */ new Map();
41179
+ await Promise.all([...byType].map(async ([resourceType, group]) => {
41180
+ try {
41181
+ const holders = await lookupType(input, resourceType, group);
41182
+ for (const c of group) {
41183
+ const holder = holders.get(c.name);
41184
+ if (holder !== void 0) found.set(c.logicalId, holder);
41185
+ }
41186
+ } catch (error) {
41187
+ typeFailures.set(resourceType, error);
41188
+ }
41189
+ }));
41190
+ return {
41191
+ found,
41192
+ typeFailures
41193
+ };
41194
+ }
41195
+ async function loadEvidence(input) {
41196
+ const [journal, retained] = await Promise.all([input.loadJournal(), input.loadRetained()]);
41197
+ const sources = [];
41198
+ for (const record of Object.values(input.records)) if (typeof record?.physicalId === "string") sources.push({
41199
+ via: "record",
41200
+ type: record.resourceType,
41201
+ id: record.physicalId
41202
+ });
41203
+ for (const orphan of input.orphans ?? []) {
41204
+ const s = orphan.state;
41205
+ if (typeof s?.physicalId === "string") sources.push({
41206
+ via: "orphan",
41207
+ type: s.resourceType,
41208
+ id: s.physicalId
41209
+ });
41210
+ }
41211
+ for (const segment of journal?.segments ?? []) for (const op of [...segment.operations ?? [], ...segment.failedOperations ?? []]) if (typeof op.physicalId === "string" && op.physicalId !== "") sources.push({
41212
+ via: "journal",
41213
+ type: op.resourceType,
41214
+ id: op.physicalId
41215
+ });
41216
+ for (const r of retained ?? []) sources.push({
41217
+ via: "retained",
41218
+ type: r.resourceType,
41219
+ id: r.physicalId,
41220
+ ...r.keptAt !== void 0 && { keptAt: r.keptAt }
41221
+ });
41222
+ return {
41223
+ retainedAbsent: retained === null,
41224
+ namedBy: (resourceType, holder) => {
41225
+ const hit = sources.find((s) => s.type === resourceType && probeFoundSameId(resourceType, s.id, holder));
41226
+ return hit === void 0 ? void 0 : {
41227
+ via: hit.via,
41228
+ ...hit.keptAt !== void 0 && { keptAt: hit.keptAt }
41229
+ };
41230
+ }
41231
+ };
41232
+ }
41233
+ async function lookupType(input, resourceType, group) {
41234
+ const provider = group[0].provider;
41235
+ const names = group.map((c) => c.name);
41236
+ return withSkipPrefix(true, async () => {
41237
+ if (provider.lookupNames !== void 0) return provider.lookupNames(resourceType, names, {
41238
+ region: input.region,
41239
+ stackName: input.stackName,
41240
+ propertiesByName: new Map(group.map((c) => [c.name, c.properties]))
41241
+ });
41242
+ const lookup = provider.import?.bind(provider);
41243
+ if (lookup === void 0) return /* @__PURE__ */ new Map();
41244
+ const byName = new Map(group.map((c) => [c.name, c]));
41245
+ const account = ["AWS::SNS::Topic", "AWS::StepFunctions::StateMachine"].includes(resourceType) ? await input.accountInfo() : void 0;
41246
+ const concurrency = PER_NAME_CONCURRENCY[resourceType] ?? DEFAULT_PER_NAME_CONCURRENCY;
41247
+ return lookupEachName(names, `${resourceType}:import`, concurrency, async (name) => {
41248
+ const c = byName.get(name);
41249
+ const arn = account !== void 0 ? createLookupArn(resourceType, name, account) : void 0;
41250
+ if (arn !== void 0 && "unbuildable" in arn) throw new Error(`cannot build the ARN ${resourceType} name ${name} would take`);
41251
+ let found;
41252
+ try {
41253
+ found = await lookup({
41254
+ logicalId: c.logicalId,
41255
+ resourceType,
41256
+ stackName: input.stackName,
41257
+ region: input.region,
41258
+ properties: c.property === void 0 ? c.properties : {
41259
+ ...c.properties,
41260
+ [c.property]: name
41261
+ },
41262
+ ...arn !== void 0 && { knownPhysicalId: arn.arn }
41263
+ });
41264
+ } catch (error) {
41265
+ if (resourceType === "AWS::S3::Bucket" && isPermanentRedirect(error)) return name;
41266
+ throw error;
41267
+ }
41268
+ return found?.physicalId;
41269
+ });
41270
+ });
41271
+ }
41272
+
41273
+ //#endregion
41274
+ //#region src/deployment/kept-in-history.ts
41275
+ function keptInEarlierRecords(records) {
41276
+ const out = [];
41277
+ for (const record of records) for (const [logicalId, raw] of Object.entries(record.resources)) {
41278
+ if (raw === null || typeof raw !== "object") continue;
41279
+ const r = raw;
41280
+ if (typeof r.resourceType !== "string" || typeof r.physicalId !== "string") continue;
41281
+ if (r.physicalId === "") continue;
41282
+ if (!shouldRetainResource(r.deletionPolicy)) continue;
41283
+ out.push({
41284
+ logicalId,
41285
+ resourceType: r.resourceType,
41286
+ physicalId: r.physicalId,
41287
+ ...record.writtenAt !== void 0 && { keptAt: record.writtenAt }
41288
+ });
41289
+ }
41290
+ return out;
41291
+ }
41292
+ function keptInEventHistory(runs, stackName) {
41293
+ const made = /* @__PURE__ */ new Map();
41294
+ const out = [];
41295
+ for (const events of runs) for (const e of events) {
41296
+ if (e.stackName !== stackName || typeof e.logicalId !== "string") continue;
41297
+ if (typeof e.resourceType !== "string") continue;
41298
+ if (e.eventType === "RESOURCE_SUCCEEDED" && (e.operation === "CREATE" || e.operation === "UPDATE") && typeof e.physicalId === "string" && e.physicalId !== "") made.set(e.logicalId, {
41299
+ resourceType: e.resourceType,
41300
+ physicalId: e.physicalId
41301
+ });
41302
+ else if (e.eventType === "RESOURCE_RETAINED") {
41303
+ const m = made.get(e.logicalId);
41304
+ if (m !== void 0 && m.resourceType === e.resourceType) {
41305
+ const keptAt = Date.parse(e.timestamp);
41306
+ out.push({
41307
+ logicalId: e.logicalId,
41308
+ ...m,
41309
+ ...Number.isFinite(keptAt) && { keptAt }
41310
+ });
41311
+ }
41312
+ }
41313
+ }
41314
+ return out;
41315
+ }
41316
+ async function loadKeptInHistory(sources, stackName, region) {
41317
+ const runsOf = stackName.split("~")[0];
41318
+ const [records, runs] = await Promise.all([sources.earlierStateResources(stackName, region).catch(() => []), (async () => {
41319
+ const listed = (await sources.listRuns(runsOf, region)).slice(0, 20);
41320
+ return (await Promise.all(listed.map((r) => sources.readRunEvents(runsOf, region, r.runId).catch(() => null)))).filter((e) => e !== null).reverse();
41321
+ })().catch(() => [])]);
41322
+ return [...keptInEarlierRecords(records), ...keptInEventHistory(runs, stackName)];
41323
+ }
41324
+
39551
41325
  //#endregion
39552
41326
  //#region src/provisioning/canonicalize-properties.ts
39553
41327
  function makeCanonicalizePropertiesFn(registry) {
@@ -40108,6 +41882,9 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40108
41882
  process.removeListener("SIGINT", sigintHandler);
40109
41883
  throw error;
40110
41884
  }
41885
+ let firstDeployStateGate;
41886
+ let firstDeploy = false;
41887
+ let failed = false;
40111
41888
  try {
40112
41889
  renderer.start();
40113
41890
  const currentStateData = await this.stateBackend.getState(stackName, this.stackRegion);
@@ -40131,7 +41908,14 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40131
41908
  refuseMalformedOrphanRecords(currentState, stackName, this.stackRegion, this.options.refusalRecovery);
40132
41909
  const migrationPending = currentStateData?.migrationPending ?? false;
40133
41910
  this.logger.debug(`Loaded current state: ${Object.keys(currentState.resources).length} resources`);
40134
- if (this.options.onCurrentStateLoaded) await this.options.onCurrentStateLoaded(stackName, currentStateData?.state);
41911
+ if (this.options.onCurrentStateLoaded) {
41912
+ const gate = this.options.onCurrentStateLoaded(stackName, currentStateData?.state);
41913
+ if (currentStateData === null || currentStateData === void 0) {
41914
+ firstDeployStateGate = gate;
41915
+ firstDeploy = true;
41916
+ gate.catch(() => void 0);
41917
+ } else await gate;
41918
+ }
40135
41919
  try {
40136
41920
  const loaded = await this.stateBackend.loadRollbackJournal(stackName, this.stackRegion);
40137
41921
  const journal = loaded && {
@@ -40262,6 +42046,11 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40262
42046
  conditions,
40263
42047
  forceStatefulRecreation: this.options.forceStatefulRecreation === true
40264
42048
  });
42049
+ if (firstDeployStateGate !== void 0) {
42050
+ const gate = firstDeployStateGate;
42051
+ firstDeployStateGate = void 0;
42052
+ await gate;
42053
+ }
40265
42054
  if (!this.diffCalculator.hasChanges(changes)) {
40266
42055
  this.logger.info("No changes detected. Stack is up to date.");
40267
42056
  let persistedOutputs = currentState.outputs ?? {};
@@ -40369,7 +42158,34 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40369
42158
  const readers = [...changes.values()].filter(isNoEchoPromotionOnly).length;
40370
42159
  this.logger.info(safeMsg`No changes detected in the template. Comparing ${String(readers)} resource(s) that read a NoEcho parameter with AWS.`);
40371
42160
  }
40372
- await requireDeploymentApproval({
42161
+ const abandonedRunAt = this.lockManager.abandonedRunEndedBy?.(stackName, this.stackRegion);
42162
+ if (abandonedRunAt !== void 0) await noteAbandonedRun(abandonedRunAt);
42163
+ this.generatedNameGuard = GeneratedNameGuard.start({
42164
+ stackName,
42165
+ region: this.stackRegion,
42166
+ changes: changes.values(),
42167
+ providerFor: (input) => this.providerRegistry.getProviderFor({
42168
+ ...input,
42169
+ quiet: true
42170
+ }),
42171
+ records: currentState.resources,
42172
+ orphans: currentState.orphans,
42173
+ loadJournal: () => this.stateBackend.loadRollbackJournal(stackName, this.stackRegion),
42174
+ loadRetained: () => this.stateBackend.loadRetainedRecord(stackName, this.stackRegion),
42175
+ loadKeptInHistory: () => {
42176
+ const reader = new DeploymentEventsReader(this.stateBackend);
42177
+ return loadKeptInHistory({
42178
+ earlierStateResources: (s, r) => this.stateBackend.earlierStateResources(s, r),
42179
+ listRuns: (s, r) => reader.listRuns(s, r),
42180
+ readRunEvents: (s, r, id) => reader.readRunEvents(s, r, id)
42181
+ }, stackName, this.stackRegion);
42182
+ },
42183
+ accountInfo: () => getAccountInfo(this.stackRegion),
42184
+ warn: (message) => this.logger.warn(message),
42185
+ ...abandonedRunAt !== void 0 && { abandonedRunAt }
42186
+ });
42187
+ if (this.generatedNameGuard !== void 0) this.logger.debug(safeMsg`Generated-name check: looking up ${String(this.generatedNameGuard.size)} planned create(s)`);
42188
+ await checkDestructivePlan({
40373
42189
  options: this.options,
40374
42190
  stackName,
40375
42191
  changes: changes.values(),
@@ -40377,6 +42193,15 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40377
42193
  template: effectiveTemplate,
40378
42194
  recreateTargetIds: recreateTargetIdsFor(this.options.recreateTargets, stackName)
40379
42195
  });
42196
+ if (await requireDeploymentApproval({
42197
+ options: this.options,
42198
+ stackName,
42199
+ changes: changes.values(),
42200
+ records: currentState.resources,
42201
+ template: effectiveTemplate,
42202
+ recreateTargetIds: recreateTargetIdsFor(this.options.recreateTargets, stackName)
42203
+ })) this.generatedNameGuard?.noteApprovalPrompted();
42204
+ this.generatedNameGuard?.recordPlannedIntents();
40380
42205
  this.resolver.resetPhysicalIdFallbackCount();
40381
42206
  const progress = {
40382
42207
  current: 0,
@@ -40384,16 +42209,29 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40384
42209
  };
40385
42210
  const { state: newState, actualCounts, completedOperations } = await withProducerRegions(() => this.producerRegionEvidence(currentState), () => this.executeDeployment(effectiveTemplate, currentState, changes, dag, executionLevels, stackName, outputsDigestSource, parameterValues, conditions, currentEtag, progress, migrationPending));
40386
42211
  await this.drainObservedCaptures(newState.resources);
40387
- const newEtag = await this.stateBackend.saveState(stackName, this.stackRegion, this.withParentInfo(conditionVerdicts ? {
42212
+ const [newEtag] = await Promise.all([this.stateBackend.saveState(stackName, this.stackRegion, this.withParentInfo(conditionVerdicts ? {
40388
42213
  ...newState,
40389
42214
  conditionVerdicts
40390
- } : newState));
42215
+ } : newState)), flushKeptForReadoption(this)]);
40391
42216
  this.logger.debug(`State saved (ETag: ${newEtag})`);
40392
- await forgetRecordedCreateTokens(Object.keys(newState.resources));
40393
- const [journaledOrphansLeft] = await Promise.all([this.settleJournalAfterSuccess(stackName, completedOperations, currentState, newState.resources, currentEtag === void 0), this.exportIndexStore ? this.exportIndexStore.updateForStack(stackName, this.stackRegion, importableOutputs({
40394
- ...newState,
40395
- outputs: this.redactOutputs(newState.outputs)
40396
- })) : Promise.resolve()]);
42217
+ const ledgerAndKeptCleanup = (async () => {
42218
+ await forgetRecordedCreateTokens(Object.keys(newState.resources));
42219
+ const readopted = await this.generatedNameGuard?.readoptedFromRetained() ?? [];
42220
+ if (readopted.length > 0) try {
42221
+ const kept = await this.stateBackend.loadRetainedResources(stackName, this.stackRegion);
42222
+ await this.stateBackend.saveRetainedResources(stackName, this.stackRegion, kept.filter((entry) => !readopted.includes(entry.logicalId)));
42223
+ } catch (error) {
42224
+ this.logger.debug(safeMsg`Could not clear re-adopted resources from the kept-resource record: ${describeAwsFailure(error).summary}`);
42225
+ }
42226
+ })();
42227
+ const [journaledOrphansLeft] = await Promise.all([
42228
+ this.settleJournalAfterSuccess(stackName, completedOperations, currentState, newState.resources, currentEtag === void 0),
42229
+ this.exportIndexStore ? this.exportIndexStore.updateForStack(stackName, this.stackRegion, importableOutputs({
42230
+ ...newState,
42231
+ outputs: this.redactOutputs(newState.outputs)
42232
+ })) : Promise.resolve(),
42233
+ ledgerAndKeptCleanup
42234
+ ]);
40397
42235
  const durationMs = Date.now() - startTime;
40398
42236
  const unchangedCount = this.diffCalculator.filterByType(changes, "NO_CHANGE").length + actualCounts.skipped;
40399
42237
  return {
@@ -40404,17 +42242,33 @@ async function doDeployWithPrefetch(stackName, template, createOnlyPrefetch) {
40404
42242
  deleteSkipped: actualCounts.deleteSkipped + journaledOrphansLeft,
40405
42243
  updatePartial: actualCounts.updatePartial,
40406
42244
  nestedUpdatePartial: actualCounts.nestedUpdatePartial,
42245
+ ...(actualCounts.crossPrefixKept ?? 0) > 0 && { crossPrefixKept: actualCounts.crossPrefixKept },
40407
42246
  unchanged: unchangedCount,
40408
42247
  durationMs,
40409
42248
  outputs: this.buildDisplayOutputs(template, this.redactOutputs(newState.outputs ?? {})),
40410
42249
  attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
40411
42250
  };
42251
+ } catch (error) {
42252
+ failed = true;
42253
+ if (firstDeployStateGate !== void 0) await firstDeployStateGate;
42254
+ throw error;
40412
42255
  } finally {
40413
42256
  try {
40414
42257
  renderer.stop();
40415
42258
  } catch {}
40416
42259
  process.removeListener("SIGINT", sigintHandler);
40417
42260
  this.observedCaptureTasks.clear();
42261
+ try {
42262
+ await flushKeptForReadoption(this);
42263
+ await this.generatedNameGuard?.settle();
42264
+ } catch {}
42265
+ if (firstDeploy && failed && this.options.onFirstDeployLeftNoRecord && !this.options.dryRun) try {
42266
+ const left = await this.stateBackend.getState(stackName, this.stackRegion);
42267
+ const journal = left === null ? await this.stateBackend.loadRollbackJournal(stackName, this.stackRegion) : void 0;
42268
+ if (left === null && !journalCanOwnResources(journal ?? null)) await this.options.onFirstDeployLeftNoRecord(stackName);
42269
+ } catch (error) {
42270
+ this.logger.debug(safeMsg`Could not check whether the failed first deploy left a record: ${describeAwsFailure(error).summary}`);
42271
+ }
40418
42272
  try {
40419
42273
  await this.lockManager.releaseLock(stackName, this.stackRegion);
40420
42274
  this.logger.debug("Lock released");
@@ -40668,6 +42522,7 @@ var DeployEngine = class {
40668
42522
  constructPathTemplate;
40669
42523
  outputsSourceUsable = true;
40670
42524
  attemptedResolvedProps = /* @__PURE__ */ new Map();
42525
+ generatedNameGuard;
40671
42526
  liveTaskLabels = /* @__PURE__ */ new Map();
40672
42527
  retainedOldOnReplacement = /* @__PURE__ */ new Set();
40673
42528
  recreatedUnderSameId = /* @__PURE__ */ new Set();
@@ -40725,6 +42580,7 @@ var DeployEngine = class {
40725
42580
  this.fingerprintChildTemplates = void 0;
40726
42581
  this.perResourceInputFingerprints = /* @__PURE__ */ new Map();
40727
42582
  this.attemptedResolvedProps = /* @__PURE__ */ new Map();
42583
+ this.generatedNameGuard = void 0;
40728
42584
  this.liveTaskLabels = /* @__PURE__ */ new Map();
40729
42585
  this.outputSecrets = /* @__PURE__ */ new Map();
40730
42586
  this.outputsPassSecretMaps = [];
@@ -40955,5 +42811,5 @@ DeployEngine.prototype.replacementNameOrigin = replacementNameOrigin;
40955
42811
  DeployEngine.prototype.orphanedNameCollisionAdvice = orphanedNameCollisionAdvice;
40956
42812
 
40957
42813
  //#endregion
40958
- export { gray as $, prefetchCreateOnlyPropertyPaths as $a, refuseMalformedOutputs as $i, tagPlanWarning as $n, wholeStringLeavesOf as $o, getAccountInfo as $r, partitionSensitiveEnv as $s, redactedDeleteAddressSkip as $t, perType as A, NO_CC_HANDLERS_REASON as Aa, decodeListingKey as Ac, malformedLocalResourceEntriesWarning as Ai, buildFinalSnapshotIdentifier as An, shareLogOnlyValues as Ao, poisonRenderedSpellingsCollidingIn as Ar, rewriteTemplateAssetReferences as As, awaitInFlightSibling as At, INDEX_SETTLE_POLL_INTERVAL_MS as B, isWarmThroughputDecrease as Ba, hasPlainPrototype$1 as Bc, malformedResourceEntriesWarning as Bi, formatDestructiveChange as Bn, isUncertifiedBaselineMaskPosition as Bo, AWS_CREDENTIAL_ENV_KEYS as Br, validateContainerRepoName as Bs, planRollback as Bt, noEchoComparisonForTemplate as C, unreadableOrphanRecords as Ca, ssmResolvedValueType as Cc, hasReadableResources as Ci, maskEventTextWithBoundBags as Cn, createUnionSecretMasker as Co, isTerminationProtectionPropagationError as Cr, AssetPublisher as Cs, isHandledOrphan as Ct, recordedProtectionNote as D, findSilentDropProperties as Da, findLargeInlineResources as Dc, malformedExportNamesWarning as Di, extractDeploymentEventError as Dn, printingCorpusOf as Do, DiffCalculator as Dr, buildAssetRedirectMap as Ds, sameJournaledOrphans as Dt, recordedProtectionEvidence as E, findActionableSilentDrops as Ea, MIGRATE_TMP_PREFIX as Ec, malformedDriftResourcePropertiesWarning as Ei, stateSecretNameNeedles as En, logOnlyValueCount as Eo, reEnableInstanceApiTermination as Er, WorkGraph as Es, makeForeignHolderScan as Et, compensateRemovedDeletionProtection as F, isStatefulRecreateTargetForReplace as Fa, AssemblyReader as Fc, malformedOrphansRefusalMessage as Fi, refusesFinalSnapshot as Fn, markSameGenerationBag as Fo, assertFlagRoleArn as Fr, getBootstrapMarkerKey as Fs, recordAfterRollbackUpdate as Ft, hasCdkAutoDeleteTag as G, configBooleanRefusal as Ga, displayAssemblyPath as Gc, previewableOrphanRecords as Gi, withCreateTokenLedger as Gn, recoverMaskedOutput as Go, s3BucketArn as Gr, describeDockerExecFailure as Gs, seedsDeleteFirstGuard as Gt, waitForIndexesSettled as H, toFiniteNumber as Ha, ownValue as Hc, malformedResourcesWarning as Hi, earliestDefined as Hn, identityKeyFor as Ho, callerEnvCredentials as Hr, buildDockerImage as Hs, recordUnderIdIsNotOwn as Ht, deleteBudgetKey as I, isStatefulRecreateTargetSync as Ia, StageLoadError as Ic, malformedOrphansWarning as Ii, unsupportedFinalSnapshotError as In, redactSecretsForState as Io, assertSendableRoleArn as Ir, isCrossRegionRedirect as Is, demoteSupersededOrphans as It, markRefusedBeforeApplying as J, readConfigString as Ja, clearBucketRegionCache as Jc, refuseMalformedOrphanRecords as Ji, DBPROXY_TAG_OPTIONS as Jn, recordMaskOnlyValue as Jo, s3BucketRegionalDomainName as Jr, finchSecretArgvRefusal as Js, getCurrentProducerRegions as Jt, isTruthyCfnBoolean as K, configIntegerRefusal as Ka, renderAssemblyPathEscape as Kc, refuseDivergentRecordRegionForDestroy as Ki, acquireIdempotencyToken as Kn, carriesSecretMask as Ko, s3BucketDomainName as Kr, describeDockerFailure as Ks, orphanDeleteNeedsIdentity as Kt, resolveDynamoDbDeleteBudgetClock as L, renderStatefulReason as La, processStackMessages as Lc, malformedOutputsRefusalMessage as Li, maskingRetryLogger as Ln, scrubResourceRecord as Lo, explicitRoleArnOrThrow as Lr, parseBootstrapMarker as Ls, isJournaledOrphan as Lt, DynamoDBGlobalTableProvider as M, findReplacedReadersOfRecreateTargets as Ma, PARTITION_TABLE as Mc, malformedOrphanRecordsRefusalMessage as Mi, createPreDeleteFinalSnapshot as Mn, errorCauseChain as Mo, producerRegionsFromState as Mr, BOOTSTRAP_MARKER_PREFIX as Ms, getStackRecords as Mt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as N, shownType as Na, canonicalizeRegion as Nc, malformedOrphanRecordsWarning as Ni, effectiveDeletionPolicy as Nn, maskSecretsInError as No, regionLessSecretName as Nr, assertAssetBucketRegion as Ns, withStackRecords as Nt, PROTECTION_PROPERTY_BY_TYPE as O, unwrittenCreateOnlyReplacement as Oa, uploadCfnTemplate as Oc, malformedExportSourceWarning as Oi, ATOMIC_FINAL_SNAPSHOT_TYPES as On, recordLogOnlyParameterValue as Oo, INTRINSIC_KEYS as Or, createAssetRedirectResolver as Os, replayFailedOperations as Ot, beginDeleteWait as P, MULTI_REGION_RECREATE_BLOCKED_TYPES as Pa, derivePartitionAndUrlSuffix as Pc, malformedOrphanRowsKeptWarning as Pi, isFinalSnapshotError as Pn, maskSecretsInText as Po, applyRoleArnIfSet as Pr, ensureAssetStorage as Ps, removeProtectionTypeList as Pt, cyan as Q, requireConfigString as Qa, refuseMalformedOrphansForOrphan as Qi, tagMapAsList as Qn, recordProvenPublicExpression as Qo, parameterTypeMayLoseSecretIdentity as Qr, isMalformedEnvKey as Qs, redactedDeleteAddressFields as Qt, resolveDynamoDbDeleteBudgetMs as R, WARM_THROUGHPUT_MEMBERS as Ra, defineOwnKey as Rc, malformedOutputsWarning as Ri, constructPathOf as Rn, DYNAMIC_REFERENCE_TOKEN_SCAN as Ro, isIamRoleArn as Rr, readBootstrapMarkerBody as Rs, isReplacementOrphan as Rt, noEchoAttributeNamesOf as S, unpreviewableOrphanRecords as Sa, warnDeprecatedNoPrefixCliFlag as Sc, hasReadableOutputs as Si, journaledOrphanPrintingBag as Sn, carryLogOnlyValues as So, ec2InstanceProtectionSite as Sr, shouldRetainResource as Ss, dropFailedHint as St, noEchoParameterNamesOf as T, withheldAccountClause as Ta, CFN_TEMPLATE_URL_LIMIT as Tc, isReadableResourceEntry as Ti, secretNamePrintingBag as Tn, literalSplitDelimitersOf as To, reDisableInstanceApiTermination as Tr, stringifyValue as Ts, loadJournaledOrphans as Tt, ECR_AUTO_DELETE_IMAGES_TAG as U, coerceCfnBoolean as Ua, absoluteAssemblyPathEscape as Uc, malformedScrubResourceEntriesRefusalMessage as Ui, ledgerForStack as Un, inheritNestedStackParameterAssociations as Uo, envCredentialsAreAssumedRole as Ur, resolveDockerContextDirectory as Us, replacementNeverSwapped as Ut, deleteTableWithIndexBusyRetry as V, toCfnInteger as Va, nullPrototypeRecord as Vc, malformedResourcePropertiesWarning as Vi, RollbackInlinePolicyWriters as Vn, pathCrossesDottedKey as Vo, applyCallerIdentityCredentials as Vr, buildDenyExternalAccessPolicy as Vs, recheckFailedPlan as Vt, S3_AUTO_DELETE_OBJECTS_TAG as W, coerceCfnInteger as Wa, describeFileReadFailure as Wc, malformedStateRefusalMessage as Wi, reserveStackCreateToken as Wn, recordNestedStackParameterExpressions as Wo, isSettledInstanceState as Wr, describeDockerCapturedOutput as Ws, resolveReplacementOldType as Wt, createReadOnlyAttributeHealerFactory as X, requireConfigArray as Xa, refuseMalformedOrphans as Xi, readTagList as Xn, recordNoEchoAttributeValues as Xo, coerceParameterTypedValue as Xr, getDockerCmd as Xs, REDACTED_DELETE_ADDRESS_SKIP_REASON as Xt, formatResourceLine as Y, replayWarn as Ya, resolveBucketRegion as Yc, refuseMalformedOrphanRecordsForDestroy as Yi, planTagDiff as Yn, recordMaskOnlyValuesIn as Yo, s3BucketWebsiteUrl as Yr, formatDockerLoginError as Ys, inheritProducerRegions as Yt, bold as Z, requireConfigObject as Za, refuseMalformedOrphansForDestroy as Zi, refuseMalformedDesiredTags as Zn, recordNoEchoParameterFreshValue as Zo, isUnboundTemplateParameter as Zr, isDockerClientEnvKey as Zs, isRedactedRecordedValue as Zt, makeCanonicalizePropertiesFn as _, repairMalformedOrphansForReadOnly as _a, resolveSkipPrefix as _c, UNREADABLE_RESOURCES_MAP_ROW as _i, isExportAliasCollision as _n, passedNoEchoParametersOf as _o, deleteSkipReason as _r, importableOutputKeys as _s, revertedNestedRowIds as _t, findNestedTemplateTreeDefect as a, refuseMalformedResourceEntriesForImport as aa, escapeRegExp$3 as ac, AWS_NO_VALUE as ai, displayTextOrWithheld as an, sameLambdaFunctionAddress as ao, isCustomResource as ar, isSingleDynamicReferenceToken as as, reachableDivergentParameters as at, serviceTokenBlockingReason as b, repairMalformedResourcePropertiesForReadOnly as ba, resolveUseCdkBootstrapAssets as bc, displayLogicalId as bi, DEFAULT_RESOURCE_WARN_AFTER_MS as bn, valueAtCoordinate as bo, markWaitAbandoned as br, orphansAfterRollback as bs, withNestedStackContext as bt, renderNestedTemplateTreeDefect as c, refuseMalformedResourcePropertiesForDestroy as ca, getDockerImageBySourceHash as cc, refStateLookupFromResource as ci, secretBearingStateKeyWarning as cn, canonicalCoordinates as co, readsNoEchoDeleteValues as cr, S3StateBackend as cs, planOrphanAdoption as ct, conditionInputsFrom as d, refuseMalformedResourcePropertiesForOrphan as da, getDefaultStateBucketName as dc, parameterInputsFor as di, exportNameNoEchoParameters as dn, maskReadbackAtCoordinates as do, withPrintingSecrets as dr, acceptedCreateOnlyDropsOf as ds, displacedPhysicalIdShown as dt, refuseMalformedOutputsForDestroy as ea, redactDockerArgvValues as ec, isImpossibleEmptyStoredAttribute as ei, updatePartialMessage as en, templateResourceTypes as eo, definedAttributes as er, STATE_SOURCED_BASELINE_RULES as es, green as et, parentSuppliedValues as f, refuseMalformedResourcesForDeploy as fa, getLegacyStateBucketName as fc, passedParameterClassesOf as fi, exportNameSecretExposure as fn, maskWholeValue as fo, CloudControlProvider as fr, describeRegionValueKind as fs, dropSettledNestedJournals as ft, mergeNoChangeOutputs as g, repairMalformedOrphanRecordsForReadOnly as ga, resolveCaptureObservedState as gc, UNREADABLE_ORPHANS_CONTAINER_ROW as gi, collectPublishedOutputNames as gn, noEchoOutputsComparison as go, deleteIndeterminateGuards as gr, hasUnverifiableParameterRefusal as gs, revertNestedChildFromJournal as gt, keptWholeReasonText as h, refuseMalformedState as ha, resolveAutoAssetStorage as hc, STATE_RESOURCES_MALFORMED as hi, collectDeclaredOutputNames as hn, noEchoLeavesOf as ho, UNSPECIFIED_SKIP_REASON as hr, hasReasonlessBaselineRefusal as hs, recordDisplacedSkips as ht, childTemplateLoader as i, refuseMalformedResourceEntriesForDestroy as ia, warnFinchArgvExposure as ic, keepsSecretReferenceToken as ii, WITHHELD_NAME_DISPLAY as in, lambdaFunctionNameForMask as io, ccBrokenReason as ir, WHOLE_DYNAMIC_REFERENCE_PATTERN as is, namesAnyDeclaredParameter as it, readProtection as j, hasNoCloudControlHandlers as ja, expectedOwnerParam as jc, malformedLocalResourcesWarning as ji, ccRoutedFinalSnapshotError as jn, createSecretMasker as jo, classifyReplaySecretRegion as jr, AssetModeResolver as js, destroyStackRecordsView as jt, isProtectionValueActive as k, withoutSilentDropProperties as ka, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as kc, malformedLocalOutputsWarning as ki, PRE_DELETE_SNAPSHOT_TYPES as kn, recordLogOnlyValue as ko, IntrinsicFunctionResolver as kr, loadPublishableAssetManifest as ks, replayRollback as kt, templateIdentity as l, refuseMalformedResourcePropertiesForDrift as la, Synthesizer as lc, parseWebACLArn as li, secretSafeKeyDisplay as ln, isMarkedCoordinate as lo, isCustomResourceType as lr, rebuildClientForBucketRegion as ls, NESTED_PENDING_PARENT_REASON as lt, isSecretBearingReferenceString as m, refuseMalformedResourcesForExport as ma, resolveApp as mc, STATE_REGION_DIVERGED as mi, noEchoParameterValueSeed as mn, noEchoCoordinatesOf as mo, unchangedBehindSecretReference as mr, hasReadableExportSet as ms, nestedChildStackName as mt, IMPLICIT_DELETE_DEPENDENCIES as n, refuseMalformedResourceEntries as na, runDockerForeground as nc, carriesFetchableDynamicReference as ni, DeploymentEventsReader as nn, withRetry as no, CC_BROKEN_REASON as nr, STATE_SOURCED_READBACK_RULES as ns, yellow as nt, isAbsoluteAssetPath as o, refuseMalformedResourceEntriesForImportSave as oa, stripControlChars as oc, cfnRefValueFromPhysicalId as oi, exportAliasCollisionScrubWarning as on, DagBuilder as oo, wouldReturnToSdkProvider as or, LockManager as os, resourcesNamingDeclaredParameter as ot, readRecordedConditionVerdicts as p, refuseMalformedResourcesForDestroy as pa, loadCdkJson as pc, JSON_LISTING_HOLE_VALUE as pi, isWholeDynamicReferenceValue as pn, maskedLeafCoordinatesOf as po, slowCcOperationTimeoutMs as pr, exportNamesCarriedFrom as ps, getNestedRevertRun as pt, getPriorAttempts as q, configStringRefusal as qa, resolveAssemblyPath as qc, refuseMalformedNestedChildOutputs as qi, DBPROXY_TAGS_WHAT as qn, provenPublicValue as qo, s3BucketDualStackDomainName as qr, dockerSpawnEnvWithSensitive as qs, findNestedStackTypeChanges as qt, computeImplicitDeleteEdges as r, refuseMalformedResourceEntriesForDeploy as ra, runDockerStreaming as rc, isNamelessDynamicReferenceError as ri, DeploymentEventsStore as rn, canonicalLambdaFunctionName as ro, ProviderRegistry as rr, TEMPLATE_SOURCED_RULES as rs, computeParameterTaint as rt, listNestedTemplateRows as s, refuseMalformedResourceEntriesForOrphan as sa, AssetManifestLoader as sc, isStalePlaceholderArnAttribute as si, secretBearing as sn, TemplateParser as so, TemplateNoEchoReresolver as sr, isLockInfoExpired as ss, makeSiblingClaimReader as st, DeployEngine as t, refuseMalformedResourceAttributesForOrphan as ta, redactedDockerCause as tc, carriesDynamicReference as ti, updatePartialReason as tn, describeTypeWithThrottleRetry as to, stringifyIfAssigned as tr, STATE_SOURCED_CROSS_GENERATION_RULES as ts, red as tt, conditionFingerprint as u, refuseMalformedResourcePropertiesForExport as ua, synthesisStatusMessage as uc, withSharedDrainBudget as ui, carriedExportAliasExposure as un, maskAtCoordinates as uo, getCurrentResourceSecrets as ur, splitImportedOps as us, displacedOpClause as ut, deferredServiceTokenWarning as v, repairMalformedOutputsForReadOnly as va, resolveStateBucketWithDefault as vc, accountArgs as vi, bindingSkippedOutputs as vn, readbackPathFor as vo, withIndeterminateGuard as vr, importableOutputs as vs, withNestedRevertRun as vt, noEchoExactEchoLeavesOf as w, unreadableResourceEntries as wa, CFN_TEMPLATE_BODY_LIMIT as wc, isReadableOrphanRecord as wi, orphanRecordsPrintingBag as wn, hasMaskableValues as wo, observeThenDisableInstanceApiTermination as wr, isSensitiveAttributeName as ws, journaledOrphanLines as wt, withResourceDeadline as x, repairMalformedResourcesForReadOnly as xa, stateBucketExistenceConfirmed as xc, hasReadableOrphans as xi, completedReplayEntries as xn, liveMatchesUnresolvedTokenFrame as xo, disableInstanceApiTermination as xr, orphansCarriedFrom as xs, deleteJournaledOrphans as xt, findServiceTokenRefusals as y, repairMalformedResourceEntriesForReadOnly as ya, resolveStateBucketWithDefaultAndSource as yc, deployRefusesOrphanRowsReason as yi, DEFAULT_RESOURCE_TIMEOUT_MS as yn, readsNoEchoSource as yo, isWaitAbandonedError as yr, isReadableBag as ys, getCurrentNestedStackContext as yt, DELETE_INDEX_WAIT_PROCEED_NOTE as z, coerceWarmThroughput as za, hasOwnKey as zc, malformedRenderedContainersWarning as zi, findDestructiveChanges as zn, dynamicReferenceTokens as zo, sendableAssumeRoleCommand as zr, validateAssetBucketName as zs, planFailedOps as zt };
40959
- //# sourceMappingURL=deploy-engine-D4FdwPCi.js.map
42814
+ export { getPriorAttempts as $, configStringRefusal as $a, nullPrototypeRecord as $c, refuseMalformedNestedChildOutputs as $i, DBPROXY_TAGS_WHAT as $n, provenPublicValue as $o, s3BucketDualStackDomainName as $r, buildDenyExternalAccessPolicy as $s, findNestedStackTypeChanges as $t, noEchoExactEchoLeavesOf as A, unreadableResourceEntries as Aa, resolveStateBucketWithDefault as Ac, isReadableOrphanRecord as Ai, orphanRecordsPrintingBag as An, hasMaskableValues as Ao, observeThenDisableInstanceApiTermination as Ar, importableOutputs as As, journaledOrphanLines as At, beginDeleteWait as B, MULTI_REGION_RECREATE_BLOCKED_TYPES as Ba, uploadCfnTemplate as Bc, malformedOrphanRowsKeptWarning as Bi, isFinalSnapshotError as Bn, maskSecretsInText as Bo, applyRoleArnIfSet as Br, createAssetRedirectResolver as Bs, removeProtectionTypeList as Bt, recordRetainedForReadoption as C, repairMalformedOrphansForReadOnly as Ca, getDefaultStateBucketName as Cc, UNREADABLE_RESOURCES_MAP_ROW as Ci, isExportAliasCollision as Cn, passedNoEchoParametersOf as Co, deleteSkipReason as Cr, acceptedCreateOnlyDropsOf as Cs, revertedNestedRowIds as Ct, withResourceDeadline as D, repairMalformedResourcesForReadOnly as Da, resolveAutoAssetStorage as Dc, hasReadableOrphans as Di, completedReplayEntries as Dn, liveMatchesUnresolvedTokenFrame as Do, disableInstanceApiTermination as Dr, hasReasonlessBaselineRefusal as Ds, deleteJournaledOrphans as Dt, serviceTokenBlockingReason as E, repairMalformedResourcePropertiesForReadOnly as Ea, resolveApp as Ec, displayLogicalId as Ei, DEFAULT_RESOURCE_WARN_AFTER_MS as En, valueAtCoordinate as Eo, markWaitAbandoned as Er, hasReadableExportSet as Es, withNestedStackContext as Et, isProtectionValueActive as F, withoutSilentDropProperties as Fa, ssmResolvedValueType as Fc, malformedLocalOutputsWarning as Fi, PRE_DELETE_SNAPSHOT_TYPES as Fn, recordLogOnlyValue as Fo, IntrinsicFunctionResolver as Fr, AssetPublisher as Fs, replayRollback as Ft, DELETE_INDEX_WAIT_PROCEED_NOTE as G, coerceWarmThroughput as Ga, canonicalizeRegion as Gc, malformedRenderedContainersWarning as Gi, findDestructiveChanges as Gn, dynamicReferenceTokens as Go, sendableAssumeRoleCommand as Gr, assertAssetBucketRegion as Gs, planFailedOps as Gt, deleteBudgetKey as H, isStatefulRecreateTargetSync as Ha, decodeListingKey as Hc, malformedOrphansWarning as Hi, unsupportedFinalSnapshotError as Hn, redactSecretsForState as Ho, assertSendableRoleArn as Hr, rewriteTemplateAssetReferences as Hs, demoteSupersededOrphans as Ht, perType as I, NO_CC_HANDLERS_REASON as Ia, CFN_TEMPLATE_BODY_LIMIT as Ic, malformedLocalResourceEntriesWarning as Ii, buildFinalSnapshotIdentifier as In, shareLogOnlyValues as Io, poisonRenderedSpellingsCollidingIn as Ir, isSensitiveAttributeName as Is, awaitInFlightSibling as It, waitForIndexesSettled as J, toFiniteNumber as Ja, StageLoadError as Jc, malformedResourcesWarning as Ji, earliestDefined as Jn, identityKeyFor as Jo, callerEnvCredentials as Jr, isCrossRegionRedirect as Js, recordUnderIdIsNotOwn as Jt, INDEX_SETTLE_POLL_INTERVAL_MS as K, isWarmThroughputDecrease as Ka, derivePartitionAndUrlSuffix as Kc, malformedResourceEntriesWarning as Ki, formatDestructiveChange as Kn, isUncertifiedBaselineMaskPosition as Ko, AWS_CREDENTIAL_ENV_KEYS as Kr, ensureAssetStorage as Ks, planRollback as Kt, readProtection as L, hasNoCloudControlHandlers as La, CFN_TEMPLATE_URL_LIMIT as Lc, malformedLocalResourcesWarning as Li, ccRoutedFinalSnapshotError as Ln, createSecretMasker as Lo, classifyReplaySecretRegion as Lr, stringifyValue as Ls, destroyStackRecordsView as Lt, recordedProtectionEvidence as M, findActionableSilentDrops as Ma, resolveUseCdkBootstrapAssets as Mc, malformedDriftResourcePropertiesWarning as Mi, stateSecretNameNeedles as Mn, logOnlyValueCount as Mo, reEnableInstanceApiTermination as Mr, orphansAfterRollback as Ms, makeForeignHolderScan as Mt, recordedProtectionNote as N, findSilentDropProperties as Na, stateBucketExistenceConfirmed as Nc, malformedExportNamesWarning as Ni, extractDeploymentEventError as Nn, printingCorpusOf as No, DiffCalculator as Nr, orphansCarriedFrom as Ns, sameJournaledOrphans as Nt, noEchoAttributeNamesOf as O, unpreviewableOrphanRecords as Oa, resolveCaptureObservedState as Oc, hasReadableOutputs as Oi, journaledOrphanPrintingBag as On, carryLogOnlyValues as Oo, ec2InstanceProtectionSite as Or, hasUnverifiableParameterRefusal as Os, dropFailedHint as Ot, PROTECTION_PROPERTY_BY_TYPE as P, unwrittenCreateOnlyReplacement as Pa, warnDeprecatedNoPrefixCliFlag as Pc, malformedExportSourceWarning as Pi, ATOMIC_FINAL_SNAPSHOT_TYPES as Pn, recordLogOnlyParameterValue as Po, INTRINSIC_KEYS as Pr, shouldRetainResource as Ps, replayFailedOperations as Pt, isTruthyCfnBoolean as Q, configIntegerRefusal as Qa, hasPlainPrototype$1 as Qc, refuseDivergentRecordRegionForDestroy as Qi, acquireIdempotencyToken as Qn, carriesSecretMask as Qo, s3BucketDomainName as Qr, validateContainerRepoName as Qs, orphanDeleteNeedsIdentity as Qt, DynamoDBGlobalTableProvider as R, findReplacedReadersOfRecreateTargets as Ra, MIGRATE_TMP_PREFIX as Rc, malformedOrphanRecordsRefusalMessage as Ri, createPreDeleteFinalSnapshot as Rn, errorCauseChain as Ro, producerRegionsFromState as Rr, WorkGraph as Rs, getStackRecords as Rt, keptForReadoption as S, repairMalformedOrphanRecordsForReadOnly as Sa, synthesisStatusMessage as Sc, UNREADABLE_ORPHANS_CONTAINER_ROW as Si, collectPublishedOutputNames as Sn, noEchoOutputsComparison as So, deleteIndeterminateGuards as Sr, splitImportedOps as Ss, revertNestedChildFromJournal as St, findServiceTokenRefusals as T, repairMalformedResourceEntriesForReadOnly as Ta, loadCdkJson as Tc, deployRefusesOrphanRowsReason as Ti, DEFAULT_RESOURCE_TIMEOUT_MS as Tn, readsNoEchoSource as To, isWaitAbandonedError as Tr, exportNamesCarriedFrom as Ts, getCurrentNestedStackContext as Tt, resolveDynamoDbDeleteBudgetClock as U, renderStatefulReason as Ua, expectedOwnerParam as Uc, malformedOutputsRefusalMessage as Ui, maskingRetryLogger as Un, scrubResourceRecord as Uo, explicitRoleArnOrThrow as Ur, AssetModeResolver as Us, isJournaledOrphan as Ut, compensateRemovedDeletionProtection as V, isStatefulRecreateTargetForReplace as Va, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Vc, malformedOrphansRefusalMessage as Vi, refusesFinalSnapshot as Vn, markSameGenerationBag as Vo, assertFlagRoleArn as Vr, loadPublishableAssetManifest as Vs, recordAfterRollbackUpdate as Vt, resolveDynamoDbDeleteBudgetMs as W, WARM_THROUGHPUT_MEMBERS as Wa, PARTITION_TABLE as Wc, malformedOutputsWarning as Wi, constructPathOf as Wn, DYNAMIC_REFERENCE_TOKEN_SCAN as Wo, isIamRoleArn as Wr, BOOTSTRAP_MARKER_PREFIX as Ws, isReplacementOrphan as Wt, S3_AUTO_DELETE_OBJECTS_TAG as X, coerceCfnInteger as Xa, defineOwnKey as Xc, malformedStateRefusalMessage as Xi, reserveStackCreateToken as Xn, recordNestedStackParameterExpressions as Xo, isSettledInstanceState as Xr, readBootstrapMarkerBody as Xs, resolveReplacementOldType as Xt, ECR_AUTO_DELETE_IMAGES_TAG as Y, coerceCfnBoolean as Ya, processStackMessages as Yc, malformedScrubResourceEntriesRefusalMessage as Yi, ledgerForStack as Yn, inheritNestedStackParameterAssociations as Yo, envCredentialsAreAssumedRole as Yr, parseBootstrapMarker as Ys, replacementNeverSwapped as Yt, hasCdkAutoDeleteTag as Z, configBooleanRefusal as Za, hasOwnKey as Zc, previewableOrphanRecords as Zi, withCreateTokenLedger as Zn, recoverMaskedOutput as Zo, s3BucketArn as Zr, validateAssetBucketName as Zs, seedsDeleteFirstGuard as Zt, makeCanonicalizePropertiesFn as _, refuseMalformedResourcePropertiesForOrphan as _a, escapeRegExp$3 as _c, parameterInputsFor as _i, exportNameNoEchoParameters as _n, maskReadbackAtCoordinates as _o, withPrintingSecrets as _r, CrossPrefixScanCache as _s, displacedPhysicalIdShown as _t, findNestedTemplateTreeDefect as a, refuseMalformedOutputs as aa, dockerSpawnEnvWithSensitive as ac, getAccountInfo as ai, resolveAssemblyPath as al, redactedDeleteAddressSkip as an, prefetchCreateOnlyPropertyPaths as ao, tagPlanWarning as ar, wholeStringLeavesOf as as, gray as at, lookupEachName as b, refuseMalformedResourcesForExport as ba, getDockerImageBySourceHash as bc, STATE_REGION_DIVERGED as bi, noEchoParameterValueSeed as bn, noEchoCoordinatesOf as bo, unchangedBehindSecretReference as br, isAccessDenied as bs, nestedChildStackName as bt, renderNestedTemplateTreeDefect as c, refuseMalformedResourceEntries as ca, getDockerCmd as cc, carriesFetchableDynamicReference as ci, DeploymentEventsReader as cn, withRetry as co, CC_BROKEN_REASON as cr, STATE_SOURCED_READBACK_RULES as cs, yellow as ct, conditionInputsFrom as d, refuseMalformedResourceEntriesForImport as da, partitionSensitiveEnv as dc, AWS_NO_VALUE as di, displayTextOrWithheld as dn, sameLambdaFunctionAddress as do, isCustomResource as dr, isSingleDynamicReferenceToken as ds, reachableDivergentParameters as dt, refuseMalformedOrphanRecords as ea, buildDockerImage as ec, s3BucketRegionalDomainName as ei, ownValue as el, getCurrentProducerRegions as en, readConfigString as eo, DBPROXY_TAG_OPTIONS as er, recordMaskOnlyValue as es, markRefusedBeforeApplying as et, parentSuppliedValues as f, refuseMalformedResourceEntriesForImportSave as fa, redactDockerArgvValues as fc, cfnRefValueFromPhysicalId as fi, exportAliasCollisionScrubWarning as fn, DagBuilder as fo, wouldReturnToSdkProvider as fr, LockManager as fs, resourcesNamingDeclaredParameter as ft, mergeNoChangeOutputs as g, refuseMalformedResourcePropertiesForExport as ga, warnFinchArgvExposure as gc, withSharedDrainBudget as gi, carriedExportAliasExposure as gn, maskAtCoordinates as go, getCurrentResourceSecrets as gr, CrossPrefixReadError as gs, displacedOpClause as gt, keptWholeReasonText as h, refuseMalformedResourcePropertiesForDrift as ha, runDockerStreaming as hc, parseWebACLArn as hi, secretSafeKeyDisplay as hn, isMarkedCoordinate as ho, isCustomResourceType as hr, rebuildClientForBucketRegion as hs, NESTED_PENDING_PARENT_REASON as ht, childTemplateLoader as i, refuseMalformedOrphansForOrphan as ia, describeDockerFailure as ic, parameterTypeMayLoseSecretIdentity as ii, renderAssemblyPathEscape as il, redactedDeleteAddressFields as in, requireConfigString as io, tagMapAsList as ir, recordProvenPublicExpression as is, cyan as it, noEchoParameterNamesOf as j, withheldAccountClause as ja, resolveStateBucketWithDefaultAndSource as jc, isReadableResourceEntry as ji, secretNamePrintingBag as jn, literalSplitDelimitersOf as jo, reDisableInstanceApiTermination as jr, isReadableBag as js, loadJournaledOrphans as jt, noEchoComparisonForTemplate as k, unreadableOrphanRecords as ka, resolveSkipPrefix as kc, hasReadableResources as ki, maskEventTextWithBoundBags as kn, createUnionSecretMasker as ko, isTerminationProtectionPropagationError as kr, importableOutputKeys as ks, isHandledOrphan as kt, templateIdentity as l, refuseMalformedResourceEntriesForDeploy as la, isDockerClientEnvKey as lc, isNamelessDynamicReferenceError as li, DeploymentEventsStore as ln, canonicalLambdaFunctionName as lo, ProviderRegistry as lr, TEMPLATE_SOURCED_RULES as ls, computeParameterTaint as lt, isSecretBearingReferenceString as m, refuseMalformedResourcePropertiesForDestroy as ma, runDockerForeground as mc, refStateLookupFromResource as mi, secretBearingStateKeyWarning as mn, canonicalCoordinates as mo, readsNoEchoDeleteValues as mr, S3StateBackend as ms, planOrphanAdoption as mt, IMPLICIT_DELETE_DEPENDENCIES as n, refuseMalformedOrphans as na, describeDockerCapturedOutput as nc, coerceParameterTypedValue as ni, describeFileReadFailure as nl, REDACTED_DELETE_ADDRESS_SKIP_REASON as nn, requireConfigArray as no, readTagList as nr, recordNoEchoAttributeValues as ns, createReadOnlyAttributeHealerFactory as nt, isAbsoluteAssetPath as o, refuseMalformedOutputsForDestroy as oa, finchSecretArgvRefusal as oc, isImpossibleEmptyStoredAttribute as oi, clearBucketRegionCache as ol, updatePartialMessage as on, templateResourceTypes as oo, definedAttributes as or, STATE_SOURCED_BASELINE_RULES as os, green as ot, readRecordedConditionVerdicts as p, refuseMalformedResourceEntriesForOrphan as pa, redactedDockerCause as pc, isStalePlaceholderArnAttribute as pi, secretBearing as pn, TemplateParser as po, TemplateNoEchoReresolver as pr, isLockInfoExpired as ps, makeSiblingClaimReader as pt, deleteTableWithIndexBusyRetry as q, toCfnInteger as qa, AssemblyReader as qc, malformedResourcePropertiesWarning as qi, RollbackInlinePolicyWriters as qn, pathCrossesDottedKey as qo, applyCallerIdentityCredentials as qr, getBootstrapMarkerKey as qs, recheckFailedPlan as qt, computeImplicitDeleteEdges as r, refuseMalformedOrphansForDestroy as ra, describeDockerExecFailure as rc, isUnboundTemplateParameter as ri, displayAssemblyPath as rl, isRedactedRecordedValue as rn, requireConfigObject as ro, refuseMalformedDesiredTags as rr, recordNoEchoParameterFreshValue as rs, bold as rt, listNestedTemplateRows as s, refuseMalformedResourceAttributesForOrphan as sa, formatDockerLoginError as sc, carriesDynamicReference as si, resolveBucketRegion as sl, updatePartialReason as sn, describeTypeWithThrottleRetry as so, stringifyIfAssigned as sr, STATE_SOURCED_CROSS_GENERATION_RULES as ss, red as st, DeployEngine as t, refuseMalformedOrphanRecordsForDestroy as ta, resolveDockerContextDirectory as tc, s3BucketWebsiteUrl as ti, absoluteAssemblyPathEscape as tl, inheritProducerRegions as tn, replayWarn as to, planTagDiff as tr, recordMaskOnlyValuesIn as ts, formatResourceLine as tt, conditionFingerprint as u, refuseMalformedResourceEntriesForDestroy as ua, isMalformedEnvKey as uc, keepsSecretReferenceToken as ui, WITHHELD_NAME_DISPLAY as un, lambdaFunctionNameForMask as uo, ccBrokenReason as ur, WHOLE_DYNAMIC_REFERENCE_PATTERN as us, namesAnyDeclaredParameter as ut, chunks as v, refuseMalformedResourcesForDeploy as va, stripControlChars as vc, passedParameterClassesOf as vi, exportNameSecretExposure as vn, maskWholeValue as vo, CloudControlProvider as vr, applyCrossPrefixScan as vs, dropSettledNestedJournals as vt, deferredServiceTokenWarning as w, repairMalformedOutputsForReadOnly as wa, getLegacyStateBucketName as wc, accountArgs as wi, bindingSkippedOutputs as wn, readbackPathFor as wo, withIndeterminateGuard as wr, describeRegionValueKind as ws, withNestedRevertRun as wt, withApiLimit as x, refuseMalformedState as xa, Synthesizer as xc, STATE_RESOURCES_MALFORMED as xi, collectDeclaredOutputNames as xn, noEchoLeavesOf as xo, UNSPECIFIED_SKIP_REASON as xr, isNotImplemented as xs, recordDisplacedSkips as xt, isAccessDeniedError as y, refuseMalformedResourcesForDestroy as ya, AssetManifestLoader as yc, JSON_LISTING_HOLE_VALUE as yi, isWholeDynamicReferenceValue as yn, maskedLeafCoordinatesOf as yo, slowCcOperationTimeoutMs as yr, crossPrefixDeniedWarning as ys, getNestedRevertRun as yt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as z, shownType as za, findLargeInlineResources as zc, malformedOrphanRecordsWarning as zi, effectiveDeletionPolicy as zn, maskSecretsInError as zo, regionLessSecretName as zr, buildAssetRedirectMap as zs, withStackRecords as zt };
42815
+ //# sourceMappingURL=deploy-engine-Bt-8KvUj.js.map