@go-to-k/cdkd 0.296.27 → 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-BiMLPagi.js → asg-provider-UKRukGI_.js} +3 -3
  2. package/dist/{asg-provider-BiMLPagi.js.map → asg-provider-UKRukGI_.js.map} +1 -1
  3. package/dist/cli.js +2 -2
  4. package/dist/{deploy-engine-DC4Yblxp.js → deploy-engine-Bt-8KvUj.js} +3621 -1642
  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-BA2eujXF.js → iam-role-provider-BBFYFBLx.js} +3 -3
  9. package/dist/{iam-role-provider-BA2eujXF.js.map → iam-role-provider-BBFYFBLx.js.map} +1 -1
  10. package/dist/index.d.ts +123 -55
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -3
  13. package/dist/{neptune-provider-DME95IcZ.js → neptune-provider-B9InVgs6.js} +3 -3
  14. package/dist/{neptune-provider-DME95IcZ.js.map → neptune-provider-B9InVgs6.js.map} +1 -1
  15. package/dist/{program-BwNb3_Ot.js → program-CN7Dqb3j.js} +548 -44
  16. package/dist/program-CN7Dqb3j.js.map +1 -0
  17. package/dist/{provider-classes-BcSDENeH.js → provider-classes-eEgFT-Vt.js} +196 -22
  18. package/dist/provider-classes-eEgFT-Vt.js.map +1 -0
  19. package/dist/{rds-provider-iouJXdXX.js → rds-provider-DgbVxaPP.js} +3 -3
  20. package/dist/{rds-provider-iouJXdXX.js.map → rds-provider-DgbVxaPP.js.map} +1 -1
  21. package/dist/{version-Cs9QbaaH.js → version-DyV_xwRX.js} +2 -2
  22. package/dist/{version-Cs9QbaaH.js.map → version-DyV_xwRX.js.map} +1 -1
  23. package/package.json +1 -1
  24. package/dist/deploy-engine-DC4Yblxp.js.map +0 -1
  25. package/dist/program-BwNb3_Ot.js.map +0 -1
  26. package/dist/provider-classes-BcSDENeH.js.map +0 -1
@@ -1,9 +1,9 @@
1
1
  import { a as runWithStackAwsClients, i as resetAwsClients, o as setAwsClients, t as AwsClients } from "./aws-clients-CnmtbrxD.js";
2
2
  import { A as UNRENDERABLE, B as stringifyJsonPayload, D as SAFE_MSG_ALTERED_CHAR, 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, T as withStackName, V as truncateCodePoints, _ as derivesPatternBName, a as getLogger, f as getLiveRenderer, h as PATTERN_B_RESOURCE_TYPES, j as cutMarker, k as STACK_REF_MAX_CODE_POINTS, l as runStackBuffered, m as PATTERN_B_NAME_PROPERTIES, o as isStdoutReservedForPayload, p as PATTERN_B_NAME_OPTIONS, r as safeStringify, s as reserveStdoutForPayload, t as describeAwsFailure, v as explicitNamePropertyFor, w as withSkipPrefix, y as generateResourceName, z as safeMsg } from "./aws-failure-text-BaWeCWRz.js";
3
- import { $t as AccountIdUnavailableError, An as commandHole, Bn as setPasteableRunFlags, D as VALUE_NOT_SHOWN, E as assertRegionMatch, En as TIMEOUT_FLAG_RESOURCE_TYPE, Fn as plainOrDescribed, Ft as buildLockContentionMessage, G as runDeleteAttempt, Gt as producerCoordinateKey, Ht as DEFAULT_STATE_PREFIX, In as quotedOrDescribed, It as forceQuitRecoveryClause, Jt as withPasteableAwsProfile, Kt as producerRecordKey, Ln as shellBoundedDisplay, Lt as formatLockExpiry, Mn as isInertUnquoted, Nn as pasteableCommand, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE_WHY, P as remedyLogicalId, Pt as buildForceUnlockCommand, Qn as isAmbiguousOutcomeError, Qt as credentialFingerprint, Rn as shellQuote, Rt as formatLockOperation, T as RESOURCE_NOT_FOUND, Tn as withErrorHandling, Ut as injectiveKey, Vn as setPasteableVerbFlags, Vt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xt as ambientCredentialConfig, Yt as ambientClientDefaults, Z as isAwsCliLiteral, Zt as clientDefaultsFor, _n as ResourceUpdateNotSupportedError, an as DeployCancelledError, ar as isThrottlingError, cn as LocalInvokeBuildError$1, er as isRetryableTransientError, fn as MalformedProducerRecordRefusalError, ft as logicalIdShown, gn as ResourceTimeoutError, hn as ProvisioningError, ir as isMarkedNonRetryable, it as isInterruptedWaitError, ln as LocalStartServiceError, mn as PartialFailureError, mt as resourceTypeShown, n as RESOLVED_PREVIOUS_PRINCIPAL_KEYS, nr as retryClassificationText, nt as endCommandInterruptScope, on as DynamicReferenceRegionAmbiguousError, or as markNonRetryable, pn as NestedStackChildDirectDestroyError, qt as setPasteableAwsProfile, rn as CrossAccountSecretRefusalError, rt as interruptWatchListenerCount, s as readRecordedPrincipals, sn as IntrinsicResolutionRefusalError, t as IAM_PRINCIPAL_NAME, tn as CdkdError, tr as isTransientServerError, tt as beginCommandInterruptScope, vn as StackHasActiveImportsError, wn as normalizeAwsError, xn as SynthesisError, yn as StackTerminationProtectionError, zn as withheldTargetClause, zt as formatLockOwner } from "./iam-policy-targets-B61e5_Sk.js";
3
+ import { $n as isAmbiguousOutcomeError, $t as credentialFingerprint, Bn as withheldTargetClause, D as VALUE_NOT_SHOWN, Dn as TIMEOUT_FLAG_RESOURCE_TYPE, E as assertRegionMatch, En as withErrorHandling, Ft as buildLockContentionMessage, G as runDeleteAttempt, Hn as setPasteableVerbFlags, Ht as CUSTOM_RESOURCE_RESPONSE_PREFIX, In as plainOrDescribed, It as forceQuitRecoveryClause, Jt as setPasteableAwsProfile, Kt as producerCoordinateKey, Ln as quotedOrDescribed, Lt as formatLockExpiry, Nn as isInertUnquoted, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, P as remedyLogicalId, Pn as pasteableCommand, Pt as buildForceUnlockCommand, Qt as clientDefaultsFor, Rn as shellBoundedDisplay, Rt as formatLockOperation, Sn as SynthesisError, T as RESOURCE_NOT_FOUND, Tn as normalizeAwsError, Ut as DEFAULT_STATE_PREFIX, Vn as setPasteableRunFlags, Wt as injectiveKey, Xt as ambientClientDefaults, Yt as withPasteableAwsProfile, Z as isAwsCliLiteral, Zt as ambientCredentialConfig, _n as ResourceTimeoutError, ar as isMarkedNonRetryable, bn as StackTerminationProtectionError, cn as IntrinsicResolutionRefusalError, en as AccountIdUnavailableError, ft as logicalIdShown, gn as ProvisioningError, hn as PartialFailureError, in as CrossAccountSecretRefusalError, it as isInterruptedWaitError, jn as commandHole, kn as SHELL_ACTIVE_WHY, ln as LocalInvokeBuildError$1, mn as NestedStackChildDirectDestroyError, mt as resourceTypeShown, n as RESOLVED_PREVIOUS_PRINCIPAL_KEYS, nn as CdkdError, nr as isTransientServerError, nt as endCommandInterruptScope, on as DeployCancelledError, or as isThrottlingError, pn as MalformedProducerRecordRefusalError, qt as producerRecordKey, rr as retryClassificationText, rt as interruptWatchListenerCount, s as readRecordedPrincipals, sn as DynamicReferenceRegionAmbiguousError, sr as markNonRetryable, t as IAM_PRINCIPAL_NAME, tr as isRetryableTransientError, tt as beginCommandInterruptScope, un as LocalStartServiceError, vn as ResourceUpdateNotSupportedError, yn as StackHasActiveImportsError, zn as shellQuote, zt as formatLockOwner } from "./iam-policy-targets-Cz2tPxXk.js";
4
4
  import { n as awsClientDefaults, r as getAssumedRoleCredentials, u as formatAuthority } from "./aws-client-defaults-D0q0z4dG.js";
