@go-to-k/cdkd 0.306.0 → 0.307.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/{asg-provider-DrREeZeh.js → asg-provider-oKlrkJeO.js} +4 -4
  2. package/dist/{asg-provider-DrREeZeh.js.map → asg-provider-oKlrkJeO.js.map} +1 -1
  3. package/dist/{aws-clients-DhsLtXsN.js → aws-clients-Bu9EMILF.js} +3 -4
  4. package/dist/aws-clients-Bu9EMILF.js.map +1 -0
  5. package/dist/{aws-failure-text-Durl920o.js → aws-failure-text-NSBdKPYK.js} +7 -1
  6. package/dist/aws-failure-text-NSBdKPYK.js.map +1 -0
  7. package/dist/cli.js +2 -2
  8. package/dist/{db-instance-modify-retry-DvidzfJp.js → db-instance-modify-retry-DOJPkECL.js} +3 -3
  9. package/dist/{db-instance-modify-retry-DvidzfJp.js.map → db-instance-modify-retry-DOJPkECL.js.map} +1 -1
  10. package/dist/{deploy-engine-Bjr-FAuZ.js → deploy-engine-BOgsnnk0.js} +477 -49
  11. package/dist/deploy-engine-BOgsnnk0.js.map +1 -0
  12. package/dist/{iam-policy-targets-BbtwI9vN.js → iam-policy-targets-TFGunWmV.js} +56 -56
  13. package/dist/{iam-policy-targets-BbtwI9vN.js.map → iam-policy-targets-TFGunWmV.js.map} +1 -1
  14. package/dist/{iam-role-provider-BJ26M4Ez.js → iam-role-provider-DfDYgfqK.js} +5 -5
  15. package/dist/{iam-role-provider-BJ26M4Ez.js.map → iam-role-provider-DfDYgfqK.js.map} +1 -1
  16. package/dist/index.js +5 -5
  17. package/dist/{neptune-provider-D_3VAhFf.js → neptune-provider-DvuvSkfJ.js} +5 -5
  18. package/dist/{neptune-provider-D_3VAhFf.js.map → neptune-provider-DvuvSkfJ.js.map} +1 -1
  19. package/dist/{program-CcYD-_fU.js → program-DU5UlgkO.js} +7 -7
  20. package/dist/{program-CcYD-_fU.js.map → program-DU5UlgkO.js.map} +1 -1
  21. package/dist/{provider-classes-C_AbFNEi.js → provider-classes-CPMW_2-R.js} +701 -175
  22. package/dist/provider-classes-CPMW_2-R.js.map +1 -0
  23. package/dist/{rds-provider-Dps9UxBz.js → rds-provider-DcBsBQLi.js} +5 -5
  24. package/dist/{rds-provider-Dps9UxBz.js.map → rds-provider-DcBsBQLi.js.map} +1 -1
  25. package/dist/{version-CZkNvTWF.js → version-Dhhyrf1v.js} +2 -2
  26. package/dist/{version-CZkNvTWF.js.map → version-Dhhyrf1v.js.map} +1 -1
  27. package/package.json +2 -2
  28. package/dist/aws-clients-DhsLtXsN.js.map +0 -1
  29. package/dist/aws-failure-text-Durl920o.js.map +0 -1
  30. package/dist/deploy-engine-Bjr-FAuZ.js.map +0 -1
  31. package/dist/provider-classes-C_AbFNEi.js.map +0 -1
@@ -1,14 +1,14 @@
1
- import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-DhsLtXsN.js";
2
- import { B as SECRET_REF_MAX_CODE_POINTS, C as generateResourceName, D as getCurrentStackInstanceId, J as displayStackName, K as displayIdent, M as recordedGeneratedNameKept, Q as safeMsg, T as generatedNameFor, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify, i as isAwsAuthoredFailure, k as isBeforeStateRead, n as describeAwsFailure, q as displaySafe, r as describeAwsStatusReason, s as getLogger, t as VERBOSE_POINTER, w as generateResourceNameWithFallback } from "./aws-failure-text-Durl920o.js";
3
- import { $ as userPoolProtectionSite, $t as injectiveKeyPrefix, A as isPlainImportJson, C as setBounded, Cr as markNonRetryable, Ct as createMaskedLogSinks, D as markNotGone, Dn as ResourceUpdateNotSupportedError, Dt as maskerOrIdentity, Et as maskDeep, F as refusalTypeShown, Ft as isAuxiliaryFailure, H as deleteWithProtectionCompensation, Hn as hasClauseBreak, I as remedyLogicalId, J as observeThenDisableProtection, K as isTerminalDeleteFailure, Kn as plainOrDescribed, L as resolveExplicitPhysicalId, Lt as markAuxiliaryFailure, M as isQuotableImportValue, N as normalizeAwsTagsToCfn, O as assertRegionMatch, Ot as withDerivedNameMasks, P as quotedRemedyLogicalId, Qt as injectiveKey, Rt as markCreatedBeforeFailure, S as replayedSendWindow, Sr as isThrottlingError, St as stateOrphanRecordRemedy, T as RESOURCE_NOT_FOUND, Tn as ProvisioningError, Tr as wrapMaskedAwsError, Tt as isSecretDerivedValue, Un as isInertUnquoted, V as deleteAfterProtectionFlipWithFinalSnapshot, Vn as commandHole, Wn as pasteableCommand, X as rdsFamilyProtectionSite, Xn as withheldTargetClause, Y as protectionFlipKey, Yn as shellQuote, _ as RecentIdSet, _r as isRetryableTransientError, _t as compositeIdSkipResult, a as onlySecretDerived, an as ambientCredentialConfig, ar as markNameCollision, at as protectedReplacementAdvice, b as isInsideWindow, br as THROTTLING_ERROR_NAMES, c as recordedPrincipalsRepair, cn as AccountIdUnavailableError, dr as explicitDenyPolicyKind, dt as startInterruptWatch, ft as ElapsedBudgetRegistry, g as AmbiguousCreateLatch, gt as compositeIdSeparatorRefusal, h as AMBIGUOUS_LATCH_TTL_MS, hr as isExplicitDenyError, ht as compositeIdFormatMessage, i as holdsSecretDerivedEntry, in as ambientClientDefaults, it as pasteableAwsCommand, j as isPlainImportValue, jt as clearCreatedBeforeFailure, k as VALUE_NOT_SHOWN, mr as isAmbiguousOutcomeError, mt as canonicalizeRoute53QueryName, nt as WITHHELD_AWS_COMMAND, o as readPrincipalLists, on as clientDefaultsFor, or as markReplayMayCollide, ot as renderDisableCommand, p as withRemovalDefaults, q as logGroupProtectionSite, r as SECRET_DERIVED_READ_LIVE, rn as withPasteableAwsProfile, rt as isAwsCliLiteral, sn as credentialFingerprint, sr as relayedNameCollision, tt as UNNAMEABLE_ID_CLAUSE, u as clearOnUpdateRemoval, un as CdkdError, ut as isInterruptedWaitError, v as ambiguousAttemptLead, vr as isTransientServerError, vt as logicalIdShown, w as withoutServerErrorRetries, wr as markRedactedCause, wt as createMaskedRetryLogger, x as replayFollowedAmbiguousAttempt, xr as isMarkedNonRetryable, xt as segmentAfterAnchor, y as createAttemptKey, yt as packCompositeId, z as ProtectionFlipRegistry, zt as markSupersedesEarlierCreate } from "./iam-policy-targets-BbtwI9vN.js";
1
+ import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-Bu9EMILF.js";
2
+ import { B as SECRET_REF_MAX_CODE_POINTS, C as generateResourceName, D as getCurrentStackInstanceId, J as displayStackName, K as displayIdent, M as recordedGeneratedNameKept, Q as safeMsg, T as generatedNameFor, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify, i as isAwsAuthoredFailure, k as isBeforeStateRead, n as describeAwsFailure, q as displaySafe, r as describeAwsStatusReason, s as getLogger, t as VERBOSE_POINTER, w as generateResourceNameWithFallback } from "./aws-failure-text-NSBdKPYK.js";
3
+ import { $ as userPoolProtectionSite, $t as injectiveKeyPrefix, A as isPlainImportJson, C as setBounded, Cr as markNonRetryable, Ct as createMaskedLogSinks, D as markNotGone, Dn as ResourceUpdateNotSupportedError, Dt as maskerOrIdentity, Et as maskDeep, F as refusalTypeShown, Ft as isAuxiliaryFailure, H as deleteWithProtectionCompensation, Hn as hasClauseBreak, I as remedyLogicalId, J as observeThenDisableProtection, K as isTerminalDeleteFailure, Kn as plainOrDescribed, L as resolveExplicitPhysicalId, Lt as markAuxiliaryFailure, M as isQuotableImportValue, N as normalizeAwsTagsToCfn, O as assertRegionMatch, Ot as withDerivedNameMasks, P as quotedRemedyLogicalId, Qt as injectiveKey, Rt as markCreatedBeforeFailure, S as replayedSendWindow, Sr as isThrottlingError, St as stateOrphanRecordRemedy, T as RESOURCE_NOT_FOUND, Tn as ProvisioningError, Tr as wrapMaskedAwsError, Tt as isSecretDerivedValue, Un as isInertUnquoted, V as deleteAfterProtectionFlipWithFinalSnapshot, Vn as commandHole, Wn as pasteableCommand, X as rdsFamilyProtectionSite, Xn as withheldTargetClause, Y as protectionFlipKey, Yn as shellQuote, _ as RecentIdSet, _r as isRetryableTransientError, _t as compositeIdSkipResult, a as onlySecretDerived, an as ambientCredentialConfig, ar as markNameCollision, at as protectedReplacementAdvice, b as isInsideWindow, br as THROTTLING_ERROR_NAMES, c as recordedPrincipalsRepair, cn as AccountIdUnavailableError, dr as explicitDenyPolicyKind, ft as isInterruptedWaitError, g as AmbiguousCreateLatch, gt as compositeIdSeparatorRefusal, h as AMBIGUOUS_LATCH_TTL_MS, hr as isExplicitDenyError, ht as compositeIdFormatMessage, i as holdsSecretDerivedEntry, in as ambientClientDefaults, it as pasteableAwsCommand, j as isPlainImportValue, jt as clearCreatedBeforeFailure, k as VALUE_NOT_SHOWN, mr as isAmbiguousOutcomeError, mt as canonicalizeRoute53QueryName, nt as WITHHELD_AWS_COMMAND, o as readPrincipalLists, on as clientDefaultsFor, or as markReplayMayCollide, ot as renderDisableCommand, p as withRemovalDefaults, pt as startInterruptWatch, q as logGroupProtectionSite, r as SECRET_DERIVED_READ_LIVE, rn as withPasteableAwsProfile, rt as isAwsCliLiteral, sn as credentialFingerprint, sr as relayedNameCollision, st as ElapsedBudgetRegistry, tt as UNNAMEABLE_ID_CLAUSE, u as clearOnUpdateRemoval, un as CdkdError, v as ambiguousAttemptLead, vr as isTransientServerError, vt as logicalIdShown, w as withoutServerErrorRetries, wr as markRedactedCause, wt as createMaskedRetryLogger, x as replayFollowedAmbiguousAttempt, xr as isMarkedNonRetryable, xt as segmentAfterAnchor, y as createAttemptKey, yt as packCompositeId, z as ProtectionFlipRegistry, zt as markSupersedesEarlierCreate } from "./iam-policy-targets-TFGunWmV.js";
4
4
  import { c as ambientRegion } from "./aws-client-defaults-BX9Y_fKp.js";
5
- import { $r as markDeleteStarted, Ai as deleteSkipReason, Bs as passedNoEchoParametersOf, C as hasCdkAutoDeleteTag, Cc as recordAttributeIdCopy, Ds as lambdaFunctionNameForMask, Dt as lookupEachName, E as markRefusedBeforeApplying, Ec as carriesSecretMask, Es as canonicalLambdaFunctionName, Et as isAccessDeniedError, F as findNestedTemplateTreeDefect, Fi as ec2InstanceProtectionSite, Fu as displayAssemblyPath, Gi as s3BucketArn, I as isAbsoluteAssetPath, Ii as isTerminationProtectionPropagationError, Io as refuseMalformedResourcesForDestroy, Iu as renderAssemblyPathEscape, Ji as s3BucketRegionalDomainName, Jo as withheldAccountClause, Jr as acquireIdempotencyToken, Js as recordReferenceProvenanceEntry, Ki as s3BucketDomainName, Kr as reserveStackCreateToken, Ks as markSameGenerationBag, L as listNestedTemplateRows, Li as observeThenDisableInstanceApiTermination, Lu as resolveAssemblyPath, Mi as isWaitAbandonedError, Ni as markWaitAbandoned, Os as sameLambdaFunctionAddress, Ot as withApiLimit, Pa as passedParameterClassesOf, Pu as describeFileReadFailure, Qn as awaitInFlightSibling, Qo as withoutSilentDropProperties, Qr as isRefusedByName, Qs as hasMaskableValues, R as renderNestedTemplateTreeDefect, Ri as reDisableInstanceApiTermination, S as S3_AUTO_DELETE_OBJECTS_TAG, Sc as physicalNameCopiesOf, T as getPriorAttempts, Ti as unchangedBehindSecretReference, Ts as withRetry, Tt as chunks, Va as accountArgs, W as enclosingDeadlineRemainingMs, Wi as isSettledInstanceState, Wr as earliestDefined, Xo as findSilentDropProperties, Yi as s3BucketWebsiteUrl, Ys as snapshotPassProvenance, _ as deleteTableWithIndexBusyRetry, _s as readConfigString, _u as decodeListingKey, ai as tagMapAsList, an as isRedactedRecordedValue, b as waitForIndexesSettled, ba as getAccountInfo, bs as requireConfigObject, bu as canonicalizeRegion, c as DynamoDBGlobalTableProvider, ci as stringifyIfAssigned, cs as coerceWarmThroughput$1, d as compensateRemovedDeletionProtection, ds as toFiniteNumber, ea as outputReferenceProvenanceOf, ei as DBPROXY_TAGS_WHAT, er as getStackRecords, f as deleteBudgetKey, fc as withoutPhysicalNameCopies, fs as coerceCfnBoolean, g as INDEX_SETTLE_POLL_INTERVAL_MS, go as refuseMalformedNestedChildOutputs, gs as configStringRefusal, h as DELETE_INDEX_WAIT_PROCEED_NOTE, hs as configIntegerRefusal, ht as withNestedStackContext, ii as refuseMalformedDesiredTags, in as REDACTED_DELETE_ADDRESS_SKIP_REASON, ja as parseWebACLArn, ji as withIndeterminateGuard, jr as secretNamedAttributeNamesOf, l as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, ls as isWarmThroughputDecrease, m as resolveDynamoDbDeleteBudgetMs, mc as dynamicReferenceTokens, mi as waitForLambdaFunctionActive, ms as configBooleanRefusal, mt as getCurrentNestedStackContext, ni as planTagDiff, nn as getCurrentProducerRegions, nr as replacedDeleteFailureVerdict, oi as tagPlanWarning, on as redactedDeleteAddressFields, p as resolveDynamoDbDeleteBudgetClock, pl as stringifyValue, ps as coerceCfnInteger, qi as s3BucketDualStackDomainName, qs as redactForState, ri as readTagList, si as definedAttributes, sn as redactedDeleteAddressSkip, ss as WARM_THROUGHPUT_MEMBERS, st as getNestedRevertRun, t as DeployEngine, ti as DBPROXY_TAG_OPTIONS, u as beginDeleteWait, ul as timePhase, us as toCfnInteger, ut as revertNestedChildFromJournal, v as maskedLogger, vi as getCurrentResourceSecrets, vl as rewriteTemplateAssetReferences, vs as replayWarn, w as isTruthyCfnBoolean, wi as slowCcOperationTimeoutMs, x as ECR_AUTO_DELETE_IMAGES_TAG, xc as recoverMaskedOutput, xs as requireConfigString, xu as derivePartitionAndUrlSuffix, y as relayedIndexBusyDelete, ys as requireConfigArray, zi as reEnableInstanceApiTermination } from "./deploy-engine-Bjr-FAuZ.js";
6
- import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-BJ26M4Ez.js";
7
- import { a as resolveSecretDerivedPrincipals, i as isResolvableSecretPrincipalList, n as runDestroyForStack, o as canonicalizeIpProtocolValue, r as holdsUnprovenSecretPrincipalToken, s as resolvedResourceTimeoutMs, t as canonicalizeIpv4Cidr } from "./program-CcYD-_fU.js";
8
- import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-DvidzfJp.js";
9
- import { RDSProvider } from "./rds-provider-Dps9UxBz.js";
10
- import { NeptuneProvider } from "./neptune-provider-D_3VAhFf.js";
11
- import { ASGProvider } from "./asg-provider-DrREeZeh.js";
5
+ import { $n as awaitInFlightSibling, $o as withoutSilentDropProperties, $r as isRefusedByName, $s as hasMaskableValues, Bi as reEnableInstanceApiTermination, C as hasCdkAutoDeleteTag, Cc as physicalNameCopiesOf, Dc as carriesSecretMask, Ds as canonicalLambdaFunctionName, Dt as isAccessDeniedError, E as markRefusedBeforeApplying, Ei as unchangedBehindSecretReference, Es as withRetry, Et as chunks, F as findNestedTemplateTreeDefect, Fa as passedParameterClassesOf, Fu as describeFileReadFailure, G as enclosingDeadlineRemainingMs, Gi as isSettledInstanceState, Gr as earliestDefined, Ha as accountArgs, I as isAbsoluteAssetPath, Ii as ec2InstanceProtectionSite, Iu as displayAssemblyPath, Ji as s3BucketDualStackDomainName, Js as redactForState, Ki as s3BucketArn, L as listNestedTemplateRows, Li as isTerminationProtectionPropagationError, Lo as refuseMalformedResourcesForDestroy, Lu as renderAssemblyPathEscape, Ma as parseWebACLArn, Mi as withIndeterminateGuard, Mr as secretNamedAttributeNamesOf, Ni as isWaitAbandonedError, Os as lambdaFunctionNameForMask, Ot as lookupEachName, Pi as markWaitAbandoned, R as renderNestedTemplateTreeDefect, Ri as observeThenDisableInstanceApiTermination, Ru as resolveAssemblyPath, S as S3_AUTO_DELETE_OBJECTS_TAG, Sc as recoverMaskedOutput, Ss as requireConfigString, Su as derivePartitionAndUrlSuffix, T as getPriorAttempts, Ti as slowCcOperationTimeoutMs, Vs as passedNoEchoParametersOf, W as enclosingDeadlineExpired, Xi as s3BucketWebsiteUrl, Xs as snapshotPassProvenance, Yi as s3BucketRegionalDomainName, Yo as withheldAccountClause, Yr as acquireIdempotencyToken, Ys as recordReferenceProvenanceEntry, Zo as findSilentDropProperties, _ as deleteTableWithIndexBusyRetry, _o as refuseMalformedNestedChildOutputs, _s as configStringRefusal, ai as refuseMalformedDesiredTags, an as REDACTED_DELETE_ADDRESS_SKIP_REASON, b as waitForIndexesSettled, bs as requireConfigArray, c as DynamoDBGlobalTableProvider, ci as definedAttributes, cn as redactedDeleteAddressSkip, cs as WARM_THROUGHPUT_MEMBERS, ct as getNestedRevertRun, d as compensateRemovedDeletionProtection, dl as timePhase, ds as toCfnInteger, dt as revertNestedChildFromJournal, ei as markDeleteStarted, f as deleteBudgetKey, fs as toFiniteNumber, g as INDEX_SETTLE_POLL_INTERVAL_MS, gs as configIntegerRefusal, gt as withNestedStackContext, h as DELETE_INDEX_WAIT_PROCEED_NOTE, hc as dynamicReferenceTokens, hi as waitForLambdaFunctionActive, hs as configBooleanRefusal, ht as getCurrentNestedStackContext, ii as readTagList, ji as deleteSkipReason, ks as sameLambdaFunctionAddress, kt as withApiLimit, l as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, li as stringifyIfAssigned, ls as coerceWarmThroughput$1, m as resolveDynamoDbDeleteBudgetMs, ml as stringifyValue, ms as coerceCfnInteger, ni as DBPROXY_TAG_OPTIONS, oi as tagMapAsList, on as isRedactedRecordedValue, p as resolveDynamoDbDeleteBudgetClock, pc as withoutPhysicalNameCopies, ps as coerceCfnBoolean, qi as s3BucketDomainName, qr as reserveStackCreateToken, qs as markSameGenerationBag, ri as planTagDiff, rn as getCurrentProducerRegions, rr as replacedDeleteFailureVerdict, si as tagPlanWarning, sn as redactedDeleteAddressFields, t as DeployEngine, ta as outputReferenceProvenanceOf, ti as DBPROXY_TAGS_WHAT, tr as getStackRecords, u as beginDeleteWait, us as isWarmThroughputDecrease, v as maskedLogger, vs as readConfigString, vu as decodeListingKey, w as isTruthyCfnBoolean, wc as recordAttributeIdCopy, x as ECR_AUTO_DELETE_IMAGES_TAG, xa as getAccountInfo, xs as requireConfigObject, xu as canonicalizeRegion, y as relayedIndexBusyDelete, yi as getCurrentResourceSecrets, yl as rewriteTemplateAssetReferences, ys as replayWarn, zi as reDisableInstanceApiTermination } from "./deploy-engine-BOgsnnk0.js";
6
+ import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-DfDYgfqK.js";
7
+ import { a as resolveSecretDerivedPrincipals, i as isResolvableSecretPrincipalList, n as runDestroyForStack, o as canonicalizeIpProtocolValue, r as holdsUnprovenSecretPrincipalToken, s as resolvedResourceTimeoutMs, t as canonicalizeIpv4Cidr } from "./program-DU5UlgkO.js";
8
+ import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-DOJPkECL.js";
9
+ import { RDSProvider } from "./rds-provider-DcBsBQLi.js";
10
+ import { NeptuneProvider } from "./neptune-provider-DvuvSkfJ.js";
11
+ import { ASGProvider } from "./asg-provider-oKlrkJeO.js";
12
12
  import { createHash, randomUUID } from "node:crypto";
