@go-to-k/cdkd 0.291.3 → 0.291.4

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.
@@ -1,8 +1,8 @@
1
- import { $ as yellow, $i as derivePartitionAndUrlSuffix, $n as safeStackName, $r as assertAssetBucketRegion, $t as requireConfigObject, A as createPreDeleteFinalSnapshot, Aa as PartialFailureError, Ai as resolveAutoAssetStorage, An as malformedOutputsRefusalMessage, Ar as formatLockExpiry, At as carriesDynamicReference, B as isStatefulRecreateTargetSync, Ba as normalizeAwsError, Bi as CFN_TEMPLATE_URL_LIMIT, Bn as refuseMalformedOrphansForDestroy, Br as isReadableBag, Bt as isSettledInstanceState, C as namesAnyDeclaredParameter, Ca as DynamicReferenceRegionAmbiguousError, Ci as AssetManifestLoader, Cn as isReadableResourceEntry, Cr as LockManager, Ct as slowCcOperationTimeoutMs, D as PRE_DELETE_SNAPSHOT_TYPES, Di as getDefaultStateBucketName, Dn as malformedOrphanRecordsWarning, Dr as buildForceUnlockCommand, Dt as disableInstanceApiTermination, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as LocalStartServiceError, Ei as synthesisStatusMessage, En as malformedLocalOutputsWarning, Er as UNREPRODUCIBLE_LOCK_CLAUSE, Et as deleteSkipReason, F as extractDeploymentEventError, Fa as StackTerminationProtectionError, Fi as resolveUseCdkBootstrapAssets, Fn as malformedResourcesWarning, Fr as hasReadableExportSet, Ft as isImpossibleEmptyStoredAttribute, G as toCfnInteger, Ga as isTransientServerError, Gi as injectiveKey, Gn as refuseMalformedResourcesForDestroy, Gr as stringifyValue, Gt as coerceCfnBoolean, H as WARM_THROUGHPUT_MEMBERS, Ha as isMarkedNonRetryable, Hi as findLargeInlineResources, Hn as refuseMalformedOutputsForDestroy, Hr as orphansCarriedFrom, Ht as normalizeAwsTagsToCfn, I as makeSiblingClaimReader, Ii as stateBucketExistenceConfirmed, In as malformedStateRefusalMessage, Ir as hasReasonlessBaselineRefusal, It as isNamelessDynamicReferenceError, J as bold, Ja as retryClassificationText, Ji as producerRecordKey, Jn as repairMalformedOutputsForReadOnly, Jr as createAssetRedirectResolver, Jt as configIntegerRefusal, K as toFiniteNumber, Ka as markNonRetryable, Ki as injectiveKeyPrefix, Kn as refuseMalformedState, Kr as WorkGraph, Kt as coerceCfnInteger, L as planOrphanAdoption, La as SynthesisError, Li as warnDeprecatedNoPrefixCliFlag, Ln as refuseDivergentRecordRegionForDestroy, Lr as hasUnverifiableParameterRefusal, Lt as isUnboundTemplateParameter, M as refusesFinalSnapshot, Ma as ResourceTimeoutError, Mi as resolveSkipPrefix, Mn as malformedRenderedContainersWarning, Mr as CUSTOM_RESOURCE_RESPONSE_PREFIX, Mt as cfnRefValueFromPhysicalId, N as unsupportedFinalSnapshotError, Na as ResourceUpdateNotSupportedError, Ni as resolveStateBucketWithDefault, Nn as malformedResourceEntriesWarning, Nr as DEFAULT_STATE_PREFIX, Nt as coerceParameterTypedValue, O as buildFinalSnapshotIdentifier, Oa as MalformedProducerRecordRefusalError, Oi as getLegacyStateBucketName, On as malformedOrphansRefusalMessage, Or as buildLockContentionMessage, Ot as isTerminationProtectionPropagationError, P as makeCanonicalizePropertiesFn, Pa as StackHasActiveImportsError, Pi as resolveStateBucketWithDefaultAndSource, Pn as malformedResourcePropertiesWarning, Pr as exportNamesCarriedFrom, Pt as getAccountInfo, Q as red, Qi as canonicalizeRegion, Qn as safeRegion, Qr as BOOTSTRAP_MARKER_PREFIX, Qt as requireConfigArray, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ri as ssmResolvedValueType, Rn as refuseMalformedNestedChildOutputs, Rr as importableOutputKeys, Rt as parameterTypeMayLoseSecretIdentity, S as computeParameterTaint, Sa as DeployCancelledError, Si as stripControlChars, Sn as hasReadableResources, Sr as scrubResourceRecord, St as isWaitAbandonedError, T as resourcesNamingDeclaredParameter, Ta as LocalInvokeBuildError$1, Ti as Synthesizer, Tn as malformedExportSourceWarning, Tr as rebuildClientForBucketRegion, Tt as deleteIndeterminateGuards, U as coerceWarmThroughput$1, Ua as isRetryableTransientError, Ui as uploadCfnTemplate, Un as refuseMalformedResourceEntries, Ur as shouldRetainResource, Ut as resolveExplicitPhysicalId, V as renderStatefulReason, Va as withErrorHandling, Vi as MIGRATE_TMP_PREFIX, Vn as refuseMalformedOutputs, Vr as orphansAfterRollback, Vt as WAFv2WebACLProvider, W as isWarmThroughputDecrease, Wa as isThrottlingError, Wi as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Wn as refuseMalformedResourcePropertiesForOrphan, Wr as AssetPublisher, Wt as assertRegionMatch, X as gray, Xa as safeStringify, Xi as expectedOwnerParam, Xn as repairMalformedResourcePropertiesForReadOnly, Xr as rewriteTemplateAssetReferences, Xt as readConfigString, Y as cyan, Ya as describeAwsFailure, Yi as decodeListingKey, Yn as repairMalformedResourceEntriesForReadOnly, Yr as loadPublishableAssetManifest, Yt as configStringRefusal, Z as green, Zi as PARTITION_TABLE, Zn as repairMalformedResourcesForReadOnly, Zr as AssetModeResolver, Zt as replayWarn, _ as bagHoldsSecretExpression, _i as partitionSensitiveEnv, _n as UNREADABLE_ORPHANS_CONTAINER_ROW, _r as maskSecretsInError, _t as endCommandInterruptScope, a as DeploymentEventsStore, aa as hasPlainPrototype, ai as validateAssetBucketName, an as s3BucketDomainName, ar as TemplateParser, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as CrossAccountSecretRefusalError, bi as runDockerStreaming, bn as hasReadableOrphans, br as recoverMaskedOutput, bt as startInterruptWatch, c as replayFailedOperations, ca as absoluteAssemblyPathEscape, ci as buildDockerImage, cn as s3BucketWebsiteUrl, cr as STATE_SOURCED_READBACK_RULES, ct as IAMRoleProvider, d as updatePartialMessage, di as describeDockerCapturedOutput, dn as applyCallerIdentityCredentials, dr as createSecretMasker, dt as ProviderRegistry, ea as AssemblyReader, ei as ensureAssetStorage, en as requireConfigString, er as findActionableSilentDrops, et as collectDeclaredOutputNames, f as updatePartialReason, fa as resolveBucketRegion, fi as describeDockerExecFailure, fn as callerEnvCredentials, fr as dynamicReferenceTokens, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as setAwsClients, gi as getDockerCmd, gn as STATE_RESOURCES_MALFORMED, gr as markSameGenerationBag, gt as beginCommandInterruptScope, h as IMPLICIT_DELETE_DEPENDENCIES, ha as resetAwsClients, hi as formatDockerLoginError, hn as INTRINSIC_KEYS, hr as isSingleDynamicReferenceToken, ht as maskerOrIdentity, i as DeploymentEventsReader, ia as hasOwnKey, ii as readBootstrapMarkerBody, in as s3BucketArn, ir as DagBuilder, it as secretBearing, j as isFinalSnapshotError, ja as ProvisioningError, ji as resolveCaptureObservedState, jn as malformedOutputsWarning, jr as shellQuote, jt as carriesFetchableDynamicReference, k as ccRoutedFinalSnapshotError, ka as NestedStackChildDirectDestroyError, ki as resolveApp, kn as malformedOrphansWarning, kr as forceQuitRecoveryClause, kt as IntrinsicFunctionResolver, l as replayRollback, la as renderAssemblyPathEscape, li as resolveDockerContextDirectory, ln as applyRoleArnIfSet, lr as TEMPLATE_SOURCED_RULES, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as getAwsClients, mi as dockerSpawnEnvWithSensitive, mn as DiffCalculator, mr as identityKeyFor, mt as maskDeep, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as processStackMessages, ni as isCrossRegionRedirect, nn as producerRegionsFromState, nr as describeTypeWithThrottleRetry, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as nullPrototypeRecord, oi as validateContainerRepoName, on as s3BucketDualStackDomainName, or as STATE_SOURCED_BASELINE_RULES, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as AwsClients, pi as describeDockerFailure, pn as envCredentialsAreAssumedRole, pr as errorCauseChain, pt as createMaskedRetryLogger, q as formatResourceLine, qa as markRedactedCause, qi as producerCoordinateKey, qn as repairMalformedOrphansForReadOnly, qr as buildAssetRedirectMap, qt as configBooleanRefusal, r as DeployEngine, ra as defineOwnKey, ri as parseBootstrapMarker, rn as withSharedDrainBudget, rr as withRetry, rt as isExportAliasCollision, s as planRollback, sa as ownValue, si as buildDenyExternalAccessPolicy, sn as s3BucketRegionalDomainName, sr as STATE_SOURCED_CROSS_GENERATION_RULES, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as failedStageNote, ti as getBootstrapMarkerKey, tn as classifyReplaySecretRegion, tr as findSilentDropProperties, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as resolveAssemblyPath, ui as warnManifestExecutable, un as AWS_CREDENTIAL_ENV_KEYS, ur as carriesSecretMask, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as CdkdError, vi as redactDockerArgvValues, vn as UNREADABLE_RESOURCES_MAP_ROW, vr as maskSecretsInText, vt as interruptWatchListenerCount, w as reachableDivergentParameters, wa as IntrinsicResolutionRefusalError, wi as getDockerImageBySourceHash, wn as malformedExportNamesWarning, wr as S3StateBackend, wt as UNSPECIFIED_SKIP_REASON, x as bindingSkippedOutputs, xi as escapeRegExp, xn as hasReadableOutputs, xr as redactSecretsForState, xt as CloudControlProvider, y as keptWholeReasonText, yi as runDockerForeground, yn as displayLogicalId, yr as recordMaskOnlyValue, yt as isInterruptedWaitError, z as isStatefulRecreateTargetForReplace, zi as CFN_TEMPLATE_BODY_LIMIT, zn as refuseMalformedOrphans, zr as importableOutputs, zt as refStateLookupFromResource } from "./deploy-engine-5fdODHji.js";
1
+ import { $ as yellow, $a as describeAwsFailure, $i as expectedOwnerParam, $n as repairMalformedResourcePropertiesForReadOnly, $r as rewriteTemplateAssetReferences, $t as requireConfigObject, A as createPreDeleteFinalSnapshot, Aa as LocalStartServiceError, Ai as getDefaultStateBucketName, An as malformedOutputsRefusalMessage, Ar as buildForceUnlockCommand, At as carriesDynamicReference, B as isStatefulRecreateTargetSync, Bi as warnDeprecatedNoPrefixCliFlag, Bn as refuseMalformedOrphansForDestroy, Br as hasUnverifiableParameterRefusal, Bt as isSettledInstanceState, C as namesAnyDeclaredParameter, Ci as runDockerStreaming, Cn as isReadableResourceEntry, Cr as recoverMaskedOutput, Ct as slowCcOperationTimeoutMs, D as PRE_DELETE_SNAPSHOT_TYPES, Da as DynamicReferenceRegionAmbiguousError, Di as getDockerImageBySourceHash, Dn as malformedOrphanRecordsWarning, Dr as S3StateBackend, Dt as disableInstanceApiTermination, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as DeployCancelledError, Ei as AssetManifestLoader, En as malformedLocalOutputsWarning, Er as LockManager, Et as deleteSkipReason, F as extractDeploymentEventError, Fa as ProvisioningError, Fi as resolveSkipPrefix, Fn as malformedResourcesWarning, Fr as CUSTOM_RESOURCE_RESPONSE_PREFIX, Ft as isImpossibleEmptyStoredAttribute, G as toCfnInteger, Ga as withErrorHandling, Gi as findLargeInlineResources, Gn as refuseMalformedResourceEntries, Gr as orphansCarriedFrom, Gt as coerceCfnBoolean, H as WARM_THROUGHPUT_MEMBERS, Hi as CFN_TEMPLATE_BODY_LIMIT, Hn as refuseMalformedOutputs, Hr as importableOutputs, Ht as normalizeAwsTagsToCfn, I as makeSiblingClaimReader, Ia as ResourceTimeoutError, Ii as resolveStateBucketWithDefault, In as malformedStateRefusalMessage, Ir as DEFAULT_STATE_PREFIX, It as isNamelessDynamicReferenceError, J as bold, Ja as isThrottlingError, Ji as injectiveKey, Jn as refuseMalformedResourcesForDestroy, Jr as stringifyValue, Jt as configIntegerRefusal, K as toFiniteNumber, Ka as isMarkedNonRetryable, Ki as uploadCfnTemplate, Kn as refuseMalformedResourceEntriesForOrphan, Kr as shouldRetainResource, Kt as coerceCfnInteger, L as planOrphanAdoption, La as ResourceUpdateNotSupportedError, Li as resolveStateBucketWithDefaultAndSource, Ln as refuseDivergentRecordRegionForDestroy, Lr as exportNamesCarriedFrom, Lt as isUnboundTemplateParameter, M as refusesFinalSnapshot, Ma as MalformedProducerRecordRefusalError, Mi as resolveApp, Mn as malformedRenderedContainersWarning, Mr as forceQuitRecoveryClause, Mt as cfnRefValueFromPhysicalId, N as unsupportedFinalSnapshotError, Na as NestedStackChildDirectDestroyError, Ni as resolveAutoAssetStorage, Nn as malformedResourceEntriesWarning, Nr as formatLockExpiry, Nt as coerceParameterTypedValue, O as buildFinalSnapshotIdentifier, Oa as IntrinsicResolutionRefusalError, Oi as Synthesizer, On as malformedOrphansRefusalMessage, Or as rebuildClientForBucketRegion, Ot as isTerminationProtectionPropagationError, P as makeCanonicalizePropertiesFn, Pa as PartialFailureError, Pi as resolveCaptureObservedState, Pn as malformedResourcePropertiesWarning, Pr as shellQuote, Pt as getAccountInfo, Q as red, Qa as retryClassificationText, Qi as decodeListingKey, Qn as repairMalformedResourceEntriesForReadOnly, Qr as loadPublishableAssetManifest, Qt as requireConfigArray, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as StackHasActiveImportsError, Ri as resolveUseCdkBootstrapAssets, Rn as refuseMalformedNestedChildOutputs, Rr as hasReadableExportSet, Rt as parameterTypeMayLoseSecretIdentity, S as computeParameterTaint, Sa as CdkdError, Si as runDockerForeground, Sn as hasReadableResources, Sr as recordMaskOnlyValue, St as isWaitAbandonedError, T as resourcesNamingDeclaredParameter, Ti as stripControlChars, Tn as malformedExportSourceWarning, Tr as scrubResourceRecord, Tt as deleteIndeterminateGuards, U as coerceWarmThroughput$1, Ui as CFN_TEMPLATE_URL_LIMIT, Un as refuseMalformedOutputsForDestroy, Ur as isReadableBag, Ut as resolveExplicitPhysicalId, V as renderStatefulReason, Va as SynthesisError, Vi as ssmResolvedValueType, Vn as refuseMalformedOrphansForOrphan, Vr as importableOutputKeys, Vt as WAFv2WebACLProvider, W as isWarmThroughputDecrease, Wa as normalizeAwsError, Wi as MIGRATE_TMP_PREFIX, Wn as refuseMalformedResourceAttributesForOrphan, Wr as orphansAfterRollback, Wt as assertRegionMatch, X as gray, Xa as markNonRetryable, Xi as producerCoordinateKey, Xn as repairMalformedOrphansForReadOnly, Xr as buildAssetRedirectMap, Xt as readConfigString, Y as cyan, Ya as isTransientServerError, Yi as injectiveKeyPrefix, Yn as refuseMalformedState, Yr as WorkGraph, Yt as configStringRefusal, Z as green, Za as markRedactedCause, Zi as producerRecordKey, Zn as repairMalformedOutputsForReadOnly, Zr as createAssetRedirectResolver, Zt as replayWarn, _ as bagHoldsSecretExpression, _a as AwsClients, _i as dockerSpawnEnvWithSensitive, _n as UNREADABLE_ORPHANS_CONTAINER_ROW, _r as identityKeyFor, _t as endCommandInterruptScope, a as DeploymentEventsStore, aa as globMatches, ai as isCrossRegionRedirect, an as s3BucketDomainName, ar as describeTypeWithThrottleRetry, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as setAwsClients, bi as partitionSensitiveEnv, bn as hasReadableOrphans, br as maskSecretsInError, bt as startInterruptWatch, c as replayFailedOperations, ca as hasOwnKey, ci as validateAssetBucketName, cn as s3BucketWebsiteUrl, cr as TemplateParser, ct as IAMRoleProvider, d as updatePartialMessage, da as ownValue, di as buildDockerImage, dn as applyCallerIdentityCredentials, dr as STATE_SOURCED_READBACK_RULES, dt as ProviderRegistry, ea as PARTITION_TABLE, ei as AssetModeResolver, en as requireConfigString, eo as safeStringify, er as repairMalformedResourcesForReadOnly, et as collectDeclaredOutputNames, f as updatePartialReason, fa as absoluteAssemblyPathEscape, fi as resolveDockerContextDirectory, fn as callerEnvCredentials, fr as TEMPLATE_SOURCED_RULES, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as resolveBucketRegion, gi as describeDockerFailure, gn as STATE_RESOURCES_MALFORMED, gr as errorCauseChain, gt as beginCommandInterruptScope, h as IMPLICIT_DELETE_DEPENDENCIES, hi as describeDockerExecFailure, hn as INTRINSIC_KEYS, hr as dynamicReferenceTokens, ht as maskerOrIdentity, i as DeploymentEventsReader, ia as failedStageNote, ii as getBootstrapMarkerKey, in as s3BucketArn, ir as findSilentDropProperties, it as secretBearing, j as isFinalSnapshotError, ji as getLegacyStateBucketName, jn as malformedOutputsWarning, jr as buildLockContentionMessage, jt as carriesFetchableDynamicReference, k as ccRoutedFinalSnapshotError, ka as LocalInvokeBuildError$1, ki as synthesisStatusMessage, kn as malformedOrphansWarning, kr as UNREPRODUCIBLE_LOCK_CLAUSE, kt as IntrinsicFunctionResolver, l as replayRollback, la as hasPlainPrototype, li as validateContainerRepoName, ln as applyRoleArnIfSet, lr as STATE_SOURCED_BASELINE_RULES, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as resolveAssemblyPath, mi as describeDockerCapturedOutput, mn as DiffCalculator, mr as createSecretMasker, mt as maskDeep, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as derivePartitionAndUrlSuffix, ni as assertAssetBucketRegion, nn as producerRegionsFromState, nr as safeStackName, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as processStackMessages, oi as parseBootstrapMarker, on as s3BucketDualStackDomainName, or as withRetry, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as renderAssemblyPathEscape, pi as warnManifestExecutable, pn as envCredentialsAreAssumedRole, pr as carriesSecretMask, pt as createMaskedRetryLogger, q as formatResourceLine, qa as isRetryableTransientError, qi as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, qn as refuseMalformedResourcePropertiesForOrphan, qr as AssetPublisher, qt as configBooleanRefusal, r as DeployEngine, ra as AssemblyReader, ri as ensureAssetStorage, rn as withSharedDrainBudget, rr as findActionableSilentDrops, rt as isExportAliasCollision, s as planRollback, sa as defineOwnKey, si as readBootstrapMarkerBody, sn as s3BucketRegionalDomainName, sr as DagBuilder, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as canonicalizeRegion, ti as BOOTSTRAP_MARKER_PREFIX, tn as classifyReplaySecretRegion, tr as safeRegion, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as nullPrototypeRecord, ui as buildDenyExternalAccessPolicy, un as AWS_CREDENTIAL_ENV_KEYS, ur as STATE_SOURCED_CROSS_GENERATION_RULES, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as getAwsClients, vi as formatDockerLoginError, vn as UNREADABLE_RESOURCES_MAP_ROW, vr as isSingleDynamicReferenceToken, vt as interruptWatchListenerCount, w as reachableDivergentParameters, wa as CrossAccountSecretRefusalError, wi as escapeRegExp, wn as malformedExportNamesWarning, wr as redactSecretsForState, wt as UNSPECIFIED_SKIP_REASON, x as bindingSkippedOutputs, xi as redactDockerArgvValues, xn as hasReadableOutputs, xr as maskSecretsInText, xt as CloudControlProvider, y as keptWholeReasonText, ya as resetAwsClients, yi as getDockerCmd, yn as displayLogicalId, yr as markSameGenerationBag, yt as isInterruptedWaitError, z as isStatefulRecreateTargetForReplace, za as StackTerminationProtectionError, zi as stateBucketExistenceConfirmed, zn as refuseMalformedOrphans, zr as hasReasonlessBaselineRefusal, zt as refStateLookupFromResource } from "./deploy-engine-CpMT9Bmm.js";
2
2
  import { C as displayAwsMessage, D as truncateCodePoints, E as isPasteableIdent, S as UNRENDERABLE, T as displaySafe, _ as withSkipPrefix, b as SECRET_REF_MAX_CODE_POINTS, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS } from "./logger-GASr9bAF.js";