5
- import { $ as gray, $a as templateResourceTypes, $i as refuseMalformedOutputsForDestroy, $o as STATE_SOURCED_BASELINE_RULES, $r as isImpossibleEmptyStoredAttribute, $s as redactDockerArgvValues, $t as updatePartialMessage, A as perType, Aa as hasNoCloudControlHandlers, Ac as expectedOwnerParam, Ai as malformedLocalResourcesWarning, An as collectDeclaredOutputNames, Ao as createSecretMasker, Ar as classifyReplaySecretRegion, As as AssetModeResolver, Bc as nullPrototypeRecord, Bi as malformedResourcePropertiesWarning, Bn as RollbackInlinePolicyWriters, Bo as pathCrossesDottedKey, Br as applyCallerIdentityCredentials, Bs as buildDenyExternalAccessPolicy, Bt as planRollback, C as noEchoComparisonForTemplate, Ca as unreadableResourceEntries, Cc as CFN_TEMPLATE_BODY_LIMIT, Ci as isReadableOrphanRecord, Cn as secretBearingStateKeyWarning, Co as hasMaskableValues, Cs as isSensitiveAttributeName, Ct as isHandledOrphan, D as recordedProtectionNote, Da as unwrittenCreateOnlyReplacement, Dc as uploadCfnTemplate, Di as malformedExportSourceWarning, Dn as exportNameSecretExposure, Do as recordLogOnlyParameterValue, Dr as INTRINSIC_KEYS, Ds as createAssetRedirectResolver, Dt as sameJournaledOrphans, E as recordedProtectionEvidence, Ec as findLargeInlineResources, Ei as malformedExportNamesWarning, En as exportNameNoEchoParameters, Eo as printingCorpusOf, Er as DiffCalculator, Es as buildAssetRedirectMap, Et as makeForeignHolderScan, Fa as isStatefulRecreateTargetSync, Fc as StageLoadError, Fi as malformedOrphansWarning, Fn as DEFAULT_RESOURCE_WARN_AFTER_MS, Fo as redactSecretsForState, Fr as assertSendableRoleArn, Fs as isCrossRegionRedirect, Ft as recordAfterRollbackUpdate, Gc as renderAssemblyPathEscape, Gi as refuseDivergentRecordRegionForDestroy, Go as carriesSecretMask, Gs as describeDockerFailure, Gt as orphanDeleteNeedsIdentity, Hc as absoluteAssemblyPathEscape, Hi as malformedScrubResourceEntriesRefusalMessage, Hn as ledgerForStack, Ho as inheritNestedStackParameterAssociations, Hr as envCredentialsAreAssumedRole, Hs as resolveDockerContextDirectory, Ht as recordUnderIdIsNotOwn, Ia as renderStatefulReason, Ic as processStackMessages, Ii as malformedOutputsRefusalMessage, In as maskingRetryLogger, Io as scrubResourceRecord, Ir as explicitRoleArnOrThrow, Is as parseBootstrapMarker, It as demoteSupersededOrphans, Jc as resolveBucketRegion, Ji as refuseMalformedOrphanRecordsForDestroy, Jo as recordMaskOnlyValuesIn, Js as formatDockerLoginError, Jt as inheritProducerRegions, Kc as resolveAssemblyPath, Ko as provenPublicValue, Ks as dockerSpawnEnvWithSensitive, Kt as findNestedStackTypeChanges, Lc as defineOwnKey, Li as malformedOutputsWarning, Ln as constructPathOf, Lo as DYNAMIC_REFERENCE_TOKEN_SCAN, Lr as isIamRoleArn, Ls as readBootstrapMarkerBody, Lt as isJournaledOrphan, Ma as shownType, Mc as canonicalizeRegion, Mi as malformedOrphanRecordsWarning, Mn as isExportAliasCollision, Mo as maskSecretsInError, Mr as regionLessSecretName, Ms as assertAssetBucketRegion, Na as MULTI_REGION_RECREATE_BLOCKED_TYPES, Nc as derivePartitionAndUrlSuffix, Ni as malformedOrphanRowsKeptWarning, Nn as bindingSkippedOutputs, No as maskSecretsInText, Nr as applyRoleArnIfSet, Ns as ensureAssetStorage, Nt as withStackRecords, O as PROTECTION_PROPERTY_BY_TYPE, Oc as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Oi as malformedLocalOutputsWarning, On as isWholeDynamicReferenceValue, Oo as recordLogOnlyValue, Or as IntrinsicFunctionResolver, Os as loadPublishableAssetManifest, Ot as replayFailedOperations, Pa as isStatefulRecreateTargetForReplace, Pc as AssemblyReader, Pi as malformedOrphansRefusalMessage, Pn as DEFAULT_RESOURCE_TIMEOUT_MS, Po as markSameGenerationBag, Pr as assertFlagRoleArn, Ps as getBootstrapMarkerKey, Pt as removeProtectionTypeList, Q as cyan, Qa as prefetchCreateOnlyPropertyPaths, Qi as refuseMalformedOutputs, Qo as wholeStringLeavesOf, Qr as getAccountInfo, Qs as partitionSensitiveEnv, Rc as hasOwnKey, Ri as malformedRenderedContainersWarning, Rn as findDestructiveChanges, Ro as dynamicReferenceTokens, Rr as sendableAssumeRoleCommand, Rs as validateAssetBucketName, Rt as isReplacementOrphan, S as noEchoAttributeNamesOf, Sa as unreadableOrphanRecords, Sc as ssmResolvedValueType, Si as hasReadableResources, Sn as secretBearing, So as createUnionSecretMasker, Ss as AssetPublisher, St as dropFailedHint, T as noEchoParameterNamesOf, Ta as findActionableSilentDrops, Tc as MIGRATE_TMP_PREFIX, Ti as malformedDriftResourcePropertiesWarning, Tn as carriedExportAliasExposure, To as logOnlyValueCount, Ts as WorkGraph, Tt as loadJournaledOrphans, Uc as describeFileReadFailure, Ui as malformedStateRefusalMessage, Uo as recordNestedStackParameterExpressions, Us as describeDockerCapturedOutput, Ut as replacementNeverSwapped, Vc as ownValue, Vi as malformedResourcesWarning, Vo as identityKeyFor, Vr as callerEnvCredentials, Vs as buildDockerImage, Vt as recheckFailedPlan, Wc as displayAssemblyPath, Wi as previewableOrphanRecords, Wn as withCreateTokenLedger, Ws as describeDockerExecFailure, Wt as resolveReplacementOldType, X as createReadOnlyAttributeHealerFactory, Xi as refuseMalformedOrphansForDestroy, Xo as recordNoEchoParameterFreshValue, Xr as isUnboundTemplateParameter, Xs as isDockerClientEnvKey, Y as formatResourceLine, Yi as refuseMalformedOrphans, Yo as recordNoEchoAttributeValues, Yr as coerceParameterTypedValue, Ys as getDockerCmd, Z as bold, Zi as refuseMalformedOrphansForOrphan, Zo as recordProvenPublicExpression, Zr as parameterTypeMayLoseSecretIdentity, Zs as isMalformedEnvKey, _ as makeCanonicalizePropertiesFn, _a as repairMalformedOutputsForReadOnly, _c as resolveStateBucketWithDefault, _i as accountArgs, _n as DeploymentEventsStore, _o as readbackPathFor, _s as importableOutputs, _t as revertedNestedRowIds, a as findNestedTemplateTreeDefect, aa as refuseMalformedResourceEntriesForImportSave, ac as stripControlChars, ai as cfnRefValueFromPhysicalId, an as secretNamePrintingBag, ao as DagBuilder, ar as wouldReturnToSdkProvider, as as LockManager, at as reachableDivergentParameters, b as serviceTokenBlockingReason, ba as repairMalformedResourcesForReadOnly, bc as stateBucketExistenceConfirmed, bi as hasReadableOrphans, bn as displayTextOrWithheld, bo as liveMatchesUnresolvedTokenFrame, bs as orphansCarriedFrom, bt as withNestedStackContext, c as renderNestedTemplateTreeDefect, ca as refuseMalformedResourcePropertiesForDrift, cc as Synthesizer, cn as PRE_DELETE_SNAPSHOT_TYPES, co as isMarkedCoordinate, cr as isCustomResourceType$1, cs as rebuildClientForBucketRegion, ct as planOrphanAdoption, d as conditionInputsFrom, da as refuseMalformedResourcesForDeploy, dc as getLegacyStateBucketName, dn as createPreDeleteFinalSnapshot, do as maskWholeValue, dr as CloudControlProvider, ds as describeRegionValueKind, dt as displacedPhysicalIdShown, ea as refuseMalformedResourceAttributesForOrphan, ec as redactedDockerCause, ei as carriesDynamicReference, en as updatePartialReason, eo as describeTypeWithThrottleRetry, es as STATE_SOURCED_CROSS_GENERATION_RULES, et as green, f as parentSuppliedValues, fa as refuseMalformedResourcesForDestroy, fc as loadCdkJson, fi as JSON_LISTING_HOLE_VALUE, fn as effectiveDeletionPolicy, fo as maskedLeafCoordinatesOf, fr as slowCcOperationTimeoutMs, fs as exportNamesCarriedFrom, ft as dropSettledNestedJournals, g as mergeNoChangeOutputs, ga as repairMalformedOrphansForReadOnly, gc as resolveSkipPrefix, gi as UNREADABLE_RESOURCES_MAP_ROW, gn as DeploymentEventsReader, gr as deleteSkipReason, gs as importableOutputKeys, h as keptWholeReasonText, ha as repairMalformedOrphanRecordsForReadOnly, hc as resolveCaptureObservedState, hi as UNREADABLE_ORPHANS_CONTAINER_ROW, hn as unsupportedFinalSnapshotError, ho as noEchoOutputsComparison, hr as deleteIndeterminateGuards, hs as hasUnverifiableParameterRefusal, ht as recordDisplacedSkips, i as childTemplateLoader, ia as refuseMalformedResourceEntriesForImport, ic as escapeRegExp, ii as AWS_NO_VALUE, in as orphanRecordsPrintingBag, ir as isCustomResource, is as isSingleDynamicReferenceToken, it as namesAnyDeclaredParameter, j as readProtection, ja as findReplacedReadersOfRecreateTargets, jc as PARTITION_TABLE, ji as malformedOrphanRecordsRefusalMessage, jn as collectPublishedOutputNames, jo as errorCauseChain, jr as producerRegionsFromState, js as BOOTSTRAP_MARKER_PREFIX, jt as destroyStackRecordsView, k as isProtectionValueActive, ka as NO_CC_HANDLERS_REASON, kc as decodeListingKey, ki as malformedLocalResourceEntriesWarning, kn as noEchoParameterValueSeed, ko as shareLogOnlyValues, kr as poisonRenderedSpellingsCollidingIn, ks as rewriteTemplateAssetReferences, kt as replayRollback, l as templateIdentity, la as refuseMalformedResourcePropertiesForExport, lc as synthesisStatusMessage, li as withSharedDrainBudget, ln as buildFinalSnapshotIdentifier, lo as maskAtCoordinates, ls as splitImportedOps, lt as NESTED_PENDING_PARENT_REASON, m as isSecretBearingReferenceString, ma as refuseMalformedState, mc as resolveAutoAssetStorage, mi as STATE_RESOURCES_MALFORMED, mn as refusesFinalSnapshot, mo as noEchoLeavesOf, mr as UNSPECIFIED_SKIP_REASON, ms as hasReasonlessBaselineRefusal, mt as nestedChildStackName$1, n as IMPLICIT_DELETE_DEPENDENCIES, na as refuseMalformedResourceEntriesForDeploy, nc as runDockerStreaming, ni as isNamelessDynamicReferenceError, nn as journaledOrphanPrintingBag, nr as ProviderRegistry, ns as TEMPLATE_SOURCED_RULES, nt as yellow, o as isAbsoluteAssetPath, oa as refuseMalformedResourceEntriesForOrphan, oc as AssetManifestLoader, oi as isStalePlaceholderArnAttribute, on as stateSecretNameNeedles, oo as TemplateParser, or as TemplateNoEchoReresolver, os as isLockInfoExpired, ot as resourcesNamingDeclaredParameter, p as readRecordedConditionVerdicts, pa as refuseMalformedResourcesForExport, pc as resolveApp, pi as STATE_REGION_DIVERGED, pn as isFinalSnapshotError, po as noEchoCoordinatesOf, ps as hasReadableExportSet, qi as refuseMalformedOrphanRecords, qo as recordMaskOnlyValue, qs as finchSecretArgvRefusal, r as computeImplicitDeleteEdges, ra as refuseMalformedResourceEntriesForDestroy, rc as warnFinchArgvExposure, ri as keepsSecretReferenceToken, rn as maskEventTextWithBoundBags, rr as ccBrokenReason, rs as WHOLE_DYNAMIC_REFERENCE_PATTERN, rt as computeParameterTaint, s as listNestedTemplateRows, sa as refuseMalformedResourcePropertiesForDestroy, sc as getDockerImageBySourceHash, si as refStateLookupFromResource, sn as ATOMIC_FINAL_SNAPSHOT_TYPES, so as canonicalCoordinates, sr as readsNoEchoDeleteValues, ss as S3StateBackend, st as makeSiblingClaimReader, t as DeployEngine, ta as refuseMalformedResourceEntries, tc as runDockerForeground, ti as carriesFetchableDynamicReference, tn as completedReplayEntries, to as withRetry, tr as CC_BROKEN_REASON, ts as STATE_SOURCED_READBACK_RULES, tt as red, u as conditionFingerprint, ua as refuseMalformedResourcePropertiesForOrphan, uc as getDefaultStateBucketName, ui as parameterInputsFor, un as ccRoutedFinalSnapshotError, uo as maskReadbackAtCoordinates, ur as withPrintingSecrets, us as acceptedCreateOnlyDropsOf, ut as displacedOpClause, v as deferredServiceTokenWarning, va as repairMalformedResourceEntriesForReadOnly, vc as resolveStateBucketWithDefaultAndSource, vi as deployRefusesOrphanRowsReason, vn as extractDeploymentEventError, vo as readsNoEchoSource, vr as isWaitAbandonedError, vs as isReadableBag, vt as withNestedRevertRun, w as noEchoExactEchoLeavesOf, wa as withheldAccountClause, wc as CFN_TEMPLATE_URL_LIMIT, wi as isReadableResourceEntry, wn as secretSafeKeyDisplay, wo as literalSplitDelimitersOf, ws as stringifyValue, wt as journaledOrphanLines, x as withResourceDeadline, xa as unpreviewableOrphanRecords, xc as warnDeprecatedNoPrefixCliFlag, xi as hasReadableOutputs, xn as exportAliasCollisionScrubWarning, xo as carryLogOnlyValues, xs as shouldRetainResource, xt as deleteJournaledOrphans, y as findServiceTokenRefusals, ya as repairMalformedResourcePropertiesForReadOnly, yc as resolveUseCdkBootstrapAssets, yi as displayLogicalId, yn as WITHHELD_NAME_DISPLAY, yo as valueAtCoordinate, ys as orphansAfterRollback, zc as hasPlainPrototype, zi as malformedResourceEntriesWarning, zn as formatDestructiveChange, zo as isUncertifiedBaselineMaskPosition, zr as AWS_CREDENTIAL_ENV_KEYS, zs as validateContainerRepoName, zt as planFailedOps } from "./deploy-engine-DC4Yblxp.js";
6
- import { t as getCdkdVersion } from "./version-Cs9QbaaH.js";
5
+ import { $c as nullPrototypeRecord, $o as provenPublicValue, $s as buildDenyExternalAccessPolicy, $t as findNestedStackTypeChanges, A as noEchoExactEchoLeavesOf, Aa as unreadableResourceEntries, Ac as resolveStateBucketWithDefault, Ai as isReadableOrphanRecord, An as orphanRecordsPrintingBag, Ao as hasMaskableValues, As as importableOutputs, At as journaledOrphanLines, Ba as MULTI_REGION_RECREATE_BLOCKED_TYPES, Bc as uploadCfnTemplate, Bi as malformedOrphanRowsKeptWarning, Bn as isFinalSnapshotError, Bo as maskSecretsInText, Br as applyRoleArnIfSet, Bs as createAssetRedirectResolver, Bt as removeProtectionTypeList, C as recordRetainedForReadoption, Ca as repairMalformedOrphansForReadOnly, Cc as getDefaultStateBucketName, Ci as UNREADABLE_RESOURCES_MAP_ROW, Cn as isExportAliasCollision, Cr as deleteSkipReason, Cs as acceptedCreateOnlyDropsOf, Ct as revertedNestedRowIds, D as withResourceDeadline, Da as repairMalformedResourcesForReadOnly, Dc as resolveAutoAssetStorage, Di as hasReadableOrphans, Dn as completedReplayEntries, Do as liveMatchesUnresolvedTokenFrame, Ds as hasReasonlessBaselineRefusal, Dt as deleteJournaledOrphans, E as serviceTokenBlockingReason, Ea as repairMalformedResourcePropertiesForReadOnly, Ec as resolveApp, Ei as displayLogicalId, En as DEFAULT_RESOURCE_WARN_AFTER_MS, Eo as valueAtCoordinate, Es as hasReadableExportSet, Et as withNestedStackContext, F as isProtectionValueActive, Fc as ssmResolvedValueType, Fi as malformedLocalOutputsWarning, Fn as PRE_DELETE_SNAPSHOT_TYPES, Fo as recordLogOnlyValue, Fr as IntrinsicFunctionResolver, Fs as AssetPublisher, Ft as replayRollback, Gc as canonicalizeRegion, Gi as malformedRenderedContainersWarning, Gn as findDestructiveChanges, Go as dynamicReferenceTokens, Gr as sendableAssumeRoleCommand, Gs as assertAssetBucketRegion, Gt as planFailedOps, Ha as isStatefulRecreateTargetSync, Hc as decodeListingKey, Hi as malformedOrphansWarning, Hn as unsupportedFinalSnapshotError, Ho as redactSecretsForState, Hr as assertSendableRoleArn, Hs as rewriteTemplateAssetReferences, Ht as demoteSupersededOrphans, I as perType, Ia as NO_CC_HANDLERS_REASON, Ic as CFN_TEMPLATE_BODY_LIMIT, Ii as malformedLocalResourceEntriesWarning, In as buildFinalSnapshotIdentifier, Io as shareLogOnlyValues, Ir as poisonRenderedSpellingsCollidingIn, Is as isSensitiveAttributeName, Jc as StageLoadError, Ji as malformedResourcesWarning, Jo as identityKeyFor, Jr as callerEnvCredentials, Js as isCrossRegionRedirect, Jt as recordUnderIdIsNotOwn, Kc as derivePartitionAndUrlSuffix, Ki as malformedResourceEntriesWarning, Kn as formatDestructiveChange, Ko as isUncertifiedBaselineMaskPosition, Kr as AWS_CREDENTIAL_ENV_KEYS, Ks as ensureAssetStorage, Kt as planRollback, L as readProtection, La as hasNoCloudControlHandlers, Lc as CFN_TEMPLATE_URL_LIMIT, Li as malformedLocalResourcesWarning, Ln as ccRoutedFinalSnapshotError, Lo as createSecretMasker, Lr as classifyReplaySecretRegion, Ls as stringifyValue, Lt as destroyStackRecordsView, M as recordedProtectionEvidence, Ma as findActionableSilentDrops, Mc as resolveUseCdkBootstrapAssets, Mi as malformedDriftResourcePropertiesWarning, Mn as stateSecretNameNeedles, Mo as logOnlyValueCount, Ms as orphansAfterRollback, Mt as makeForeignHolderScan, N as recordedProtectionNote, Nc as stateBucketExistenceConfirmed, Ni as malformedExportNamesWarning, Nn as extractDeploymentEventError, No as printingCorpusOf, Nr as DiffCalculator, Ns as orphansCarriedFrom, Nt as sameJournaledOrphans, O as noEchoAttributeNamesOf, Oa as unpreviewableOrphanRecords, Oc as resolveCaptureObservedState, Oi as hasReadableOutputs, On as journaledOrphanPrintingBag, Oo as carryLogOnlyValues, Os as hasUnverifiableParameterRefusal, Ot as dropFailedHint, P as PROTECTION_PROPERTY_BY_TYPE, Pa as unwrittenCreateOnlyReplacement, Pc as warnDeprecatedNoPrefixCliFlag, Pi as malformedExportSourceWarning, Pn as ATOMIC_FINAL_SNAPSHOT_TYPES, Po as recordLogOnlyParameterValue, Pr as INTRINSIC_KEYS, Ps as shouldRetainResource, Pt as replayFailedOperations, Qc as hasPlainPrototype, Qi as refuseDivergentRecordRegionForDestroy, Qo as carriesSecretMask, Qs as validateContainerRepoName, Qt as orphanDeleteNeedsIdentity, Ra as findReplacedReadersOfRecreateTargets, Rc as MIGRATE_TMP_PREFIX, Ri as malformedOrphanRecordsRefusalMessage, Rn as createPreDeleteFinalSnapshot, Ro as errorCauseChain, Rr as producerRegionsFromState, Rs as WorkGraph, S as keptForReadoption, Sa as repairMalformedOrphanRecordsForReadOnly, Sc as synthesisStatusMessage, Si as UNREADABLE_ORPHANS_CONTAINER_ROW, Sn as collectPublishedOutputNames, So as noEchoOutputsComparison, Sr as deleteIndeterminateGuards, Ss as splitImportedOps, T as findServiceTokenRefusals, Ta as repairMalformedResourceEntriesForReadOnly, Tc as loadCdkJson, Ti as deployRefusesOrphanRowsReason, Tn as DEFAULT_RESOURCE_TIMEOUT_MS, To as readsNoEchoSource, Tr as isWaitAbandonedError, Ts as exportNamesCarriedFrom, Ua as renderStatefulReason, Uc as expectedOwnerParam, Ui as malformedOutputsRefusalMessage, Un as maskingRetryLogger, Uo as scrubResourceRecord, Ur as explicitRoleArnOrThrow, Us as AssetModeResolver, Ut as isJournaledOrphan, Va as isStatefulRecreateTargetForReplace, Vc as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Vi as malformedOrphansRefusalMessage, Vn as refusesFinalSnapshot, Vo as markSameGenerationBag, Vr as assertFlagRoleArn, Vs as loadPublishableAssetManifest, Vt as recordAfterRollbackUpdate, Wc as PARTITION_TABLE, Wi as malformedOutputsWarning, Wn as constructPathOf, Wo as DYNAMIC_REFERENCE_TOKEN_SCAN, Wr as isIamRoleArn, Ws as BOOTSTRAP_MARKER_PREFIX, Wt as isReplacementOrphan, Xc as defineOwnKey, Xi as malformedStateRefusalMessage, Xo as recordNestedStackParameterExpressions, Xs as readBootstrapMarkerBody, Xt as resolveReplacementOldType, Yc as processStackMessages, Yi as malformedScrubResourceEntriesRefusalMessage, Yn as ledgerForStack, Yo as inheritNestedStackParameterAssociations, Yr as envCredentialsAreAssumedRole, Ys as parseBootstrapMarker, Yt as replacementNeverSwapped, Zc as hasOwnKey, Zi as previewableOrphanRecords, Zn as withCreateTokenLedger, Zs as validateAssetBucketName, Zt as seedsDeleteFirstGuard, _ as makeCanonicalizePropertiesFn, _a as refuseMalformedResourcePropertiesForOrphan, _c as escapeRegExp, _i as parameterInputsFor, _n as exportNameNoEchoParameters, _o as maskReadbackAtCoordinates, _r as withPrintingSecrets, _s as CrossPrefixScanCache, _t as displacedPhysicalIdShown, a as findNestedTemplateTreeDefect, aa as refuseMalformedOutputs, ac as dockerSpawnEnvWithSensitive, ai as getAccountInfo, al as resolveAssemblyPath, ao as prefetchCreateOnlyPropertyPaths, as as wholeStringLeavesOf, at as gray, ba as refuseMalformedResourcesForExport, bc as getDockerImageBySourceHash, bi as STATE_REGION_DIVERGED, bn as noEchoParameterValueSeed, bo as noEchoCoordinatesOf, bs as isAccessDenied, bt as nestedChildStackName$1, c as renderNestedTemplateTreeDefect, ca as refuseMalformedResourceEntries, cc as getDockerCmd, ci as carriesFetchableDynamicReference, cn as DeploymentEventsReader, co as withRetry, cr as CC_BROKEN_REASON, cs as STATE_SOURCED_READBACK_RULES, ct as yellow, d as conditionInputsFrom, da as refuseMalformedResourceEntriesForImport, dc as partitionSensitiveEnv, di as AWS_NO_VALUE, dn as displayTextOrWithheld, dr as isCustomResource, ds as isSingleDynamicReferenceToken, dt as reachableDivergentParameters, ea as refuseMalformedOrphanRecords, ec as buildDockerImage, el as ownValue, es as recordMaskOnlyValue, f as parentSuppliedValues, fa as refuseMalformedResourceEntriesForImportSave, fc as redactDockerArgvValues, fi as cfnRefValueFromPhysicalId, fn as exportAliasCollisionScrubWarning, fo as DagBuilder, fr as wouldReturnToSdkProvider, fs as LockManager, ft as resourcesNamingDeclaredParameter, g as mergeNoChangeOutputs, ga as refuseMalformedResourcePropertiesForExport, gc as warnFinchArgvExposure, gi as withSharedDrainBudget, gn as carriedExportAliasExposure, go as maskAtCoordinates, gs as CrossPrefixReadError, gt as displacedOpClause, h as keptWholeReasonText, ha as refuseMalformedResourcePropertiesForDrift, hc as runDockerStreaming, hn as secretSafeKeyDisplay, ho as isMarkedCoordinate, hr as isCustomResourceType$1, hs as rebuildClientForBucketRegion, ht as NESTED_PENDING_PARENT_REASON, i as childTemplateLoader, ia as refuseMalformedOrphansForOrphan, ic as describeDockerFailure, ii as parameterTypeMayLoseSecretIdentity, il as renderAssemblyPathEscape, is as recordProvenPublicExpression, it as cyan, j as noEchoParameterNamesOf, ja as withheldAccountClause, jc as resolveStateBucketWithDefaultAndSource, ji as isReadableResourceEntry, jn as secretNamePrintingBag, jo as literalSplitDelimitersOf, js as isReadableBag, jt as loadJournaledOrphans, k as noEchoComparisonForTemplate, ka as unreadableOrphanRecords, kc as resolveSkipPrefix, ki as hasReadableResources, kn as maskEventTextWithBoundBags, ko as createUnionSecretMasker, ks as importableOutputKeys, kt as isHandledOrphan, l as templateIdentity, la as refuseMalformedResourceEntriesForDeploy, lc as isDockerClientEnvKey, li as isNamelessDynamicReferenceError, ln as DeploymentEventsStore, lr as ProviderRegistry, ls as TEMPLATE_SOURCED_RULES, lt as computeParameterTaint, m as isSecretBearingReferenceString, ma as refuseMalformedResourcePropertiesForDestroy, mc as runDockerForeground, mi as refStateLookupFromResource, mn as secretBearingStateKeyWarning, mo as canonicalCoordinates, mr as readsNoEchoDeleteValues, ms as S3StateBackend, mt as planOrphanAdoption, n as IMPLICIT_DELETE_DEPENDENCIES, na as refuseMalformedOrphans, nc as describeDockerCapturedOutput, ni as coerceParameterTypedValue, nl as describeFileReadFailure, ns as recordNoEchoAttributeValues, nt as createReadOnlyAttributeHealerFactory, o as isAbsoluteAssetPath, oa as refuseMalformedOutputsForDestroy, oc as finchSecretArgvRefusal, oi as isImpossibleEmptyStoredAttribute, on as updatePartialMessage, oo as templateResourceTypes, os as STATE_SOURCED_BASELINE_RULES, ot as green, p as readRecordedConditionVerdicts, pa as refuseMalformedResourceEntriesForOrphan, pc as redactedDockerCause, pi as isStalePlaceholderArnAttribute, pn as secretBearing, po as TemplateParser, pr as TemplateNoEchoReresolver, ps as isLockInfoExpired, pt as makeSiblingClaimReader, qc as AssemblyReader, qi as malformedResourcePropertiesWarning, qn as RollbackInlinePolicyWriters, qo as pathCrossesDottedKey, qr as applyCallerIdentityCredentials, qs as getBootstrapMarkerKey, qt as recheckFailedPlan, r as computeImplicitDeleteEdges, ra as refuseMalformedOrphansForDestroy, rc as describeDockerExecFailure, ri as isUnboundTemplateParameter, rl as displayAssemblyPath, rs as recordNoEchoParameterFreshValue, rt as bold, s as listNestedTemplateRows, sa as refuseMalformedResourceAttributesForOrphan, sc as formatDockerLoginError, si as carriesDynamicReference, sl as resolveBucketRegion, sn as updatePartialReason, so as describeTypeWithThrottleRetry, ss as STATE_SOURCED_CROSS_GENERATION_RULES, st as red, t as DeployEngine, ta as refuseMalformedOrphanRecordsForDestroy, tc as resolveDockerContextDirectory, tl as absoluteAssemblyPathEscape, tn as inheritProducerRegions, ts as recordMaskOnlyValuesIn, tt as formatResourceLine, u as conditionFingerprint, ua as refuseMalformedResourceEntriesForDestroy, uc as isMalformedEnvKey, ui as keepsSecretReferenceToken, un as WITHHELD_NAME_DISPLAY, ur as ccBrokenReason, us as WHOLE_DYNAMIC_REFERENCE_PATTERN, ut as namesAnyDeclaredParameter, va as refuseMalformedResourcesForDeploy, vc as stripControlChars, vn as exportNameSecretExposure, vo as maskWholeValue, vr as CloudControlProvider, vs as applyCrossPrefixScan, vt as dropSettledNestedJournals, w as deferredServiceTokenWarning, wa as repairMalformedOutputsForReadOnly, wc as getLegacyStateBucketName, wi as accountArgs, wn as bindingSkippedOutputs, wo as readbackPathFor, ws as describeRegionValueKind, wt as withNestedRevertRun, xa as refuseMalformedState, xc as Synthesizer, xi as STATE_RESOURCES_MALFORMED, xn as collectDeclaredOutputNames, xo as noEchoLeavesOf, xr as UNSPECIFIED_SKIP_REASON, xs as isNotImplemented, xt as recordDisplacedSkips, ya as refuseMalformedResourcesForDestroy, yc as AssetManifestLoader, yi as JSON_LISTING_HOLE_VALUE, yn as isWholeDynamicReferenceValue, yo as maskedLeafCoordinatesOf, yr as slowCcOperationTimeoutMs, ys as crossPrefixDeniedWarning, za as shownType, zc as findLargeInlineResources, zi as malformedOrphanRecordsWarning, zn as effectiveDeletionPolicy, zo as maskSecretsInError, zr as regionLessSecretName, zs as buildAssetRedirectMap, zt as withStackRecords } from "./deploy-engine-Bt-8KvUj.js";
6
+ import { t as getCdkdVersion } from "./version-DyV_xwRX.js";
7
7
  import { randomBytes, randomUUID } from "node:crypto";