13
13
  import { CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListBucketsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client } from "@aws-sdk/client-s3";
14
14
  import { AddRoleToInstanceProfileCommand, AddUserToGroupCommand, AttachGroupPolicyCommand, AttachRolePolicyCommand, AttachUserPolicyCommand, CreateAccessKeyCommand, CreateGroupCommand, CreateInstanceProfileCommand, CreateLoginProfileCommand, CreatePolicyCommand, CreatePolicyVersionCommand, CreateUserCommand, DeleteAccessKeyCommand, DeleteGroupCommand, DeleteGroupPolicyCommand, DeleteInstanceProfileCommand, DeleteLoginProfileCommand, DeletePolicyCommand, DeletePolicyVersionCommand, DeleteRolePolicyCommand, DeleteUserCommand, DeleteUserPermissionsBoundaryCommand, DeleteUserPolicyCommand, DetachGroupPolicyCommand, DetachRolePolicyCommand, DetachUserPolicyCommand, GetAccessKeyLastUsedCommand, GetGroupCommand, GetGroupPolicyCommand, GetInstanceProfileCommand, GetPolicyCommand, GetPolicyVersionCommand, GetRolePolicyCommand, GetUserCommand, GetUserPolicyCommand, IAMClient, ListAccessKeysCommand, ListAttachedGroupPoliciesCommand, ListAttachedUserPoliciesCommand, ListEntitiesForPolicyCommand, ListGroupPoliciesCommand, ListGroupsForUserCommand, ListPoliciesCommand, ListPolicyTagsCommand, ListPolicyVersionsCommand, ListUserPoliciesCommand, NoSuchEntityException, PutGroupPolicyCommand, PutRolePolicyCommand, PutUserPermissionsBoundaryCommand, PutUserPolicyCommand, RemoveRoleFromInstanceProfileCommand, RemoveUserFromGroupCommand, TagPolicyCommand, TagUserCommand, UntagPolicyCommand, UntagUserCommand, UpdateAccessKeyCommand, UpdateGroupCommand, UpdateLoginProfileCommand, UpdateUserCommand } from "@aws-sdk/client-iam";