3
3
  import { n as awsClientDefaults } from "./aws-client-defaults-BoIxyCir.js";
4
- import { t as getCdkdVersion } from "./version-BKm47b9j.js";
5
- import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-CLqajoRp.js";
4
+ import { t as getCdkdVersion } from "./version-ChuDKy_E.js";
5
+ import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-_vdcb9QG.js";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { createHash, randomBytes, randomUUID } from "node:crypto";
8
8
  import { CopyObjectCommand, 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, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, NotFound, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -290,7 +290,7 @@ const STATE_KEY_MAX_CODE_POINTS = STACK_REF_MAX_CODE_POINTS + 64;
290
290
  * Parse context key=value pairs from CLI arguments into a Record
291
291
  */
292
292
  function parseContextOptions(contextArgs) {
293
- const context = {};
293
+ const context = nullPrototypeRecord();
294
294
  if (contextArgs) for (const arg of contextArgs) {
295
295
  const eqIndex = arg.indexOf("=");
296
296
  if (eqIndex > 0) context[arg.substring(0, eqIndex)] = arg.substring(eqIndex + 1);
@@ -2063,7 +2063,8 @@ function createBootstrapCommand() {
2063
2063
  * appear in a CloudFormation stack name, so this is unambiguous)
2064
2064
  * - Pattern contains no `/` → matched only against `stackName`
2065
2065
  *
2066
- * Wildcards (`*`) are supported in either case. Results are de-duplicated by
2066
+ * Wildcards (`*`) are supported in either case; every other character is
2067
+ * literal. Results are de-duplicated by
2067
2068
  * `stackName`, so a pattern that incidentally matches the same stack via both
2068
2069
  * fields is returned only once.
2069
2070
  */
@@ -2133,10 +2134,14 @@ function describeStack(stack) {
2133
2134
  function renderNoStackMatch(patterns, available, assembly) {
2134
2135
  return (patterns.length > 0 ? `No stacks matching ${patterns.join(", ")} found in assembly. ` + (available.length > 0 ? `Available: ${available.map(describeStack).join(", ")}` : "The assembly has no stacks") : "No stacks found in assembly") + failedStageNote(patterns, assembly.failedStages);
2135
2136
  }
2137
+ /**
2138
+ * `*` matches any run of characters and every other character is literal —
2139
+ * `globMatches` owns that rule for this matcher and for the failed-Stage
2140
+ * attribution alike ([#3508](https://github.com/go-to-k/cdkd/issues/3508)).
2141
+ */
2136
2142
  function stackMatchesPattern(stack, pattern) {
2137
2143
  const target = pattern.includes("/") ? stack.displayName ?? stack.stackName : stack.stackName;
2138
- if (pattern.includes("*")) return new RegExp("^" + pattern.replace(/\*/g, ".*") + "$").test(target);
2139
- return target === pattern;
2144
+ return globMatches(pattern, target);
2140
2145
  }
2141
2146
 
2142
2147
  //#endregion
@@ -22354,17 +22359,21 @@ var DynamoDBGlobalTableProvider = class {
22354
22359
  } catch (error) {
22355
22360
  throw new ProvisioningError(error instanceof Error ? error.message : String(error), resourceType, logicalId, void 0, error instanceof Error ? error : void 0);
22356
22361
  }
22362
+ let wiringProperties = properties;
22357
22363
  if (indexesOmitted) {
22358
22364
  effectiveProperties = { ...effectiveProperties ?? properties };
22359
22365
  delete effectiveProperties["GlobalSecondaryIndexes"];
22360
- const replicasForOmit = effectiveProperties["Replicas"];
22361
- if (Array.isArray(replicasForOmit)) effectiveProperties["Replicas"] = replicasForOmit.map((entry) => {
22362
- const replica = asRecord$1(entry);
22363
- if (!replica || replica["Region"] !== currentRegion) return entry;
22364
- const copy = { ...replica };
22365
- delete copy["GlobalSecondaryIndexes"];
22366
- return copy;
22367
- });
22366
+ const recorded = withdrawReplicaIndexBlocks(effectiveProperties["Replicas"]);
22367
+ if (recorded.changed) effectiveProperties["Replicas"] = recorded.replicas;
22368
+ const wired = withdrawReplicaIndexBlocks(properties["Replicas"]);
22369
+ if (wired.changed) {
22370
+ wiringProperties = {
22371
+ ...properties,
22372
+ Replicas: wired.replicas
22373
+ };
22374
+ const crossRegion = wired.withdrawnRegions.filter((region) => region !== currentRegion);
22375
+ if (crossRegion.length > 0) warn(`DynamoDB GlobalTable ${logicalId}: omitting the GlobalSecondaryIndexes overrides of replica(s) ${crossRegion.join(", ")}: they name indexes this create does not build, so there is nothing for them to apply to`);
22376
+ }
22368
22377
  const keptKeyAttributes = collectDesiredKeyAttributeNames(properties, { indexListKeys: ["LocalSecondaryIndexes"] });
22369
22378
  if (keptKeyAttributes.size > 0 && Array.isArray(attributeDefinitions)) {
22370
22379
  const prunedAttributeDefinitions = attributeDefinitions.filter((definition) => {
@@ -22397,7 +22406,8 @@ var DynamoDBGlobalTableProvider = class {
22397
22406
  if (billingMode !== "PROVISIONED" && Object.keys(createOnDemand).length > 0) createParams.OnDemandThroughput = createOnDemand;
22398
22407
  const localReplicaTags = replicas.find((r) => r["Region"] === currentRegion)?.["Tags"];
22399
22408
  if (localReplicaTags && localReplicaTags.length > 0) createParams.Tags = localReplicaTags;
22400
- for (const replica of replicas) {
22409
+ const wiringReplicas = wiringProperties["Replicas"] ?? [];
22410
+ for (const replica of wiringReplicas) {
22401
22411
  const replicaRegion = replica["Region"];
22402
22412
  if (!replicaRegion || replicaRegion === currentRegion) continue;
22403
22413
  toSdkReplicaGlobalSecondaryIndexes(replica["GlobalSecondaryIndexes"], billingMode, diagnostics, maskSecrets);
@@ -22413,7 +22423,7 @@ var DynamoDBGlobalTableProvider = class {
22413
22423
  }
22414
22424
  try {
22415
22425
  const tableInfo = await this.waitForTableActive(tableName, logicalId);
22416
- for (const replica of replicas) {
22426
+ for (const replica of wiringReplicas) {
22417
22427
  const region = replica["Region"];
22418
22428
  if (!region || region === currentRegion) continue;
22419
22429
  await this.addReplica(tableName, replica, region, logicalId, billingMode, void 0, maskSecrets);
@@ -22438,7 +22448,7 @@ var DynamoDBGlobalTableProvider = class {
22438
22448
  }));
22439
22449
  }
22440
22450
  if (billingMode === "PROVISIONED") try {
22441
- await this.reconcileAutoScalingTargets(tableName, [], collectAutoScalingTargets(properties, currentRegion), currentRegion, void 0, maskSecrets);
22451
+ await this.reconcileAutoScalingTargets(tableName, [], collectAutoScalingTargets(wiringProperties, currentRegion), currentRegion, void 0, maskSecrets);
22442
22452
  } catch (autoScalingErr) {
22443
22453
  warn(`Auto-scaling registration failed for ${tableName}: ${describeAwsFailure(autoScalingErr).detail}. The table was created successfully; re-run the deploy to register the scaling targets.`);
22444
22454
  }
@@ -22560,13 +22570,55 @@ var DynamoDBGlobalTableProvider = class {
22560
22570
  if (tableOverrides.OnDemandThroughputOverride) create.OnDemandThroughputOverride = tableOverrides.OnDemandThroughputOverride;
22561
22571
  if (replica["TableClassOverride"]) create.TableClassOverride = replica["TableClassOverride"];
22562
22572
  const replicaUpdates = [{ Create: create }];
22563
- await this.dynamoDBClient.send(new UpdateTableCommand({
22564
- TableName: tableName,
22565
- ReplicaUpdates: replicaUpdates
22566
- }));
22573
+ for (let attempt = 1;; attempt++) try {
22574
+ await this.dynamoDBClient.send(new UpdateTableCommand({
22575
+ TableName: tableName,
22576
+ ReplicaUpdates: replicaUpdates
22577
+ }));
22578
+ break;
22579
+ } catch (error) {
22580
+ if (attempt >= 3 || !isReplicaCopyExistsRefusal(error)) throw error;
22581
+ if (!await this.waitForRegionalCopyReleased(tableName, region, maskSecrets)) throw error;
22582
+ await new Promise((resolve) => setTimeout(resolve, REPLICA_COPY_RELEASE_POLL_MS));
22583
+ }
22567
22584
  await this.waitForReplicaActive(tableName, region, logicalId);
22568
22585
  }
22569
22586
  /**
22587
+ * Poll the replica REGION for its same-named table until it is gone,
22588
+ * answering `true` once it is (so the replica-add may be retried) and
22589
+ * `false` for anything that is not a copy on its way out: a table in any
22590
+ * status but `DELETING`, a probe error, or the cap running out. Only ever
22591
+ * READS the region — the caller re-throws AWS's own refusal on `false`.
22592
+ * Interruptible, like every other bounded wait on this provider's paths.
22593
+ */
22594
+ async waitForRegionalCopyReleased(tableName, region, maskSecrets) {
22595
+ const client = this.getRegionalClient(region);
22596
+ const watch = startInterruptWatch(maskSecrets(`DynamoDB ${region} copy of ${tableName} to finish deleting`));
22597
+ let announced = false;
22598
+ try {
22599
+ for (let poll = 0; poll < 180; poll++) {
22600
+ if (watch.isInterrupted()) throw watch.onInterrupted();
22601
+ let status;
22602
+ try {
22603
+ status = (await client.send(new DescribeTableCommand({ TableName: tableName }))).Table?.TableStatus;
22604
+ } catch (probeError) {
22605
+ if (probeError instanceof ResourceNotFoundException$1) return true;
22606
+ this.logger.debug(maskSecrets(`Could not read the ${region} copy of ${tableName}: ${describeAwsFailure(probeError).detail}`));
22607
+ return false;
22608
+ }
22609
+ if (status !== "DELETING") return false;
22610
+ if (!announced) {
22611
+ this.logger.info(maskSecrets(`The ${region} copy of ${tableName} is still being deleted; waiting for it before adding the replica`));
22612
+ announced = true;
22613
+ }
22614
+ await new Promise((resolve) => setTimeout(resolve, REPLICA_COPY_RELEASE_POLL_MS));
22615
+ }
22616
+ return false;
22617
+ } finally {
22618
+ watch.dispose();
22619
+ }
22620
+ }
22621
+ /**
22570
22622
  * Update a DynamoDB Global Table in place.
22571
22623
  *
22572
22624
  * AWS-side state-machine constraint: `UpdateTable` does not accept
@@ -23178,7 +23230,7 @@ var DynamoDBGlobalTableProvider = class {
23178
23230
  const oldEnabled = oldSettings !== void 0 && oldSettings !== null;
23179
23231
  const newEnabled = newSettings !== void 0 && newSettings !== null;
23180
23232
  if (!oldEnabled && !newEnabled) return;
23181
- const watch = startInterruptWatch(`DynamoDB auto-scaling for ${tableName}`);
23233
+ const watch = startInterruptWatch(maskSecrets(`DynamoDB auto-scaling for ${tableName}`));
23182
23234
  try {
23183
23235
  if (newEnabled) {
23184
23236
  const minCapacity = coerceCfnInteger(newSettings["MinCapacity"] ?? 0);
@@ -24531,6 +24583,65 @@ function collectAutoScalingTargets(properties, localRegion) {
24531
24583
  return specs;
24532
24584
  }
24533
24585
  /**
24586
+ * How long `addReplica` waits out a same-named regional copy that is still
24587
+ * DELETING (issue #3569): polls x interval, ~15 minutes. A regional copy has
24588
+ * been measured to linger for minutes after it left the source table's
24589
+ * `Replicas[]`.
24590
+ */
24591
+ const REPLICA_COPY_RELEASE_POLLS = 180;
24592
+ const REPLICA_COPY_RELEASE_POLL_MS = 5e3;
24593
+ /** Replica-add attempts in total, the first included. */
24594
+ const REPLICA_COPY_RELEASE_ATTEMPTS = 3;
24595
+ /**
24596
+ * AWS's refusal of a `ReplicaUpdates[].Create` whose region already holds a
24597
+ * table of that name. Keyed on the MESSAGE: the error class is a generic
24598
+ * `ValidationException`, shared with every other malformed replica request.
24599
+ */
24600
+ function isReplicaCopyExistsRefusal(error) {
24601
+ return error instanceof Error && /one or more replicas already existed as tables/i.test(error.message);
24602
+ }
24603
+ /**
24604
+ * `Replicas` with every entry's `GlobalSecondaryIndexes` key REMOVED — the
24605
+ * replay-CREATE GSI omit arm's prune of the per-replica index blocks (issue
24606
+ * #1741, second instance), which name indexes that create does not build.
24607
+ *
24608
+ * Copy-on-write: an entry that carries the key is copied without it, every
24609
+ * other entry (a non-object included — an unresolved intrinsic must reach AWS
24610
+ * as-is, not be rewritten) is passed through by reference, and the caller's
24611
+ * array is never mutated. The caller's bag IS `previousState.properties` on
24612
+ * this path. A non-array container is returned untouched with `changed: false`.
24613
+ *
24614
+ * `withdrawnRegions` lists the `Region` of each entry whose block was a
24615
+ * non-empty ARRAY, i.e. one `toSdkReplicaGlobalSecondaryIndexes` would have
24616
+ * turned into a real override on the wire; a malformed or empty block was
24617
+ * never sendable, so withdrawing it is not a loss worth announcing.
24618
+ */
24619
+ function withdrawReplicaIndexBlocks(replicas) {
24620
+ if (!Array.isArray(replicas)) return {
24621
+ replicas,
24622
+ changed: false,
24623
+ withdrawnRegions: []
24624
+ };
24625
+ let changed = false;
24626
+ const withdrawnRegions = [];
24627
+ const out = replicas.map((entry) => {
24628
+ const replica = asRecord$1(entry);
24629
+ if (!replica || !Object.prototype.hasOwnProperty.call(replica, "GlobalSecondaryIndexes")) return entry;
24630
+ changed = true;
24631
+ const block = replica["GlobalSecondaryIndexes"];
24632
+ const region = replica["Region"];
24633
+ if (Array.isArray(block) && block.length > 0 && typeof region === "string") withdrawnRegions.push(region);
24634
+ const copy = { ...replica };
24635
+ delete copy["GlobalSecondaryIndexes"];
24636
+ return copy;
24637
+ });
24638
+ return {
24639
+ replicas: changed ? out : replicas,
24640
+ changed,
24641
+ withdrawnRegions
24642
+ };
24643
+ }
24644
+ /**
24534
24645
  * Every attribute name some KEY SCHEMA in the desired template references:
24535
24646
  * the table's own `KeySchema`, each GSI's, and each LSI's. This is the set
24536
24647
  * the `AttributeDefinitions`-removal guard in `update()` tests membership
@@ -46201,11 +46312,29 @@ function isEmptyObjectPlaceholder(value) {
46201
46312
  * - `EMAIL_OTP` -> `EmailMfaConfiguration` (carries the email-OTP
46202
46313
  * message/subject template — i.e. CFn's
46203
46314
  * `EmailAuthenticationMessage` / `Subject`)
46315
+ *
46316
+ * **The email-OTP model, stated once (issue #1924): the `EmailMfaConfiguration`
46317
+ * block's PRESENCE is the factor.** `EmailMfaConfigType` is exactly
46318
+ * `{Message?, Subject?}` -- unlike `SoftwareTokenMfaConfigType` it has no
46319
+ * `Enabled` member, so the API has no way to carry a message template without
46320
+ * enabling email OTP, nor to report one. That is read off the API's TYPE, not
46321
+ * measured: a live probe needs a DEVELOPER email sender (a COGNITO_DEFAULT pool
46322
+ * refuses the block outright), which the maintainer's account does not have.
46323
+ * Both sides honor that: `buildMfaConfigRequest` sends the block for `EMAIL_OTP` OR a bare
46324
+ * message/subject (announcing the second, since the template did not list the
46325
+ * factor), and `readCurrentState` reads a present block back as `EMAIL_OTP`.
46204
46326
  */
46205
46327
  const MFA_FACTOR_SMS = "SMS_MFA";
46206
46328
  const MFA_FACTOR_SOFTWARE_TOKEN = "SOFTWARE_TOKEN_MFA";
46207
46329
  const MFA_FACTOR_EMAIL_OTP = "EMAIL_OTP";
46208
46330
  /**
46331
+ * The one `WebAuthnConfiguration.FactorConfiguration` value AWS accepts beside
46332
+ * `MfaConfiguration: ON` when `WEB_AUTHN` is an allowed first auth factor
46333
+ * (issue #2064). Typed against the SDK enum so a rename upstream is a compile
46334
+ * error rather than a silently never-matching comparison.
46335
+ */
46336
+ const WEB_AUTHN_MULTI_FACTOR = "MULTI_FACTOR_WITH_USER_VERIFICATION";
46337
+ /**
46209
46338
  * CFn path every `MfaConfiguration` shape refusal in this provider reports.
46210
46339
  * One constant so the three sites that READ the property -- `create`,
46211
46340
  * `update`, and `narrowMfaConfiguration` (the diff / effectiveProperties
@@ -46295,7 +46424,7 @@ function readEnabledMfas(properties) {
46295
46424
  * mirrors how CloudFormation/CDK sequence the two calls.
46296
46425
  */
46297
46426
  function hasMfaConfigProps(properties) {
46298
- return readEnabledMfas(properties).declaresFactor || !!properties["EmailAuthenticationMessage"] || !!properties["EmailAuthenticationSubject"] || !!properties["WebAuthnRelyingPartyID"] || !!properties["WebAuthnUserVerification"];
46427
+ return readEnabledMfas(properties).declaresFactor || !!properties["EmailAuthenticationMessage"] || !!properties["EmailAuthenticationSubject"] || !!properties["WebAuthnRelyingPartyID"] || !!properties["WebAuthnUserVerification"] || !!properties["WebAuthnFactorConfiguration"];
46299
46428
  }
46300
46429
  /**
46301
46430
  * Build the `SetUserPoolMfaConfig` request from the CFn-level MFA properties,
@@ -46361,6 +46490,7 @@ function buildMfaConfigRequest(physicalId, properties, logger, declaredMfaConfig
46361
46490
  const emailSubject = properties["EmailAuthenticationSubject"] || void 0;
46362
46491
  const webAuthnRpId = properties["WebAuthnRelyingPartyID"] || void 0;
46363
46492
  const webAuthnUserVerification = properties["WebAuthnUserVerification"] || void 0;
46493
+ const webAuthnFactorConfiguration = properties["WebAuthnFactorConfiguration"] || void 0;
46364
46494
  if (!hasMfaConfigProps(properties)) return void 0;
46365
46495
  const request = { UserPoolId: physicalId };
46366
46496
  const factors = new Set(enabledMfas ?? []);
@@ -46371,13 +46501,15 @@ function buildMfaConfigRequest(physicalId, properties, logger, declaredMfaConfig
46371
46501
  ...emailMessage !== void 0 ? { Message: emailMessage } : {},
46372
46502
  ...emailSubject !== void 0 ? { Subject: emailSubject } : {}
46373
46503
  };
46374
- if (webAuthnRpId !== void 0 || webAuthnUserVerification !== void 0) request.WebAuthnConfiguration = {
46504
+ if (webAuthnRpId !== void 0 || webAuthnUserVerification !== void 0 || webAuthnFactorConfiguration !== void 0) request.WebAuthnConfiguration = {
46375
46505
  ...webAuthnRpId !== void 0 ? { RelyingPartyId: webAuthnRpId } : {},
46376
- ...webAuthnUserVerification !== void 0 ? { UserVerification: webAuthnUserVerification } : {}
46506
+ ...webAuthnUserVerification !== void 0 ? { UserVerification: webAuthnUserVerification } : {},
46507
+ ...webAuthnFactorConfiguration !== void 0 ? { FactorConfiguration: webAuthnFactorConfiguration } : {}
46377
46508
  };
46378
46509
  const enablesMfaFactor = declaresFactor || request.EmailMfaConfiguration !== void 0;
46379
46510
  request.MfaConfiguration = declaredMfaConfiguration || (enablesMfaFactor ? "OPTIONAL" : "OFF");
46380
46511
  if (enabledMfasBlank) warn(`UserPool ${physicalId}: EnabledMfas is an empty string, which declares no MFA factor and is treated as absent — a mangled Fn::Join or an empty String parameter collapses to this shape. Nothing is enabled from it and MfaConfiguration is ${request.MfaConfiguration}; declare the factor names as a list (e.g. ["${MFA_FACTOR_SOFTWARE_TOKEN}"]) if a factor was intended.`);
46512
+ if (request.EmailMfaConfiguration !== void 0 && !factors.has(MFA_FACTOR_EMAIL_OTP) && !enabledMfasMalformed) warn(`UserPool ${physicalId}: EmailAuthenticationMessage / EmailAuthenticationSubject is sent in SetUserPoolMfaConfig's EmailMfaConfiguration block, which has no enable switch of its own -- sending it ENABLES the ${MFA_FACTOR_EMAIL_OTP} MFA factor although EnabledMfas does not list it, and a read-back reports EnabledMfas with ${MFA_FACTOR_EMAIL_OTP}. Add ${MFA_FACTOR_EMAIL_OTP} to EnabledMfas to declare it, or remove the message and subject if email OTP is not wanted.`);
46381
46513
  const anyFactorBlock = hasAnyMfaFactorBlock(request);
46382
46514
  const maskLeaves = (v) => maskDeep(v, maskSecrets);
46383
46515
  const dropped = unrecognizedFactors.map((f) => JSON.stringify(maskLeaves(f)) ?? String(f));
@@ -46551,7 +46683,7 @@ const POLICIES_SUB_KEY_ANNOUNCEMENT = {
46551
46683
  * The PRE-FLIGHT: the reason this user-pool configuration cannot be applied at
46552
46684
  * all, or `undefined` when nothing is known to refuse it.
46553
46685
  *
46554
- * Two rules, both for combinations AWS rejects 100% of the time, and both
46686
+ * Three rules, all for combinations AWS rejects 100% of the time, and all
46555
46687
  * raised BEFORE the first AWS call on BOTH the create and the update path. The
46556
46688
  * ordering is what makes them worth refusing rather than warning about: on the
46557
46689
  * UPDATE path `UpdateUserPool` lands FIRST and `SetUserPoolMfaConfig` is
@@ -46606,20 +46738,33 @@ const POLICIES_SUB_KEY_ANNOUNCEMENT = {
46606
46738
  *
46607
46739
  * -- with NO WebAuthn block at all, with `UserVerification: preferred`, and with
46608
46740
  * `required`. The only accepted shape is
46609
- * `WebAuthnConfiguration.FactorConfiguration = MULTI_FACTOR_WITH_USER_VERIFICATION`,
46610
- * and the PINNED SDK (`@aws-sdk/client-cognito-identity-provider` 3.1018.0)
46611
- * does not carry that field -- `WebAuthnConfigurationType` is exactly
46612
- * `{RelyingPartyId?, UserVerification?}` -- so cdkd cannot reach it today.
46613
- * Telling the user to switch to `WEB_AUTHN` would therefore be advice that
46614
- * cannot be followed, which is why the remedy names removing the factor or
46615
- * lowering `MfaConfiguration` instead.
46616
- *
46617
- * That same measurement means `WEB_AUTHN` + ON reproduces this very
46618
- * partial-apply shape while NOT being on the deny-list. Deliberately left
46619
- * uncovered: the correct rule there is CONDITIONAL on
46620
- * `WebAuthnConfiguration.FactorConfiguration`, which the pinned SDK cannot
46621
- * express, so a flat deny-list entry would be an OVER-REFUSAL of the shape that
46622
- * becomes valid the moment the SDK gains the field. Tracked as issue #2064.
46741
+ * `WebAuthnConfiguration.FactorConfiguration = MULTI_FACTOR_WITH_USER_VERIFICATION`
46742
+ * (the CFn `WebAuthnFactorConfiguration`), so switching to `WEB_AUTHN` is a
46743
+ * two-property edit with its own rule -- rule 3 -- and the remedy names the
46744
+ * one-property fix instead.
46745
+ *
46746
+ * Rule 3 (issue #2064) -- the request resolves `MfaConfiguration` to ON while
46747
+ * the allowed first auth factors include `WEB_AUTHN` and the request does not
46748
+ * carry `FactorConfiguration: MULTI_FACTOR_WITH_USER_VERIFICATION`. It cannot
46749
+ * be a deny-list entry: the SAME factor is legal or illegal by that one field.
46750
+ * MEASURED us-east-1 2026-09-23, on a pool allowing `[PASSWORD, WEB_AUTHN]`:
46751
+ *
46752
+ * {ON, SoftwareToken, FactorConfiguration: MULTI} -> ACCEPTED
46753
+ * {ON, SoftwareToken, FactorConfiguration: MULTI, UV: preferred} -> ACCEPTED
46754
+ * {OFF, FactorConfiguration: MULTI} -> ACCEPTED
46755
+ * {ON, SoftwareToken, FactorConfiguration: SINGLE_FACTOR} -> rejected
46756
+ * {ON, SoftwareToken, no WebAuthn block}, live value MULTI -> rejected
46757
+ *
46758
+ * all rejections reading "Cannot set WebAuthn factor configuration to
46759
+ * SINGLE_FACTOR if MFA is required and WebAuthn is an allowed first auth
46760
+ * factor". The last line is what licenses reading the REQUEST rather than the
46761
+ * pool: `SetUserPoolMfaConfig` is a full replace here too, so an omitted block
46762
+ * is SINGLE_FACTOR whatever the pool held. It is the #1975 partial apply
46763
+ * exactly -- measured from both an OFF and an OPTIONAL pool, `UpdateUserPool`
46764
+ * adding `WEB_AUTHN` LANDED and the `SetUserPoolMfaConfig(ON)` after it was
46765
+ * rejected. (From a pool already at ON, `UpdateUserPool` itself refuses to add
46766
+ * `WEB_AUTHN` -- "WEB_AUTHN cannot be used as an auth factor when MFA is
46767
+ * enabled if not configured for MFA" -- atomically.)
46623
46768
  *
46624
46769
  * SCOPE LIMIT, deliberate and load-bearing: rule 2 fires only when a
46625
46770
  * `SetUserPoolMfaConfig` request is actually BUILT (`hasMfaConfigProps`), i.e.
@@ -46656,13 +46801,27 @@ const POLICIES_SUB_KEY_ANNOUNCEMENT = {
46656
46801
  * NO logger, so the pre-flight is silent and `applyMfaConfig`'s own warnings
46657
46802
  * still fire exactly once.
46658
46803
  *
46659
- * WHAT THIS CANNOT SEE, stated because the message says "refuses it before
46660
- * sending anything" and that reads as a completeness claim: the pre-flight
46661
- * inspects the TEMPLATE, never the live pool, so two template edits reach the
46662
- * same partial apply without tripping it -- DELETING the `SignInPolicy` block
46663
- * while setting `MfaConfiguration: ON`, and OMITTING `MfaConfiguration` while
46664
- * adding `EMAIL_OTP` to a pool whose live MFA is already ON. Both need a
46665
- * live-state guard and are tracked in #2051.
46804
+ * WHICH FACTOR LIST rules 2 and 3 read (issue #2051): the one the pool will
46805
+ * hold when `SetUserPoolMfaConfig` runs. When the template SENDS
46806
+ * `Policies.SignInPolicy.AllowedFirstAuthFactors` as a list that is the
46807
+ * template's list; when it does not, it is the LIVE list, because an omitted
46808
+ * sub-key -- or a sent `SignInPolicy` without the member -- is PRESERVED by
46809
+ * `UpdateUserPool` (the ledger at `readLiveMfaConfiguration`;
46810
+ * `sendsFirstAuthFactorList`). `update()` supplies that live
46811
+ * list as `liveFirstAuthFactors`, read only when a rule could fire on it; on
46812
+ * create, and when the read fails, it is absent and only the template is
46813
+ * judged -- AWS's own default `[PASSWORD]` cannot trip either rule. MEASURED
46814
+ * us-east-1 2026-09-23: a pool at `[PASSWORD, EMAIL_OTP]` + OPTIONAL took an
46815
+ * `UpdateUserPool` omitting `Policies` (its `AutoVerifiedAttributes` canary
46816
+ * landed, the factor list survived), then `SetUserPoolMfaConfig(ON)` was
46817
+ * rejected -- the partial apply of DELETING `SignInPolicy` while setting ON.
46818
+ *
46819
+ * The OTHER #2051 path -- omitting `MfaConfiguration` while adding `EMAIL_OTP`
46820
+ * to a pool whose live MFA is ON -- is NOT a partial apply and is not guarded:
46821
+ * MEASURED the same day, `UpdateUserPool` itself rejects the added factor
46822
+ * ("Only PASSWORD and WEB_AUTHN (if configured) can be enabled as an auth
46823
+ * factor if MFA is enabled") and its co-sent `AutoVerifiedAttributes` did NOT
46824
+ * land, so AWS answers it atomically before any second call.
46666
46825
  *
46667
46826
  * Deliberately UNCONDITIONAL -- no `CreateContext.replayingState` downgrade.
46668
46827
  * `.claude/rules/providers.md` says a create-path pre-flight refusal MUST
@@ -46670,16 +46829,23 @@ const POLICIES_SUB_KEY_ANNOUNCEMENT = {
46670
46829
  * oversight, and the rule's own reasoning is what licenses it: the downgrade
46671
46830
  * exists because a refusal against a STATE record leaves a resource
46672
46831
  * un-rollbackable with no template-side remedy. That presupposes the replay
46673
- * could otherwise SUCCEED. Here it cannot -- both combinations are rejected by
46832
+ * could otherwise SUCCEED. Here it cannot -- every combination is rejected by
46674
46833
  * AWS 100% of the time (measured above, and CloudFormation rolls back on the
46675
46834
  * same templates), so downgrading would trade a clear cdkd-worded refusal for
46676
46835
  * the identical failure arriving later from AWS, on the create path with a
46677
- * pool to roll back and on the update path with a partial apply. A state record
46678
- * additionally cannot legitimately HOLD either combination: state is written
46679
- * only after a SUCCESSFUL apply, and neither can be applied. Revisit this if
46680
- * AWS ever starts accepting one of them.
46681
- */
46682
- function describeUnsupportedMfaCombination(properties, declaredMfaConfiguration) {
46836
+ * pool to roll back and on the update path with a partial apply. Revisit this
46837
+ * if AWS ever starts accepting one of them.
46838
+ *
46839
+ * That argument is about the REPLAY failing either way, not about state being
46840
+ * unable to hold the combination -- the live-list arm can meet a perfectly
46841
+ * legitimate record. Example: a record at `ON` with no `SignInPolicy`, then a
46842
+ * failed deploy that lowered MFA and added `EMAIL_OTP`; the rollback replays
46843
+ * the `ON` record against a live `EMAIL_OTP` and is refused. It would have been
46844
+ * rejected by AWS all the same, and in both cases the pool keeps the MFA value
46845
+ * the failed deploy left -- a rollback cannot restore `ON` until the live
46846
+ * factor list allows it, which the refusal text names.
46847
+ */
46848
+ function describeUnsupportedMfaCombination(properties, declaredMfaConfiguration, liveFirstAuthFactors) {
46683
46849
  const request = buildMfaConfigRequest("", properties, void 0, declaredMfaConfiguration);
46684
46850
  if (request && request.MfaConfiguration === "OFF" && hasAnyMfaFactorBlock(request)) {
46685
46851
  const blocks = [
@@ -46689,11 +46855,74 @@ function describeUnsupportedMfaCombination(properties, declaredMfaConfiguration)
46689
46855
  ];
46690
46856
  return `${MFA_CONFIGURATION_PATH} is OFF while an MFA factor is configured (SetUserPoolMfaConfig would carry ${blocks.join(", ")}, built from EnabledMfas / EmailAuthenticationMessage / EmailAuthenticationSubject). AWS rejects that combination ("Invalid MFA configuration given, can't turn off MFA and configure an MFA together"), so cdkd refuses it before sending anything rather than leaving a partly-applied update behind. Set MfaConfiguration to ON or OPTIONAL (or remove it) to enable the declared factor. (If MFA is genuinely not wanted, remove EnabledMfas / EmailAuthenticationMessage / EmailAuthenticationSubject instead.)`;
46691
46857
  }
46692
- if (request && request.MfaConfiguration === "ON") {
46693
- const denied = MFA_INCOMPATIBLE_FIRST_AUTH_FACTORS;
46694
- const offending = readAllowedFirstAuthFactors(properties).filter((factor) => denied.includes(factor));
46695
- if (offending.length > 0) return `${MFA_CONFIGURATION_PATH} is ON while Policies.SignInPolicy.AllowedFirstAuthFactors allows ${offending.join(", ")}. AWS rejects that combination ("Only PASSWORD and WEB_AUTHN (if configured) can be enabled as an auth factor if MFA is enabled"), and on an update the sign-in policy has already been applied by the time it does, so cdkd refuses it before sending anything rather than leaving a partly-applied update behind. Remove ${offending.join(", ")} from Policies.SignInPolicy.AllowedFirstAuthFactors, leaving PASSWORD. (Setting MfaConfiguration to OPTIONAL or OFF also clears the conflict, but weakens MFA.)`;
46696
- }
46858
+ if (!request || request.MfaConfiguration !== "ON") return void 0;
46859
+ const fromTemplate = sendsFirstAuthFactorList(properties);
46860
+ const factors = fromTemplate ? readAllowedFirstAuthFactors(properties) : liveFirstAuthFactors ?? [];
46861
+ const where = fromTemplate ? `Policies.SignInPolicy.AllowedFirstAuthFactors allows` : `the pool's LIVE Policies.SignInPolicy.AllowedFirstAuthFactors allows`;
46862
+ const liveNote = fromTemplate ? "" : " (this template does not declare Policies.SignInPolicy.AllowedFirstAuthFactors, and UpdateUserPool PRESERVES an omitted sub-key, so the live list is what SetUserPoolMfaConfig meets)";
46863
+ const partialApply = "and on an update the rest of the change has already been applied by the time it does, so cdkd refuses it before sending anything rather than leaving a partly-applied update behind.";
46864
+ const denied = MFA_INCOMPATIBLE_FIRST_AUTH_FACTORS;
46865
+ const offending = factors.filter((factor) => denied.includes(factor));
46866
+ if (offending.length > 0) return fromTemplate ? `${MFA_CONFIGURATION_PATH} is ON while Policies.SignInPolicy.AllowedFirstAuthFactors allows ${offending.join(", ")}. AWS rejects that combination ("Only PASSWORD and WEB_AUTHN (if configured) can be enabled as an auth factor if MFA is enabled"), and on an update the sign-in policy has already been applied by the time it does, so cdkd refuses it before sending anything rather than leaving a partly-applied update behind. Remove ${offending.join(", ")} from Policies.SignInPolicy.AllowedFirstAuthFactors, leaving PASSWORD. (Setting MfaConfiguration to OPTIONAL or OFF also clears the conflict, but weakens MFA.)` : `${MFA_CONFIGURATION_PATH} is ON while ${where} ${offending.join(", ")}${liveNote}. AWS rejects that combination ("Only PASSWORD and WEB_AUTHN (if configured) can be enabled as an auth factor if MFA is enabled"), ${partialApply} Declare Policies.SignInPolicy with AllowedFirstAuthFactors that leave out ${offending.join(", ")} (for example [PASSWORD]) -- removing the block cannot remove a factor. (Setting MfaConfiguration to OPTIONAL or OFF also clears the conflict, but weakens MFA.)`;
46867
+ if (factors.includes("WEB_AUTHN") && request.WebAuthnConfiguration?.FactorConfiguration !== WEB_AUTHN_MULTI_FACTOR) return `${MFA_CONFIGURATION_PATH} is ON while ${where} WEB_AUTHN${liveNote} and WebAuthnFactorConfiguration is not ${WEB_AUTHN_MULTI_FACTOR}. AWS rejects that combination ("Cannot set WebAuthn factor configuration to SINGLE_FACTOR if MFA is required and WebAuthn is an allowed first auth factor"), ${partialApply} Set WebAuthnFactorConfiguration to ${WEB_AUTHN_MULTI_FACTOR}, which is the only value AWS accepts beside MFA ON, or ${fromTemplate ? "remove WEB_AUTHN from Policies.SignInPolicy.AllowedFirstAuthFactors" : "declare Policies.SignInPolicy with AllowedFirstAuthFactors that leave out WEB_AUTHN"}. (Setting MfaConfiguration to OPTIONAL also clears the conflict, but weakens MFA.)`;
46868
+ }
46869
+ /**
46870
+ * Does this bag put `Policies.SignInPolicy.AllowedFirstAuthFactors` on the
46871
+ * wire as a LIST? Only then does the pool's list change. MEASURED us-east-1
46872
+ * 2026-09-23: an `UpdateUserPool` carrying `SignInPolicy: {}` landed (its
46873
+ * `AutoVerifiedAttributes` canary applied) and left a live
46874
+ * `[PASSWORD, EMAIL_OTP]` intact -- so a SENT sub-key without the member is,
46875
+ * for the factor list, the same as an omitted one. The sub-key gate is the
46876
+ * wire's own (`sendsPoliciesSubKey`); the member gate mirrors
46877
+ * `readAllowedFirstAuthFactors`, which reads a non-list as nothing. A declared
46878
+ * non-list takes the live arm, the side that can refuse (what AWS does with
46879
+ * that shape is unmeasured). An EMPTY list counts as sent and judges nothing, which is safe:
46880
+ * MEASURED the same day, `UpdateUserPool` rejects `AllowedFirstAuthFactors: []`
46881
+ * ("Member must have length greater than or equal to 1") atomically -- its
46882
+ * co-sent `AutoVerifiedAttributes` did not land.
46883
+ */
46884
+ function sendsFirstAuthFactorList(properties) {
46885
+ if (!sendsPoliciesSubKey(properties, "SignInPolicy")) return false;
46886
+ const signInPolicy = properties["Policies"]["SignInPolicy"];
46887
+ return Array.isArray(signInPolicy["AllowedFirstAuthFactors"]);
46888
+ }
46889
+ /**
46890
+ * Does the pre-flight need the pool's LIVE first-auth-factor list (issue
46891
+ * #2051)? Only when rules 2 / 3 can evaluate -- a `SetUserPoolMfaConfig`
46892
+ * request resolving to ON -- AND the template does not send
46893
+ * `Policies.SignInPolicy`, so the live list is what that call will meet. Every
46894
+ * other update spends no extra read.
46895
+ */
46896
+ function mfaPreflightNeedsLiveSignInPolicy(properties, declaredMfaConfiguration) {
46897
+ return buildMfaConfigRequest("", properties, void 0, declaredMfaConfiguration)?.MfaConfiguration === "ON" && !sendsFirstAuthFactorList(properties);
46898
+ }
46899
+ /**
46900
+ * Could this update need `SetUserPoolMfaConfig` BEFORE `UpdateUserPool`
46901
+ * (issue #3562)? True only for the shape that FAILS in cdkd's usual order and
46902
+ * DEPLOYS under CloudFormation: the request keeps MFA `ON`, carries
46903
+ * `FactorConfiguration: MULTI_FACTOR_WITH_USER_VERIFICATION`, and the
46904
+ * template's factor list includes `WEB_AUTHN`. Whether the order actually
46905
+ * flips is then decided by the pool's LIVE MFA state
46906
+ * (`readMfaFirstPrior`) -- this only decides whether that read is worth making.
46907
+ *
46908
+ * MEASURED us-east-1 2026-09-23, from a pool at `ON` + SINGLE_FACTOR +
46909
+ * `[PASSWORD]`:
46910
+ *
46911
+ * UpdateUserPool adding WEB_AUTHN first -> REJECTED ("WEB_AUTHN cannot be
46912
+ * used as an auth factor when MFA is enabled if not configured for MFA")
46913
+ * SetUserPoolMfaConfig(ON, MULTI) first, then UpdateUserPool -> both ACCEPTED
46914
+ * CloudFormation, the same template edit -> UPDATE_COMPLETE
46915
+ *
46916
+ * The OTHER order-dependent edit the issue measured -- lowering MFA from `ON`
46917
+ * while ADDING `EMAIL_OTP` / `SMS_OTP` -- deliberately keeps cdkd's order:
46918
+ * CloudFormation ROLLS BACK that edit (same day, UPDATE_ROLLBACK_COMPLETE with
46919
+ * the same AWS message), so succeeding there would hide from a cdkd user a
46920
+ * failure their production CloudFormation deploy will hit. cdkd's own
46921
+ * rejection is atomic (`UpdateUserPool` refuses before anything lands).
46922
+ */
46923
+ function mfaMayNeedToPrecedeUpdateUserPool(properties, declaredMfaConfiguration) {
46924
+ const request = buildMfaConfigRequest("", properties, void 0, declaredMfaConfiguration);
46925
+ return request?.MfaConfiguration === "ON" && request.WebAuthnConfiguration?.FactorConfiguration === WEB_AUTHN_MULTI_FACTOR && readAllowedFirstAuthFactors(properties).includes("WEB_AUTHN");
46697
46926
  }
46698
46927
  /**
46699
46928
  * Replace a DECLARED-but-unusable `MfaConfiguration` with the value cdkd
@@ -46777,9 +47006,10 @@ var CognitoUserPoolProvider = class {
46777
47006
  "EmailAuthenticationMessage",
46778
47007
  "EmailAuthenticationSubject",
46779
47008
  "WebAuthnRelyingPartyID",
46780
- "WebAuthnUserVerification"
47009
+ "WebAuthnUserVerification",
47010
+ "WebAuthnFactorConfiguration"
46781
47011
  ])]]);
46782
- unhandledByDesign = /* @__PURE__ */ new Map([["AWS::Cognito::UserPool", /* @__PURE__ */ new Map([["WebAuthnFactorConfiguration", "No wire path in the PINNED SDK (@aws-sdk/client-cognito-identity-provider 3.1018.0): WebAuthnConfigurationType is {RelyingPartyId?, UserVerification?} and no CreateUserPool/UpdateUserPool field accepts SINGLE_FACTOR | MULTI_FACTOR_WITH_USER_VERIFICATION. This is an SDK-VERSION limit, NOT an API one -- the live API does honour FactorConfiguration (measured us-east-1 2026-08-20: SetUserPoolMfaConfig(ON) on a pool allowing WEB_AUTHN as a first auth factor is rejected with \"Cannot set WebAuthn factor configuration to SINGLE_FACTOR if MFA is required and WebAuthn is an allowed first auth factor\", i.e. the service reads a field the SDK cannot send). RE-EVALUATE THIS ENTRY ON AN SDK BUMP: if WebAuthnConfigurationType gains FactorConfiguration, the property becomes handleable and this entry must go"]])]]);
47012
+ unhandledByDesign = /* @__PURE__ */ new Map();
46783
47013
  /**
46784
47014
  * Warn when `MfaConfiguration` is declared as a BLANK string (issue #1925
46785
47015
  * item 2, review round 2).
@@ -46822,8 +47052,8 @@ var CognitoUserPoolProvider = class {
46822
47052
  * physical id on update, matching what each path passes to its other
46823
47053
  * `ProvisioningError`s.
46824
47054
  */
46825
- assertMfaCombinationApplicable(logicalId, resourceType, target, properties, declaredMfaConfiguration) {
46826
- const reason = describeUnsupportedMfaCombination(properties, declaredMfaConfiguration);
47055
+ assertMfaCombinationApplicable(logicalId, resourceType, target, properties, declaredMfaConfiguration, liveFirstAuthFactors) {
47056
+ const reason = describeUnsupportedMfaCombination(properties, declaredMfaConfiguration, liveFirstAuthFactors);
46827
47057
  if (reason === void 0) return;
46828
47058
  throw new ProvisioningError(reason, resourceType, logicalId, target);
46829
47059
  }
@@ -47105,6 +47335,14 @@ var CognitoUserPoolProvider = class {
47105
47335
  *
47106
47336
  * - `AutoVerifiedAttributes` — DOES reset when omitted (2026-08-18).
47107
47337
  * - `MfaConfiguration` — does NOT reset when omitted (2026-08-18, above).
47338
+ * - `DeletionProtection` — does NOT reset when omitted (2026-09-23, issue
47339
+ * #2675): a pool created `ACTIVE` stayed `ACTIVE` through an
47340
+ * `UpdateUserPool` omitting it, whose co-sent `AutoVerifiedAttributes`
47341
+ * change landed (the call ran), and an explicit `INACTIVE` then applied
47342
+ * (the field is writable on this call rather than ignored).
47343
+ * - `WebAuthnConfiguration.FactorConfiguration` (a `SetUserPoolMfaConfig`
47344
+ * field) — does NOT reset through an `UpdateUserPool` that omits every MFA
47345
+ * member (2026-09-23, issue #2064).
47108
47346
  * - `Policies` — neither sub-key resets, measured in BOTH directions
47109
47347
  * (2026-08-19, issue #1968; details at `toSdkUserPoolPolicies`): a
47110
47348
  * container sent without `SignInPolicy` left `SignInPolicy` intact, a
@@ -47125,6 +47363,9 @@ var CognitoUserPoolProvider = class {
47125
47363
  * rejected the same way (2026-08-19, issue #1968; the transcript lives at
47126
47364
  * `describeUnsupportedMfaCombination`, which since issue #1977 REFUSES that
47127
47365
  * combination before any call rather than warning about it).
47366
+ * - `WebAuthnConfiguration.FactorConfiguration` — an omitted block is read as
47367
+ * SINGLE_FACTOR even on a pool holding MULTI_FACTOR_WITH_USER_VERIFICATION
47368
+ * (2026-09-23, issue #2064; transcript at `describeUnsupportedMfaCombination`).
47128
47369
  *
47129
47370
  * Nothing here licenses a claim about a field on neither list, or about one
47130
47371
  * API from the other's section. Measure it.
@@ -47163,6 +47404,79 @@ var CognitoUserPoolProvider = class {
47163
47404
  }
47164
47405
  }
47165
47406
  /**
47407
+ * The pool's live `Policies.SignInPolicy.AllowedFirstAuthFactors`, for the
47408
+ * pre-flight (issue #2051), or `undefined` when it cannot be read.
47409
+ *
47410
+ * FAILS OPEN: an unreadable pool is judged on the template alone, which is
47411
+ * the pre-#2051 behavior -- AWS then answers with its own rejection. Refusing
47412
+ * on a failed read would block deploys over a question cdkd never answered.
47413
+ * `update()` already needs `cognito-idp:DescribeUserPool` (its post-update
47414
+ * attribute read), so this adds no permission. An ABSENT list (a pool with
47415
+ * no sign-in policy) is AWS's default `[PASSWORD]`, which trips no rule, so
47416
+ * it reads as empty.
47417
+ */
47418
+ async readLiveAllowedFirstAuthFactors(physicalId) {
47419
+ try {
47420
+ const factors = (await this.retryOnTransientControlPlane(() => this.getClient().send(new DescribeUserPoolCommand({ UserPoolId: physicalId })), `DescribeUserPool(${physicalId}) before the MFA pre-flight`)).UserPool?.Policies?.SignInPolicy?.AllowedFirstAuthFactors;
47421
+ return Array.isArray(factors) ? factors : [];
47422
+ } catch (error) {
47423
+ this.logger.debug(`DescribeUserPool failed for UserPool ${physicalId} before the MFA pre-flight (${error instanceof Error ? error.name : typeof error}): ${describeAwsFailure(error).detail}`);
47424
+ return;
47425
+ }
47426
+ }
47427
+ /**
47428
+ * The pool's FULL live MFA configuration when `SetUserPoolMfaConfig` has to
47429
+ * go FIRST (issue #3562), or `undefined` to keep the usual order.
47430
+ *
47431
+ * MFA-first is needed exactly when the live pool is at `ON` without
47432
+ * `MULTI_FACTOR_WITH_USER_VERIFICATION`: `UpdateUserPool` then refuses to add
47433
+ * `WEB_AUTHN` until the factor configuration has changed. Anything else --
47434
+ * live `OFF` / `OPTIONAL`, live `MULTI` already, or a read that FAILED --
47435
+ * keeps `UpdateUserPool` first, which is the pre-#3562 behaviour and at worst
47436
+ * the atomic rejection it always was. The returned response is also what
47437
+ * `restoreMfaConfig` replays if `UpdateUserPool` fails after the MFA call
47438
+ * landed.
47439
+ */
47440
+ async readMfaFirstPrior(physicalId) {
47441
+ try {
47442
+ const live = await this.retryOnTransientControlPlane(() => this.getClient().send(new GetUserPoolMfaConfigCommand({ UserPoolId: physicalId })), `GetUserPoolMfaConfig(${physicalId}) for the call order`);
47443
+ return live.MfaConfiguration === "ON" && live.WebAuthnConfiguration?.FactorConfiguration !== WEB_AUTHN_MULTI_FACTOR ? live : void 0;
47444
+ } catch (error) {
47445
+ this.logger.debug(`GetUserPoolMfaConfig failed for UserPool ${physicalId} while choosing the call order (${error instanceof Error ? error.name : typeof error}): ${describeAwsFailure(error).detail}`);
47446
+ return;
47447
+ }
47448
+ }
47449
+ /**
47450
+ * Put back the MFA configuration `readMfaFirstPrior` read, after
47451
+ * `UpdateUserPool` failed behind an MFA-first `SetUserPoolMfaConfig` (issue
47452
+ * #3562). Without this the reversed order leaves the #1975 partial apply
47453
+ * mirrored: the MFA change landed, the rest did not. MEASURED us-east-1
47454
+ * 2026-09-23: replaying the earlier `GetUserPoolMfaConfig` members through
47455
+ * `SetUserPoolMfaConfig` restored the pool exactly, after a MULTI change had
47456
+ * landed and the `UpdateUserPool` behind it was rejected.
47457
+ *
47458
+ * Best effort: the caller re-throws the ORIGINAL error either way, and a
47459
+ * failed restore is announced (error CLASS at warn, detail at debug) rather
47460
+ * than replacing it.
47461
+ */
47462
+ async restoreMfaConfig(physicalId, prior) {
47463
+ const request = {
47464
+ UserPoolId: physicalId,
47465
+ ...prior.MfaConfiguration !== void 0 && { MfaConfiguration: prior.MfaConfiguration },
47466
+ ...prior.SmsMfaConfiguration !== void 0 && { SmsMfaConfiguration: prior.SmsMfaConfiguration },
47467
+ ...prior.SoftwareTokenMfaConfiguration !== void 0 && { SoftwareTokenMfaConfiguration: prior.SoftwareTokenMfaConfiguration },
47468
+ ...prior.EmailMfaConfiguration !== void 0 && { EmailMfaConfiguration: prior.EmailMfaConfiguration },
47469
+ ...prior.WebAuthnConfiguration !== void 0 && { WebAuthnConfiguration: prior.WebAuthnConfiguration }
47470
+ };
47471
+ try {
47472
+ await this.retryOnTransientControlPlane(() => this.getClient().send(new SetUserPoolMfaConfigCommand(request)), `SetUserPoolMfaConfig(${physicalId}) restore`);
47473
+ this.logger.debug(`Restored the previous MFA configuration on UserPool ${physicalId}`);
47474
+ } catch (restoreError) {
47475
+ this.logger.warn(`UserPool ${physicalId}: UpdateUserPool failed after SetUserPoolMfaConfig had already applied the new MFA configuration, and restoring the previous one also failed (${restoreError instanceof Error ? restoreError.name : typeof restoreError}). The pool may now carry the NEW MFA configuration with its OLD sign-in policy; re-run the deploy, or check it with aws cognito-idp get-user-pool-mfa-config --user-pool-id ${physicalId}.`);
47476
+ this.logger.debug(`MFA restore failure detail for UserPool ${physicalId}: ${describeAwsFailure(restoreError).detail}`);
47477
+ }
47478
+ }
47479
+ /**
47166
47480
  * Retry a Cognito control-plane call on transient "settling" errors. A
47167
47481
  * SetUserPoolMfaConfig issued immediately after CreateUserPool (or another
47168
47482
  * control-plane write) can briefly hit `ConcurrentModificationException` /
@@ -47276,9 +47590,11 @@ var CognitoUserPoolProvider = class {
47276
47590
  this.logger.debug(`Updating Cognito User Pool ${logicalId}: ${physicalId}`);
47277
47591
  const mfaConfiguration = readDeclaredMfaConfiguration(properties["MfaConfiguration"], { onUnusable: (message) => this.logger.warn(message) });
47278
47592
  this.warnOnBlankMfaConfiguration(properties["MfaConfiguration"]);
47279
- this.assertMfaCombinationApplicable(logicalId, resourceType, physicalId, properties, mfaConfiguration);
47593
+ const liveFirstAuthFactors = mfaPreflightNeedsLiveSignInPolicy(properties, mfaConfiguration) ? await this.readLiveAllowedFirstAuthFactors(physicalId) : void 0;
47594
+ this.assertMfaCombinationApplicable(logicalId, resourceType, physicalId, properties, mfaConfiguration, liveFirstAuthFactors);
47280
47595
  const liveMfa = mfaConfiguration === "" && hasMfaConfigProps(properties) ? await this.readLiveMfaConfiguration(physicalId) : void 0;
47281
47596
  this.warnOnUnremovablePoliciesSubKeys(physicalId, properties, previousProperties);
47597
+ const mfaFirstPrior = mfaMayNeedToPrecedeUpdateUserPool(properties, mfaConfiguration) ? await this.readMfaFirstPrior(physicalId) : void 0;
47282
47598
  try {
47283
47599
  const updateParams = { UserPoolId: physicalId };
47284
47600
  if (properties["Policies"]) {
@@ -47303,14 +47619,23 @@ var CognitoUserPoolProvider = class {
47303
47619
  if (properties["SmsAuthenticationMessage"] !== void 0) updateParams.SmsAuthenticationMessage = properties["SmsAuthenticationMessage"];
47304
47620
  if (properties["SmsVerificationMessage"] !== void 0) updateParams.SmsVerificationMessage = properties["SmsVerificationMessage"];
47305
47621
  if (properties["UserPoolTier"]) updateParams.UserPoolTier = properties["UserPoolTier"];
47306
- await this.getClient().send(new UpdateUserPoolCommand(updateParams));
47307
- await this.reconcileSchemaCustomAttributes(logicalId, physicalId, resourceType, properties["Schema"], previousProperties["Schema"], (properties["DeletionProtection"] ? properties["DeletionProtection"] : previousProperties["DeletionProtection"]) === "ACTIVE");
47308
- await this.applyMfaConfig(physicalId, properties, mfaConfiguration, {
47622
+ const mfaOptions = {
47309
47623
  ...liveMfa?.value !== void 0 ? { liveMfaConfiguration: liveMfa.value } : {},
47310
47624
  ...liveMfa?.failed === true ? { liveReadFailed: true } : {},
47311
47625
  declaredKind: classifyDeclaredMfaConfiguration(properties["MfaConfiguration"]),
47312
47626
  ...context?.maskSecrets && { maskSecrets: context.maskSecrets }
47313
- });
47627
+ };
47628
+ if (mfaFirstPrior) {
47629
+ await this.applyMfaConfig(physicalId, properties, mfaConfiguration, mfaOptions);
47630
+ try {
47631
+ await this.getClient().send(new UpdateUserPoolCommand(updateParams));
47632
+ } catch (updateError) {
47633
+ await this.restoreMfaConfig(physicalId, mfaFirstPrior);
47634
+ throw updateError;
47635
+ }
47636
+ } else await this.getClient().send(new UpdateUserPoolCommand(updateParams));
47637
+ await this.reconcileSchemaCustomAttributes(logicalId, physicalId, resourceType, properties["Schema"], previousProperties["Schema"], (properties["DeletionProtection"] ? properties["DeletionProtection"] : previousProperties["DeletionProtection"]) === "ACTIVE");
47638
+ if (!mfaFirstPrior) await this.applyMfaConfig(physicalId, properties, mfaConfiguration, mfaOptions);
47314
47639
  this.logger.debug(`Successfully updated Cognito User Pool ${logicalId}`);
47315
47640
  const userPool = (await this.getClient().send(new DescribeUserPoolCommand({ UserPoolId: physicalId }))).UserPool;
47316
47641
  const region = await this.getClient().config.region();
@@ -47380,7 +47705,7 @@ var CognitoUserPoolProvider = class {
47380
47705
  before: "aws cognito-idp update-user-pool --user-pool-id",
47381
47706
  identifier: physicalId,
47382
47707
  after: "--deletion-protection INACTIVE",
47383
- caveat: "Note UpdateUserPool's behaviour on an omitted member differs per field, and is unmeasured for DeletionProtection, so send your complete pool configuration alongside that flag rather than the flag alone."
47708
+ caveat: "Note UpdateUserPool resets some members a call omits (AutoVerifiedAttributes among them), so send your complete pool configuration alongside that flag rather than the flag alone."
47384
47709
  }
47385
47710
  }) : `AWS::Cognito::UserPool is a stateful type, so re-run with ${replaceFlags} to recreate it (this deletes all users in the pool).`;
47386
47711
  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}`);
@@ -47520,6 +47845,7 @@ var CognitoUserPoolProvider = class {
47520
47845
  result["EmailAuthenticationSubject"] = mfa.EmailMfaConfiguration?.Subject ?? "";
47521
47846
  result["WebAuthnRelyingPartyID"] = mfa.WebAuthnConfiguration?.RelyingPartyId ?? "";
47522
47847
  result["WebAuthnUserVerification"] = mfa.WebAuthnConfiguration?.UserVerification ?? "";
47848
+ result["WebAuthnFactorConfiguration"] = mfa.WebAuthnConfiguration?.FactorConfiguration ?? "";
47523
47849
  } catch (mfaErr) {
47524
47850
  this.logger.debug(`GetUserPoolMfaConfig failed for ${physicalId}, skipping MFA-derived drift keys: ${describeAwsFailure(mfaErr).detail}`);
47525
47851
  }
@@ -85045,6 +85371,36 @@ function resolveCdkPathToLogicalIds(input, index) {
85045
85371
  //#endregion
85046
85372
  //#region src/analyzer/orphan-rewriter.ts
85047
85373
  /**
85374
+ * Why a reference to an orphaned record that is NOT a readable resource record
85375
+ * is left in place rather than resolved (go-to-k/cdkd#3350).
85376
+ *
85377
+ * `cdkd orphan` may drop such a record — refusing to would close the way out of
85378
+ * it — but it must not resolve THROUGH one. Measured before this guard: a
85379
+ * string or number record made a sibling's `{"Ref": O}` resolve to `undefined`,
85380
+ * which the save then dropped from the JSON, and its `Fn::Sub` `${O}` became
85381
+ * the literal `x-undefined`. Reported as unresolvable instead, so a plain run
85382
+ * aborts naming the site and `--force` leaves the intrinsic untouched — there
85383
+ * is no cached value to fall back to either, since the cache lives inside the
85384
+ * record that cannot be read.
85385
+ */
85386
+ const UNREADABLE_ORPHAN_RECORD_REASON = "the orphaned resource's state record is not a readable resource record (not an object, no resource type, or no physical id), so nothing in it can be substituted";
85387
+ /**
85388
+ * Whether the fetcher may read an orphaned record at all: the ENTRY class's
85389
+ * predicate PLUS a non-empty string `physicalId`. The entry predicate stops at
85390
+ * `resourceType` on purpose (its own note), but every LIVE value this fetcher
85391
+ * produces is derived from the physical id — `{"resourceType": "T"}` alone
85392
+ * made `{"Ref": O}` resolve to `undefined` and `Fn::Sub` to `x-undefined`
85393
+ * exactly as a string record did, and a type whose `Ref` recovery reads the id
85394
+ * threw a bare `TypeError` (review of go-to-k/cdkd#3568). The `--force` cache
85395
+ * is skipped for such a record too, deliberately: a record with no identity is
85396
+ * not one whose cached values can be trusted to describe a live resource.
85397
+ */
85398
+ function isResolvableOrphanRecord(entry) {
85399
+ if (!isReadableResourceEntry(entry)) return false;
85400
+ const physicalId = entry.physicalId;
85401
+ return typeof physicalId === "string" && physicalId !== "";
85402
+ }
85403
+ /**
85048
85404
  * Live-fetch helper. Wraps `provider.getAttribute(...)` for one orphan
85049
85405
  * resource and memoizes results so multiple references to the same
85050
85406
  * `(orphan, attr)` pair only hit AWS once.
@@ -85115,8 +85471,12 @@ var AttributeFetcher = class {
85115
85471
  * already does with a masked cached attribute; the two arms now agree.
85116
85472
  */
85117
85473
  ref(orphanLogicalId) {
85474
+ if (!Object.hasOwn(this.orphans, orphanLogicalId)) throw new Error(`Internal: Ref to '${orphanLogicalId}' has no orphan entry — should have been filtered out`);
85118
85475
  const o = this.orphans[orphanLogicalId];
85119
- if (!o) throw new Error(`Internal: Ref to '${orphanLogicalId}' has no orphan entry — should have been filtered out`);
85476
+ if (!isResolvableOrphanRecord(o)) return {
85477
+ ok: false,
85478
+ reason: UNREADABLE_ORPHAN_RECORD_REASON
85479
+ };
85120
85480
  let maskedKey;
85121
85481
  const value = cfnRefValueFromPhysicalId(o.resourceType, o.physicalId, refStateLookupFromResource(o, (key) => {
85122
85482
  maskedKey = key;
@@ -85155,11 +85515,15 @@ var AttributeFetcher = class {
85155
85515
  ok: true,
85156
85516
  value: this.cache.get(cacheKey)
85157
85517
  };
85158
- const orphan = this.orphans[orphanLogicalId];
85159
- if (!orphan) return {
85518
+ if (!Object.hasOwn(this.orphans, orphanLogicalId)) return {
85160
85519
  ok: false,
85161
85520
  reason: `Internal: GetAtt to '${orphanLogicalId}' has no orphan entry`
85162
85521
  };
85522
+ const orphan = this.orphans[orphanLogicalId];
85523
+ if (!isResolvableOrphanRecord(orphan)) return {
85524
+ ok: false,
85525
+ reason: UNREADABLE_ORPHAN_RECORD_REASON
85526
+ };
85163
85527
  let provider;
85164
85528
  try {
85165
85529
  provider = this.providerRegistry.getProviderFor({
@@ -85196,7 +85560,15 @@ var AttributeFetcher = class {
85196
85560
  reason
85197
85561
  };
85198
85562
  const orphan = this.orphans[orphanLogicalId];
85199
- const stored = orphan.attributes?.[attribute];
85563
+ const bag = orphan.attributes;
85564
+ if (bag !== void 0 && !isReadableBag(bag)) {
85565
+ this.logger.warn(`--force: state.attributes of '${displaySafe(orphanLogicalId, { asciiOnly: true })}' is not a readable map, so it is not consulted for '${displaySafe(attribute, { asciiOnly: true })}'; leaving the original intrinsic in place.`);
85566
+ return {
85567
+ ok: false,
85568
+ reason: `${reason}; the state.attributes cache is not a readable map`
85569
+ };
85570
+ }
85571
+ const stored = bag !== void 0 && Object.hasOwn(bag, attribute) ? bag[attribute] : void 0;
85200
85572
  const cached = isImpossibleEmptyStoredAttribute(orphan.resourceType, attribute, stored) ? void 0 : stored;
85201
85573
  if (cached === void 0) {
85202
85574
  this.logger.warn(`--force: state.attributes also lacks '${orphanLogicalId}.${attribute}'; leaving the original intrinsic in place.`);
@@ -85256,11 +85628,10 @@ var AttributeFetcher = class {
85256
85628
  */
85257
85629
  async function rewriteResourceReferences(state, orphanLogicalIds, providerRegistry, options = {}) {
85258
85630
  const orphanSet = new Set(orphanLogicalIds);
85259
- const orphans = {};
85631
+ const orphans = Object.create(null);
85260
85632
  for (const id of orphanLogicalIds) {
85261
- const r = state.resources[id];
85262
- if (!r) throw new Error(`rewriteResourceReferences: orphan '${id}' not found in state.resources`);
85263
- orphans[id] = r;
85633
+ if (!Object.hasOwn(state.resources, id)) throw new Error(`rewriteResourceReferences: orphan '${id}' not found in state.resources`);
85634
+ orphans[id] = state.resources[id];
85264
85635
  }
85265
85636
  const fetcher = new AttributeFetcher(orphans, providerRegistry, options);
85266
85637
  const rewrites = [];
@@ -85704,10 +86075,13 @@ async function orphanCommand(pathArgs, options) {
85704
86075
  const stateData = await stateBackend.getState(stackInfo.stackName, targetRegion);
85705
86076
  if (!stateData) throw new Error(`No state found for stack '${displaySafe(stackInfo.stackName)}' (${displaySafe(targetRegion, { asciiOnly: true })}). Nothing to orphan. (Did the stack get deployed?)`);
85706
86077
  const { state, etag, migrationPending } = stateData;
85707
- refuseMalformedState(state, stackInfo.stackName, targetRegion);
85708
- refuseMalformedOutputs(state, stackInfo.stackName, targetRegion);
86078
+ refuseMalformedState(state, stackInfo.stackName, recordRegion, recovery);
86079
+ refuseMalformedOutputs(state, stackInfo.stackName, recordRegion, recovery);
86080
+ refuseMalformedResourceEntriesForOrphan(state, orphanLogicalIds, stackInfo.stackName, recordRegion, recovery);
85709
86081
  refuseMalformedResourcePropertiesForOrphan(state, orphanLogicalIds, stackInfo.stackName, recordRegion, recovery);
85710
- const missing = orphanLogicalIds.filter((id) => !(id in state.resources));
86082
+ refuseMalformedResourceAttributesForOrphan(state, orphanLogicalIds, stackInfo.stackName, recordRegion, recovery);
86083
+ refuseMalformedOrphansForOrphan(state, stackInfo.stackName, recordRegion, recovery);
86084
+ const missing = orphanLogicalIds.filter((id) => !Object.hasOwn(state.resources, id));
85711
86085
  if (missing.length > 0) {
85712
86086
  const have = displayIdentList(Object.keys(state.resources), ", ");
85713
86087
  throw new Error(`Resource(s) not in state for stack '${displaySafe(stackInfo.stackName)}' (${displaySafe(targetRegion, { asciiOnly: true })}): ${displayIdentList(missing, ", ")}.\nAvailable logical IDs: ${have}`);
@@ -97769,4 +98143,4 @@ function buildProgram() {
97769
98143
 
97770
98144
  //#endregion
97771
98145
  export { buildProgram };
97772
- //# sourceMappingURL=program-lTNPrurx.js.map
98146
+ //# sourceMappingURL=program-C5r-kmIQ.js.map