8
8
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetObjectCommand, HeadBucketCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, NotFound, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutBucketVersioningCommand, PutObjectCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
9
9
  import { GetRoleCommand, GetUserCommand } from "@aws-sdk/client-iam";
@@ -1306,6 +1306,14 @@ function createListCommand() {
1306
1306
 
1307
1307
  //#endregion
1308
1308
  //#region src/utils/interrupt-signals.ts
1309
+ const postCleanupListeners = /* @__PURE__ */ new WeakSet();
1310
+ function prependPostCleanupSigintListener(listener) {
1311
+ postCleanupListeners.add(listener);
1312
+ process.prependListener("SIGINT", listener);
1313
+ return () => {
1314
+ process.removeListener("SIGINT", listener);
1315
+ };
1316
+ }
1309
1317
  function forwardSigtermToSigint() {
1310
1318
  beginCommandInterruptScope();
1311
1319
  try {
@@ -1333,7 +1341,7 @@ function watchCommandInterrupt(opts) {
1333
1341
  }
1334
1342
  let stacksInFlight = 0;
1335
1343
  function gracefulOwnerArmed() {
1336
- return process.listeners("SIGINT").filter((l) => l !== handler).length - interruptWatchListenerCount() > 0;
1344
+ return process.listeners("SIGINT").filter((l) => l !== handler && !postCleanupListeners.has(l)).length - interruptWatchListenerCount() > 0;
1337
1345
  }
1338
1346
  const handler = () => {
1339
1347
  if (stacksInFlight > 0 && gracefulOwnerArmed()) {
@@ -1923,8 +1931,8 @@ function resolveRequireApproval(cliValue, logger, cdkJson = loadCdkJson()) {
1923
1931
  throw new CdkdError(`cdk.json "requireApproval" must be one of ${REQUIRE_APPROVAL_VALUES.join(", ")}, got: ${displayIdent(typeof configured === "string" ? configured : JSON.stringify(configured))}`, "INVALID_REQUIRE_APPROVAL");
1924
1932
  }
1925
1933
  function createApprovalPrompter(options) {
1934
+ if (options.yes) return Object.assign(() => Promise.resolve(true), { autoApproves: true });
1926
1935
  return (request) => {
1927
- if (options.yes) return Promise.resolve(true);
1928
1936
  return serializePrompt(() => getLiveRenderer().suspendWhile(async () => {
1929
1937
  process.stdout.write(renderApprovalRequest(request));
1930
1938
  return confirmOrRefuse("Do you wish to deploy these changes?", {
@@ -2396,7 +2404,7 @@ function collectCrossStackRefs(node, onRef) {
2396
2404
  //#region src/provisioning/register-providers.ts
2397
2405
  let providerClasses;
2398
2406
  function loadProviderClasses() {
2399
- providerClasses ??= import("./provider-classes-BcSDENeH.js");
2407
+ providerClasses ??= import("./provider-classes-eEgFT-Vt.js");
2400
2408
  return providerClasses;
2401
2409
  }
2402
2410
  function registerAllProviders(registry, classes) {
@@ -2637,6 +2645,262 @@ function createPrefixMigrationGate(opts) {
2637
2645
  };
2638
2646
  }
2639
2647
 
2648
+ //#endregion
2649
+ //#region src/cli/commands/registry-release.ts
2650
+ async function releaseRegistryMarkerQuietly(backend, stackName, region, logger, known) {
2651
+ if (stackName.includes("~")) return;
2652
+ try {
2653
+ const released = known === void 0 ? await backend.releaseRegistryMarker(stackName, region) : await backend.releaseRegistryMarker(stackName, region, known);
2654
+ logger.debug(safeMsg`Stack registry marker: ${released}`);
2655
+ } catch (error) {
2656
+ logger.warn(safeMsg`Could not delete the stack registry marker of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}). It names this state prefix, which no longer ` + `records the stack, so a deploy under another prefix treats it as stale.`);
2657
+ }
2658
+ }
2659
+
2660
+ //#endregion
2661
+ //#region src/cli/commands/cross-prefix-gate.ts
2662
+ function deployStackRegion(stack, baseRegion) {
2663
+ return stack.region || baseRegion;
2664
+ }
2665
+ function createCrossPrefixDeployGate(opts) {
2666
+ return async (gateStackName, state) => {
2667
+ if (gateStackName !== opts.stackName) return;
2668
+ if (state !== void 0) return;
2669
+ const result = await opts.guard.firstDeploy(opts.stackName, opts.region);
2670
+ applyCrossPrefixScan(result, {
2671
+ stackName: opts.stackName,
2672
+ region: opts.region,
2673
+ bucket: opts.bucket,
2674
+ recovery: opts.recovery
2675
+ }, "deploy", ...reportOnce(result));
2676
+ };
2677
+ }
2678
+ const reported = /* @__PURE__ */ new WeakSet();
2679
+ function reportOnce(result) {
2680
+ const first = !reported.has(result);
2681
+ reported.add(result);
2682
+ return first ? [(message) => getLogger().warn(message), (message) => getLogger().info(message)] : [() => void 0, () => void 0];
2683
+ }
2684
+ function createCrossPrefixDestructiveGate(opts) {
2685
+ return async (stackName, _destructive, stage) => {
2686
+ const result = await opts.cache.full(stackName, opts.region);
2687
+ applyCrossPrefixScan(result, {
2688
+ stackName,
2689
+ region: opts.region,
2690
+ bucket: opts.bucket,
2691
+ recovery: opts.recovery
2692
+ }, stage === "late" ? "deploy-late-replace" : "deploy-destructive", ...reportOnce(result));
2693
+ };
2694
+ }
2695
+ function createCrossPrefixHolder(opts) {
2696
+ return async (stackName) => {
2697
+ const result = await opts.cache.full(stackName, opts.region);
2698
+ switch (result.kind) {
2699
+ case "found": return {
2700
+ kind: "unreadable",
2701
+ what: safeMsg`bucket ${opts.bucket} also records this stack under another state prefix (${displayIdent(result.prefixes[0])}), whose record may hold it`
2702
+ };
2703
+ case "in-progress": return {
2704
+ kind: "unreadable",
2705
+ what: safeMsg`bucket ${opts.bucket} assigns this stack to another state prefix (${displayIdent(result.prefix)}), where a deploy may be in progress`
2706
+ };
2707
+ case "failed": return {
2708
+ kind: "unreadable",
2709
+ what: safeMsg`the other state prefixes of bucket ${opts.bucket} could not be checked`,
2710
+ retryable: true
2711
+ };
2712
+ case "denied":
2713
+ reportOnce(result)[0](crossPrefixDeniedWarning({
2714
+ stackName,
2715
+ region: opts.region,
2716
+ bucket: opts.bucket
2717
+ }, result.error, result.stage));
2718
+ return;
2719
+ default: return;
2720
+ }
2721
+ };
2722
+ }
2723
+ function crossPrefixEngineOptions(opts) {
2724
+ const backend = opts.backend;
2725
+ return {
2726
+ ...backend !== void 0 && { onFirstDeployLeftNoRecord: async (stackName) => {
2727
+ if (stackName !== opts.stackName) return;
2728
+ const known = await opts.guard.knownMarker?.(stackName, opts.region);
2729
+ await releaseRegistryMarkerQuietly(backend, stackName, opts.region, getLogger(), known);
2730
+ } },
2731
+ firstDeployGate: createCrossPrefixDeployGate({
2732
+ stackName: opts.stackName,
2733
+ region: opts.region,
2734
+ bucket: opts.bucket,
2735
+ recovery: opts.recovery,
2736
+ guard: opts.guard
2737
+ }),
2738
+ onDestructivePlan: createCrossPrefixDestructiveGate({
2739
+ region: opts.region,
2740
+ bucket: opts.bucket,
2741
+ recovery: opts.recovery,
2742
+ cache: opts.guard
2743
+ }),
2744
+ crossPrefixHolder: createCrossPrefixHolder({
2745
+ region: opts.region,
2746
+ bucket: opts.bucket,
2747
+ cache: opts.guard
2748
+ })
2749
+ };
2750
+ }
2751
+ function composeStateLoadedGates(crossPrefix, migration) {
2752
+ return async (stackName, state) => {
2753
+ await crossPrefix(stackName, state);
2754
+ if (migration) await migration(stackName, state);
2755
+ };
2756
+ }
2757
+
2758
+ //#endregion
2759
+ //#region src/state/stack-registry.ts
2760
+ function unwrapReadError(error) {
2761
+ return error instanceof CrossPrefixReadError ? error.cause : error;
2762
+ }
2763
+ function topLevelStackName(stackName) {
2764
+ return stackName.split("~")[0];
2765
+ }
2766
+ var CrossPrefixGuard = class {
2767
+ scan;
2768
+ backend;
2769
+ readOnly;
2770
+ markers = /* @__PURE__ */ new Map();
2771
+ answers = /* @__PURE__ */ new Map();
2772
+ constructor(backend, opts = {}) {
2773
+ this.backend = backend;
2774
+ this.readOnly = opts.readOnly === true;
2775
+ this.scan = opts.scan ?? new CrossPrefixScanCache(backend);
2776
+ }
2777
+ get target() {
2778
+ return this.scan.target;
2779
+ }
2780
+ full(stackName, region, when = "now") {
2781
+ const key = JSON.stringify([stackName, region]);
2782
+ let answer = this.answers.get(key);
2783
+ if (answer === void 0) {
2784
+ answer = this.evaluate(stackName, region, false, when);
2785
+ this.answers.set(key, answer);
2786
+ } else if (when === "now") this.scan.target.rank(stackName, region, "now");
2787
+ return answer;
2788
+ }
2789
+ firstDeploy(stackName, region) {
2790
+ const key = JSON.stringify([stackName, region]);
2791
+ const answer = this.evaluate(stackName, region, true, "now");
2792
+ this.answers.set(key, answer);
2793
+ return answer;
2794
+ }
2795
+ async knownMarker(stackName, region) {
2796
+ const read = this.markers.get(JSON.stringify([topLevelStackName(stackName), region]));
2797
+ if (read === void 0) return void 0;
2798
+ return read.catch(() => void 0);
2799
+ }
2800
+ marker(top, region, fresh = false) {
2801
+ const key = JSON.stringify([top, region]);
2802
+ let read = fresh ? void 0 : this.markers.get(key);
2803
+ if (read === void 0) {
2804
+ read = this.backend.getRegistryMarker(top, region);
2805
+ this.markers.set(key, read);
2806
+ }
2807
+ return read;
2808
+ }
2809
+ async evaluate(stackName, region, firstDeploy, when) {
2810
+ const top = topLevelStackName(stackName);
2811
+ const claimable = top === stackName && !this.readOnly;
2812
+ if (firstDeploy && claimable && !this.markers.has(JSON.stringify([top, region]))) {
2813
+ if (await this.claim(top, region) === "claimed") return { kind: "clear" };
2814
+ }
2815
+ for (let attempt = 0; attempt < 2; attempt++) {
2816
+ let marker;
2817
+ try {
2818
+ marker = await this.marker(top, region, attempt > 0);
2819
+ } catch (error) {
2820
+ return this.fallback(stackName, region, when, error);
2821
+ }
2822
+ if (marker === null) {
2823
+ if (firstDeploy) {
2824
+ if (!claimable) return { kind: "clear" };
2825
+ const claimed = await this.claim(top, region);
2826
+ if (claimed === "conflict") continue;
2827
+ if (claimed !== "claimed") return this.fallback(stackName, region, when, claimed.error);
2828
+ return { kind: "clear" };
2829
+ }
2830
+ const scanned = await this.scan.full(stackName, region, when);
2831
+ if (scanned.kind === "clear" && claimable) {
2832
+ if (await this.claim(top, region) === "conflict") continue;
2833
+ }
2834
+ return scanned;
2835
+ }
2836
+ if (marker.prefix === this.backend.prefix) return { kind: "clear" };
2837
+ let held;
2838
+ let locked;
2839
+ try {
2840
+ held = await this.backend.recordUnderPrefix(marker.prefix, stackName, region);
2841
+ locked = held === "holder" ? false : await this.backend.lockUnderPrefix(marker.prefix, top, region);
2842
+ } catch (error) {
2843
+ return isAccessDenied(error) ? {
2844
+ kind: "denied",
2845
+ error,
2846
+ stage: "probe"
2847
+ } : {
2848
+ kind: "failed",
2849
+ error
2850
+ };
2851
+ }
2852
+ if (held === "holder") return {
2853
+ kind: "found",
2854
+ prefixes: [marker.prefix]
2855
+ };
2856
+ if (locked) return {
2857
+ kind: "in-progress",
2858
+ prefix: marker.prefix
2859
+ };
2860
+ const stale = held === "empty" ? [marker.prefix] : [];
2861
+ const scanned = await this.scan.full(stackName, region, when);
2862
+ if (scanned.kind !== "clear") return scanned;
2863
+ const allStale = [.../* @__PURE__ */ new Set([...stale, ...scanned.stale ?? []])];
2864
+ const answer = {
2865
+ kind: "clear",
2866
+ ...allStale.length > 0 && { stale: allStale }
2867
+ };
2868
+ if (!claimable) return answer;
2869
+ if (await this.claim(top, region, marker.etag) === "conflict") continue;
2870
+ return answer;
2871
+ }
2872
+ return {
2873
+ kind: "failed",
2874
+ error: new CrossPrefixReadError(`_cdkd-registry/${region}/${top}.json`, Object.assign(/* @__PURE__ */ new Error("the marker changed twice while cdkd was claiming it"), { name: "ConcurrentClaim" }))
2875
+ };
2876
+ }
2877
+ async claim(top, region, ifMatch) {
2878
+ try {
2879
+ const result = await this.backend.claimRegistryMarker(top, region, ifMatch);
2880
+ if (result === "claimed") this.markers.set(JSON.stringify([top, region]), Promise.resolve({
2881
+ prefix: this.backend.prefix,
2882
+ etag: ""
2883
+ }));
2884
+ return result;
2885
+ } catch (error) {
2886
+ return { error };
2887
+ }
2888
+ }
2889
+ async fallback(stackName, region, when, error) {
2890
+ if (!isAccessDenied(error) && !isNotImplemented(unwrapReadError(error))) return {
2891
+ kind: "failed",
2892
+ error
2893
+ };
2894
+ const scanned = await this.scan.full(stackName, region, when);
2895
+ return scanned.kind === "clear" ? {
2896
+ kind: "denied",
2897
+ error,
2898
+ stage: "registry",
2899
+ ...scanned.stale && { stale: scanned.stale }
2900
+ } : scanned;
2901
+ }
2902
+ };
2903
+
2640
2904
  //#endregion
2641
2905
  //#region src/cli/commands/deploy.ts
2642
2906
  async function deployCommand(stacks, options) {
@@ -2706,6 +2970,7 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2706
2970
  };
2707
2971
  process.on("SIGINT", topLevelSigintHandler);
2708
2972
  const unforwardSigterm = forwardSigtermToSigint();
2973
+ let preflightBackendForCleanup;
2709
2974
  try {
2710
2975
  logger.info(cyan(synthesisStatusMessage(app, "Synthesizing CDK app...")));
2711
2976
  const synthesizer = new Synthesizer();
@@ -2721,6 +2986,7 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2721
2986
  };
2722
2987
  const [result, statePrep] = await Promise.all([synthesizer.synthesize(synthOptions), statePrepPromise]);
2723
2988
  const { stateBucket, preflightStateBackend, exportIndexStore } = statePrep;
2989
+ preflightBackendForCleanup = preflightStateBackend;
2724
2990
  synthOptions.stateBucket = stateBucket;
2725
2991
  const refusalRecovery = {
2726
2992
  profile: options.profile,
@@ -2787,6 +3053,8 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2787
3053
  ignoreErrors: options.ignoreErrors === true
2788
3054
  });
2789
3055
  refuseMalformedNestedTemplateTrees(targetStacks);
3056
+ const baseRegion = namedCliRegion(options.region) ?? "us-east-1";
3057
+ const crossPrefixGuard = new CrossPrefixGuard(preflightStateBackend, { readOnly: options.dryRun === true });
2790
3058
  await synthesizer.expandMacrosForStacks(targetStacks, synthOptions);
2791
3059
  const { STSClient, GetCallerIdentityCommand } = await import("@aws-sdk/client-sts");
2792
3060
  const stsClient = new STSClient({
@@ -2816,7 +3084,6 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2816
3084
  };
2817
3085
  const dagBuilder = new DagBuilder({ relaxCdkVpcDefensiveDeps: !!options.aggressiveVpcParallel });
2818
3086
  const diffCalculator = new DiffCalculator();
2819
- const baseRegion = namedCliRegion(options.region) ?? "us-east-1";
2820
3087
  const workGraph = new WorkGraph();
2821
3088
  const stackMap = new Map(targetStacks.map((s) => [s.stackName, s]));
2822
3089
  const stackRedirects = /* @__PURE__ */ new Map();
@@ -2864,13 +3131,14 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2864
3131
  logger.debug(`Work graph: ${summary["asset-publish"]} asset(s), ${summary["stack"]} stack(s)`);
2865
3132
  const bufferStackOutput = targetStacks.length > 1;
2866
3133
  let totalUnaddressed = 0;
3134
+ let totalCrossPrefixKept = 0;
2867
3135
  let cancelledStacks = 0;
2868
3136
  const runStack = async (stackInfo) => {
2869
3137
  return withSkipPrefix(skipPrefix, () => runStackInner(stackInfo));
2870
3138
  };
2871
3139
  const runStackInner = async (stackInfo) => {
2872
3140
  if (deployInterrupted) throw new DeployCancelledError(`Deploy interrupted before stack '${stackInfo.stackName}' started — not starting it.`);
2873
- const stackRegion = stackInfo.region || baseRegion;
3141
+ const stackRegion = deployStackRegion(stackInfo, baseRegion);
2874
3142
  logger.info(`\n${cyan("Deploying stack:")} ${bold(cyan(stackInfo.stackName))}${stackRegion !== baseRegion ? gray(` (region: ${stackRegion})`) : ""}`);
2875
3143
  const stackAwsClients = new AwsClients({
2876
3144
  region: stackRegion,
@@ -2908,6 +3176,14 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2908
3176
  skipPrefix,
2909
3177
  yes: options.yes
2910
3178
  });
3179
+ const crossPrefix = crossPrefixEngineOptions({
3180
+ stackName: stackInfo.stackName,
3181
+ region: stackRegion,
3182
+ bucket: stateBucket,
3183
+ recovery: refusalRecovery,
3184
+ guard: crossPrefixGuard,
3185
+ backend: preflightStateBackend
3186
+ });
2911
3187
  let recreateTargets;
2912
3188
  if (options.recreateViaCcApi?.length || options.recreateViaSdkProvider?.length) {
2913
3189
  const stateForRecreateCheck = await stackStateBackend.getState(stackInfo.stackName, stackRegion);
@@ -2987,7 +3263,10 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
2987
3263
  refusalRecovery,
2988
3264
  ...assetRedirect && { assetRedirect },
2989
3265
  ...eventRecorder && { eventRecorder },
2990
- ...migrationGate && { onCurrentStateLoaded: migrationGate },
3266
+ onCurrentStateLoaded: composeStateLoadedGates(crossPrefix.firstDeployGate, migrationGate),
3267
+ ...crossPrefix.onFirstDeployLeftNoRecord && { onFirstDeployLeftNoRecord: crossPrefix.onFirstDeployLeftNoRecord },
3268
+ onDestructivePlan: crossPrefix.onDestructivePlan,
3269
+ crossPrefixHolder: crossPrefix.crossPrefixHolder,
2991
3270
  ...options.pinCcApi?.length && { pinCcApi: {
2992
3271
  stackName: stackInfo.stackName,
2993
3272
  logicalIds: new Set(options.pinCcApi)
@@ -3038,10 +3317,15 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
3038
3317
  logger.info(` Updated: ${updatedTotal > 0 ? yellow(updatedTotal) : gray(updatedTotal)}`);
3039
3318
  logger.info(` Deleted: ${deployResult.deleted > 0 ? red(deployResult.deleted) : gray(deployResult.deleted)}`);
3040
3319
  if (deployResult.deleteSkipped > 0) logger.info(` Skipped (not deleted): ${yellow(deployResult.deleteSkipped)}`);
3320
+ const crossPrefixKept = deployResult.crossPrefixKept ?? 0;
3321
+ if (crossPrefixKept > 0) logger.info(` Kept (replacement refused: another state prefix records the stack, or the check could not run): ${yellow(crossPrefixKept)}`);
3041
3322
  if (ownUpdatePartial > 0) logger.info(safeMsg` of which left an orphaned predecessor: ${yellow(ownUpdatePartial)}`);
3042
3323
  if (nestedUpdatePartial > 0) logger.info(safeMsg` Left an orphaned predecessor in a nested stack: ${yellow(nestedUpdatePartial)}`);
3043
- const stackUnaddressed = deployResult.deleteSkipped + deployResult.updatePartial;
3044
- if (!options.dryRun) totalUnaddressed += stackUnaddressed;
3324
+ const stackUnaddressed = deployResult.deleteSkipped + deployResult.updatePartial + crossPrefixKept;
3325
+ if (!options.dryRun) {
3326
+ totalUnaddressed += stackUnaddressed;
3327
+ totalCrossPrefixKept += crossPrefixKept;
3328
+ }
3045
3329
  logger.info(` Unchanged: ${gray(deployResult.unchanged)}`);
3046
3330
  logger.info(` Duration: ${cyan((deployResult.durationMs / 1e3).toFixed(2) + "s")}`);
3047
3331
  if (deployResult.attributeFallbackCount > 0) logger.warn(`${deployResult.attributeFallbackCount} attribute resolution(s) fell back to the physical ID (potentially wrong values); re-run with --strict-getatt to fail on these`);
@@ -3057,7 +3341,7 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
3057
3341
  created: deployResult.created,
3058
3342
  updated: updatedTotal,
3059
3343
  deleted: deployResult.deleted,
3060
- ...deployResult.deleteSkipped + deployResult.updatePartial > 0 && { skipped: deployResult.deleteSkipped + deployResult.updatePartial }
3344
+ ...stackUnaddressed > 0 && { skipped: stackUnaddressed }
3061
3345
  }, deployResult.durationMs);
3062
3346
  } catch (deployError) {
3063
3347
  if (deployError instanceof DeployCancelledError) {
@@ -3102,11 +3386,12 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
3102
3386
  if (!outcome.ok) throw outcome.error;
3103
3387
  }
3104
3388
  });
3105
- if (totalUnaddressed > 0 && !options.allowUnaddressed) throw new PartialFailureError(`Deploy left ${totalUnaddressed} resource(s) unaddressed, so they may still exist in AWS. The two cases differ in what happens next: a DELETE the provider could not issue KEEPS its state record, so the next 'cdkd deploy' re-attempts it, while a replacement's surviving predecessor is NOT tracked and will never be retried — delete it by hand. The per-stack summaries above give the breakdown, and each resource's own warning names its cause and remedy. ` + (cancelledStacks > 0 ? `Note ${cancelledStacks} stack(s) were also cancelled and never deployed, so the template is not fully applied beyond the resources named above. ` : "") + `Pass --allow-unaddressed to exit 0 instead.`);
3389
+ if (totalUnaddressed > 0 && !options.allowUnaddressed) throw new PartialFailureError(`Deploy left ${totalUnaddressed} resource(s) unaddressed, so they may still exist in AWS. The two cases differ in what happens next: a DELETE the provider could not issue KEEPS its state record, so the next 'cdkd deploy' re-attempts it, while a replacement's surviving predecessor is NOT tracked and will never be retried — delete it by hand. ` + (totalCrossPrefixKept > 0 ? "A replacement kept because another state prefix records the stack, or the check could not run, keeps its old resource and applies no new value — resolve the pair, or let the check run, and re-deploy. " : "") + "The per-stack summaries above give the breakdown, and each resource's own warning names its cause and remedy. " + (cancelledStacks > 0 ? `Note ${cancelledStacks} stack(s) were also cancelled and never deployed, so the template is not fully applied beyond the resources named above. ` : "") + `Pass --allow-unaddressed to exit 0 instead.`);
3106
3390
  } finally {
3107
3391
  unforwardSigterm();
3108
3392
  process.removeListener("SIGINT", topLevelSigintHandler);
3109
3393
  awsClients.destroy();
3394
+ preflightBackendForCleanup?.destroyClient();
3110
3395
  }
3111
3396
  }
3112
3397
  function createDeployCommand() {
@@ -4372,7 +4657,7 @@ function maskOutputChangeForDisplay(change, mask, nameCorpus) {
4372
4657
  return changed ? shown : change;
4373
4658
  }
4374
4659
  async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator, options = {}) {
4375
- const { parameters, canonicalizeProperties, cfnFallback, inheritSecretBearingTemplate, inheritedSecrets, attributeHealer, parentUnresolvedParameters, inheritedNoEchoParameters, inheritedNoEchoParametersAnyVerdict } = options;
4660
+ const { parameters, canonicalizeProperties, cfnFallback, inheritSecretBearingTemplate, inheritedSecrets, inheritedDerivedNames, attributeHealer, parentUnresolvedParameters, inheritedNoEchoParameters, inheritedNoEchoParametersAnyVerdict } = options;
4376
4661
  const noEchoParametersOf = (t) => /* @__PURE__ */ new Set([...noEchoParameterNamesOf(t), ...inheritedNoEchoParameters ?? []]);
4377
4662
  const inheritedForResolver = inheritedSecrets !== void 0 && hasMaskableValues(inheritedSecrets) ? inheritedSecrets : void 0;
4378
4663
  const intrinsicResolver = new IntrinsicFunctionResolver(region, { cfnFallback: cfnFallback ?? true });
@@ -4502,7 +4787,11 @@ async function computeStackDiff(currentState, template, region, stackName, state
4502
4787
  diffSecrets,
4503
4788
  inheritedForResolver,
4504
4789
  outputsPassSecrets
4505
- ], [splitPieces, derivedNames]);
4790
+ ], [
4791
+ splitPieces,
4792
+ derivedNames,
4793
+ ...inheritedDerivedNames ? [inheritedDerivedNames] : []
4794
+ ]);
4506
4795
  const maskForLog = printing.mask;
4507
4796
  const resolveRecordingInto = (bag, printingSecrets) => (value) => intrinsicResolver.resolve(value, {
4508
4797
  recordedSecretValues: bag,
@@ -4706,6 +4995,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
4706
4995
  deployRefusals: shownDeployRefusals,
4707
4996
  effectiveTemplate,
4708
4997
  printingSecrets,
4998
+ derivedNames: diffPrintingSecrets([derivedNames, inheritedDerivedNames]),
4709
4999
  resolvedParameters: mergedParameters,
4710
5000
  conditions,
4711
5001
  knownConditions: conditions === void 0 ? void 0 : Object.fromEntries(Object.entries(conditions).filter(([name]) => !stillUnknown.includes(name))),
@@ -4879,7 +5169,7 @@ function noEchoFedChildParameters(parentStackRow, parentNoEchoParameters, parent
4879
5169
  })) fed.add(name);
4880
5170
  return fed;
4881
5171
  }
4882
- async function resolveChildStackParameters(parentStackRow, parentTemplate, parentState, region, parentStackName, stateBackend, parentParameters, parentConditions, cfnFallback, printingSecrets, attributeHealer, unresolvedKeys, trust) {
5172
+ async function resolveChildStackParameters(parentStackRow, parentTemplate, parentState, region, parentStackName, stateBackend, parentParameters, parentConditions, cfnFallback, printingSecrets, attributeHealer, unresolvedKeys, trust, derivedNameSink) {
4883
5173
  const rawParams = parentStackRow.Properties?.["Parameters"];
4884
5174
  if (!rawParams || typeof rawParams !== "object" || Array.isArray(rawParams)) return {};
4885
5175
  const resolver = new IntrinsicFunctionResolver(region, { cfnFallback: cfnFallback ?? true });
@@ -4891,7 +5181,7 @@ async function resolveChildStackParameters(parentStackRow, parentTemplate, paren
4891
5181
  template: parentTemplate,
4892
5182
  resources: parentState.resources,
4893
5183
  secretNameNeedles: stateSecretNameNeedles(parentState.resources),
4894
- secretNameSink: /* @__PURE__ */ new Map(),
5184
+ secretNameSink: derivedNameSink ?? /* @__PURE__ */ new Map(),
4895
5185
  stateBackend,
4896
5186
  stackName: parentStackName,
4897
5187
  bestEffort: true,
@@ -4918,7 +5208,7 @@ function recordedTemplateResources(template, state) {
4918
5208
  return recorded;
4919
5209
  }
4920
5210
  async function buildDiffTree(args) {
4921
- const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parentHasSecretReference, parameters, parentUnresolvedParameters, canonicalizeProperties, assetRedirect, cfnFallback, previewOrphanAdoption, attributeHealerFor, ancestorTemplatePaths, isNestedChild, inheritedSecrets, inheritedNoEchoParameters, inheritedNoEchoParametersAnyVerdict, refusalRecovery } = args;
5211
+ const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parentHasSecretReference, parameters, parentUnresolvedParameters, canonicalizeProperties, assetRedirect, cfnFallback, previewOrphanAdoption, attributeHealerFor, ancestorTemplatePaths, isNestedChild, inheritedSecrets, inheritedDerivedNames, inheritedNoEchoParameters, inheritedNoEchoParametersAnyVerdict, refusalRecovery } = args;
4922
5212
  const attributeHealer = attributeHealerFor?.(stackName, region);
4923
5213
  const { state, unreadable, unreadableContainers, deployRefusals } = await loadStateOrEmpty(stackName, region, stateBackend, refusalRecovery);
4924
5214
  const createOnlyPrefetch = prefetchCreateOnlyPropertyPaths(templateResourceTypes(recordedTemplateResources(template, state)));
@@ -4932,6 +5222,7 @@ async function buildDiffTree(args) {
4932
5222
  ...cfnFallback !== void 0 && { cfnFallback },
4933
5223
  ...previewOrphanAdoption && { previewOrphanAdoption },
4934
5224
  ...inheritedSecrets && { inheritedSecrets },
5225
+ ...inheritedDerivedNames && { inheritedDerivedNames },
4935
5226
  ...inheritedNoEchoParameters && { inheritedNoEchoParameters },
4936
5227
  ...inheritedNoEchoParametersAnyVerdict && { inheritedNoEchoParametersAnyVerdict },
4937
5228
  ...attributeHealer && { attributeHealer },
@@ -4943,7 +5234,7 @@ async function buildDiffTree(args) {
4943
5234
  } finally {
4944
5235
  createOnlyPrefetch.cancel();
4945
5236
  }
4946
- const { changes, outputChanges, adoptedOrphans, adoptedRecords, blocking, unreadableOrphans, deployRefusals: adoptedDeployRefusals, effectiveTemplate, printingSecrets, resolvedParameters, conditions, knownConditions, trust } = stackDiff;
5237
+ const { changes, outputChanges, adoptedOrphans, adoptedRecords, blocking, unreadableOrphans, deployRefusals: adoptedDeployRefusals, effectiveTemplate, printingSecrets, derivedNames: nodeDerivedNames, resolvedParameters, conditions, knownConditions, trust } = stackDiff;
4947
5238
  const stateAfterAdoption = Object.keys(adoptedRecords).length > 0 ? {
4948
5239
  ...state,
4949
5240
  resources: {
@@ -4992,8 +5283,10 @@ async function buildDiffTree(args) {
4992
5283
  ...inheritedNoEchoParameters ?? [],
4993
5284
  ...inheritedNoEchoParametersAnyVerdict ?? []
4994
5285
  ]), void 0, stateAfterAdoption.resources);
4995
- const childParameters = await resolveChildStackParameters(resource, effectiveTemplate, stateAfterAdoption, region, stackName, stateBackend, resolvedParameters, conditions, cfnFallback, printingSecrets, attributeHealer, childUnresolvedParameters, trust);
4996
- node.children.push(await buildDiffTree({
5286
+ const rowDerivedNames = /* @__PURE__ */ new Map();
5287
+ const childParameters = await resolveChildStackParameters(resource, effectiveTemplate, stateAfterAdoption, region, stackName, stateBackend, resolvedParameters, conditions, cfnFallback, printingSecrets, attributeHealer, childUnresolvedParameters, trust, rowDerivedNames);
5288
+ const childDerivedNames = diffPrintingSecrets([inheritedDerivedNames, rowDerivedNames]);
5289
+ const buildChild = () => buildDiffTree({
4997
5290
  stackName: childStackName,
4998
5291
  displayName: childStackName,
4999
5292
  region,
@@ -5013,10 +5306,12 @@ async function buildDiffTree(args) {
5013
5306
  isNestedChild: true,
5014
5307
  parentHasSecretReference: secretBearingAbove,
5015
5308
  inheritedSecrets: printingSecrets,
5309
+ ...hasMaskableValues(childDerivedNames) && { inheritedDerivedNames: childDerivedNames },
5016
5310
  ...childNoEchoParameters.size > 0 && { inheritedNoEchoParameters: childNoEchoParameters },
5017
5311
  ...childNoEchoParametersAnyVerdict.size > 0 && { inheritedNoEchoParametersAnyVerdict: childNoEchoParametersAnyVerdict },
5018
5312
  ...refusalRecovery && { refusalRecovery }
5019
- }));
5313
+ });
5314
+ node.children.push(await (hasMaskableValues(childDerivedNames) ? withPrintingSecrets(childDerivedNames, buildChild) : buildChild()));
5020
5315
  }
5021
5316
  if (!isNestedChild) {
5022
5317
  const defect = findNestedTemplateTreeDefect(nestedTemplates);
@@ -5025,15 +5320,17 @@ async function buildDiffTree(args) {
5025
5320
  for (const [logicalId, resource] of Object.entries(state.resources ?? {})) {
5026
5321
  if (resource.resourceType !== "AWS::CloudFormation::Stack") continue;
5027
5322
  if (templateChildIds.has(logicalId)) continue;
5028
- node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator, secretBearingAbove, printingSecrets, refusalRecovery));
5323
+ node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator, secretBearingAbove, printingSecrets, refusalRecovery, diffPrintingSecrets([nodeDerivedNames, stateDerivedNames(state.resources ?? {})])));
5029
5324
  }
5030
5325
  return node;
5031
5326
  }
5032
- async function buildDeletedSubtree(stackName, region, stateBackend, diffCalculator, parentHasSecretReference, inheritedSecrets, refusalRecovery) {
5327
+ async function buildDeletedSubtree(stackName, region, stateBackend, diffCalculator, parentHasSecretReference, inheritedSecrets, refusalRecovery, inheritedDerivedNames) {
5033
5328
  const { state, unreadable, unreadableContainers } = await loadStateOrEmpty(stackName, region, stateBackend, refusalRecovery);
5329
+ const derivedNames = diffPrintingSecrets([inheritedDerivedNames, stateDerivedNames(state.resources ?? {})]);
5034
5330
  const { changes, outputChanges } = await computeStackDiff(state, EMPTY_TEMPLATE, region, stackName, stateBackend, diffCalculator, {
5035
5331
  inheritSecretBearingTemplate: parentHasSecretReference,
5036
5332
  inheritedSecrets,
5333
+ ...hasMaskableValues(derivedNames) && { inheritedDerivedNames: derivedNames },
5037
5334
  ...refusalRecovery && { refusalRecovery }
5038
5335
  });
5039
5336
  const node = {
@@ -5053,10 +5350,16 @@ async function buildDeletedSubtree(stackName, region, stateBackend, diffCalculat
5053
5350
  };
5054
5351
  for (const [logicalId, resource] of Object.entries(state.resources ?? {})) {
5055
5352
  if (resource.resourceType !== "AWS::CloudFormation::Stack") continue;
5056
- node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator, parentHasSecretReference, inheritedSecrets, refusalRecovery));
5353
+ node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator, parentHasSecretReference, inheritedSecrets, refusalRecovery, derivedNames));
5057
5354
  }
5058
5355
  return node;
5059
5356
  }
5357
+ function stateDerivedNames(resources) {
5358
+ const bag = /* @__PURE__ */ new Map();
5359
+ const needlesOf = stateSecretNameNeedles(resources);
5360
+ for (const logicalId of Object.keys(resources)) for (const needle of needlesOf(logicalId) ?? []) recordLogOnlyValue(bag, needle);
5361
+ return bag;
5362
+ }
5060
5363
  const EMPTY_ALLOW_SET = /* @__PURE__ */ new Set();
5061
5364
  function diffReplaces(change, record) {
5062
5365
  if (change?.changeType !== "UPDATE") return false;
@@ -10726,19 +11029,40 @@ async function acquireStackLock(opts) {
10726
11029
  get interrupted() {
10727
11030
  return interrupted;
10728
11031
  },
10729
- async release({ failureMessage, beforeRelease }) {
11032
+ async release({ failureMessage, beforeRelease, holdUntil }) {
10730
11033
  if (released) return;
10731
11034
  released = true;
10732
- try {
10733
- await beforeRelease?.();
11035
+ const releaseNow = async () => {
10734
11036
  try {
10735
11037
  await lockManager.releaseLock(stackName, region);
10736
11038
  lockHeld = false;
10737
11039
  } catch (releaseErr) {
10738
11040
  getLogger().warn(safeMsg`${failureMessage}: ${describeAwsFailure(releaseErr).detail}`);
10739
11041
  }
11042
+ };
11043
+ let deferred = false;
11044
+ try {
11045
+ await beforeRelease?.();
11046
+ if (holdUntil !== void 0) {
11047
+ process.removeListener("SIGINT", sigintHandler);
11048
+ let forced = false;
11049
+ const removeDeferred = prependPostCleanupSigintListener(() => {
11050
+ if (!interrupted) {
11051
+ interrupted = true;
11052
+ return;
11053
+ }
11054
+ if (forced || !lockHeld) return;
11055
+ forced = true;
11056
+ lockManager.releaseLock(stackName, region).catch(() => {});
11057
+ process.stderr.write(`\nForce-quit (post-destroy cleanup): stack lock may not be released.${forceQuitRecoveryClause(stackName, region, recovery)}\n`);
11058
+ });
11059
+ holdUntil.defer(holdUntil.work.then(() => void 0, () => void 0).then(releaseNow).finally(removeDeferred));
11060
+ deferred = true;
11061
+ return;
11062
+ }
11063
+ await releaseNow();
10740
11064
  } finally {
10741
- process.removeListener("SIGINT", sigintHandler);
11065
+ if (!deferred) process.removeListener("SIGINT", sigintHandler);
10742
11066
  }
10743
11067
  }
10744
11068
  };
@@ -10846,6 +11170,16 @@ function countProtectedJournaledOrphans(orphans, region) {
10846
11170
  }
10847
11171
  return count;
10848
11172
  }
11173
+ async function releaseRegistryMarkerAfterDestroy(ctx, stackName, region, logger) {
11174
+ if (ctx.crossPrefixCheck === void 0) return;
11175
+ try {
11176
+ const known = await ctx.crossPrefixCheck.cache.knownMarker?.(stackName, region);
11177
+ const released = await ctx.stateBackend.releaseRegistryMarker(stackName, region, known);
11178
+ logger.debug(safeMsg`Stack registry marker: ${released}`);
11179
+ } catch (error) {
11180
+ logger.warn(safeMsg`Could not delete the stack registry marker of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}). It names this state prefix, which no longer ` + `records the stack, so a deploy under another prefix treats it as stale.`);
11181
+ }
11182
+ }
10849
11183
  async function runDestroyForStack(stackName, state, ctx) {
10850
11184
  const providerClasses = await loadProviderClasses();
10851
11185
  const logger = getLogger();
@@ -10860,8 +11194,11 @@ async function runDestroyForStack(stackName, state, ctx) {
10860
11194
  errorCount: 0,
10861
11195
  interrupted: false
10862
11196
  };
11197
+ const retainedForReadoption = [];
11198
+ let retainedEarlier;
10863
11199
  const guardIndeterminateTargets = /* @__PURE__ */ new Set();
10864
11200
  const regionForState = state.region ?? ctx.baseRegion;
11201
+ const crossPrefixScan = ctx.crossPrefixCheck?.cache.full(stackName, regionForState);
10865
11202
  const refusalRecovery = {
10866
11203
  profile: ctx.profile,
10867
11204
  stateBucket: ctx.stateBucket,
@@ -10884,6 +11221,15 @@ async function runDestroyForStack(stackName, state, ctx) {
10884
11221
  const resourceCount = Object.keys(state.resources).length;
10885
11222
  const orphanCount = (state.orphans ?? []).length;
10886
11223
  refuseMalformedOutputsForDestroy(state, stackName, regionForState, refusalRecovery);
11224
+ if (crossPrefixScan) applyCrossPrefixScan(await crossPrefixScan, {
11225
+ stackName,
11226
+ region: regionForState,
11227
+ bucket: ctx.stateBucket,
11228
+ recovery: {
11229
+ profile: ctx.profile,
11230
+ stateBucket: ctx.stateBucket
11231
+ }
11232
+ }, "destroy", (message) => logger.warn(message), (message) => logger.info(message));
10887
11233
  if (resourceCount === 0 && orphanCount === 0 && journaledOrphans.count === 0) {
10888
11234
  logger.info(`Stack ${displayStackName(stackName)} has no resources, cleaning up state...`);
10889
11235
  const emptyLock = await acquireStackLock({
@@ -10907,6 +11253,7 @@ async function runDestroyForStack(stackName, state, ctx) {
10907
11253
  if (!(!recheck || recheckResources === 0 && recheckOrphans === 0)) throw new Error(`Stack ${displayStackName(stackName)} (${displaySafe(regionForState, { asciiOnly: true })}) was empty when this run started but now has ${recheckResources} resource(s) and ${recheckOrphans} rollback-orphaned resource(s) — another cdkd process wrote to it. Re-run the destroy to act on the current state.`);
10908
11254
  await ctx.stateBackend.deleteState(stackName, regionForState);
10909
11255
  logger.info(`${green("✓")} State deleted`);
11256
+ await Promise.all([recordRetainedForReadoption(ctx.stateBackend, stackName, regionForState, [], logger), releaseRegistryMarkerAfterDestroy(ctx, stackName, regionForState, logger)]);
10910
11257
  } finally {
10911
11258
  await emptyLock.release({ failureMessage: "Failed to release lock after empty-state cleanup" });
10912
11259
  }
@@ -10994,11 +11341,14 @@ async function runDestroyForStack(stackName, state, ctx) {
10994
11341
  }
10995
11342
  const renderer = getLiveRenderer();
10996
11343
  let statePreserved = false;
11344
+ let heldTail;
11345
+ let stackFinished = false;
10997
11346
  let journaledOrphanFailures = 0;
10998
11347
  let journaledOrphanSkips = 0;
10999
11348
  const lock = await acquireStackLock({
11000
11349
  ...stackLockBase,
11001
11350
  onFirstSignal: () => {
11351
+ if (stackFinished) return;
11002
11352
  renderer.printAbove(() => {
11003
11353
  process.stderr.write("\nInterrupted — finishing in-flight deletes, then flushing state and releasing the lock (press Ctrl-C again to force-quit)...\n");
11004
11354
  });
@@ -11172,6 +11522,17 @@ async function runDestroyForStack(stackName, state, ctx) {
11172
11522
  if (shouldRetainResource(resource.deletionPolicy)) {
11173
11523
  logger.info(` ⊘ ${displaySafe(logicalId)} (${displaySafe(resource.resourceType)}) retained — DeletionPolicy: ${displaySafe(resource.deletionPolicy)}`);
11174
11524
  result.retainedCount++;
11525
+ if (keptForReadoption(resource)) {
11526
+ retainedForReadoption.push({
11527
+ logicalId,
11528
+ resourceType: resource.resourceType,
11529
+ physicalId: resource.physicalId
11530
+ });
11531
+ if (retainedEarlier === void 0) {
11532
+ retainedEarlier = Promise.resolve().then(() => ctx.stateBackend.loadRetainedRecord(stackName, regionForState));
11533
+ retainedEarlier.catch(() => void 0);
11534
+ }
11535
+ }
11175
11536
  recordDestroyEvent(ctx.eventRecorder, {
11176
11537
  eventType: "RESOURCE_RETAINED",
11177
11538
  stackName,
@@ -11383,7 +11744,16 @@ async function runDestroyForStack(stackName, state, ctx) {
11383
11744
  if (!preserveState) {
11384
11745
  await ctx.stateBackend.deleteState(stackName, regionForState);
11385
11746
  logger.debug("State deleted");
11386
- if (ctx.exportIndexStore) await ctx.exportIndexStore.removeStack(stackName, regionForState);
11747
+ const writeKept = () => recordRetainedForReadoption(ctx.stateBackend, stackName, regionForState, retainedForReadoption, logger, retainedEarlier);
11748
+ const releaseMarker = () => releaseRegistryMarkerAfterDestroy(ctx, stackName, regionForState, logger);
11749
+ if (ctx.deferRegistryTail !== void 0) {
11750
+ heldTail = writeKept().then(releaseMarker);
11751
+ await ctx.exportIndexStore?.removeStack(stackName, regionForState);
11752
+ } else await Promise.all([
11753
+ writeKept(),
11754
+ releaseMarker(),
11755
+ ctx.exportIndexStore?.removeStack(stackName, regionForState)
11756
+ ]);
11387
11757
  } else {
11388
11758
  try {
11389
11759
  await ctx.stateBackend.saveState(stackName, regionForState, buildDestroySnapshot());
@@ -11430,6 +11800,10 @@ async function runDestroyForStack(stackName, state, ctx) {
11430
11800
  try {
11431
11801
  await lock.release({
11432
11802
  failureMessage: `Failed to release lock for stack ${displayStackName(stackName)}`,
11803
+ ...heldTail !== void 0 && ctx.deferRegistryTail !== void 0 && { holdUntil: {
11804
+ work: heldTail,
11805
+ defer: ctx.deferRegistryTail
11806
+ } },
11433
11807
  beforeRelease: async () => {
11434
11808
  try {
11435
11809
  renderer.stop();
@@ -11440,6 +11814,7 @@ async function runDestroyForStack(stackName, state, ctx) {
11440
11814
  logger.debug("Releasing lock...");
11441
11815
  }
11442
11816
  });
11817
+ stackFinished = true;
11443
11818
  } finally {
11444
11819
  restoreBaseRegionAndClients();
11445
11820
  }
@@ -11490,6 +11865,10 @@ function orderConsumersBeforeProducers(stackNames, consumerToProducers) {
11490
11865
  }
11491
11866
  return ordered;
11492
11867
  }
11868
+ function plannedDestroyRegion(refs, synthRegion, cliRegion) {
11869
+ if (refs.length === 1) return refs[0]?.region || cliRegion;
11870
+ if (refs.length > 1 && synthRegion && refs.some((r) => r.region === synthRegion)) return synthRegion;
11871
+ }
11493
11872
  async function purgeEventsAfterDestroy(reader, stackName, region, opts, logger) {
11494
11873
  if (opts.purgeEvents !== true || opts.runResult !== "SUCCEEDED" || opts.interrupted) return null;
11495
11874
  try {
@@ -11547,6 +11926,9 @@ async function destroyCommand(stackArgs, options) {
11547
11926
  interruptWatch.dispose();
11548
11927
  throw error;
11549
11928
  }
11929
+ let stateBackendForCleanup;
11930
+ const deferredTails = [];
11931
+ let deferRegistryTail;
11550
11932
  try {
11551
11933
  const stateConfig = {
11552
11934
  bucket: stateBucket,
@@ -11556,6 +11938,7 @@ async function destroyCommand(stackArgs, options) {
11556
11938
  ...options.region && { region: options.region },
11557
11939
  ...options.profile && { profile: options.profile }
11558
11940
  });
11941
+ stateBackendForCleanup = stateBackend;
11559
11942
  await stateBackend.verifyBucketExists();
11560
11943
  const lockManager = new LockManager(awsClients.s3, stateConfig);
11561
11944
  const exportIndexStore = new ExportIndexStore(awsClients.s3, stateBucket, options.statePrefix, region, stateBackend, { profile: options.profile });
@@ -11698,6 +12081,14 @@ async function destroyCommand(stackArgs, options) {
11698
12081
  arr.push(ref);
11699
12082
  stateRefsByName.set(ref.stackName, arr);
11700
12083
  }
12084
+ const crossPrefixCheck = { cache: new CrossPrefixGuard(stateBackend) };
12085
+ if (stackNames.length > 1) deferRegistryTail = (released) => deferredTails.push(released);
12086
+ for (const name of stackNames) {
12087
+ const synth = appStacks.find((s) => s.stackName === name);
12088
+ if (synth?.terminationProtection === true && !options.removeProtection) continue;
12089
+ const planned = plannedDestroyRegion(stateRefsByName.get(name) ?? [], synth?.region, region);
12090
+ if (planned !== void 0) crossPrefixCheck.cache.full(name, planned, "prestart");
12091
+ }
11701
12092
  for (const [stackIndex, stackName] of stackNames.entries()) {
11702
12093
  logger.info(`\nPreparing to destroy stack: ${displaySafe(stackName)}`);
11703
12094
  const refs = stateRefsByName.get(stackName) ?? [];
@@ -11715,15 +12106,12 @@ async function destroyCommand(stackArgs, options) {
11715
12106
  continue;
11716
12107
  }
11717
12108
  }
12109
+ const plannedRegion = plannedDestroyRegion(refs, synthRegion, region);
11718
12110
  let stackTargetRegion;
11719
12111
  if (refs.length === 0) {
11720
12112
  logger.warn(`No state found for stack ${displaySafe(stackName)}, skipping`);
11721
12113
  continue;
11722
- } else if (refs.length === 1) {
11723
- const onlyRegion = refs[0]?.region;
11724
- if (!onlyRegion) stackTargetRegion = region;
11725
- else stackTargetRegion = onlyRegion;
11726
- } else if (synthRegion && refs.some((r) => r.region === synthRegion)) stackTargetRegion = synthRegion;
12114
+ } else if (plannedRegion !== void 0) stackTargetRegion = plannedRegion;
11727
12115
  else {
11728
12116
  const regions = refs.map((r) => r.region === void 0 ? "(legacy)" : plainOrDescribed(r.region, "region")).join(", ");
11729
12117
  const orphanOneClause = withheldAccountClause(accountRecovery, "the command below prints").trimEnd();
@@ -11801,6 +12189,8 @@ async function destroyCommand(stackArgs, options) {
11801
12189
  skipFinalSnapshot: options.skipFinalSnapshot === true,
11802
12190
  resolveSecretDerivedPrincipals: {},
11803
12191
  stackDestroy: true,
12192
+ crossPrefixCheck,
12193
+ ...deferRegistryTail !== void 0 && { deferRegistryTail },
11804
12194
  exportIndexStore,
11805
12195
  ...TemplateNoEchoReresolver.usable(synthStack?.template) && (synthStack.region === void 0 || synthStack.region === stackTargetRegion) && { noEchoReresolver: new TemplateNoEchoReresolver({
11806
12196
  template: synthStack.template,
@@ -11854,9 +12244,11 @@ async function destroyCommand(stackArgs, options) {
11854
12244
  if (interrupted || interruptWatch.interrupted() && stoppedEarly) throw new PartialFailureError(`Destroy interrupted by Ctrl-C. State preserved — re-run 'cdkd destroy' to finish.`);
11855
12245
  if (totalSkipped > 0) throw new PartialFailureError(`Destroy skipped ${totalSkipped} entr${totalSkipped === 1 ? "y" : "ies"} whose delete cdkd did not confirm, so the underlying resources may still exist in AWS. A skipped nested stack counts as ONE entry and may cover several of its own resources — the per-stack summaries above give the exact breakdown. State preserved (the records are kept). The per-resource 'skipped (...)' lines and their warnings name each cause and whether repairing the record in state.json helps: where it does, repair it and re-run 'cdkd destroy'; otherwise (for example a custom-resource Delete handler that reported FAILED), delete the resources by hand and drop the records with 'cdkd state orphan <stack> --stack-region <region>'.`);
11856
12246
  } finally {
12247
+ await Promise.allSettled(deferredTails);
11857
12248
  unforwardSigterm();
11858
12249
  interruptWatch.dispose();
11859
12250
  awsClients.destroy();
12251
+ stateBackendForCleanup?.destroyClient();
11860
12252
  }
11861
12253
  }
11862
12254
  function createDestroyCommand() {
@@ -14004,7 +14396,7 @@ async function exportCommand(stackArg, options) {
14004
14396
  2. Re-run the phase 2 UPDATE manually with the full synth template:
14005
14397
  ${phase2RetryCommand(cfnStackName)}\n 3. Once phase 2 succeeds, clean up cdkd's stale state record.${orphan.note}\n Run: ${orphan.command}`);
14006
14398
  }
14007
- await stateBackend.deleteState(resolvedStackName, targetRegion);
14399
+ await removeExportedStackRecord(stateBackend, resolvedStackName, targetRegion, logger);
14008
14400
  logger.info(`cdkd state for ${quotedOrNotShown(resolvedStackName)} (${quotedRegion(targetRegion)}) removed. Manage the stack with 'cdk deploy' or 'aws cloudformation' from here on.`);
14009
14401
  printNextSteps({
14010
14402
  cfnStackName,
@@ -15608,6 +16000,11 @@ async function buildResolvedParametersPerStack(args) {
15608
16000
  intrinsicSkippedByCdkdName
15609
16001
  };
15610
16002
  }
16003
+ async function removeExportedStackRecord(stateBackend, stackName, region, logger) {
16004
+ await stateBackend.deleteState(stackName, region);
16005
+ await recordRetainedForReadoption(stateBackend, stackName, region, [], logger);
16006
+ await releaseRegistryMarkerQuietly(stateBackend, stackName, region, logger);
16007
+ }
15611
16008
  async function runPerStackImportLoop(args) {
15612
16009
  const logger = getLogger();
15613
16010
  const { rootStackName, rootRegion, rootStackInfoNestedTemplates, rootTemplateFormat, tree, rootTemplate, cfnStackNameOverrides, rootParameters, deps, options } = args;
@@ -15885,7 +16282,7 @@ async function runPerStackImportLoop(args) {
15885
16282
  }
15886
16283
  const stateDeletionFailures = [];
15887
16284
  for (const node of leafFirst) try {
15888
- await deps.stateBackend.deleteState(node.stackName, node.region);
16285
+ await removeExportedStackRecord(deps.stateBackend, node.stackName, node.region, logger);
15889
16286
  logger.info(`cdkd state for ${quotedOrNotShown(node.stackName)} (${quotedRegion(node.region)}) removed.`);
15890
16287
  } catch (err) {
15891
16288
  stateDeletionFailures.push({
@@ -16111,6 +16508,10 @@ const STATE_READ_REASONS = {
16111
16508
  "read-failed": STATE_READ_FAILED_REASON,
16112
16509
  "resources-malformed": "resources is not a JSON object; run `cdkd state show --json` to see the record"
16113
16510
  };
16511
+ function stateDestroyTargets(refs, stackRegion) {
16512
+ if (stackRegion) return refs.filter((r) => r.region === stackRegion || !r.region);
16513
+ return refs.length === 1 ? [...refs] : void 0;
16514
+ }
16114
16515
  function resourceCountOrNull(resources) {
16115
16516
  if (resources === void 0 || resources === null) return 0;
16116
16517
  if (typeof resources !== "object" || Array.isArray(resources)) return null;
@@ -16231,7 +16632,10 @@ async function setupStateBackend(options) {
16231
16632
  bucket,
16232
16633
  prefix,
16233
16634
  exportIndexStore: new ExportIndexStore(awsClients.s3, bucket, prefix, region, stateBackend, { profile: options.profile }),
16234
- dispose: () => awsClients.destroy()
16635
+ dispose: () => {
16636
+ awsClients.destroy();
16637
+ stateBackend.destroyClient();
16638
+ }
16235
16639
  };
16236
16640
  }
16237
16641
  function renderRecovery(options, setup) {
@@ -16672,6 +17076,43 @@ function createStateShowCommand() {
16672
17076
  cmd.addOption(deprecatedRegionOption);
16673
17077
  return cmd;
16674
17078
  }
17079
+ async function clearRetainedQuietly(backend, stackName, region, logger) {
17080
+ try {
17081
+ await backend.saveRetainedResources(stackName, region, []);
17082
+ return true;
17083
+ } catch (error) {
17084
+ logger.warn(safeMsg`Could not empty the kept-resource record of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}): a later deploy here may still take a kept ` + `resource back. Re-run 'cdkd state orphan' once it can write.`);
17085
+ return false;
17086
+ }
17087
+ }
17088
+ async function clearRetainedWithoutRecord(backend, stackName, stackRegion, logger) {
17089
+ if (stackName.includes("/")) return {
17090
+ cleared: [],
17091
+ attempted: 0
17092
+ };
17093
+ const base = `${backend.prefix}/${stackName}/`;
17094
+ let regions;
17095
+ try {
17096
+ const keys = (await backend.listRawKeys(base)).map((key) => key.slice(base.length).split("/")).filter((parts) => parts.length >= 2 && parts[0] !== "");
17097
+ const recorded = new Set(keys.filter((parts) => parts.length === 2 && parts[1] === "state.json").map((parts) => parts[0]));
17098
+ regions = [...new Set(keys.map((parts) => parts[0]).filter((region) => stackRegion === void 0 || region === stackRegion).filter((region) => !recorded.has(region)))];
17099
+ } catch (error) {
17100
+ logger.warn(safeMsg`Could not look for a kept-resource record of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}).`);
17101
+ return {
17102
+ cleared: [],
17103
+ attempted: 0
17104
+ };
17105
+ }
17106
+ const cleared = [];
17107
+ for (const region of regions) {
17108
+ if (await clearRetainedQuietly(backend, stackName, region, logger)) cleared.push(region);
17109
+ await releaseRegistryMarkerQuietly(backend, stackName, region, logger);
17110
+ }
17111
+ return {
17112
+ cleared,
17113
+ attempted: regions.length
17114
+ };
17115
+ }
16675
17116
  async function stateOrphanCommand(stackArgs, options) {
16676
17117
  const logger = getLogger();
16677
17118
  if (options.verbose) logger.setLevel("debug");
@@ -16687,6 +17128,12 @@ async function stateOrphanCommand(stackArgs, options) {
16687
17128
  for (const stackName of stackArgs) {
16688
17129
  const stackRefs = refs.filter((r) => r.stackName === stackName);
16689
17130
  if (stackRefs.length === 0) {
17131
+ const { cleared, attempted } = await clearRetainedWithoutRecord(setup.stateBackend, stackName, options.stackRegion, logger);
17132
+ if (attempted > 0 && cleared.length === 0) continue;
17133
+ if (cleared.length > 0) {
17134
+ logger.info(safeMsg`Cleared the kept-resource record of ${plainOrDescribed(stackName, "stack name")} ` + safeMsg`(${cleared.map((r) => displaySafe(r, { asciiOnly: true })).join(", ")}): ` + `a later deploy here no longer takes a kept resource back.`);
17135
+ continue;
17136
+ }
16690
17137
  logger.info(safeMsg`No state found for stack: ${plainOrDescribed(stackName, "stack name")}, skipping` + (isPasteableIdent(stackName) ? "" : safeMsg`. ${STATE_LIST_POINTER}`));
16691
17138
  continue;
16692
17139
  }
@@ -16730,10 +17177,13 @@ async function stateOrphanCommand(stackArgs, options) {
16730
17177
  await warnOnLiveForeignLock(setup.lockManager, stackName, target.region, logger);
16731
17178
  await setup.stateBackend.deleteState(stackName, target.region);
16732
17179
  await setup.lockManager.forceReleaseLock(stackName, target.region);
17180
+ await clearRetainedQuietly(setup.stateBackend, stackName, target.region, logger);
17181
+ await releaseRegistryMarkerQuietly(setup.stateBackend, stackName, target.region, logger);
16733
17182
  } else {
16734
17183
  await warnOnLiveForeignLock(setup.lockManager, stackName, void 0, logger);
16735
17184
  await setup.stateBackend.deleteLegacyState(stackName);
16736
17185
  await setup.lockManager.forceReleaseLock(stackName, void 0);
17186
+ await clearRetainedWithoutRecord(setup.stateBackend, stackName, void 0, logger);
16737
17187
  }
16738
17188
  logger.info(safeMsg`✓ Removed state for stack: ${describedStackRef(target)}` + ((options.yes || options.force) && refIsDescribed(target) ? safeMsg`. ${STATE_LIST_POINTER}` : ""));
16739
17189
  }
@@ -16881,6 +17331,8 @@ async function stateDestroyCommand(stackArgs, options) {
16881
17331
  interruptWatch.dispose();
16882
17332
  throw error;
16883
17333
  }
17334
+ const deferredTails = [];
17335
+ let deferRegistryTail;
16884
17336
  try {
16885
17337
  const stateRefs = await setup.stateBackend.listStacks();
16886
17338
  const knownStackNames = new Set(stateRefs.map((r) => r.stackName));
@@ -16898,16 +17350,23 @@ async function stateDestroyCommand(stackArgs, options) {
16898
17350
  if (!options.stackRegion) return laterRefs.length > 0;
16899
17351
  return laterRefs.some((r) => r.region === options.stackRegion || !r.region);
16900
17352
  });
17353
+ const crossPrefixCheck = { cache: new CrossPrefixGuard(setup.stateBackend) };
17354
+ if (stackNames.length > 1) deferRegistryTail = (released) => deferredTails.push(released);
17355
+ for (const name of stackNames) {
17356
+ const refs = stateRefs.filter((r) => r.stackName === name);
17357
+ for (const ref of stateDestroyTargets(refs, options.stackRegion) ?? []) crossPrefixCheck.cache.full(name, ref.region ?? setup.region, "prestart");
17358
+ }
16901
17359
  for (const [stackIndex, stackName] of stackNames.entries()) {
16902
17360
  const refs = stateRefs.filter((r) => r.stackName === stackName);
16903
17361
  let targets;
17362
+ const planned = stateDestroyTargets(refs, options.stackRegion);
16904
17363
  if (options.stackRegion) {
16905
- targets = refs.filter((r) => r.region === options.stackRegion || !r.region);
17364
+ targets = planned ?? [];
16906
17365
  if (targets.length === 0) {
16907
17366
  logger.warn(safeMsg`Skipping ${plainOrDescribed(stackName, "stack name")} (no state record matches ` + safeMsg`--stack-region ${displayIdent(options.stackRegion)})`);
16908
17367
  continue;
16909
17368
  }
16910
- } else if (refs.length === 1) targets = refs;
17369
+ } else if (planned !== void 0) targets = planned;
16911
17370
  else throw multipleRegionsError(stackName, refs, `Use --stack-region ${commandHole("region")} to pick one.`);
16912
17371
  for (const [refIndex, ref] of targets.entries()) {
16913
17372
  logger.info(safeMsg`\nPreparing to destroy stack: ${formatStackRefSafe(ref)}`);
@@ -16964,6 +17423,8 @@ async function stateDestroyCommand(stackArgs, options) {
16964
17423
  skipFinalSnapshot: options.skipFinalSnapshot === true,
16965
17424
  resolveSecretDerivedPrincipals: {},
16966
17425
  stackDestroy: true,
17426
+ crossPrefixCheck,
17427
+ ...deferRegistryTail !== void 0 && { deferRegistryTail },
16967
17428
  exportIndexStore: setup.exportIndexStore,
16968
17429
  ...options.allowUnsupportedTypes?.length && { allowUnsupportedTypes: options.allowUnsupportedTypes },
16969
17430
  ...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
@@ -17004,6 +17465,7 @@ async function stateDestroyCommand(stackArgs, options) {
17004
17465
  if (interrupted || interruptWatch.interrupted() && stoppedEarly) throw new PartialFailureError(`Destroy interrupted by Ctrl-C. State preserved — re-run 'cdkd state destroy' to finish.`);
17005
17466
  if (totalSkipped > 0) throw new PartialFailureError(`Destroy skipped ${totalSkipped} entr${totalSkipped === 1 ? "y" : "ies"} whose delete cdkd did not confirm, so the underlying resources may still exist in AWS. A skipped nested stack counts as ONE entry and may cover several of its own resources — the per-stack summaries above give the exact breakdown. State preserved (the records are kept). The per-resource 'skipped (...)' lines and their warnings name each cause and whether repairing the record in state.json helps: where it does, repair it and re-run 'cdkd state destroy'; otherwise (for example a custom-resource Delete handler that reported FAILED), delete the resources by hand and drop the records with 'cdkd state orphan <stack> --stack-region <region>'.`);
17006
17467
  } finally {
17468
+ await Promise.allSettled(deferredTails);
17007
17469
  unforwardSigterm();
17008
17470
  interruptWatch.dispose();
17009
17471
  setup.dispose();
@@ -17666,6 +18128,7 @@ async function rollbackCommand(stackArg, options) {
17666
18128
  });
17667
18129
  return;
17668
18130
  }
18131
+ const crossPrefixScan = new CrossPrefixGuard(setup.stateBackend).full(stackName, region);
17669
18132
  stackAwsClients = new AwsClients({
17670
18133
  region,
17671
18134
  ...options.profile && { profile: options.profile }
@@ -17700,6 +18163,15 @@ async function rollbackCommand(stackArg, options) {
17700
18163
  segments: journal.segments.filter((s) => s.reason !== NESTED_PENDING_PARENT_REASON)
17701
18164
  };
17702
18165
  if (!journal || journal.segments.length === 0 && orphanedPending === 0) throw new Error(`Nothing to roll back for ${plainOrDescribed(stackName, "stack name")} (${plainOrDescribed(region, "region")}). Run 'cdkd deploy' to (re)deploy, or 'cdkd destroy' to clean up.`);
18166
+ applyCrossPrefixScan(await crossPrefixScan, {
18167
+ stackName,
18168
+ region,
18169
+ bucket: setup.bucket,
18170
+ recovery: {
18171
+ profile: options.profile,
18172
+ stateBucket: setup.bucket
18173
+ }
18174
+ }, "rollback", (message) => logger.warn(message), (message) => logger.info(message));
17703
18175
  if (!stateData) throw new Error(`Rollback journal exists for ${safeStack(stackName)} (${safe(region)}) but its state.json is missing (keys: ${safe(setup.prefix)}/${safeStack(stackName)}/${safe(region)}/state.json and .../rollback-journal.json). State appears corrupted — inspect the bucket manually.`);
17704
18176
  demoteSupersededOrphans(journal.segments, Array.isArray(stateData.state.orphans) ? stateData.state.orphans : []);
17705
18177
  if (!options.revertFailed) for (const segment of journal.segments) {
@@ -17869,6 +18341,7 @@ async function rollbackCommand(stackArg, options) {
17869
18341
  let failedOpFailures = 0;
17870
18342
  let failedOpWarnings = 0;
17871
18343
  const failedOps = splitImportedOps(segment.failedOperations ?? [], segment);
18344
+ const failedForGuard = segment.failedOperations ?? [];
17872
18345
  const failedToReplay = failedOpsToReplay(failedOps.replay, options.revertFailed === true);
17873
18346
  if (failedToReplay.length > 0) {
17874
18347
  const failedResult = await withPrintingSecrets(failedOpsPrinting, () => withPrintingSecrets(journaledOrphanPrintingBag(failedToReplay, stateResources), () => replayFailedOperations(failedToReplay, stateResources, stackName, ctx, {
@@ -17885,7 +18358,8 @@ async function rollbackCommand(stackArg, options) {
17885
18358
  ...failedOps.imported,
17886
18359
  ...failedOps.displaced,
17887
18360
  ...failedOps.replay.filter((op) => !failedToReplay.includes(op)),
17888
- ...failedResult.remainingFailedOps
18361
+ ...failedResult.remainingFailedOps,
18362
+ ...completedOps.length > 0 ? failedToReplay.filter((op) => seedsDeleteFirstGuard(op) && !failedResult.remainingFailedOps.includes(op)) : []
17889
18363
  ];
17890
18364
  if (!declinedDivergentRewrite && remaining.length !== (segment.failedOperations ?? []).length) try {
17891
18365
  await setup.stateBackend.setRollbackJournalFailedOperations(stackName, region, remaining);
@@ -17905,7 +18379,8 @@ async function rollbackCommand(stackArg, options) {
17905
18379
  afterOp: saveState,
17906
18380
  isInterrupted: () => interrupted,
17907
18381
  onOrphan: (record) => mintedOrphans.push(record),
17908
- inlinePolicyWriters
18382
+ inlinePolicyWriters,
18383
+ failedOperations: failedForGuard
17909
18384
  }));
17910
18385
  return {
17911
18386
  failures: replayResult.failures + failedOpFailures,
@@ -17940,6 +18415,8 @@ async function rollbackCommand(stackArg, options) {
17940
18415
  const survivingOrphans = orphansAfterRollback(baseState, mintedOrphans).orphans ?? [];
17941
18416
  if (journal.segments.length === 0 && oldestInitialDeploy && Object.keys(stateResources).length === 0 && survivingOrphans.length === 0) {
17942
18417
  await setup.stateBackend.deleteState(stackName, region);
18418
+ await recordRetainedForReadoption(setup.stateBackend, stackName, region, [], logger);
18419
+ await releaseRegistryMarkerQuietly(setup.stateBackend, stackName, region, logger);
17943
18420
  logger.info(`State for ${stackRegionShown(stackName, region)} removed (stack fully rolled back).`);
17944
18421
  }
17945
18422
  if (declinedDivergentRewrite) throw new PartialFailureError(`Rollback stopped: ${declinedDivergentReason}.` + (totalFailures > 0 ? ` ${totalFailures} operation(s) also failed.` : "") + " Journal preserved (this segment, any older ones, and their failed operations) — re-run the rollback once the record's region field matches its key.");
@@ -19087,8 +19564,20 @@ async function forceUnlockCommand(stackArgs, options) {
19087
19564
  const where = r ? `${displayStackName(stackName)} (${displayIdent(r)})` : `${displayStackName(stackName)} (legacy lock key)`;
19088
19565
  logger.info(`Force-unlocking stack: ${where}`);
19089
19566
  try {
19090
- await lockManager.forceReleaseLock(stackName, r);
19567
+ let ledgerError;
19568
+ let recorded = false;
19569
+ await lockManager.forceReleaseLock(stackName, r, async (horizon) => {
19570
+ if (r === void 0) return;
19571
+ const ledger = ledgerForStack(stateBackend, stackName, r);
19572
+ for (let attempt = 0; attempt < 2 && !recorded; attempt++) try {
19573
+ await ledger.noteAbandoned(horizon);
19574
+ recorded = true;
19575
+ } catch (error) {
19576
+ ledgerError = error;
19577
+ }
19578
+ });
19091
19579
  logger.info(`✓ Lock released for stack: ${where}`);
19580
+ if (!recorded && ledgerError !== void 0) logger.warn(safeMsg`Lock released, but the create-token ledger of ${where} could not record when the ` + safeMsg`abandoned run stopped: ${describeAwsFailure(ledgerError).summary}. ` + "A later deploy may take back a resource of those names that another deployment creates.");
19092
19581
  } catch (error) {
19093
19582
  const message = describeAwsFailure(error).detail;
19094
19583
  if (message.includes("No lock found") || message.includes("NoSuchKey")) logger.info(`No lock found for stack: ${where}`);
@@ -19198,6 +19687,20 @@ var ObservedBaselineRefusals = class extends Set {
19198
19687
  unverifiableParameter = /* @__PURE__ */ new Set();
19199
19688
  hadDeployedParameterSource = false;
19200
19689
  };
19690
+ async function claimRegistryMarkerAfterImport(backend, stackName, region, logger) {
19691
+ const answer = await new CrossPrefixGuard(backend).full(stackName, region);
19692
+ const regionShown = displaySafe(region, { asciiOnly: true });
19693
+ switch (answer.kind) {
19694
+ case "clear": return;
19695
+ case "found":
19696
+ logger.warn(safeMsg`The state bucket also records ${displayStackName(stackName)} (${regionShown}) under another state prefix ` + safeMsg`(${answer.prefixes.map((p) => displayIdent(p)).join(", ")}). One stack name per ` + "account and region is supported: drop one of the records with 'cdkd state orphan' before deploying or destroying either.");
19697
+ return;
19698
+ case "in-progress":
19699
+ logger.warn(safeMsg`A deploy of ${displayStackName(stackName)} (${regionShown}) holds a lock under another state prefix ` + safeMsg`(${displayIdent(answer.prefix)}). One stack name per account and region is ` + `supported: keep one of the two before deploying or destroying either.`);
19700
+ return;
19701
+ default: logger.warn(safeMsg`Could not record ${displayStackName(stackName)} (${regionShown}) in the state bucket's stack registry` + (answer.kind === "denied" || answer.kind === "failed" ? safeMsg` (${describeAwsFailure(answer.error).summary})` : "") + `. Its next guarded command records it.`);
19702
+ }
19703
+ }
19201
19704
  async function importCommand(stackArg, options) {
19202
19705
  const providerClasses = await loadProviderClasses();
19203
19706
  const logger = getLogger();
@@ -19418,6 +19921,7 @@ async function importCommand(stackArg, options) {
19418
19921
  await recordImportOnRollbackJournal(stateBackend, stackInfo.stackName, targetRegion, importedRows.map((r) => r.logicalId), stackState.resources, logger);
19419
19922
  await stateBackend.saveState(stackInfo.stackName, targetRegion, stackState, saveOptions);
19420
19923
  logger.info(`✓ State written: ${stackInfo.stackName} (${targetRegion})`);
19924
+ await claimRegistryMarkerAfterImport(stateBackend, stackInfo.stackName, targetRegion, logger);
19421
19925
  logger.info(` ${importedRows.length} resource(s) imported. Run 'cdkd diff' to see how the imported state lines up with the template.`);
19422
19926
  if (migrationCfnStackName && migrationTree && accountIdForNestedSynth) await importNestedStackChildrenRecursive({
19423
19927
  lockRecovery,
@@ -27745,4 +28249,4 @@ function collectVerbFlags(program) {
27745
28249
 
27746
28250
  //#endregion
27747
28251
  export { canonicalizeIpProtocolValue as a, buildProgram, resolveSecretDerivedPrincipals as i, runDestroyForStack as n, resolvedResourceTimeoutMs as o, isResolvableSecretPrincipalList as r, canonicalizeIpv4Cidr as t };
27748
- //# sourceMappingURL=program-BwNb3_Ot.js.map
28252
+ //# sourceMappingURL=program-CN7Dqb3j.js.map