@@ -16,7 +16,7 @@ import { CreateQueueCommand, DeleteQueueCommand, GetQueueAttributesCommand, GetQ
16
16
  import { CreateTopicCommand, DeleteTopicCommand, GetSubscriptionAttributesCommand, GetTopicAttributesCommand, InvalidParameterException, ListSubscriptionsByTopicCommand, ListTagsForResourceCommand, ListTopicsCommand, NotFoundException, SNSClient, SetSubscriptionAttributesCommand, SetTopicAttributesCommand, SubscribeCommand, TagResourceCommand, UnsubscribeCommand, UntagResourceCommand } from "@aws-sdk/client-sns";
17
17
  import { AddPermissionCommand, CreateEventSourceMappingCommand, CreateFunctionCommand, CreateFunctionUrlConfigCommand, DeleteEventSourceMappingCommand, DeleteFunctionCodeSigningConfigCommand, DeleteFunctionCommand, DeleteFunctionConcurrencyCommand, DeleteFunctionEventInvokeConfigCommand, DeleteFunctionUrlConfigCommand, DeleteLayerVersionCommand, GetEventSourceMappingCommand, GetFunctionCodeSigningConfigCommand, GetFunctionCommand, GetFunctionConcurrencyCommand, GetFunctionEventInvokeConfigCommand, GetFunctionRecursionConfigCommand, GetFunctionUrlConfigCommand, GetLayerVersionByArnCommand, GetPolicyCommand as GetPolicyCommand$1, GetRuntimeManagementConfigCommand, LambdaClient, ListEventSourceMappingsCommand, ListLayerVersionsCommand, ListTagsCommand, PublishLayerVersionCommand, PutFunctionCodeSigningConfigCommand, PutFunctionConcurrencyCommand, PutFunctionEventInvokeConfigCommand, PutFunctionRecursionConfigCommand, PutRuntimeManagementConfigCommand, RemovePermissionCommand, ResourceNotFoundException, TagResourceCommand as TagResourceCommand$1, UntagResourceCommand as UntagResourceCommand$1, UpdateEventSourceMappingCommand, UpdateFunctionCodeCommand, UpdateFunctionConfigurationCommand, UpdateFunctionUrlConfigCommand, waitUntilFunctionActiveV2, waitUntilFunctionUpdatedV2 } from "@aws-sdk/client-lambda";
18
18
  import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
19
- import { AllocateAddressCommand, AssociateAddressCommand, AssociateIamInstanceProfileCommand, AssociateRouteTableCommand, AttachInternetGatewayCommand, AttachVpnGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAddressesCommand, DescribeAvailabilityZonesCommand, DescribeIamInstanceProfileAssociationsCommand, DescribeInstanceAttributeCommand, DescribeInstanceCreditSpecificationsCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupRulesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DescribeVpnGatewaysCommand, DetachInternetGatewayCommand, DetachVpnGatewayCommand, DisassociateAddressCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifyInstanceCreditSpecificationCommand, ModifyInstanceMetadataOptionsCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, MonitorInstancesCommand, ReleaseAddressCommand, ReplaceNetworkAclAssociationCommand, ReplaceNetworkAclEntryCommand, ReplaceRouteCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, UnmonitorInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
19
+ import { AllocateAddressCommand, AssociateAddressCommand, AssociateIamInstanceProfileCommand, AssociateNatGatewayAddressCommand, AssociateRouteTableCommand, AttachInternetGatewayCommand, AttachVpnGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAddressesCommand, DescribeAvailabilityZonesCommand, DescribeIamInstanceProfileAssociationsCommand, DescribeInstanceAttributeCommand, DescribeInstanceCreditSpecificationsCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupRulesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DescribeVpnGatewaysCommand, DetachInternetGatewayCommand, DetachVpnGatewayCommand, DisassociateAddressCommand, DisassociateNatGatewayAddressCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifyInstanceCreditSpecificationCommand, ModifyInstanceMetadataOptionsCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, MonitorInstancesCommand, ReleaseAddressCommand, ReplaceNetworkAclAssociationCommand, ReplaceNetworkAclEntryCommand, ReplaceRouteCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, UnmonitorInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
20
20
  import { CreateTableCommand, DeleteResourcePolicyCommand, DeleteTableCommand, DescribeContinuousBackupsCommand, DescribeContributorInsightsCommand, DescribeKinesisStreamingDestinationCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DisableKinesisStreamingDestinationCommand, DynamoDBClient, EnableKinesisStreamingDestinationCommand, GetResourcePolicyCommand, ListTagsOfResourceCommand, PolicyNotFoundException, PutResourcePolicyCommand, ResourceNotFoundException as ResourceNotFoundException$1, TagResourceCommand as TagResourceCommand$2, UntagResourceCommand as UntagResourceCommand$2, UpdateContinuousBackupsCommand, UpdateContributorInsightsCommand, UpdateTableCommand, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";
21
21
  import { APIGatewayClient, CreateAuthorizerCommand, CreateDeploymentCommand, CreateResourceCommand, CreateStageCommand, DeleteAuthorizerCommand, DeleteDeploymentCommand, DeleteIntegrationCommand, DeleteIntegrationResponseCommand, DeleteMethodCommand, DeleteMethodResponseCommand, DeleteResourceCommand, DeleteStageCommand, GetAccountCommand, GetAuthorizerCommand, GetAuthorizersCommand, GetDeploymentCommand, GetDeploymentsCommand, GetMethodCommand, GetResourceCommand, GetStageCommand, NotFoundException as NotFoundException$1, PutIntegrationCommand, PutIntegrationResponseCommand, PutMethodCommand, PutMethodResponseCommand, TagResourceCommand as TagResourceCommand$3, UntagResourceCommand as UntagResourceCommand$3, UpdateAccountCommand, UpdateAuthorizerCommand, UpdateMethodCommand, UpdateStageCommand } from "@aws-sdk/client-api-gateway";
22
22
  import { CreateEventBusCommand, DeleteEventBusCommand, DeleteRuleCommand, DescribeEventBusCommand, DescribeRuleCommand, EventBridgeClient, ListRulesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$1, ListTargetsByRuleCommand, PutPermissionCommand, PutRuleCommand, PutTargetsCommand, RemoveTargetsCommand, ResourceNotFoundException as ResourceNotFoundException$2, TagResourceCommand as TagResourceCommand$4, UntagResourceCommand as UntagResourceCommand$4, UpdateEventBusCommand } from "@aws-sdk/client-eventbridge";
@@ -56,7 +56,7 @@ import { CreatePipeCommand, DeletePipeCommand, DescribePipeCommand, NotFoundExce
56
56
  import { AccessPointAlreadyExists, AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemAlreadyExists, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, PutBackupPolicyCommand, PutFileSystemPolicyCommand, PutLifecycleConfigurationCommand, UpdateFileSystemCommand, UpdateFileSystemProtectionCommand } from "@aws-sdk/client-efs";
57
57
  import { CreateFileSystemCommand as CreateFileSystemCommand$1, CreateFileSystemFromBackupCommand, DeleteFileSystemCommand as DeleteFileSystemCommand$1, DescribeFileSystemsCommand as DescribeFileSystemsCommand$1, FSxClient, FileSystemNotFound as FileSystemNotFound$1, TagResourceCommand as TagResourceCommand$22, UntagResourceCommand as UntagResourceCommand$22, UpdateFileSystemCommand as UpdateFileSystemCommand$1 } from "@aws-sdk/client-fsx";
58
58
  import { AddInstanceFleetCommand, AddInstanceGroupsCommand, AddTagsCommand as AddTagsCommand$1, DescribeClusterCommand, EMRClient, InvalidRequestException, ListClustersCommand, ListInstanceFleetsCommand, ListInstanceGroupsCommand, ModifyClusterCommand, ModifyInstanceFleetCommand, ModifyInstanceGroupsCommand, PutAutoScalingPolicyCommand, PutAutoTerminationPolicyCommand, PutManagedScalingPolicyCommand, RemoveAutoScalingPolicyCommand, RemoveAutoTerminationPolicyCommand, RemoveManagedScalingPolicyCommand, RemoveTagsCommand as RemoveTagsCommand$1, RunJobFlowCommand, SetTerminationProtectionCommand, SetVisibleToAllUsersCommand, TerminateJobFlowsCommand } from "@aws-sdk/client-emr";
59
- import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$14, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
59
+ import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$14, StartDeliveryStreamEncryptionCommand, StopDeliveryStreamEncryptionCommand, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
60
60
  import { AddTagsCommand as AddTagsCommand$2, CloudTrailClient, CreateTrailCommand, DeleteTrailCommand, GetEventSelectorsCommand, GetInsightSelectorsCommand, GetTrailCommand, GetTrailStatusCommand, ListTagsCommand as ListTagsCommand$2, PutEventSelectorsCommand, PutInsightSelectorsCommand, RemoveTagsCommand as RemoveTagsCommand$2, StartLoggingCommand, StopLoggingCommand, TrailNotFoundException, UpdateTrailCommand } from "@aws-sdk/client-cloudtrail";
61
61
  import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ResourceNotFoundException as ResourceNotFoundException$15, UpdateProjectCommand, UpdateProjectVisibilityCommand } from "@aws-sdk/client-codebuild";
62
62
  import { CodeCommitClient, CreateCommitCommand, CreateRepositoryCommand as CreateRepositoryCommand$1, DeleteRepositoryCommand as DeleteRepositoryCommand$1, GetRepositoryCommand, GetRepositoryTriggersCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, PutRepositoryTriggersCommand, RepositoryDoesNotExistException, TagResourceCommand as TagResourceCommand$23, UntagResourceCommand as UntagResourceCommand$23, UpdateRepositoryDescriptionCommand, UpdateRepositoryEncryptionKeyCommand, UpdateRepositoryNameCommand } from "@aws-sdk/client-codecommit";
@@ -2943,7 +2943,7 @@ function manualBucketDeletionClause(bucketName, maskSecrets, journaled) {
2943
2943
  return command ? `${lead}: ${command}` : `${lead}, via the console: the bucket name cannot be reproduced safely on a command line, so any command shown here could act on a different bucket or run part of the name as shell.`;
2944
2944
  }
2945
2945
  function configItemId(item) {
2946
- if (!isPlainObject$2(item)) return void 0;
2946
+ if (!isPlainObject$3(item)) return void 0;
2947
2947
  const id = item["Id"];
2948
2948
  if (typeof id === "string") return id;
2949
2949
  if (typeof id === "number" && Number.isFinite(id)) return String(id);
@@ -2951,11 +2951,11 @@ function configItemId(item) {
2951
2951
  function declaresBucketObjectLock(properties) {
2952
2952
  return properties["ObjectLockEnabled"] === true || properties["ObjectLockEnabled"] === "true";
2953
2953
  }
2954
- function isPlainObject$2(value) {
2954
+ function isPlainObject$3(value) {
2955
2955
  return typeof value === "object" && value !== null && !Array.isArray(value);
2956
2956
  }
2957
2957
  function effectiveS3BucketDestination(declared, sentFormat) {
2958
- if (!isPlainObject$2(declared)) return declared;
2958
+ if (!isPlainObject$3(declared)) return declared;
2959
2959
  if (!declared["BucketArn"]) return declared;
2960
2960
  const out = { BucketArn: declared["BucketArn"] };
2961
2961
  if (declared["BucketAccountId"] !== void 0) out["BucketAccountId"] = declared["BucketAccountId"];
@@ -2991,7 +2991,7 @@ function effectiveInventoryItem(item, sent) {
2991
2991
  const scheduleContainerUsable = configStringRefusal(declaredSchedule, "Frequency", INVENTORY_DEFAULT_SCHEDULE_FREQUENCY, "AWS::S3::Bucket InventoryConfigurations[].Schedule") === void 0;
2992
2992
  const canFoldSchedule = sent?.frequency !== void 0 || scheduleFrequencyUsable || !declaresScheduleFrequency && scheduleContainerUsable;
2993
2993
  if (canFoldSchedule) {
2994
- const declaredFrequency = declaresScheduleFrequency ? item["ScheduleFrequency"] : isPlainObject$2(declaredSchedule) && declaredSchedule["Frequency"] !== void 0 ? declaredSchedule["Frequency"] : INVENTORY_DEFAULT_SCHEDULE_FREQUENCY;
2994
+ const declaredFrequency = declaresScheduleFrequency ? item["ScheduleFrequency"] : isPlainObject$3(declaredSchedule) && declaredSchedule["Frequency"] !== void 0 ? declaredSchedule["Frequency"] : INVENTORY_DEFAULT_SCHEDULE_FREQUENCY;
2995
2995
  const frequency = sent?.frequency ?? declaredFrequency;
2996
2996
  if (!Object.is(item["ScheduleFrequency"], frequency)) patch["ScheduleFrequency"] = frequency;
2997
2997
  }
@@ -3008,9 +3008,9 @@ function effectiveInventoryItem(item, sent) {
3008
3008
  }
3009
3009
  function effectiveAnalyticsItem(item, sent) {
3010
3010
  const storageClassAnalysis = item["StorageClassAnalysis"];
3011
- if (!isPlainObject$2(storageClassAnalysis)) return item;
3011
+ if (!isPlainObject$3(storageClassAnalysis)) return item;
3012
3012
  const dataExport = storageClassAnalysis["DataExport"];
3013
- if (!isPlainObject$2(dataExport)) return item;
3013
+ if (!isPlainObject$3(dataExport)) return item;
3014
3014
  const patch = {};
3015
3015
  const outputSchemaVersion = sent?.outputSchemaVersion ?? declaredOrDefault(dataExport, "OutputSchemaVersion", ANALYTICS_DEFAULT_OUTPUT_SCHEMA_VERSION);
3016
3016
  if (!Object.is(dataExport["OutputSchemaVersion"], outputSchemaVersion)) patch["OutputSchemaVersion"] = outputSchemaVersion;
@@ -3052,7 +3052,7 @@ const EVENTBRIDGE_CONFIG_PATH = "AWS::S3::Bucket NotificationConfiguration.Event
3052
3052
  const EVENTBRIDGE_CONFIG_KEY = "EventBridgeConfiguration";
3053
3053
  const EVENTBRIDGE_DEFAULT_ENABLED = true;
3054
3054
  function eventBridgeEnabledOf(eb) {
3055
- const declared = isPlainObject$2(eb) ? eb["EventBridgeEnabled"] : void 0;
3055
+ const declared = isPlainObject$3(eb) ? eb["EventBridgeEnabled"] : void 0;
3056
3056
  return coerceCfnBoolean(declared) ?? EVENTBRIDGE_DEFAULT_ENABLED;
3057
3057
  }
3058
3058
  const NOTIFICATION_LIST_KEYS = [
@@ -3082,7 +3082,7 @@ function foldNotificationEvents(item) {
3082
3082
  return out;
3083
3083
  }
3084
3084
  function effectiveNotificationConfiguration(config) {
3085
- if (!isPlainObject$2(config)) return config;
3085
+ if (!isPlainObject$3(config)) return config;
3086
3086
  let out = config;
3087
3087
  for (const listKey of NOTIFICATION_LIST_KEYS) out = canonicalizeItemList(out, listKey, foldNotificationEvents);
3088
3088
  out = dropEmptyNotificationFamilies(out);
@@ -3093,8 +3093,8 @@ function foldEventBridgeConfiguration(config) {
3093
3093
  if (eb === void 0) return config;
3094
3094
  if (eb !== null && configBooleanRefusal(eb, "EventBridgeEnabled", EVENTBRIDGE_CONFIG_PATH)) return config;
3095
3095
  const enabled = eb === null ? false : eventBridgeEnabledOf(eb);
3096
- const declared = isPlainObject$2(eb) ? eb["EventBridgeEnabled"] : void 0;
3097
- if (isPlainObject$2(eb) && Object.keys(eb).length === 1 && Object.is(declared, enabled)) return config;
3096
+ const declared = isPlainObject$3(eb) ? eb["EventBridgeEnabled"] : void 0;
3097
+ if (isPlainObject$3(eb) && Object.keys(eb).length === 1 && Object.is(declared, enabled)) return config;
3098
3098
  return {
3099
3099
  ...config,
3100
3100
  [EVENTBRIDGE_CONFIG_KEY]: { EventBridgeEnabled: enabled }
@@ -3136,7 +3136,7 @@ function deepSameValue(a, b) {
3136
3136
  if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
3137
3137
  return a.every((element, index) => deepSameValue(element, b[index]));
3138
3138
  }
3139
- if (isPlainObject$2(a) && isPlainObject$2(b)) {
3139
+ if (isPlainObject$3(a) && isPlainObject$3(b)) {
3140
3140
  const keysA = Object.keys(a);
3141
3141
  if (keysA.length !== Object.keys(b).length) return false;
3142
3142
  return keysA.every((key) => Object.hasOwn(b, key) && deepSameValue(a[key], b[key]));
@@ -3158,9 +3158,9 @@ function foldLegacySingularTransitions(rule) {
3158
3158
  let out;
3159
3159
  for (const [pluralKey, singularKey] of LEGACY_SINGULAR_TRANSITIONS) {
3160
3160
  const singular = rule[singularKey];
3161
- const hasSingular = isPlainObject$2(singular);
3161
+ const hasSingular = isPlainObject$3(singular);
3162
3162
  const plural = rule[pluralKey];
3163
- const needsFilter = Array.isArray(plural) && plural.some((element) => !isPlainObject$2(element));
3163
+ const needsFilter = Array.isArray(plural) && plural.some((element) => !isPlainObject$3(element));
3164
3164
  if (!hasSingular && !needsFilter) continue;
3165
3165
  let collided = false;
3166
3166
  const merged = mergeLegacySingular(plural, hasSingular ? singular : void 0, () => {
@@ -3209,7 +3209,7 @@ function foldLifecycleExpiration(rule) {
3209
3209
  const iso = cfnDateToIso(expiration);
3210
3210
  if (iso === void 0) return rule;
3211
3211
  date = iso;
3212
- } else if (isPlainObject$2(expiration)) {
3212
+ } else if (isPlainObject$3(expiration)) {
3213
3213
  if (expiration["Days"] !== void 0) days = expiration["Days"];
3214
3214
  if (expiration["Date"]) {
3215
3215
  const iso = cfnDateToIso(expiration["Date"]);
@@ -3242,10 +3242,10 @@ function foldNoncurrentVersionExpiration(rule) {
3242
3242
  const legacy = rule["NoncurrentVersionExpirationInDays"];
3243
3243
  if (legacy === void 0) return rule;
3244
3244
  const declaredObject = rule["NoncurrentVersionExpiration"];
3245
- if (declaredObject !== void 0 && !isPlainObject$2(declaredObject)) return rule;
3245
+ if (declaredObject !== void 0 && !isPlainObject$3(declaredObject)) return rule;
3246
3246
  const out = { ...rule };
3247
3247
  delete out["NoncurrentVersionExpirationInDays"];
3248
- if (isPlainObject$2(declaredObject)) return out;
3248
+ if (isPlainObject$3(declaredObject)) return out;
3249
3249
  const days = coerceCfnNumber(legacy);
3250
3250
  if (days === void 0) return rule;
3251
3251
  out["NoncurrentVersionExpiration"] = { NoncurrentDays: days };
@@ -3277,10 +3277,10 @@ function foldLifecycleScope(rule, useFilterForm) {
3277
3277
  return out;
3278
3278
  }
3279
3279
  function effectiveLifecycleConfiguration(config) {
3280
- if (!isPlainObject$2(config)) return config;
3280
+ if (!isPlainObject$3(config)) return config;
3281
3281
  const rules = config["Rules"];
3282
3282
  if (!Array.isArray(rules)) return config;
3283
- const objectRules = rules.filter(isPlainObject$2);
3283
+ const objectRules = rules.filter(isPlainObject$3);
3284
3284
  if (objectRules.length !== rules.length || objectRules.length === 0) return config;
3285
3285
  if (objectRules.some(lifecycleRuleRefused)) return config;
3286
3286
  const useFilterForm = lifecycleUsesFilterForm(objectRules);
@@ -3312,7 +3312,7 @@ function canonicalizeItemList(properties, key, fold) {
3312
3312
  if (!Array.isArray(list)) return properties;
3313
3313
  let changed = false;
3314
3314
  const mapped = list.map((element) => {
3315
- if (!isPlainObject$2(element)) return element;
3315
+ if (!isPlainObject$3(element)) return element;
3316
3316
  const next = fold(element);
3317
3317
  if (next !== element) changed = true;
3318
3318
  return next;
@@ -3326,7 +3326,7 @@ function describeValue$1(value, maskSecrets = (text) => text) {
3326
3326
  if (value === null) return "null";
3327
3327
  if (Array.isArray(value)) return "an array";
3328
3328
  if (typeof value === "string") return `a string ${displaySafe(JSON.stringify(maskDeep(value, maskSecrets)))}`;
3329
- if (isPlainObject$2(value)) return `an object with keys [${Object.keys(value).map((key) => displaySafe(maskSecrets(key))).join(", ")}]`;
3329
+ if (isPlainObject$3(value)) return `an object with keys [${Object.keys(value).map((key) => displaySafe(maskSecrets(key))).join(", ")}]`;
3330
3330
  return `a ${typeof value} (${maskSecrets(String(value))})`;
3331
3331
  }
3332
3332
  function coerceCfnNumber(value) {
@@ -3336,8 +3336,8 @@ function coerceCfnNumber(value) {
3336
3336
  return Number.isFinite(n) ? n : void 0;
3337
3337
  }
3338
3338
  function mergeLegacySingular(plural, singular, onCollision) {
3339
- const out = (Array.isArray(plural) ? plural : []).filter(isPlainObject$2);
3340
- if (!isPlainObject$2(singular)) return out;
3339
+ const out = (Array.isArray(plural) ? plural : []).filter(isPlainObject$3);
3340
+ if (!isPlainObject$3(singular)) return out;
3341
3341
  const sc = singular["StorageClass"];
3342
3342
  if (typeof sc === "string" && out.some((e) => e["StorageClass"] === sc)) {
3343
3343
  onCollision(sc);
@@ -3693,7 +3693,7 @@ var S3BucketProvider = class S3BucketProvider {
3693
3693
  if (!(exp?.["Days"] !== void 0 || exp?.["Date"] !== void 0)) sdkRule.Expiration = { ExpiredObjectDeleteMarker: true };
3694
3694
  else this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(maskDeep(rule["Id"], this.shownMask))} on ${this.shown(bucketName)} sets ExpiredObjectDeleteMarker alongside an expiration Days/Date; S3 forbids combining them, so the delete-marker cleanup was not applied.`);
3695
3695
  }
3696
- const nve = isPlainObject$2(rule["NoncurrentVersionExpiration"]) ? rule["NoncurrentVersionExpiration"] : void 0;
3696
+ const nve = isPlainObject$3(rule["NoncurrentVersionExpiration"]) ? rule["NoncurrentVersionExpiration"] : void 0;
3697
3697
  const legacyNveDays = rule["NoncurrentVersionExpirationInDays"];
3698
3698
  if (nve) sdkRule.NoncurrentVersionExpiration = {
3699
3699
  NoncurrentDays: nve["NoncurrentDays"],
@@ -3718,7 +3718,7 @@ var S3BucketProvider = class S3BucketProvider {
3718
3718
  const singularTransition = rule["Transition"];
3719
3719
  const allTransitions = mergeLegacySingular(transitions, singularTransition, (sc) => this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(maskDeep(rule["Id"], this.shownMask))} on ${this.shown(bucketName)} declares both Transitions and the legacy Transition for storage class ${this.shown(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
3720
3720
  if (allTransitions.length > 0) sdkRule.Transitions = allTransitions.map(toSdkTransition);
3721
- const abort = isPlainObject$2(rule["AbortIncompleteMultipartUpload"]) ? rule["AbortIncompleteMultipartUpload"] : void 0;
3721
+ const abort = isPlainObject$3(rule["AbortIncompleteMultipartUpload"]) ? rule["AbortIncompleteMultipartUpload"] : void 0;
3722
3722
  if (abort) sdkRule.AbortIncompleteMultipartUpload = { DaysAfterInitiation: abort["DaysAfterInitiation"] };
3723
3723
  const { prefix, tagFilters, sizeGt, sizeLt } = lifecycleRuleScope(rule);
3724
3724
  const hasTags = tagFilters != null && tagFilters.length > 0;
@@ -3950,7 +3950,7 @@ var S3BucketProvider = class S3BucketProvider {
3950
3950
  throw new Error(message);
3951
3951
  };
3952
3952
  if (dest === void 0 || dest === null) return;
3953
- if (!isPlainObject$2(dest)) return drop(`${destinationPath} must be an object (got ${describeValue$1(dest, maskSecrets)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
3953
+ if (!isPlainObject$3(dest)) return drop(`${destinationPath} must be an object (got ${describeValue$1(dest, maskSecrets)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
3954
3954
  if (!dest["BucketArn"]) return drop(`${destinationPath} has no destination bucket (BucketArn) (got ${describeValue$1(dest, maskSecrets)}) — the request would be rejected by S3, or silently carry no destination`);
3955
3955
  return dest;
3956
3956
  }
@@ -8211,6 +8211,8 @@ var LambdaFunctionProvider = class {
8211
8211
  S3Bucket: builtCode.S3Bucket,
8212
8212
  S3Key: builtCode.S3Key,
8213
8213
  S3ObjectVersion: builtCode.S3ObjectVersion,
8214
+ S3ObjectStorageMode: builtCode.S3ObjectStorageMode,
8215
+ SourceKMSKeyArn: builtCode.SourceKMSKeyArn,
8214
8216
  ZipFile: builtCode.ZipFile,
8215
8217
  ImageUri: builtCode.ImageUri,
8216
8218
  Architectures: architecturesChanged ? normalizeArchitectures(properties["Architectures"]) : void 0
@@ -8471,6 +8473,8 @@ var LambdaFunctionProvider = class {
8471
8473
  if (code["S3Bucket"]) result.S3Bucket = code["S3Bucket"];
8472
8474
  if (code["S3Key"]) result.S3Key = code["S3Key"];
8473
8475
  if (code["S3ObjectVersion"]) result.S3ObjectVersion = code["S3ObjectVersion"];
8476
+ if (code["S3ObjectStorageMode"]) result.S3ObjectStorageMode = code["S3ObjectStorageMode"];
8477
+ if (code["SourceKMSKeyArn"]) result.SourceKMSKeyArn = code["SourceKMSKeyArn"];
8474
8478
  if (code["ZipFile"]) result.ZipFile = this.createZipFromInlineCode(code["ZipFile"], runtime);
8475
8479
  if (code["ImageUri"]) result.ImageUri = code["ImageUri"];
8476
8480
  return result;
@@ -8683,6 +8687,7 @@ var LambdaFunctionProvider = class {
8683
8687
  "Code.S3Bucket",
8684
8688
  "Code.S3Key",
8685
8689
  "Code.S3ObjectVersion",
8690
+ "Code.S3ObjectStorageMode",
8686
8691
  "Code.ZipFile",
8687
8692
  "Code.SourceKMSKeyArn"
8688
8693
  ];
@@ -9374,7 +9379,7 @@ var LambdaEventSourceMappingProvider = class {
9374
9379
  async create(logicalId, resourceType, properties, context) {
9375
9380
  const log = this.operationSinks(context?.maskSecrets, properties);
9376
9381
  log.debug(`Creating event source mapping ${logicalId}`);
9377
- const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
9382
+ const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, void 0, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
9378
9383
  const functionName = properties["FunctionName"];
9379
9384
  if (!functionName) throw new ProvisioningError(`FunctionName is required for event source mapping ${logicalId}`, resourceType, logicalId);
9380
9385
  if (declaredConsumptionMode(properties) !== void 0) {
@@ -9388,7 +9393,7 @@ var LambdaEventSourceMappingProvider = class {
9388
9393
  if (properties["BatchSize"]) params.BatchSize = properties["BatchSize"];
9389
9394
  if (properties["StartingPosition"]) params.StartingPosition = properties["StartingPosition"];
9390
9395
  if (properties["Enabled"] !== void 0) params.Enabled = properties["Enabled"];
9391
- if (properties["MaximumBatchingWindowInSeconds"]) params.MaximumBatchingWindowInSeconds = properties["MaximumBatchingWindowInSeconds"];
9396
+ if (properties["MaximumBatchingWindowInSeconds"] !== void 0) params.MaximumBatchingWindowInSeconds = properties["MaximumBatchingWindowInSeconds"];
9392
9397
  if (properties["MaximumRetryAttempts"] !== void 0) params.MaximumRetryAttempts = properties["MaximumRetryAttempts"];
9393
9398
  if (properties["BisectBatchOnFunctionError"] !== void 0) params.BisectBatchOnFunctionError = properties["BisectBatchOnFunctionError"];
9394
9399
  if (properties["MaximumRecordAgeInSeconds"]) params.MaximumRecordAgeInSeconds = properties["MaximumRecordAgeInSeconds"];
@@ -9468,22 +9473,29 @@ var LambdaEventSourceMappingProvider = class {
9468
9473
  }
9469
9474
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
9470
9475
  const log = this.operationSinks(context?.maskSecrets, properties, previousProperties);
9471
- refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
9476
+ refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
9477
+ const restoring = context?.replayingState === true || context?.desiredFromAwsReadback === true;
9478
+ for (const key of ["Queues", "Topics"]) {
9479
+ if (JSON.stringify(properties[key]) === JSON.stringify(previousProperties[key])) continue;
9480
+ const reason = `${key} cannot be changed on an existing event source mapping (UpdateEventSourceMapping does not take it, and CloudFormation refuses the change too)`;
9481
+ if (!restoring) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${reason}; deploy with --replace to delete and recreate the mapping`);
9482
+ log.warn(safeMsg`AWS::Lambda::EventSourceMapping ${logicalId}: ${reason}. Proceeding without it: this update restores a recorded or read-back configuration.`);
9483
+ }
9472
9484
  const desiredMode = declaredConsumptionMode(properties);
9473
9485
  if (desiredMode !== void 0 && JSON.stringify(desiredMode) !== JSON.stringify(declaredConsumptionMode(previousProperties))) {
9474
9486
  const message = consumptionModeRefusalMessage(logicalId, "update");
9475
- if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(message, resourceType, logicalId, physicalId);
9487
+ if (!restoring) throw new ProvisioningError(message, resourceType, logicalId, physicalId);
9476
9488
  log.warn(safeMsg`${message} Proceeding without it: this update restores a recorded or read-back configuration.`);
9477
9489
  }
9478
9490
  try {
9479
- return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, context);
9491
+ return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, restoring);
9480
9492
  } catch (error) {
9481
9493
  if (error instanceof CdkdError) throw error;
9482
9494
  const cause = error instanceof Error ? error : void 0;
9483
9495
  throw this.wrapMaskedError(log, error, (text) => new ProvisioningError(`Failed to update event source mapping ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
9484
9496
  }
9485
9497
  }
9486
- async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, context) {
9498
+ async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, restoring) {
9487
9499
  log.debug(`Updating event source mapping ${logicalId}: ${physicalId}`);
9488
9500
  const updateParams = {
9489
9501
  UUID: physicalId,
@@ -9504,7 +9516,7 @@ var LambdaEventSourceMappingProvider = class {
9504
9516
  if (properties["ScalingConfig"] !== void 0) updateParams.ScalingConfig = properties["ScalingConfig"];
9505
9517
  if (properties["DocumentDBEventSourceConfig"] !== void 0) updateParams.DocumentDBEventSourceConfig = properties["DocumentDBEventSourceConfig"];
9506
9518
  for (const key of ["SelfManagedKafkaEventSourceConfig", "AmazonManagedKafkaEventSourceConfig"]) {
9507
- const block = kafkaConfigForUpdate(properties[key], previousProperties[key], { restoring: context?.replayingState === true || context?.desiredFromAwsReadback === true });
9519
+ const block = kafkaConfigForUpdate(properties[key], previousProperties[key], { restoring });
9508
9520
  if (block !== void 0) updateParams[key] = block;
9509
9521
  }
9510
9522
  if (properties["KmsKeyArn"] !== void 0) updateParams.KMSKeyArn = properties["KmsKeyArn"];
@@ -9549,7 +9561,7 @@ var LambdaEventSourceMappingProvider = class {
9549
9561
  };
9550
9562
  }
9551
9563
  async applyTagDiff(arn, resourceType, logicalId, oldTagsRaw, newTagsRaw, log) {
9552
- const plan = planTagDiff(oldTagsRaw, newTagsRaw);
9564
+ const plan = planTagDiff(oldTagsRaw, newTagsRaw, DBPROXY_TAG_OPTIONS);
9553
9565
  const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
9554
9566
  if (tagWarning !== void 0) log.warn(tagWarning);
9555
9567
  const tagsToAdd = Object.fromEntries(plan.set);
@@ -9759,6 +9771,7 @@ var LambdaLayerVersionProvider = class {
9759
9771
  if (content["S3Bucket"]) contentInput.S3Bucket = content["S3Bucket"];
9760
9772
  if (content["S3Key"]) contentInput.S3Key = content["S3Key"];
9761
9773
  if (content["S3ObjectVersion"]) contentInput.S3ObjectVersion = content["S3ObjectVersion"];
9774
+ if (content["S3ObjectStorageMode"]) contentInput.S3ObjectStorageMode = content["S3ObjectStorageMode"];
9762
9775
  const orphanWindow = publishLayerVersionLatch.take(logicalId);
9763
9776
  if (orphanWindow !== void 0) await this.reportPossibleLayerOrphans(logicalId, orphanWindow, log, layerName);
9764
9777
  const createClient = await this.getCreateClient();
@@ -11624,7 +11637,7 @@ const STREAM_POLICY_KEY = "ResourcePolicy";
11624
11637
  const STREAM_TAGS_KEY = "Tags";
11625
11638
  const POLICY_PATH = `${STREAM_SPECIFICATION_KEY}.${STREAM_POLICY_KEY}`;
11626
11639
  const TAGS_PATH = `${STREAM_SPECIFICATION_KEY}.${STREAM_TAGS_KEY}`;
11627
- function isPlainObject$1(value) {
11640
+ function isPlainObject$2(value) {
11628
11641
  return typeof value === "object" && value !== null && !Array.isArray(value);
11629
11642
  }
11630
11643
  function refusalOf(guard) {
@@ -11636,7 +11649,7 @@ function refusalOf(guard) {
11636
11649
  }
11637
11650
  }
11638
11651
  function blockMembers(block) {
11639
- return isPlainObject$1(block) ? block : {};
11652
+ return isPlainObject$2(block) ? block : {};
11640
11653
  }
11641
11654
  function readStreamPolicy(block) {
11642
11655
  const value = blockMembers(block)[STREAM_POLICY_KEY];
@@ -11811,7 +11824,7 @@ function streamTagsMatchDeclared(liveTags, desiredBlock) {
11811
11824
  }
11812
11825
  function canonicalJson(value) {
11813
11826
  if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
11814
- if (isPlainObject$1(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
11827
+ if (isPlainObject$2(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
11815
11828
  return JSON.stringify(value) ?? "null";
11816
11829
  }
11817
11830
 
@@ -12149,6 +12162,32 @@ function indexDeclares(desired, key, bagInformative) {
12149
12162
  function declaresIndexList(value) {
12150
12163
  return Array.isArray(value) && value.length > 0;
12151
12164
  }
12165
+ function deletionProtectionRefusal(value, logicalId) {
12166
+ return configBooleanRefusal({ DeletionProtectionEnabled: value }, "DeletionProtectionEnabled", `AWS::DynamoDB::Table ${logicalId}`);
12167
+ }
12168
+ function localSecondaryIndexesKey(value) {
12169
+ if (value === void 0 || value === null) return "[]";
12170
+ if (!Array.isArray(value)) return JSON.stringify(value);
12171
+ const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
12172
+ const entries = value.map((entry) => {
12173
+ if (!isRecord(entry)) return JSON.stringify(entry);
12174
+ const keySchema = Array.isArray(entry["KeySchema"]) ? entry["KeySchema"].map((element) => isRecord(element) ? {
12175
+ AttributeName: element["AttributeName"],
12176
+ KeyType: element["KeyType"]
12177
+ } : element) : entry["KeySchema"];
12178
+ const projection = entry["Projection"];
12179
+ const projectionKey = isRecord(projection) ? {
12180
+ ProjectionType: projection["ProjectionType"],
12181
+ NonKeyAttributes: Array.isArray(projection["NonKeyAttributes"]) ? projection["NonKeyAttributes"].length > 0 ? [...projection["NonKeyAttributes"]].map(String).sort() : void 0 : projection["NonKeyAttributes"]
12182
+ } : projection;
12183
+ return JSON.stringify({
12184
+ IndexName: entry["IndexName"],
12185
+ KeySchema: keySchema,
12186
+ Projection: projectionKey
12187
+ });
12188
+ });
12189
+ return JSON.stringify(entries.sort());
12190
+ }
12152
12191
  function desiredIndexEntriesByName(value) {
12153
12192
  const byName = /* @__PURE__ */ new Map();
12154
12193
  if (!declaresIndexList(value)) return byName;
@@ -12281,7 +12320,11 @@ var DynamoDBTableProvider = class {
12281
12320
  Key: t.Key,
12282
12321
  Value: t.Value
12283
12322
  }));
12284
- if (properties["DeletionProtectionEnabled"] !== void 0) createParams.DeletionProtectionEnabled = properties["DeletionProtectionEnabled"];
12323
+ if (properties["DeletionProtectionEnabled"] !== void 0) {
12324
+ const protectionRefusal = deletionProtectionRefusal(properties["DeletionProtectionEnabled"], logicalId);
12325
+ if (protectionRefusal !== void 0) throw new ProvisioningError(`${maskSecrets(protectionRefusal)}. Nothing was created; fix the template value`, resourceType, logicalId);
12326
+ createParams.DeletionProtectionEnabled = coerceCfnBoolean(properties["DeletionProtectionEnabled"]);
12327
+ }
12285
12328
  if (properties["TableClass"]) createParams.TableClass = properties["TableClass"];
12286
12329
  const createResourcePolicyDoc = this.extractResourcePolicyDocument(properties["ResourcePolicy"]);
12287
12330
  if (createResourcePolicyDoc !== void 0) createParams.ResourcePolicy = createResourcePolicyDoc;
@@ -12355,7 +12398,18 @@ var DynamoDBTableProvider = class {
12355
12398
  const ceilingRefusal = onDemandCeilingRefusal(properties, previousProperties, logicalId);
12356
12399
  if (ceilingRefusal !== void 0) throw new ProvisioningError(`${ceilingRefusal}. Nothing was applied to the table; fix the template value`, resourceType, logicalId, physicalId);
12357
12400
  }
12401
+ const deletionProtectionChanged = JSON.stringify(properties["DeletionProtectionEnabled"]) !== JSON.stringify(previousProperties["DeletionProtectionEnabled"]);
12402
+ if (deletionProtectionChanged && context?.replayingState !== true && context?.desiredFromAwsReadback !== true) {
12403
+ const protectionRefusal = deletionProtectionRefusal(properties["DeletionProtectionEnabled"], logicalId);
12404
+ if (protectionRefusal !== void 0) throw new ProvisioningError(`${maskSecrets(protectionRefusal)}. Nothing was applied to the table; fix the template value`, resourceType, logicalId, physicalId);
12405
+ }
12358
12406
  const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
12407
+ const desiredLsiKey = localSecondaryIndexesKey(properties["LocalSecondaryIndexes"]);
12408
+ if (desiredLsiKey !== localSecondaryIndexesKey(previousProperties["LocalSecondaryIndexes"]) && (table === void 0 || desiredLsiKey !== localSecondaryIndexesKey(table.LocalSecondaryIndexes))) {
12409
+ const lsiMessage = `AWS::DynamoDB::Table ${logicalId}: LocalSecondaryIndexes changed, but DynamoDB cannot add, remove or modify a local secondary index on an existing table, and CloudFormation fails the same update rather than replacing the table`;
12410
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`${lsiMessage}. Nothing was applied to the table; revert the LocalSecondaryIndexes change, or create a new table under a new logical ID (a new table starts empty)`, resourceType, logicalId, physicalId);
12411
+ warn(`${lsiMessage}; the LocalSecondaryIndexes change was not applied`);
12412
+ }
12359
12413
  let latestStreamArn = table?.LatestStreamArn;
12360
12414
  if (table?.TableArn) await this.applyTagDiff(table.TableArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
12361
12415
  const normalizeTableClass = (v) => typeof v === "string" && v.length > 0 ? v : "STANDARD";
@@ -12503,6 +12557,19 @@ var DynamoDBTableProvider = class {
12503
12557
  this.logger.debug(`Updated SSESpecification on DynamoDB table ${physicalId}`);
12504
12558
  }
12505
12559
  }
12560
+ if (deletionProtectionChanged) {
12561
+ const rawDeletionProtection = properties["DeletionProtectionEnabled"];
12562
+ const desiredDeletionProtection = rawDeletionProtection === void 0 ? false : coerceCfnBoolean(rawDeletionProtection);
12563
+ if (desiredDeletionProtection === void 0) warn(`AWS::DynamoDB::Table ${logicalId}: DeletionProtectionEnabled is not a boolean, so it was not applied`);
12564
+ else if (table?.DeletionProtectionEnabled !== desiredDeletionProtection) {
12565
+ await this.dynamoDBClient.send(new UpdateTableCommand({
12566
+ TableName: physicalId,
12567
+ DeletionProtectionEnabled: desiredDeletionProtection
12568
+ }));
12569
+ await this.waitForTableActiveAfterUpdate(physicalId);
12570
+ debug(`Set DeletionProtectionEnabled=${desiredDeletionProtection} on DynamoDB table ${physicalId}`);
12571
+ }
12572
+ }
12506
12573
  if (JSON.stringify(properties["StreamSpecification"]) !== JSON.stringify(previousProperties["StreamSpecification"])) {
12507
12574
  const newViewType = this.extractStreamViewType(properties["StreamSpecification"]);
12508
12575
  const prevViewType = this.extractStreamViewType(previousProperties["StreamSpecification"]);
@@ -13287,6 +13354,11 @@ var DynamoDBTableProvider = class {
13287
13354
  canonicalizeDriftProperties(resourceType, properties) {
13288
13355
  if (resourceType !== "AWS::DynamoDB::Table") return properties;
13289
13356
  let result = properties;
13357
+ const protection = coerceCfnBoolean(result["DeletionProtectionEnabled"]);
13358
+ if (protection !== void 0 && protection !== result["DeletionProtectionEnabled"]) result = {
13359
+ ...result,
13360
+ DeletionProtectionEnabled: protection
13361
+ };
13290
13362
  for (const listKey of ["GlobalSecondaryIndexes", "LocalSecondaryIndexes"]) {
13291
13363
  const list = result[listKey];
13292
13364
  if (!Array.isArray(list)) continue;
@@ -16194,6 +16266,125 @@ function isNamedError(error, names) {
16194
16266
  return typeof name === "string" && names.has(name);
16195
16267
  }
16196
16268
  const NAT_GATEWAY_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["NatGatewayNotFound"]);
16269
+ function readNatZoneAddresses(raw) {
16270
+ if (raw === void 0 || raw === null) return { kind: "absent" };
16271
+ const unusable = (reason) => ({
16272
+ kind: "unusable",
16273
+ reason
16274
+ });
16275
+ if (!Array.isArray(raw)) return unusable("is not a list");
16276
+ if (raw.length === 0) return unusable("is an empty list");
16277
+ const entries = [];
16278
+ const seen = /* @__PURE__ */ new Set();
16279
+ for (const [index, item] of raw.entries()) {
16280
+ if (typeof item !== "object" || item === null || Array.isArray(item)) return unusable(`entry ${index} is not an object`);
16281
+ const record = item;
16282
+ const zone = record["AvailabilityZone"];
16283
+ const zoneId = record["AvailabilityZoneId"];
16284
+ if (zone !== void 0 && (typeof zone !== "string" || zone === "")) return unusable(`entry ${index}'s AvailabilityZone is not a zone name`);
16285
+ if (zoneId !== void 0 && (typeof zoneId !== "string" || zoneId === "")) return unusable(`entry ${index}'s AvailabilityZoneId is not a zone id`);
16286
+ if (zone === void 0 && zoneId === void 0) return unusable(`entry ${index} names neither AvailabilityZone nor AvailabilityZoneId`);
16287
+ const ids = record["AllocationIds"];
16288
+ if (!Array.isArray(ids) || ids.length === 0 || ids.some((id) => typeof id !== "string" || id === "")) return unusable(`entry ${index}'s AllocationIds is not a non-empty list of allocation ids`);
16289
+ for (const id of ids) {
16290
+ if (seen.has(id)) return unusable(`declares allocation id ${id} more than once`);
16291
+ seen.add(id);
16292
+ }
16293
+ entries.push({
16294
+ ...zone !== void 0 && { availabilityZone: zone },
16295
+ ...zoneId !== void 0 && { availabilityZoneId: zoneId },
16296
+ allocationIds: [...ids]
16297
+ });
16298
+ }
16299
+ return {
16300
+ kind: "usable",
16301
+ entries
16302
+ };
16303
+ }
16304
+ function natGatewayAttributes(gateway) {
16305
+ const addresses = gateway.NatGatewayAddresses ?? [];
16306
+ const primary = addresses.find((a) => a.IsPrimary === true) ?? addresses[0];
16307
+ return definedAttributes({
16308
+ NatGatewayId: gateway.NatGatewayId,
16309
+ EniId: gateway.AvailabilityMode === "regional" ? void 0 : primary?.NetworkInterfaceId,
16310
+ RouteTableId: gateway.RouteTableId,
16311
+ AutoProvisionZones: gateway.AutoProvisionZones,
16312
+ AutoScalingIps: gateway.AutoScalingIps
16313
+ });
16314
+ }
16315
+ const NAT_ADDRESS_SETTLE_POLLS = 90;
16316
+ const NAT_ADDRESS_SETTLE_DELAY_MS = 1e4;
16317
+ const NAT_ADDRESS_UNLISTED_POLLS = 6;
16318
+ function natAddressInZone(address, entry) {
16319
+ return entry.availabilityZone !== void 0 && address.AvailabilityZone === entry.availabilityZone || entry.availabilityZoneId !== void 0 && address.AvailabilityZoneId === entry.availabilityZoneId;
16320
+ }
16321
+ function natAddressHeld(address) {
16322
+ return typeof address.AllocationId === "string" && address.Status !== "disassociating" && address.Status !== "failed";
16323
+ }
16324
+ function planNatZoneAddressUpdate(desired, live) {
16325
+ const held = live.filter(natAddressHeld);
16326
+ const associate = [];
16327
+ const moved = [];
16328
+ const awaitingRelease = [];
16329
+ const wanted = /* @__PURE__ */ new Set();
16330
+ for (const entry of desired) {
16331
+ const missing = [];
16332
+ for (const allocationId of entry.allocationIds) {
16333
+ wanted.add(allocationId);
16334
+ const holder = held.find((a) => a.AllocationId === allocationId);
16335
+ if (holder === void 0) {
16336
+ missing.push(allocationId);
16337
+ if (live.some((a) => a.AllocationId === allocationId && a.Status === "disassociating")) awaitingRelease.push(allocationId);
16338
+ } else if (!natAddressInZone(holder, entry)) moved.push(allocationId);
16339
+ }
16340
+ if (missing.length > 0) associate.push({
16341
+ ...entry,
16342
+ allocationIds: missing
16343
+ });
16344
+ }
16345
+ return {
16346
+ associate,
16347
+ disassociate: held.filter((a) => !wanted.has(a.AllocationId)).map((a) => ({
16348
+ allocationId: a.AllocationId,
16349
+ associationId: a.AssociationId
16350
+ })),
16351
+ moved,
16352
+ awaitingRelease,
16353
+ keptSettled: held.some((a) => wanted.has(a.AllocationId) && a.Status === "succeeded")
16354
+ };
16355
+ }
16356
+ function readbackNatZoneAddresses(live, recorded) {
16357
+ const held = live.filter(natAddressHeld).filter((a) => a.AvailabilityZone !== void 0 || a.AvailabilityZoneId !== void 0);
16358
+ const out = [];
16359
+ const emit = (entry, addresses) => {
16360
+ if (addresses.length === 0) return;
16361
+ const ids = addresses.map((a) => a.AllocationId);
16362
+ const ordered = [...entry.allocationIds.filter((id) => ids.includes(id)), ...ids.filter((id) => !entry.allocationIds.includes(id))];
16363
+ out.push({
16364
+ ...entry.availabilityZone !== void 0 && { AvailabilityZone: entry.availabilityZone },
16365
+ ...entry.availabilityZoneId !== void 0 && { AvailabilityZoneId: entry.availabilityZoneId },
16366
+ AllocationIds: ordered
16367
+ });
16368
+ };
16369
+ let rest = held;
16370
+ for (const entry of recorded) {
16371
+ emit(entry, rest.filter((a) => natAddressInZone(a, entry)));
16372
+ rest = rest.filter((a) => !natAddressInZone(a, entry));
16373
+ }
16374
+ const zones = [...new Set(rest.map((a) => a.AvailabilityZone ?? a.AvailabilityZoneId ?? ""))];
16375
+ for (const zone of zones) {
16376
+ const inZone = rest.filter((a) => (a.AvailabilityZone ?? a.AvailabilityZoneId ?? "") === zone);
16377
+ const first = inZone[0];
16378
+ emit(first.AvailabilityZone !== void 0 ? {
16379
+ availabilityZone: first.AvailabilityZone,
16380
+ allocationIds: []
16381
+ } : {
16382
+ availabilityZoneId: first.AvailabilityZoneId,
16383
+ allocationIds: []
16384
+ }, inZone);
16385
+ }
16386
+ return out;
16387
+ }
16197
16388
  const EIP_ALLOCATION_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["InvalidAllocationID.NotFound"]);
16198
16389
  const INSTANCE_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["InvalidInstanceID.NotFound"]);
16199
16390
  const VPC_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["InvalidVpcID.NotFound"]);
@@ -16275,7 +16466,10 @@ var EC2Provider = class {
16275
16466
  "SecondaryAllocationIds",
16276
16467
  "SecondaryPrivateIpAddresses",
16277
16468
  "SecondaryPrivateIpAddressCount",
16278
- "Tags"
16469
+ "Tags",
16470
+ "AvailabilityMode",
16471
+ "VpcId",
16472
+ "AvailabilityZoneAddresses"
16279
16473
  ])],
16280
16474
  ["AWS::EC2::RouteTable", /* @__PURE__ */ new Set(["VpcId", "Tags"])],
16281
16475
  ["AWS::EC2::Route", /* @__PURE__ */ new Set([
@@ -16353,7 +16547,7 @@ var EC2Provider = class {
16353
16547
  unhandledByDesign = /* @__PURE__ */ new Map([
16354
16548
  ["AWS::EC2::Instance", /* @__PURE__ */ new Map([["ElasticGpuSpecifications", "AWS Elastic GPU end-of-life (announced 2023-11); no replacement API"], ["ElasticInferenceAccelerators", "AWS Elastic Inference end-of-life 2024-04; use AWS Inferentia / Trainium accelerator instance families instead"]])],
16355
16549
  ["AWS::EC2::SecurityGroupIngress", /* @__PURE__ */ new Map([["GroupName", "EC2-Classic-only — use GroupId for VPC security groups (EC2-Classic retired 2022-08-15)"], ["SourceSecurityGroupName", "EC2-Classic-only — use SourceSecurityGroupId for VPC peer security groups (EC2-Classic retired 2022-08-15)"]])],
16356
- ["AWS::EC2::NatGateway", /* @__PURE__ */ new Map([["VpcId", "AWS derives the VPC from SubnetId; the ec2:CreateNatGateway API has no VpcId parameter"], ["MaxDrainDurationSeconds", "write-only address-drain timeout with no CreateNatGateway member and no NAT gateway modify API; only ec2:DisassociateNatGatewayAddress / UnassignPrivateNatGatewayAddress accept it, and cdkd rejects NatGateway updates outright — routed via Cloud Control instead"]])],
16550
+ ["AWS::EC2::NatGateway", /* @__PURE__ */ new Map([["MaxDrainDurationSeconds", "write-only address-drain timeout with no CreateNatGateway member and no NAT gateway modify API; only ec2:DisassociateNatGatewayAddress / UnassignPrivateNatGatewayAddress accept it, and the cdkd NatGateway update releases only the AvailabilityZoneAddresses of a regional gateway, never the secondary addresses of a zonal one — routed via Cloud Control instead"]])],
16357
16551
  ["AWS::EC2::EIP", /* @__PURE__ */ new Map([
16358
16552
  ["Address", "Bring-your-own-IP: allocating a specific address you own is not yet supported; cdkd allocates an Amazon-owned address"],
16359
16553
  ["IpamPoolId", "Allocation from an IPAM pool is not yet supported"],
@@ -16519,7 +16713,7 @@ var EC2Provider = class {
16519
16713
  case "AWS::EC2::InternetGateway": return this.updateInternetGateway(logicalId, physicalId);
16520
16714
  case "AWS::EC2::EIP": return this.updateEip(logicalId, physicalId, resourceType, properties, previousProperties, context);
16521
16715
  case "AWS::EC2::VPCGatewayAttachment": return this.updateVpcGatewayAttachment(logicalId, physicalId, resourceType, properties, previousProperties, context);
16522
- case "AWS::EC2::NatGateway": return this.updateNatGateway(logicalId, physicalId);
16716
+ case "AWS::EC2::NatGateway": return this.updateNatGateway(logicalId, physicalId, resourceType, properties, previousProperties, context);
16523
16717
  case "AWS::EC2::RouteTable": return this.updateRouteTable(logicalId, physicalId);
16524
16718
  case "AWS::EC2::Route": return this.updateRoute(logicalId, physicalId, resourceType, properties, previousProperties, context);
16525
16719
  case "AWS::EC2::SubnetRouteTableAssociation": return this.updateSubnetRouteTableAssociation(logicalId, physicalId);
@@ -16561,9 +16755,15 @@ var EC2Provider = class {
16561
16755
  case "AWS::EC2::SecurityGroup": return this.getSecurityGroupAttribute(physicalId, attributeName);
16562
16756
  case "AWS::EC2::Instance": return this.getInstanceAttribute(physicalId, attributeName);
16563
16757
  case "AWS::EC2::EIP": return this.getEipAttribute(physicalId, attributeName);
16758
+ case "AWS::EC2::NatGateway": return this.getNatGatewayAttribute(physicalId, attributeName);
16564
16759
  default: return;
16565
16760
  }
16566
16761
  }
16762
+ async getNatGatewayAttribute(physicalId, attributeName) {
16763
+ if (attributeName === "NatGatewayId") return physicalId;
16764
+ const gateway = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.NatGatewayId === physicalId);
16765
+ return gateway === void 0 ? void 0 : natGatewayAttributes(gateway)[attributeName];
16766
+ }
16567
16767
  async isSameResource(journaledPhysicalId, record, resourceType, context) {
16568
16768
  let read;
16569
16769
  let identity;
@@ -17060,7 +17260,7 @@ var EC2Provider = class {
17060
17260
  }
17061
17261
  }
17062
17262
  updateInternetGateway(logicalId, physicalId) {
17063
- return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::InternetGateway", logicalId, "destroy + redeploy the InternetGateway. IGW properties are immutable in AWS."));
17263
+ return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::InternetGateway", logicalId, "destroy + redeploy the InternetGateway. IGW properties are immutable in AWS"));
17064
17264
  }
17065
17265
  async deleteInternetGateway(logicalId, physicalId, resourceType, context) {
17066
17266
  this.logger.debug(`Deleting InternetGateway ${logicalId}: ${physicalId}`);
@@ -17569,8 +17769,11 @@ var EC2Provider = class {
17569
17769
  async createNatGateway(logicalId, resourceType, properties, context) {
17570
17770
  this.logger.debug(`Creating NatGateway ${logicalId}`);
17571
17771
  const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
17772
+ const regional = properties["AvailabilityMode"] === "regional";
17572
17773
  const subnetId = properties["SubnetId"];
17573
- if (!subnetId) throw new ProvisioningError(`SubnetId is required for NatGateway ${logicalId}`, resourceType, logicalId);
17774
+ if (!subnetId && !regional) throw new ProvisioningError(`SubnetId is required for NatGateway ${logicalId} (a regional NAT gateway, AvailabilityMode: regional, takes VpcId instead)`, resourceType, logicalId);
17775
+ const zoneAddresses = readNatZoneAddresses(properties["AvailabilityZoneAddresses"]);
17776
+ if (zoneAddresses.kind === "unusable") throw new ProvisioningError(`AvailabilityZoneAddresses of NatGateway ${logicalId} ${zoneAddresses.reason}; each entry needs AvailabilityZone or AvailabilityZoneId and a non-empty AllocationIds list`, resourceType, logicalId);
17574
17777
  const natGatewayToken = acquireIdempotencyToken({
17575
17778
  scope: "CreateNatGateway",
17576
17779
  logicalId
@@ -17581,6 +17784,13 @@ var EC2Provider = class {
17581
17784
  ...TagSpecifications && { TagSpecifications },
17582
17785
  ClientToken: natGatewayToken.value,
17583
17786
  SubnetId: subnetId,
17787
+ AvailabilityMode: properties["AvailabilityMode"],
17788
+ VpcId: properties["VpcId"],
17789
+ ...zoneAddresses.kind === "usable" && { AvailabilityZoneAddresses: zoneAddresses.entries.map((entry) => ({
17790
+ AvailabilityZone: entry.availabilityZone,
17791
+ AvailabilityZoneId: entry.availabilityZoneId,
17792
+ AllocationIds: entry.allocationIds
17793
+ })) },
17584
17794
  AllocationId: properties["AllocationId"],
17585
17795
  ConnectivityType: properties["ConnectivityType"] ?? void 0,
17586
17796
  PrivateIpAddress: properties["PrivateIpAddress"],
@@ -17591,21 +17801,26 @@ var EC2Provider = class {
17591
17801
  const natGatewayId = response.NatGateway.NatGatewayId;
17592
17802
  createdId = natGatewayId;
17593
17803
  if (!tagsApplied) await this.applyTags(natGatewayId, desiredTags, logicalId, maskerOrIdentity(context?.maskSecrets));
17804
+ let described;
17594
17805
  if (process.env["CDKD_NO_WAIT"] !== "true") {
17595
17806
  this.logger.debug(`Waiting for NatGateway ${natGatewayId} to reach available state...`);
17596
- await waitUntilNatGatewayAvailable({
17807
+ described = (await waitUntilNatGatewayAvailable({
17597
17808
  client: this.ec2Client,
17598
17809
  maxWaitTime: 900,
17599
17810
  minDelay: 5,
17600
17811
  maxDelay: 10
17601
- }, { NatGatewayIds: [natGatewayId] });
17812
+ }, { NatGatewayIds: [natGatewayId] })).reason?.NatGateways?.find((g) => g.NatGatewayId === natGatewayId);
17602
17813
  this.logger.debug(`NatGateway ${natGatewayId} is available`);
17603
17814
  } else this.logger.debug(`NatGateway ${natGatewayId} created (skipping available-state wait per --no-wait)`);
17604
17815
  this.logger.debug(`Successfully created NatGateway ${logicalId}: ${natGatewayId}`);
17605
17816
  natGatewayToken.release();
17606
17817
  return {
17607
17818
  physicalId: natGatewayId,
17608
- attributes: { NatGatewayId: natGatewayId }
17819
+ attributes: {
17820
+ ...natGatewayAttributes(response.NatGateway ?? {}),
17821
+ ...described !== void 0 && natGatewayAttributes(described),
17822
+ NatGatewayId: natGatewayId
17823
+ }
17609
17824
  };
17610
17825
  } catch (error) {
17611
17826
  const cause = error instanceof Error ? error : void 0;
@@ -17614,8 +17829,125 @@ var EC2Provider = class {
17614
17829
  throw thrown;
17615
17830
  }
17616
17831
  }
17617
- updateNatGateway(logicalId, physicalId) {
17618
- return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::NatGateway", logicalId, "destroy + redeploy the NatGateway (and the dependent Routes). NAT Gateway properties are immutable in AWS."));
17832
+ async updateNatGateway(logicalId, physicalId, resourceType, properties, previousProperties, context) {
17833
+ this.logger.debug(safeMsg`Updating NatGateway ${logicalId}: ${physicalId}`);
17834
+ const refuse = (property) => {
17835
+ throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `destroy + redeploy the NatGateway (and the dependent Routes). cdkd cannot change ${property} of an existing NAT gateway`);
17836
+ };
17837
+ for (const key of [
17838
+ "SubnetId",
17839
+ "ConnectivityType",
17840
+ "AllocationId",
17841
+ "PrivateIpAddress",
17842
+ "AvailabilityMode",
17843
+ "VpcId"
17844
+ ]) {
17845
+ const next = properties[key];
17846
+ const prev = previousProperties[key];
17847
+ if (next !== void 0 && prev !== void 0 && JSON.stringify(next) !== JSON.stringify(prev)) refuse(key);
17848
+ }
17849
+ if (previousProperties["AvailabilityZoneAddresses"] == null && properties["AvailabilityZoneAddresses"] != null) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "destroy + redeploy the NatGateway (and the dependent Routes). Adding AvailabilityZoneAddresses to a gateway created without it replaces the gateway");
17850
+ for (const key of [
17851
+ "SecondaryAllocationIds",
17852
+ "SecondaryPrivateIpAddresses",
17853
+ "SecondaryPrivateIpAddressCount"
17854
+ ]) if (JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key])) refuse(key);
17855
+ refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
17856
+ const mask = maskerOrIdentity(context?.maskSecrets);
17857
+ try {
17858
+ let zonePlan;
17859
+ if (JSON.stringify(properties["AvailabilityZoneAddresses"]) !== JSON.stringify(previousProperties["AvailabilityZoneAddresses"])) zonePlan = await this.planNatGatewayZoneAddresses(logicalId, physicalId, resourceType, properties["AvailabilityZoneAddresses"]);
17860
+ if (zonePlan !== void 0) await this.applyNatGatewayZoneAddresses(logicalId, physicalId, resourceType, zonePlan);
17861
+ await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], mask);
17862
+ this.logger.debug(safeMsg`Successfully updated NatGateway ${logicalId}`);
17863
+ return {
17864
+ physicalId,
17865
+ wasReplaced: false
17866
+ };
17867
+ } catch (error) {
17868
+ if (error instanceof CdkdError) throw error;
17869
+ const cause = error instanceof Error ? error : void 0;
17870
+ throw this.wrapCaughtError(mask, error, (text) => new ProvisioningError(`Failed to update NatGateway ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
17871
+ }
17872
+ }
17873
+ async planNatGatewayZoneAddresses(logicalId, physicalId, resourceType, rawDesired) {
17874
+ const desired = readNatZoneAddresses(rawDesired);
17875
+ if (desired.kind === "unusable") throw markNonRetryable(new ProvisioningError(`AvailabilityZoneAddresses of NatGateway ${logicalId} ${desired.reason}; each entry needs AvailabilityZone or AvailabilityZoneId and a non-empty AllocationIds list`, resourceType, logicalId, physicalId));
17876
+ if (desired.kind === "absent") throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} cannot drop AvailabilityZoneAddresses: a regional NAT gateway created with explicit zones does not return to automatic zone expansion, and CloudFormation refuses the same update. Keep at least one zone declared, or rename the logical id or change a create-only property to replace the gateway`, resourceType, logicalId, physicalId));
17877
+ const gateway = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.NatGatewayId === physicalId);
17878
+ if (gateway === void 0) throw new ProvisioningError(`NatGateway ${logicalId} (${physicalId}) was not returned by DescribeNatGateways, so its addresses cannot be updated`, resourceType, logicalId, physicalId);
17879
+ const plan = planNatZoneAddressUpdate(desired.entries, gateway.NatGatewayAddresses ?? []);
17880
+ for (const d of plan.disassociate) {
17881
+ const status = gateway.NatGatewayAddresses?.find((x) => x.AllocationId === d.allocationId)?.Status ?? "unknown";
17882
+ this.logger.debug(safeMsg`NatGateway ${physicalId} plans to release ${d.allocationId} (live status ${status})`);
17883
+ }
17884
+ for (const id of plan.awaitingRelease) this.logger.debug(safeMsg`NatGateway ${physicalId} plans to associate ${id}, which AWS is still releasing`);
17885
+ if (plan.moved.length > 0) throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} declares ${plan.moved.join(", ")} in a different zone from the one that holds it; cdkd does not move an Elastic IP between zones in one update. Remove it from AvailabilityZoneAddresses in one deploy and add it to the new zone in the next`, resourceType, logicalId, physicalId));
17886
+ return plan;
17887
+ }
17888
+ async applyNatGatewayZoneAddresses(logicalId, physicalId, resourceType, plan) {
17889
+ const budget = { polls: NAT_ADDRESS_SETTLE_POLLS };
17890
+ if (plan.awaitingRelease.length > 0) {
17891
+ const ids = new Set(plan.awaitingRelease);
17892
+ await this.pollNatGateway(logicalId, physicalId, resourceType, budget, `the release of ${plan.awaitingRelease.join(", ")}`, "nothing was associated or released", (gateway) => (gateway.NatGatewayAddresses ?? []).some((a) => typeof a.AllocationId === "string" && ids.has(a.AllocationId) && a.Status === "disassociating") ? "wait" : "done");
17893
+ }
17894
+ for (const entry of plan.associate) await this.ec2Client.send(new AssociateNatGatewayAddressCommand({
17895
+ NatGatewayId: physicalId,
17896
+ AllocationIds: entry.allocationIds,
17897
+ AvailabilityZone: entry.availabilityZone,
17898
+ AvailabilityZoneId: entry.availabilityZoneId
17899
+ }));
17900
+ if (plan.disassociate.length === 0) return;
17901
+ let associationIds = plan.disassociate.map((d) => d.associationId).filter((id) => id !== void 0);
17902
+ const unassociated = plan.disassociate.filter((d) => d.associationId === void 0);
17903
+ if (unassociated.length > 0) {
17904
+ const targets = new Set(unassociated.map((d) => d.allocationId));
17905
+ const gateway = await this.pollNatGateway(logicalId, physicalId, resourceType, budget, `the association of ${unassociated.map((d) => d.allocationId).join(", ")} before releasing it`, "the release was not sent", (gw) => (gw.NatGatewayAddresses ?? []).some((a) => typeof a.AllocationId === "string" && targets.has(a.AllocationId) && natAddressHeld(a) && !(a.Status === "succeeded" && typeof a.AssociationId === "string")) ? "wait" : "done");
17906
+ for (const a of gateway.NatGatewayAddresses ?? []) if (typeof a.AllocationId === "string" && targets.has(a.AllocationId) && natAddressHeld(a) && typeof a.AssociationId === "string") associationIds.push(a.AssociationId);
17907
+ associationIds = [...new Set(associationIds)];
17908
+ }
17909
+ if (associationIds.length === 0) return;
17910
+ if (!plan.keptSettled) {
17911
+ const releasing = new Set(plan.disassociate.map((d) => d.allocationId));
17912
+ const added = plan.associate.flatMap((e) => e.allocationIds);
17913
+ let unlisted = 0;
17914
+ await this.pollNatGateway(logicalId, physicalId, resourceType, budget, "an address the template keeps to associate before releasing the last associated one", "the release was not sent", (gw) => {
17915
+ const kept = (gw.NatGatewayAddresses ?? []).filter((a) => typeof a.AllocationId === "string" && !releasing.has(a.AllocationId));
17916
+ if (kept.some((a) => a.Status === "succeeded")) return "done";
17917
+ if (kept.some((a) => a.Status === "associating")) return "wait";
17918
+ const missing = added.filter((id) => !kept.some((a) => a.AllocationId === id));
17919
+ if (missing.length > 0) {
17920
+ unlisted++;
17921
+ if (unlisted <= NAT_ADDRESS_UNLISTED_POLLS) return "wait";
17922
+ return markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} does not list ${missing.join(", ")} after associating it, so its last associated address was not released. Check \`aws ec2 describe-nat-gateways --nat-gateway-ids ${physicalId}\` and re-run the deploy`, resourceType, logicalId, physicalId));
17923
+ }
17924
+ const failed = added.filter((id) => kept.find((a) => a.AllocationId === id)?.Status === "failed");
17925
+ return markNonRetryable(new ProvisioningError(failed.length > 0 ? `NatGateway ${logicalId} could not associate ${failed.join(", ")}, so its last associated address was not released. Read the failure with \`aws ec2 describe-nat-gateways --nat-gateway-ids ${physicalId}\` and fix the declared Elastic IP` : `NatGateway ${logicalId} has no other associated or associating address, so its last associated address was not released. Declare an Elastic IP the gateway can associate`, resourceType, logicalId, physicalId));
17926
+ });
17927
+ }
17928
+ await this.ec2Client.send(new DisassociateNatGatewayAddressCommand({
17929
+ NatGatewayId: physicalId,
17930
+ AssociationIds: associationIds
17931
+ }));
17932
+ }
17933
+ async pollNatGateway(logicalId, physicalId, resourceType, budget, what, unsent, decide) {
17934
+ this.logger.debug(safeMsg`Waiting for NatGateway ${physicalId}: ${what}...`);
17935
+ const watch = startInterruptWatch(`NatGateway ${logicalId} address wait`);
17936
+ try {
17937
+ while (budget.polls > 0) {
17938
+ budget.polls--;
17939
+ if (watch.isInterrupted()) throw watch.onInterrupted();
17940
+ const gateway = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.NatGatewayId === physicalId);
17941
+ if (gateway === void 0 || gateway.State === "deleting" || gateway.State === "deleted" || gateway.State === "failed") throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} (${physicalId}) is ${gateway?.State ?? "no longer returned by DescribeNatGateways"}, so cdkd stopped waiting for ${what}`, resourceType, logicalId, physicalId));
17942
+ const verdict = decide(gateway);
17943
+ if (verdict === "done") return gateway;
17944
+ if (verdict !== "wait") throw verdict;
17945
+ await this.sleep(NAT_ADDRESS_SETTLE_DELAY_MS);
17946
+ }
17947
+ } finally {
17948
+ watch.dispose();
17949
+ }
17950
+ throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} ran out of its ${NAT_ADDRESS_SETTLE_POLLS * NAT_ADDRESS_SETTLE_DELAY_MS / 6e4}-minute address wait while waiting for ${what}; ${unsent}. Re-run the deploy once \`aws ec2 describe-nat-gateways --nat-gateway-ids ${physicalId}\` shows its addresses settled`, resourceType, logicalId, physicalId));
17619
17951
  }
17620
17952
  async deleteNatGateway(logicalId, physicalId, resourceType, context) {
17621
17953
  this.logger.debug(`Deleting NatGateway ${logicalId}: ${physicalId}`);
@@ -19219,7 +19551,7 @@ var EC2Provider = class {
19219
19551
  case "AWS::EC2::VPC": return await this.readVpcCurrentState(physicalId);
19220
19552
  case "AWS::EC2::Subnet": return await this.readSubnetCurrentState(physicalId);
19221
19553
  case "AWS::EC2::InternetGateway": return await this.readInternetGatewayCurrentState(physicalId);
19222
- case "AWS::EC2::NatGateway": return await this.readNatGatewayCurrentState(physicalId);
19554
+ case "AWS::EC2::NatGateway": return await this.readNatGatewayCurrentState(physicalId, properties);
19223
19555
  case "AWS::EC2::RouteTable": return await this.readRouteTableCurrentState(physicalId);
19224
19556
  case "AWS::EC2::SecurityGroup": return await this.readSecurityGroupCurrentState(physicalId, properties);
19225
19557
  case "AWS::EC2::Instance": return await this.readInstanceCurrentState(physicalId);
@@ -19303,15 +19635,22 @@ var EC2Provider = class {
19303
19635
  if (!(await this.ec2Client.send(new DescribeInternetGatewaysCommand({ InternetGatewayIds: [physicalId] }))).InternetGateways?.[0]) return RESOURCE_NOT_FOUND;
19304
19636
  return {};
19305
19637
  }
19306
- async readNatGatewayCurrentState(physicalId) {
19638
+ async readNatGatewayCurrentState(physicalId, properties) {
19307
19639
  const gw = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.State !== "deleted" && g.State !== "deleting");
19308
19640
  if (!gw) return RESOURCE_NOT_FOUND;
19309
19641
  const result = {};
19310
19642
  if (gw.SubnetId !== void 0) result["SubnetId"] = gw.SubnetId;
19311
19643
  if (gw.ConnectivityType !== void 0) result["ConnectivityType"] = gw.ConnectivityType;
19312
- const primary = gw.NatGatewayAddresses?.[0];
19313
- if (primary?.AllocationId !== void 0) result["AllocationId"] = primary.AllocationId;
19314
- if (primary?.PrivateIp !== void 0) result["PrivateIpAddress"] = primary.PrivateIp;
19644
+ const regional = gw.AvailabilityMode === "regional";
19645
+ const primary = gw.NatGatewayAddresses?.find((a) => a.IsPrimary === true) ?? gw.NatGatewayAddresses?.[0];
19646
+ if (primary?.AllocationId !== void 0 && (!regional || properties?.["AllocationId"] != null)) result["AllocationId"] = primary.AllocationId;
19647
+ if (primary?.PrivateIp !== void 0 && (!regional || properties?.["PrivateIpAddress"] != null)) result["PrivateIpAddress"] = primary.PrivateIp;
19648
+ if (gw.AvailabilityMode !== void 0) result["AvailabilityMode"] = gw.AvailabilityMode;
19649
+ if (gw.VpcId !== void 0) result["VpcId"] = gw.VpcId;
19650
+ if (gw.AvailabilityMode === "regional" && gw.AutoProvisionZones === "disabled") {
19651
+ const recorded = readNatZoneAddresses(properties?.["AvailabilityZoneAddresses"]);
19652
+ result["AvailabilityZoneAddresses"] = readbackNatZoneAddresses(gw.NatGatewayAddresses ?? [], recorded.kind === "usable" ? recorded.entries : []);
19653
+ }
19315
19654
  return result;
19316
19655
  }
19317
19656
  async readEipCurrentState(physicalId, properties, afterOwnWrite) {
@@ -19703,10 +20042,13 @@ var EC2Provider = class {
19703
20042
  attributes: { Id: rule.SecurityGroupRuleId }
19704
20043
  };
19705
20044
  }
19706
- case "AWS::EC2::NatGateway": return (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.State !== "deleted" && g.State !== "deleting") ? {
19707
- physicalId,
19708
- attributes: {}
19709
- } : null;
20045
+ case "AWS::EC2::NatGateway": {
20046
+ const gw = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.State !== "deleted" && g.State !== "deleting");
20047
+ return gw ? {
20048
+ physicalId,
20049
+ attributes: natGatewayAttributes(gw)
20050
+ } : null;
20051
+ }
19710
20052
  case "AWS::EC2::EIP": {
19711
20053
  const { allocationId, publicIp } = this.parseEipPhysicalId(physicalId);
19712
20054
  const filter = allocationId ? { AllocationIds: [allocationId] } : { PublicIps: publicIp ? [publicIp] : [] };
@@ -30936,14 +31278,9 @@ function sanitizeDescription(value) {
30936
31278
  if (typeof value === "string" && value.length === 0) return void 0;
30937
31279
  return value;
30938
31280
  }
30939
- function isPlainObject(value) {
31281
+ function isPlainObject$1(value) {
30940
31282
  return typeof value === "object" && value !== null && !Array.isArray(value);
30941
31283
  }
30942
- const SDK_UNSUPPORTED_RULE_KEYS = [
30943
- "PreParseTextTransformations",
30944
- "Monetize",
30945
- "PriceMultiplier"
30946
- ];
30947
31284
  function toSdkByteMatchStatement(byteMatchStatement) {
30948
31285
  const encoded = byteMatchStatement["SearchStringBase64"];
30949
31286
  if (typeof encoded !== "string") return byteMatchStatement;
@@ -30960,10 +31297,10 @@ const ARN_REFERENCE_STATEMENT_KEYS = [
30960
31297
  function toSdkStatement(statement) {
30961
31298
  const converted = { ...statement };
30962
31299
  const byteMatchStatement = converted["ByteMatchStatement"];
30963
- if (isPlainObject(byteMatchStatement)) converted["ByteMatchStatement"] = toSdkByteMatchStatement(byteMatchStatement);
31300
+ if (isPlainObject$1(byteMatchStatement)) converted["ByteMatchStatement"] = toSdkByteMatchStatement(byteMatchStatement);
30964
31301
  for (const key of ARN_REFERENCE_STATEMENT_KEYS) {
30965
31302
  const reference = converted[key];
30966
- if (!isPlainObject(reference) || !("Arn" in reference)) continue;
31303
+ if (!isPlainObject$1(reference) || !("Arn" in reference)) continue;
30967
31304
  const { Arn: arn, ...rest } = reference;
30968
31305
  converted[key] = {
30969
31306
  ...rest,
@@ -30971,28 +31308,28 @@ function toSdkStatement(statement) {
30971
31308
  };
30972
31309
  }
30973
31310
  const notStatement = converted["NotStatement"];
30974
- if (isPlainObject(notStatement)) {
31311
+ if (isPlainObject$1(notStatement)) {
30975
31312
  const nested = notStatement["Statement"];
30976
- if (isPlainObject(nested)) converted["NotStatement"] = {
31313
+ if (isPlainObject$1(nested)) converted["NotStatement"] = {
30977
31314
  ...notStatement,
30978
31315
  Statement: toSdkStatement(nested)
30979
31316
  };
30980
31317
  }
30981
31318
  for (const key of ["AndStatement", "OrStatement"]) {
30982
31319
  const combined = converted[key];
30983
- if (!isPlainObject(combined)) continue;
31320
+ if (!isPlainObject$1(combined)) continue;
30984
31321
  const nested = combined["Statements"];
30985
31322
  if (!Array.isArray(nested)) continue;
30986
31323
  converted[key] = {
30987
31324
  ...combined,
30988
- Statements: nested.map((item) => isPlainObject(item) ? toSdkStatement(item) : item)
31325
+ Statements: nested.map((item) => isPlainObject$1(item) ? toSdkStatement(item) : item)
30989
31326
  };
30990
31327
  }
30991
31328
  for (const key of ["RateBasedStatement", "ManagedRuleGroupStatement"]) {
30992
31329
  const scoping = converted[key];
30993
- if (!isPlainObject(scoping)) continue;
31330
+ if (!isPlainObject$1(scoping)) continue;
30994
31331
  const nested = scoping["ScopeDownStatement"];
30995
- if (!isPlainObject(nested)) continue;
31332
+ if (!isPlainObject$1(nested)) continue;
30996
31333
  converted[key] = {
30997
31334
  ...scoping,
30998
31335
  ScopeDownStatement: toSdkStatement(nested)
@@ -31004,9 +31341,9 @@ function toSdkRules(rules) {
31004
31341
  if (!rules) return [];
31005
31342
  if (!Array.isArray(rules)) return rules;
31006
31343
  return rules.map((rule) => {
31007
- if (!isPlainObject(rule)) return rule;
31344
+ if (!isPlainObject$1(rule)) return rule;
31008
31345
  const statement = rule["Statement"];
31009
- if (!isPlainObject(statement)) return rule;
31346
+ if (!isPlainObject$1(statement)) return rule;
31010
31347
  return {
31011
31348
  ...rule,
31012
31349
  Statement: toSdkStatement(statement)
@@ -31018,7 +31355,7 @@ function toCfnByteMatchStatement(byteMatchStatement, baseline) {
31018
31355
  if (raw === void 0) return byteMatchStatement;
31019
31356
  const bytes = raw instanceof Uint8Array ? Buffer.from(raw) : typeof raw === "string" ? Buffer.from(raw, "utf8") : void 0;
31020
31357
  if (!bytes) return byteMatchStatement;
31021
- const base = isPlainObject(baseline) ? baseline : void 0;
31358
+ const base = isPlainObject$1(baseline) ? baseline : void 0;
31022
31359
  const baseEncoded = base?.["SearchStringBase64"];
31023
31360
  const basePlain = base?.["SearchString"];
31024
31361
  const converted = { ...byteMatchStatement };
@@ -31043,12 +31380,12 @@ function toCfnByteMatchStatement(byteMatchStatement, baseline) {
31043
31380
  }
31044
31381
  function toCfnStatement(statement, baseline) {
31045
31382
  const converted = { ...statement };
31046
- const base = isPlainObject(baseline) ? baseline : void 0;
31383
+ const base = isPlainObject$1(baseline) ? baseline : void 0;
31047
31384
  const byteMatchStatement = converted["ByteMatchStatement"];
31048
- if (isPlainObject(byteMatchStatement)) converted["ByteMatchStatement"] = toCfnByteMatchStatement(byteMatchStatement, base?.["ByteMatchStatement"]);
31385
+ if (isPlainObject$1(byteMatchStatement)) converted["ByteMatchStatement"] = toCfnByteMatchStatement(byteMatchStatement, base?.["ByteMatchStatement"]);
31049
31386
  for (const key of ARN_REFERENCE_STATEMENT_KEYS) {
31050
31387
  const reference = converted[key];
31051
- if (!isPlainObject(reference) || !("ARN" in reference)) continue;
31388
+ if (!isPlainObject$1(reference) || !("ARN" in reference)) continue;
31052
31389
  const { ARN: arn, ...rest } = reference;
31053
31390
  converted[key] = {
31054
31391
  ...rest,
@@ -31056,37 +31393,37 @@ function toCfnStatement(statement, baseline) {
31056
31393
  };
31057
31394
  }
31058
31395
  const notStatement = converted["NotStatement"];
31059
- if (isPlainObject(notStatement)) {
31396
+ if (isPlainObject$1(notStatement)) {
31060
31397
  const nested = notStatement["Statement"];
31061
- if (isPlainObject(nested)) {
31398
+ if (isPlainObject$1(nested)) {
31062
31399
  const baseNot = base?.["NotStatement"];
31063
31400
  converted["NotStatement"] = {
31064
31401
  ...notStatement,
31065
- Statement: toCfnStatement(nested, isPlainObject(baseNot) ? baseNot["Statement"] : void 0)
31402
+ Statement: toCfnStatement(nested, isPlainObject$1(baseNot) ? baseNot["Statement"] : void 0)
31066
31403
  };
31067
31404
  }
31068
31405
  }
31069
31406
  for (const key of ["AndStatement", "OrStatement"]) {
31070
31407
  const combined = converted[key];
31071
- if (!isPlainObject(combined)) continue;
31408
+ if (!isPlainObject$1(combined)) continue;
31072
31409
  const nested = combined["Statements"];
31073
31410
  if (!Array.isArray(nested)) continue;
31074
31411
  const baseCombined = base?.[key];
31075
- const baseList = isPlainObject(baseCombined) && Array.isArray(baseCombined["Statements"]) ? baseCombined["Statements"] : void 0;
31412
+ const baseList = isPlainObject$1(baseCombined) && Array.isArray(baseCombined["Statements"]) ? baseCombined["Statements"] : void 0;
31076
31413
  converted[key] = {
31077
31414
  ...combined,
31078
- Statements: nested.map((item, i) => isPlainObject(item) ? toCfnStatement(item, baseList?.[i]) : item)
31415
+ Statements: nested.map((item, i) => isPlainObject$1(item) ? toCfnStatement(item, baseList?.[i]) : item)
31079
31416
  };
31080
31417
  }
31081
31418
  for (const key of ["RateBasedStatement", "ManagedRuleGroupStatement"]) {
31082
31419
  const scoping = converted[key];
31083
- if (!isPlainObject(scoping)) continue;
31420
+ if (!isPlainObject$1(scoping)) continue;
31084
31421
  const nested = scoping["ScopeDownStatement"];
31085
- if (!isPlainObject(nested)) continue;
31422
+ if (!isPlainObject$1(nested)) continue;
31086
31423
  const baseScoping = base?.[key];
31087
31424
  converted[key] = {
31088
31425
  ...scoping,
31089
- ScopeDownStatement: toCfnStatement(nested, isPlainObject(baseScoping) ? baseScoping["ScopeDownStatement"] : void 0)
31426
+ ScopeDownStatement: toCfnStatement(nested, isPlainObject$1(baseScoping) ? baseScoping["ScopeDownStatement"] : void 0)
31090
31427
  };
31091
31428
  }
31092
31429
  return converted;
@@ -31095,27 +31432,16 @@ function toCfnRules(rules, baselineRules) {
31095
31432
  if (!Array.isArray(rules)) return [];
31096
31433
  const baseList = Array.isArray(baselineRules) ? baselineRules : void 0;
31097
31434
  return rules.map((rule, i) => {
31098
- if (!isPlainObject(rule)) return rule;
31435
+ if (!isPlainObject$1(rule)) return rule;
31099
31436
  const statement = rule["Statement"];
31100
- if (!isPlainObject(statement)) return rule;
31437
+ if (!isPlainObject$1(statement)) return rule;
31101
31438
  const baseRule = baseList?.[i];
31102
31439
  return {
31103
31440
  ...rule,
31104
- Statement: toCfnStatement(statement, isPlainObject(baseRule) ? baseRule["Statement"] : void 0)
31441
+ Statement: toCfnStatement(statement, isPlainObject$1(baseRule) ? baseRule["Statement"] : void 0)
31105
31442
  };
31106
31443
  });
31107
31444
  }
31108
- function collectSdkUnsupportedRuleKeys(value, found) {
31109
- if (Array.isArray(value)) {
31110
- for (const item of value) collectSdkUnsupportedRuleKeys(item, found);
31111
- return;
31112
- }
31113
- if (!isPlainObject(value)) return;
31114
- for (const [key, nested] of Object.entries(value)) {
31115
- if (SDK_UNSUPPORTED_RULE_KEYS.includes(key)) found.add(key);
31116
- collectSdkUnsupportedRuleKeys(nested, found);
31117
- }
31118
- }
31119
31445
  var WAFv2WebACLProvider = class {
31120
31446
  wafv2Client;
31121
31447
  createClient;
@@ -31157,7 +31483,6 @@ var WAFv2WebACLProvider = class {
31157
31483
  const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
31158
31484
  const name = properties["Name"] || generatedNameFor("AWS::WAFv2::WebACL", logicalId);
31159
31485
  const scope = requireConfigString(properties["Scope"], "REGIONAL", "AWS::WAFv2::WebACL Scope", replayWarn(this.logger, context));
31160
- this.warnOnSdkUnsupportedRuleKeys(logicalId, properties["Rules"]);
31161
31486
  try {
31162
31487
  const tags = desiredTags.map((tag) => ({
31163
31488
  Key: tag.Key,
@@ -31207,7 +31532,6 @@ var WAFv2WebACLProvider = class {
31207
31532
  this.logger.debug(`Updating WAFv2 WebACL ${logicalId}: ${physicalId}`);
31208
31533
  assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
31209
31534
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
31210
- this.warnOnSdkUnsupportedRuleKeys(logicalId, properties["Rules"]);
31211
31535
  try {
31212
31536
  const { id, name, scope } = parseWebACLArn(physicalId);
31213
31537
  const getResponse = await this.getClient().send(new GetWebACLCommand({
@@ -31286,16 +31610,6 @@ var WAFv2WebACLProvider = class {
31286
31610
  throw error instanceof Error && error.name.includes("NotFound") ? markNotGone(thrown) : thrown;
31287
31611
  }
31288
31612
  }
31289
- warnOnSdkUnsupportedRuleKeys(logicalId, rules) {
31290
- const found = /* @__PURE__ */ new Set();
31291
- collectSdkUnsupportedRuleKeys(rules, found);
31292
- if (found.size === 0) return;
31293
- const sorted = [...found].sort();
31294
- const names = sorted.join(", ");
31295
- const subject = sorted.length === 1 ? "property" : "properties";
31296
- const verb = sorted.length === 1 ? "has" : "have";
31297
- this.logger.warn(`WAFv2 WebACL ${logicalId}: rule ${subject} ${names} ${verb} no member in the installed AWS SDK WAFv2 model and will NOT be sent to AWS. Upgrade cdkd once its @aws-sdk/client-wafv2 dependency carries the ${subject}.`);
31298
- }
31299
31613
  async applyTagDiff(arn, resourceType, logicalId, oldTagsRaw, newTagsRaw) {
31300
31614
  const plan = planTagDiff(oldTagsRaw, newTagsRaw);
31301
31615
  const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
@@ -31472,6 +31786,44 @@ const STANDARD_USER_POOL_ATTRIBUTES = /* @__PURE__ */ new Set([
31472
31786
  "website",
31473
31787
  "zoneinfo"
31474
31788
  ]);
31789
+ function createTimeOnlyChanges(properties, previousProperties) {
31790
+ return [
31791
+ [
31792
+ "UsernameAttributes",
31793
+ properties["UsernameAttributes"],
31794
+ previousProperties["UsernameAttributes"],
31795
+ "list"
31796
+ ],
31797
+ [
31798
+ "AliasAttributes",
31799
+ properties["AliasAttributes"],
31800
+ previousProperties["AliasAttributes"],
31801
+ "list"
31802
+ ],
31803
+ [
31804
+ "UsernameConfiguration",
31805
+ properties["UsernameConfiguration"],
31806
+ previousProperties["UsernameConfiguration"],
31807
+ "object"
31808
+ ]
31809
+ ].filter(([, desired, previous, shape]) => canonicalCreateTimeOnlyValue(shape, desired) !== canonicalCreateTimeOnlyValue(shape, previous)).map(([name]) => name);
31810
+ }
31811
+ function withPreviousCreateTimeOnly(bag, previousProperties, kept) {
31812
+ if (kept.length === 0) return bag;
31813
+ const out = { ...bag };
31814
+ for (const key of kept) if (previousProperties[key] === void 0) delete out[key];
31815
+ else out[key] = previousProperties[key];
31816
+ return out;
31817
+ }
31818
+ function canonicalCreateTimeOnlyValue(shape, declared) {
31819
+ const value = declared ?? (shape === "object" ? {} : []);
31820
+ if (Array.isArray(value)) return JSON.stringify(value.map((v) => JSON.stringify(v)).sort());
31821
+ if (typeof value === "object") {
31822
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => [k, typeof v === "boolean" ? String(v) : v]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
31823
+ return JSON.stringify(entries);
31824
+ }
31825
+ return JSON.stringify(value);
31826
+ }
31475
31827
  function isEmptyObjectPlaceholder(value) {
31476
31828
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
31477
31829
  }
@@ -31954,6 +32306,13 @@ var CognitoUserPoolProvider = class {
31954
32306
  throw new ProvisioningError(`${describeAwsFailure(error).detail}. Nothing was applied to user pool ${physicalId}`, resourceType, logicalId, physicalId, error instanceof Error ? error : void 0);
31955
32307
  }
31956
32308
  this.warnOnBlankMfaConfiguration(properties["MfaConfiguration"]);
32309
+ const createTimeOnly = createTimeOnlyChanges(properties, previousProperties);
32310
+ const keptCreateTimeOnly = stateBorneDesired ? createTimeOnly : [];
32311
+ if (createTimeOnly.length > 0) {
32312
+ const changed = createTimeOnly.join(", ");
32313
+ if (stateBorneDesired) this.logger.warn(safeMsg`Cognito User Pool ${logicalId} (${physicalId}): ${changed} cannot be changed in place ` + safeMsg`(UpdateUserPool has no such member), so the pool keeps its current value and cdkd ` + safeMsg`records that value.`);
32314
+ else throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${changed} cannot be changed on an existing user pool — UpdateUserPool has no such member, and CloudFormation refuses the same change ("Updates are not allowed for property"). Nothing was applied to user pool ${physicalId}. ` + this.replacementRemedy(physicalId, previousProperties["DeletionProtection"] === "ACTIVE"));
32315
+ }
31957
32316
  const liveFirstAuthFactors = mfaPreflightNeedsLiveSignInPolicy(properties, mfaConfiguration) ? await this.readLiveAllowedFirstAuthFactors(physicalId) : void 0;
31958
32317
  this.assertMfaCombinationApplicable(logicalId, resourceType, physicalId, properties, mfaConfiguration, liveFirstAuthFactors);
31959
32318
  const liveMfa = mfaConfiguration === "" && hasMfaConfigProps(properties) ? await this.readLiveMfaConfiguration(physicalId) : void 0;
@@ -31961,6 +32320,7 @@ var CognitoUserPoolProvider = class {
31961
32320
  const mfaFirstPrior = mfaMayNeedToPrecedeUpdateUserPool(properties, mfaConfiguration) ? await this.readMfaFirstPrior(physicalId) : void 0;
31962
32321
  try {
31963
32322
  const updateParams = { UserPoolId: physicalId };
32323
+ if (typeof properties["UserPoolName"] === "string" && properties["UserPoolName"] !== "") updateParams.PoolName = properties["UserPoolName"];
31964
32324
  if (properties["Policies"]) {
31965
32325
  const sdkPolicies = this.toSdkUserPoolPolicies(properties["Policies"]);
31966
32326
  if (sdkPolicies) updateParams.Policies = sdkPolicies;
@@ -32006,7 +32366,7 @@ var CognitoUserPoolProvider = class {
32006
32366
  const { urlSuffix } = derivePartitionAndUrlSuffix(region);
32007
32367
  const providerName = `cognito-idp.${region}.${urlSuffix}/${physicalId}`;
32008
32368
  const providerUrl = `https://cognito-idp.${region}.${urlSuffix}/${physicalId}`;
32009
- const effectiveProperties = narrowMfaConfiguration(properties);
32369
+ const effectiveProperties = withPreviousCreateTimeOnly(narrowMfaConfiguration(properties), previousProperties, keptCreateTimeOnly);
32010
32370
  return {
32011
32371
  physicalId,
32012
32372
  wasReplaced: false,
@@ -32049,20 +32409,7 @@ var CognitoUserPoolProvider = class {
32049
32409
  ...modified.map((n) => `modified attribute '${n}'`),
32050
32410
  ...addedStandard.map((n) => `added standard attribute '${n}'`)
32051
32411
  ];
32052
- if (immutableChanges.length > 0) {
32053
- const replaceFlags = "cdkd deploy --replace --force-stateful-recreation";
32054
- const remedy = deletionProtected ? protectedReplacementAdvice({
32055
- evidence: "cdkd's properties for this user pool carry DeletionProtection: ACTIVE",
32056
- replaceFlags,
32057
- disable: {
32058
- before: "aws cognito-idp update-user-pool --user-pool-id",
32059
- identifier: physicalId,
32060
- after: "--deletion-protection INACTIVE",
32061
- caveat: "Note UpdateUserPool resets some members a call omits (self sign-up, Lambda triggers, advanced security and AutoVerifiedAttributes among them), so send your complete pool configuration alongside that flag rather than the flag alone."
32062
- }
32063
- }) : `AWS::Cognito::UserPool is a stateful type, so re-run with ${replaceFlags} to recreate it (this deletes all users in the pool).`;
32064
- throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `the Schema change (${immutableChanges.join("; ")}) is immutable on AWS — AWS can only ADD custom attributes in place, so removing or modifying an attribute requires recreating the pool. ${remedy}`);
32065
- }
32412
+ if (immutableChanges.length > 0) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `the Schema change (${immutableChanges.join("; ")}) is immutable on AWS — AWS can only ADD custom attributes in place, so removing or modifying an attribute requires recreating the pool. ${this.replacementRemedy(physicalId, deletionProtected)}`);
32066
32413
  const addedCustom = added.filter((a) => a.Name !== void 0 && !STANDARD_USER_POOL_ATTRIBUTES.has(a.Name));
32067
32414
  if (addedCustom.length === 0) return;
32068
32415
  this.logger.debug(`Adding ${addedCustom.length} custom attribute(s) to ${physicalId}: ` + addedCustom.map((a) => a.Name).join(", "));
@@ -32071,6 +32418,19 @@ var CognitoUserPoolProvider = class {
32071
32418
  CustomAttributes: addedCustom
32072
32419
  }));
32073
32420
  }
32421
+ replacementRemedy(physicalId, deletionProtected) {
32422
+ const replaceFlags = "cdkd deploy --replace --force-stateful-recreation";
32423
+ return deletionProtected ? protectedReplacementAdvice({
32424
+ evidence: "cdkd's properties for this user pool carry DeletionProtection: ACTIVE",
32425
+ replaceFlags,
32426
+ disable: {
32427
+ before: "aws cognito-idp update-user-pool --user-pool-id",
32428
+ identifier: physicalId,
32429
+ after: "--deletion-protection INACTIVE",
32430
+ caveat: "Note UpdateUserPool resets some members a call omits (self sign-up, Lambda triggers, advanced security and AutoVerifiedAttributes among them), so send your complete pool configuration alongside that flag rather than the flag alone."
32431
+ }
32432
+ }) : `AWS::Cognito::UserPool is a stateful type, so re-run with ${replaceFlags} to recreate it (this deletes all users in the pool).`;
32433
+ }
32074
32434
  async delete(logicalId, physicalId, resourceType, _properties, context) {
32075
32435
  let flipRecord;
32076
32436
  await deleteWithProtectionCompensation({
@@ -32922,6 +33282,16 @@ function sameAsRecorded(desired, recorded) {
32922
33282
  }
32923
33283
  return isDeepStrictEqual(desired, recorded);
32924
33284
  }
33285
+ function unappliedDnsConfigMembers(properties, previousProperties, changedProperties) {
33286
+ if (changedProperties !== void 0 && !changedProperties.has("DnsConfig")) return [];
33287
+ const desired = properties["DnsConfig"];
33288
+ const previous = previousProperties["DnsConfig"];
33289
+ if (!isPlainObject(desired) || !isPlainObject(previous)) return [];
33290
+ return ["NamespaceId", "RoutingPolicy"].filter((member) => !sameAsRecorded(desired[member], previous[member]));
33291
+ }
33292
+ function isPlainObject(value) {
33293
+ return typeof value === "object" && value !== null && !Array.isArray(value);
33294
+ }
32925
33295
  function isRecordedStandIn(value) {
32926
33296
  return dynamicReferenceTokens(value).length > 0 || value.includes("***");
32927
33297
  }
@@ -33286,14 +33656,13 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
33286
33656
  this.logger.debug(`Creating service discovery service ${logicalId}`);
33287
33657
  const tags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
33288
33658
  const client = this.getClient();
33289
- const name = properties["Name"];
33659
+ const name = properties["Name"] || generatedNameFor("AWS::ServiceDiscovery::Service", logicalId);
33290
33660
  const namespaceId = properties["NamespaceId"];
33291
33661
  const description = properties["Description"];
33292
33662
  const dnsConfig = properties["DnsConfig"];
33293
33663
  const healthCheckCustomConfig = properties["HealthCheckCustomConfig"];
33294
33664
  const healthCheckConfig = properties["HealthCheckConfig"];
33295
33665
  const type = properties["Type"];
33296
- if (!name) throw new ProvisioningError(`Name is required for ServiceDiscovery Service ${logicalId}`, resourceType, logicalId);
33297
33666
  let leftBehindServiceId;
33298
33667
  try {
33299
33668
  const watch = startInterruptWatch(`Cloud Map service ${logicalId}`);
@@ -33391,8 +33760,10 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
33391
33760
  const hasTagChange = tagPlan.set.size > 0 || tagPlan.remove.length > 0;
33392
33761
  const tagWarning = tagPlanWarning(tagPlan, resourceType, logicalId);
33393
33762
  if (tagWarning !== void 0) this.logger.warn(tagWarning);
33763
+ const unapplied = unappliedDnsConfigMembers(properties, previousProperties, changedProperties);
33394
33764
  if (!hasServiceChange && !hasAttrUpsert && !hasAttrRemove && !hasTagChange) {
33395
33765
  this.logger.debug(`No mutable diff for ServiceDiscovery Service ${logicalId}, skipping update`);
33766
+ await this.warnUnappliedDnsConfigMembers(logicalId, physicalId, properties, unapplied);
33396
33767
  return {
33397
33768
  physicalId,
33398
33769
  wasReplaced: false
@@ -33453,6 +33824,7 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
33453
33824
  }));
33454
33825
  }
33455
33826
  this.logger.debug(`Successfully updated service discovery service ${logicalId}`);
33827
+ await this.warnUnappliedDnsConfigMembers(logicalId, physicalId, properties, unapplied);
33456
33828
  return {
33457
33829
  physicalId,
33458
33830
  wasReplaced: false
@@ -33481,6 +33853,30 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
33481
33853
  keepRemovedFromLive: true
33482
33854
  };
33483
33855
  }
33856
+ async warnUnappliedDnsConfigMembers(logicalId, physicalId, properties, candidates) {
33857
+ if (candidates.length === 0) return;
33858
+ let members = candidates;
33859
+ try {
33860
+ const live = (await this.getClient().send(new GetServiceCommand({ Id: physicalId }))).Service;
33861
+ const dns = properties["DnsConfig"];
33862
+ const desired = {
33863
+ NamespaceId: dns.NamespaceId ?? properties["NamespaceId"],
33864
+ RoutingPolicy: dns.RoutingPolicy
33865
+ };
33866
+ const held = {
33867
+ NamespaceId: live?.NamespaceId ?? live?.DnsConfig?.NamespaceId,
33868
+ RoutingPolicy: live?.DnsConfig?.RoutingPolicy
33869
+ };
33870
+ members = candidates.filter((m) => desired[m] === void 0 || desired[m] !== held[m]);
33871
+ } catch {
33872
+ this.logger.debug(safeMsg`Could not read service discovery service ${logicalId} back to confirm its DnsConfig; warning unconfirmed`);
33873
+ }
33874
+ if (members.length === 0) return;
33875
+ const paths = members.map((m) => `DnsConfig.${m}`).join(" and ");
33876
+ const [it, value] = members.length > 1 ? ["them", "values"] : ["it", "value"];
33877
+ const remedy = members.includes("NamespaceId") ? "To move the service, declare the namespace in the top-level NamespaceId: a change there replaces the service." : "To change it, replace the service, for example by giving it a new Name.";
33878
+ this.logger.warn(safeMsg`${logicalId} (AWS::ServiceDiscovery::Service): ${paths} changed, but Cloud Map cannot change ${it} on an existing service, so the service keeps its current ${value}, as CloudFormation does. ${remedy}`);
33879
+ }
33484
33880
  async keepUndeclaredServiceFields(physicalId, serviceChange) {
33485
33881
  if (serviceChange.Description !== void 0 && serviceChange.HealthCheckConfig !== void 0) return;
33486
33882
  const live = (await this.getClient().send(new GetServiceCommand({ Id: physicalId }))).Service;
@@ -34032,31 +34428,19 @@ var AppSyncProvider = class {
34032
34428
  deepEqual(a, b) {
34033
34429
  return JSON.stringify(a) === JSON.stringify(b);
34034
34430
  }
34035
- async graphQLApiNameUnchangedBehindSecret(logicalId, physicalId, resourceType, desired, previous, mask) {
34036
- if (!isSecretDerivedValue(previous, maskerOrIdentity(void 0))) return false;
34431
+ async unchangedGraphqlApiName(apiId, resourceType, logicalId, desired, recorded, mask) {
34432
+ if (desired === void 0 || desired === recorded) return recorded;
34037
34433
  let liveName;
34038
34434
  try {
34039
- liveName = (await this.getClient().send(new GetGraphqlApiCommand({ apiId: physicalId }))).graphqlApi?.name;
34435
+ liveName = (await this.getClient().send(new GetGraphqlApiCommand({ apiId }))).graphqlApi?.name;
34040
34436
  } catch (error) {
34041
- throw this.wrapGraphQLApiNameLookupError(error, logicalId, physicalId, resourceType, mask);
34437
+ throw this.wrapUpdateError(error, resourceType, logicalId, apiId, "GraphqlApi", mask);
34042
34438
  }
34043
- if (liveName === void 0) throw this.wrapGraphQLApiNameLookupError(void 0, logicalId, physicalId, resourceType, mask);
34044
- return unchangedBehindSecretReference({
34045
- resourceType,
34046
- key: "Name",
34047
- desired,
34048
- previous,
34049
- physicalName: liveName
34050
- });
34051
- }
34052
- wrapGraphQLApiNameLookupError(error, logicalId, physicalId, resourceType, mask) {
34053
- const failureClass = error === void 0 ? "an answer with no name" : error instanceof Error && error.name !== "" ? error.name : "an unreadable failure";
34054
- const next = failureClass === "NotFoundException" ? `the API ${physicalId} no longer exists; check it with 'cdkd drift' before deploying again` : "re-run once the lookup can succeed";
34055
- return markRedactedCause(new ProvisioningError(`Name of AWS::AppSync::GraphQLApi ${logicalId} is secret-derived, and whether the value its secret resolves to is still the API's name could not be confirmed (${mask(failureClass)}) — ${next}`, resourceType, logicalId, physicalId, error instanceof Error ? error : void 0));
34439
+ if (liveName === void 0 || liveName === "") throw new ProvisioningError(`Could not read the current name of AppSync GraphqlApi ${apiId} to update it without renaming it`, resourceType, logicalId, apiId);
34440
+ return liveName;
34056
34441
  }
34057
34442
  async updateGraphQLApi(logicalId, physicalId, resourceType, properties, previousProperties, context) {
34058
34443
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
34059
- if (properties["Name"] !== void 0 && previousProperties["Name"] !== void 0 && properties["Name"] !== previousProperties["Name"] && !await this.graphQLApiNameUnchangedBehindSecret(logicalId, physicalId, resourceType, properties["Name"], previousProperties["Name"], maskerOrIdentity(context?.maskSecrets))) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphqlApi.Name is immutable — destroy + redeploy to rename");
34060
34444
  for (const immutable of ["ApiType", "Visibility"]) if (properties[immutable] !== void 0 && previousProperties[immutable] !== void 0 && properties[immutable] !== previousProperties[immutable]) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS AppSync GraphqlApi.${immutable} is immutable — destroy + redeploy to change it`);
34061
34445
  if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) this.refuseChangedMalformedGraphQLApiBlocks(properties, previousProperties, logicalId, physicalId, resourceType);
34062
34446
  const newAuthType = properties["AuthenticationType"];
@@ -34069,10 +34453,11 @@ var AppSyncProvider = class {
34069
34453
  const hasAuthDiff = ("AuthenticationType" in properties || "AuthenticationType" in previousProperties) && newAuthType !== oldAuthType;
34070
34454
  const hasLogDiff = ("LogConfig" in properties || "LogConfig" in previousProperties) && !this.deepEqual(newLog, oldLog);
34071
34455
  const hasConfigDiff = MUTABLE_GRAPHQL_API_CONFIG_PROPERTIES.some((key) => (key in properties || key in previousProperties) && !this.deepEqual(properties[key], previousProperties[key]));
34072
- if (hasAuthDiff || hasXrayDiff || hasLogDiff || hasConfigDiff) {
34456
+ const hasNameDiff = properties["Name"] !== void 0 && (context?.changedProperties !== void 0 ? context.changedProperties.has("Name") : properties["Name"] !== previousProperties["Name"]);
34457
+ if (hasNameDiff || hasAuthDiff || hasXrayDiff || hasLogDiff || hasConfigDiff) {
34073
34458
  const input = {
34074
34459
  apiId: physicalId,
34075
- name: properties["Name"] ?? previousProperties["Name"],
34460
+ name: hasNameDiff ? properties["Name"] : await this.unchangedGraphqlApiName(physicalId, resourceType, logicalId, properties["Name"], previousProperties["Name"], maskerOrIdentity(context?.maskSecrets)),
34076
34461
  authenticationType: newAuthType ?? oldAuthType ?? "API_KEY"
34077
34462
  };
34078
34463
  if (newXray !== void 0) input.xrayEnabled = newXray;
@@ -34113,6 +34498,14 @@ var AppSyncProvider = class {
34113
34498
  };
34114
34499
  }
34115
34500
  async updateGraphQLSchema(logicalId, physicalId, resourceType, properties, previousProperties, mask = maskerOrIdentity(void 0)) {
34501
+ if (properties["ApiId"] !== void 0 && previousProperties["ApiId"] !== void 0 && properties["ApiId"] !== previousProperties["ApiId"] && !await unchangedBehindSecretReference({
34502
+ resourceType,
34503
+ key: "ApiId",
34504
+ desired: properties["ApiId"],
34505
+ previous: previousProperties["ApiId"],
34506
+ physicalName: physicalId,
34507
+ maskSecrets: mask
34508
+ })) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphQLSchema.ApiId cannot move a schema to another API in place (CloudFormation fails a template change of it too) — deploy with --replace, or give the schema a new logical ID, to create it on the new API");
34116
34509
  const newDef = properties["Definition"];
34117
34510
  const oldDef = previousProperties["Definition"];
34118
34511
  const newLoc = properties["DefinitionS3Location"];
@@ -34151,11 +34544,7 @@ var AppSyncProvider = class {
34151
34544
  }
34152
34545
  async updateDataSource(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
34153
34546
  const [idApiId, idName] = physicalId.split("|");
34154
- for (const field of [
34155
- "ApiId",
34156
- "Name",
34157
- "Type"
34158
- ]) {
34547
+ for (const field of ["ApiId", "Name"]) {
34159
34548
  const next = properties[field];
34160
34549
  const prev = previousProperties[field];
34161
34550
  if (next !== void 0 && prev !== void 0 && next !== prev && !await unchangedBehindSecretReference({
@@ -34163,7 +34552,7 @@ var AppSyncProvider = class {
34163
34552
  key: field,
34164
34553
  desired: next,
34165
34554
  previous: prev,
34166
- physicalName: field === "ApiId" ? idApiId : field === "Name" ? idName : void 0,
34555
+ physicalName: field === "ApiId" ? idApiId : idName,
34167
34556
  maskSecrets: mask
34168
34557
  })) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS AppSync DataSource.${field} is immutable — destroy + redeploy to change`);
34169
34558
  }
@@ -34171,6 +34560,7 @@ var AppSyncProvider = class {
34171
34560
  if (!apiId || !name) throw new ProvisioningError(compositeIdFormatMessage(APPSYNC_DATASOURCE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
34172
34561
  const type = properties["Type"] ?? previousProperties["Type"];
34173
34562
  if (![
34563
+ "Type",
34174
34564
  "Description",
34175
34565
  "ServiceRoleArn",
34176
34566
  "DynamoDBConfig",
@@ -44377,6 +44767,46 @@ var EMRInstanceFleetConfigProvider = class {
44377
44767
 
44378
44768
  //#endregion
44379
44769
  //#region src/provisioning/providers/firehose-provider.ts
44770
+ const ENCRYPTION_KEY = "DeliveryStreamEncryptionConfigurationInput";
44771
+ function readEncryptionInput(value, emptyIsAbsent) {
44772
+ if (value === void 0 || value === null) return { kind: "absent" };
44773
+ if (typeof value !== "object" || Array.isArray(value)) return { kind: "unusable" };
44774
+ const block = value;
44775
+ if (emptyIsAbsent && Object.keys(block).length === 0) return { kind: "absent" };
44776
+ const keyType = block["KeyType"];
44777
+ const keyArn = block["KeyArn"] || block["KeyARN"];
44778
+ if (typeof keyType !== "string" || keyType.length === 0) return { kind: "unusable" };
44779
+ if (keyArn !== void 0 && keyArn !== null && keyArn !== "" && typeof keyArn !== "string") return { kind: "unusable" };
44780
+ return typeof keyArn === "string" && keyArn.length > 0 ? {
44781
+ kind: "usable",
44782
+ keyType,
44783
+ keyArn
44784
+ } : {
44785
+ kind: "usable",
44786
+ keyType
44787
+ };
44788
+ }
44789
+ function sameEncryptionInput(next, nextRead, prev) {
44790
+ const b = readEncryptionInput(prev, true);
44791
+ if (nextRead.kind === "unusable" || b.kind === "unusable") return JSON.stringify(next) === JSON.stringify(prev);
44792
+ if (nextRead.kind === "absent" || b.kind === "absent") return nextRead.kind === b.kind;
44793
+ return nextRead.keyType === b.keyType && nextRead.keyArn === b.keyArn;
44794
+ }
44795
+ function encryptionMatches(live, desired) {
44796
+ if (live?.Status !== "ENABLED" || live.KeyType !== desired.keyType) return false;
44797
+ return desired.keyType !== "CUSTOMER_MANAGED_CMK" || live.KeyARN === desired.keyArn;
44798
+ }
44799
+ function liveEncryptionAsCfn(live) {
44800
+ const status = live?.Status;
44801
+ if (status !== "ENABLED" && status !== "ENABLING" && status !== "DISABLING_FAILED") return {};
44802
+ return {
44803
+ ...live?.KeyARN !== void 0 && { KeyARN: live.KeyARN },
44804
+ ...live?.KeyType !== void 0 && { KeyType: live.KeyType }
44805
+ };
44806
+ }
44807
+ const ENCRYPTION_POLL_INTERVAL_MS = 5e3;
44808
+ const ENCRYPTION_POLL_MAX_ATTEMPTS = 120;
44809
+ const terminalEncryptionFailures = /* @__PURE__ */ new WeakSet();
44380
44810
  function isReadableTagList(value) {
44381
44811
  if (value === void 0 || value === null) return true;
44382
44812
  return Array.isArray(value) && value.every((t) => typeof t === "object" && t !== null && !Array.isArray(t) && typeof t.Key === "string" && t.Key.length > 0 && !holdsSecretDerivedEntry(t.Key));
@@ -44601,15 +45031,24 @@ var FirehoseProvider = class {
44601
45031
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
44602
45032
  assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
44603
45033
  try {
44604
- return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties);
45034
+ return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context);
44605
45035
  } catch (error) {
44606
45036
  if (error instanceof CdkdError) throw error;
44607
45037
  const cause = error instanceof Error ? error : void 0;
44608
45038
  throw this.wrapCaughtError(maskerOrIdentity(context?.maskSecrets), error, (text) => new ProvisioningError(`Failed to update Firehose delivery stream ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
44609
45039
  }
44610
45040
  }
44611
- async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties) {
45041
+ async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context) {
44612
45042
  this.logger.debug(`Updating Firehose delivery stream ${logicalId}: ${physicalId}`);
45043
+ const desiredEncryption = readEncryptionInput(properties[ENCRYPTION_KEY], context?.desiredFromAwsReadback === true);
45044
+ const encryptionChanged = !sameEncryptionInput(properties[ENCRYPTION_KEY], desiredEncryption, previousProperties[ENCRYPTION_KEY]);
45045
+ let encryptionSkipped = false;
45046
+ if (encryptionChanged && desiredEncryption.kind === "unusable") {
45047
+ const message = `${ENCRYPTION_KEY} of Firehose delivery stream ${logicalId} is not an object with a string KeyType (and a string KeyARN, if any)`;
45048
+ if (context?.replayingState !== true) throw markNonRetryable(new ProvisioningError(`${message} — nothing was updated`, resourceType, logicalId, physicalId));
45049
+ this.logger.warn(safeMsg`${message}; its encryption is left unchanged`);
45050
+ encryptionSkipped = true;
45051
+ }
44613
45052
  const destKey = this.findDestinationKey(properties);
44614
45053
  const prevDestKey = this.findDestinationKey(previousProperties);
44615
45054
  if (destKey && prevDestKey && destKey !== prevDestKey) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `Switching Firehose destination type from '${prevDestKey}' to '${destKey}' is not supported in-place — AWS UpdateDestination requires the same destination type as the original CreateDeliveryStream. Re-deploy with cdkd deploy --replace.`);
@@ -44671,11 +45110,21 @@ var FirehoseProvider = class {
44671
45110
  const prevDest = previousProperties[activeDest] ?? {};
44672
45111
  if (JSON.stringify(nextDest) !== JSON.stringify(prevDest)) await this.applySnowflakeDestinationUpdate(logicalId, physicalId, nextDest);
44673
45112
  }
45113
+ if (encryptionChanged && desiredEncryption.kind !== "unusable") await this.applyEncryptionUpdate(logicalId, physicalId, resourceType, desiredEncryption, maskerOrIdentity(context?.maskSecrets));
44674
45114
  const desc = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription;
44675
45115
  return {
44676
45116
  physicalId,
44677
45117
  wasReplaced: false,
44678
- attributes: { ...desc?.DeliveryStreamARN !== void 0 && { Arn: desc.DeliveryStreamARN } }
45118
+ attributes: { ...desc?.DeliveryStreamARN !== void 0 && { Arn: desc.DeliveryStreamARN } },
45119
+ ...encryptionSkipped && { effectiveProperties: this.withRecordedEncryption(properties, previousProperties[ENCRYPTION_KEY], desc?.DeliveryStreamEncryptionConfiguration) }
45120
+ };
45121
+ }
45122
+ withRecordedEncryption(properties, previous, live) {
45123
+ const { [ENCRYPTION_KEY]: _skipped, ...rest } = properties;
45124
+ if (previous === void 0 || previous === null) return rest;
45125
+ return {
45126
+ ...rest,
45127
+ [ENCRYPTION_KEY]: liveEncryptionAsCfn(live)
44679
45128
  };
44680
45129
  }
44681
45130
  async applyExtendedS3DestinationUpdate(logicalId, physicalId, nextConfig) {
@@ -44718,6 +45167,87 @@ var FirehoseProvider = class {
44718
45167
  }))
44719
45168
  }));
44720
45169
  }
45170
+ async applyEncryptionUpdate(logicalId, physicalId, resourceType, desired, mask) {
45171
+ const settled = await this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
45172
+ what: "settle",
45173
+ done: (enc) => enc?.Status !== "ENABLING" && enc?.Status !== "DISABLING"
45174
+ });
45175
+ if (desired.kind === "absent") {
45176
+ if (settled?.Status !== "ENABLED" && settled?.Status !== "DISABLING_FAILED") return;
45177
+ this.refuseToStartTransition(logicalId, physicalId, resourceType, "disable");
45178
+ await this.getClient().send(new StopDeliveryStreamEncryptionCommand({ DeliveryStreamName: physicalId }));
45179
+ await this.warnIfUnfinished(logicalId, "StopDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
45180
+ what: "disable",
45181
+ done: (enc) => enc === void 0 || enc.Status === "DISABLED",
45182
+ inProgress: "DISABLING",
45183
+ failed: "DISABLING_FAILED",
45184
+ staleFailure: settled.Status === "DISABLING_FAILED"
45185
+ }));
45186
+ return;
45187
+ }
45188
+ if (encryptionMatches(settled, desired)) return;
45189
+ this.refuseToStartTransition(logicalId, physicalId, resourceType, "enable");
45190
+ await this.getClient().send(new StartDeliveryStreamEncryptionCommand({
45191
+ DeliveryStreamName: physicalId,
45192
+ DeliveryStreamEncryptionConfigurationInput: {
45193
+ KeyType: desired.keyType,
45194
+ ...desired.keyArn !== void 0 && { KeyARN: desired.keyArn }
45195
+ }
45196
+ }));
45197
+ await this.warnIfUnfinished(logicalId, "StartDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
45198
+ what: "enable",
45199
+ done: (enc) => encryptionMatches(enc, desired),
45200
+ inProgress: "ENABLING",
45201
+ failed: "ENABLING_FAILED",
45202
+ staleFailure: settled?.Status === "ENABLING_FAILED"
45203
+ }));
45204
+ }
45205
+ async warnIfUnfinished(logicalId, call, wait) {
45206
+ try {
45207
+ return await wait();
45208
+ } catch (error) {
45209
+ const outcome = typeof error === "object" && error !== null && terminalEncryptionFailures.has(error) ? "AWS reported the change failed, so the stream may no longer match" : "the stream may still finish the change, so it may no longer match";
45210
+ this.logger.warn(safeMsg`Firehose delivery stream ${logicalId}: ${call} was sent but the encryption change did not finish; ${outcome} the previous setting cdkd keeps recorded. Run 'cdkd drift' to compare, then 'cdkd drift --revert' to apply the recorded setting or 'cdkd drift --accept' to record the stream's.`);
45211
+ throw error;
45212
+ }
45213
+ }
45214
+ refuseToStartTransition(logicalId, physicalId, resourceType, what) {
45215
+ const watch = startInterruptWatch(`Firehose ${logicalId} encryption ${what}`);
45216
+ try {
45217
+ if (watch.isInterrupted()) throw watch.onInterrupted();
45218
+ } finally {
45219
+ watch.dispose();
45220
+ }
45221
+ if (!enclosingDeadlineExpired() && enclosingDeadlineRemainingMs() > 0) return;
45222
+ throw markNonRetryable(new ProvisioningError(`The resource timeout expired before encryption could be ${what}d on Firehose delivery stream ${logicalId}; no encryption call was sent`, resourceType, logicalId, physicalId));
45223
+ }
45224
+ async waitForEncryption(logicalId, physicalId, resourceType, mask, opts) {
45225
+ const { what, done, inProgress, failed } = opts;
45226
+ const watch = startInterruptWatch(`Firehose ${logicalId} encryption ${what}`);
45227
+ try {
45228
+ let last;
45229
+ let sawInProgress = false;
45230
+ for (let attempt = 1; attempt <= ENCRYPTION_POLL_MAX_ATTEMPTS; attempt++) {
45231
+ if (watch.isInterrupted()) throw watch.onInterrupted();
45232
+ if (enclosingDeadlineRemainingMs() <= 0) throw markNonRetryable(new ProvisioningError(`The resource timeout expired while waiting to ${what} encryption on Firehose delivery stream ${logicalId} (last status: ${last ?? "none reported"})`, resourceType, logicalId, physicalId));
45233
+ const enc = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription?.DeliveryStreamEncryptionConfiguration;
45234
+ if (done(enc)) return enc;
45235
+ last = enc?.Status;
45236
+ if (last !== void 0 && last === inProgress) sawInProgress = true;
45237
+ if (failed !== void 0 && last === failed && (sawInProgress || !opts.staleFailure)) {
45238
+ const failure = enc?.FailureDescription;
45239
+ const terminal = markNonRetryable(new ProvisioningError(`Failed to ${what} encryption on Firehose delivery stream ${logicalId}: AWS reports ${failed}` + (failure ? ` (${mask(`${failure.Type ?? ""}: ${failure.Details ?? ""}`)})` : ""), resourceType, logicalId, physicalId));
45240
+ terminalEncryptionFailures.add(terminal);
45241
+ throw terminal;
45242
+ }
45243
+ if (watch.isInterrupted()) throw watch.onInterrupted();
45244
+ await new Promise((resolve) => setTimeout(resolve, Math.max(0, Math.min(ENCRYPTION_POLL_INTERVAL_MS, enclosingDeadlineRemainingMs()))));
45245
+ }
45246
+ throw markNonRetryable(new ProvisioningError(`Timed out waiting to ${what} encryption on Firehose delivery stream ${logicalId} (last status: ${last ?? "none reported"})`, resourceType, logicalId, physicalId));
45247
+ } finally {
45248
+ watch.dispose();
45249
+ }
45250
+ }
44721
45251
  findDestinationKey(properties) {
44722
45252
  for (const key of [
44723
45253
  "ExtendedS3DestinationConfiguration",
@@ -45123,11 +45653,7 @@ var FirehoseProvider = class {
45123
45653
  else if (dest?.AmazonOpenSearchServerlessDestinationDescription) result["AmazonOpenSearchServerlessDestinationConfiguration"] = mapNonS3DestinationToCfn(dest.AmazonOpenSearchServerlessDestinationDescription);
45124
45654
  else if (dest?.SplunkDestinationDescription) result["SplunkDestinationConfiguration"] = mapNonS3DestinationToCfn(dest.SplunkDestinationDescription);
45125
45655
  else if (dest?.HttpEndpointDestinationDescription) result["HttpEndpointDestinationConfiguration"] = mapHttpEndpointDescriptionToCfn(dest.HttpEndpointDestinationDescription);
45126
- const enc = desc.DeliveryStreamEncryptionConfiguration;
45127
- const encOut = {};
45128
- if (enc?.KeyARN !== void 0) encOut["KeyARN"] = enc.KeyARN;
45129
- if (enc?.KeyType !== void 0) encOut["KeyType"] = enc.KeyType;
45130
- result["DeliveryStreamEncryptionConfigurationInput"] = encOut;
45656
+ result["DeliveryStreamEncryptionConfigurationInput"] = liveEncryptionAsCfn(desc.DeliveryStreamEncryptionConfiguration);
45131
45657
  try {
45132
45658
  const tagsResp = await this.getClient().send(new ListTagsForDeliveryStreamCommand({ DeliveryStreamName: physicalId }));
45133
45659
  result["Tags"] = normalizeAwsTagsToCfn(tagsResp.Tags);
@@ -49325,4 +49851,4 @@ var ACMCertificateProvider = class {
49325
49851
 
49326
49852
  //#endregion
49327
49853
  export { ACMCertificateProvider, ASGProvider, AgentCoreBrowserProvider, AgentCoreCodeInterpreterProvider, AgentCoreEvaluatorProvider, AgentCoreRuntimeProvider, ApiGatewayProvider, ApiGatewayV2Provider, AppSyncProvider, BudgetsBudgetProvider, CloudFrontDistributionProvider, CloudFrontOACProvider, CloudFrontOAIProvider, CloudTrailProvider, CloudWatchAlarmProvider, CloudWatchAnomalyDetectorProvider, CodeBuildProvider, CodeCommitRepositoryProvider, CognitoUserPoolProvider, DLMLifecyclePolicyProvider, DocDBProvider, DocDBSubnetGroupProvider, DynamoDBGlobalTableProvider, DynamoDBTableProvider, EC2Provider, ECRProvider, ECSProvider, EFSProvider, ELBv2Provider, EMRClusterProvider, EMRInstanceFleetConfigProvider, EMRInstanceGroupConfigProvider, ElastiCacheProvider, EventBridgeBusProvider, EventBridgeRuleProvider, FSxFileSystemProvider, FirehoseProvider, GlueConnectionProvider, GlueCrawlerProvider, GlueJobProvider, GlueProvider, GlueSecurityConfigurationProvider, GlueTriggerProvider, GlueWorkflowProvider, IAMAccessKeyProvider, IAMInstanceProfileProvider, IAMManagedPolicyProvider, IAMPolicyProvider, IAMRoleProvider, IAMUserGroupProvider, KMSProvider, KinesisStreamConsumerProvider, KinesisStreamProvider, LambdaEventInvokeConfigProvider, LambdaEventSourceMappingProvider, LambdaFunctionProvider, LambdaLayerVersionProvider, LambdaMicrovmImageProvider, LambdaNetworkConnectorProvider, LambdaPermissionProvider, LambdaUrlProvider, LambdaWebFunctionEndpointProvider, LambdaWebFunctionRevisionProvider, LogsLogGroupProvider, NeptuneProvider, NestedStackProvider, PipesPipeProvider, RDSDBProxyEndpointProvider, RDSDBProxyProvider, RDSDBProxyTargetGroupProvider, RDSProvider, Route53Provider, S3BucketPolicyProvider, S3BucketProvider, S3DirectoryBucketProvider, S3TablesProvider, S3VectorsProvider, SNSSubscriptionProvider, SNSTopicPolicyProvider, SNSTopicProvider, SQSQueuePolicyProvider, SQSQueueProvider, SSMParameterProvider, SchedulerScheduleProvider, SecretsManagerSecretProvider, ServiceDiscoveryProvider, StepFunctionsProvider, WAFv2WebACLProvider, WaitConditionHandleProvider };
49328
- //# sourceMappingURL=provider-classes-C_AbFNEi.js.map
49854
+ //# sourceMappingURL=provider-classes-CPMW_2-R.js.map