@go-to-k/cdkd 0.291.24 → 0.291.26

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 synthesisStatusMessage, $n as refuseMalformedOrphanRecordsForDestroy, $r as forceQuitRecoveryClause, $t as configIntegerRefusal, A as createPreDeleteFinalSnapshot, Aa as credentialFingerprint, Ai as validateContainerRepoName, An as hasReadableOutputs, Ao as retryClassificationText, Ar as TEMPLATE_SOURCED_RULES, At as deleteSkipReason, B as isStatefulRecreateTargetSync, Ba as absoluteAssemblyPathEscape, Bi as getDockerCmd, Bn as malformedOrphansRefusalMessage, Br as maskSecretsInText, Bt as isImpossibleEmptyStoredAttribute, C as namesAnyDeclaredParameter, Ca as expectedOwnerParam, Ci as assertAssetBucketRegion, Cn as STATE_REGION_DIVERGED, Co as shellQuote, Cr as describeTypeWithThrottleRetry, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as ambientClientDefaults, Di as parseBootstrapMarker, Dn as deployRefusesOrphanRowsReason, Do as isTransientServerError, Dr as STATE_SOURCED_BASELINE_RULES, Dt as maskerOrIdentity, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as derivePartitionAndUrlSuffix, Ei as isCrossRegionRedirect, En as UNREADABLE_RESOURCES_MAP_ROW, Eo as isThrottlingError, Er as TemplateParser, Et as maskDeep, F as extractDeploymentEventError, Fa as defineOwnKey, Fi as describeDockerExecFailure, Fn as malformedExportSourceWarning, Fr as identityKeyFor, Ft as carriesDynamicReference, G as toCfnInteger, Ga as resolveBucketRegion, Gi as runDockerForeground, Gn as malformedResourceEntriesWarning, Gr as redactSecretsForState, Gt as isSettledInstanceState, H as WARM_THROUGHPUT_MEMBERS, Ha as renderAssemblyPathEscape, Hi as isMalformedEnvKey, Hn as malformedOutputsRefusalMessage, Hr as recordMaskOnlyValue, Ht as isUnboundTemplateParameter, I as makeSiblingClaimReader, Ia as hasOwnKey, Ii as describeDockerFailure, In as malformedLocalOutputsWarning, Ir as isSingleDynamicReferenceToken, It as carriesFetchableDynamicReference, J as bold, Ja as resetAwsClients, Ji as escapeRegExp, Jn as malformedStateRefusalMessage, Jr as S3StateBackend, Jt as resolveExplicitPhysicalId, K as toFiniteNumber, Ka as AwsClients, Ki as runDockerStreaming, Kn as malformedResourcePropertiesWarning, Kr as scrubResourceRecord, Kt as WAFv2WebACLProvider, L as planOrphanAdoption, La as hasPlainPrototype, Li as dockerSpawnEnvWithSensitive, Ln as malformedOrphanRecordsRefusalMessage, Lr as isUncertifiedBaselineMaskPosition, Lt as cfnRefValueFromPhysicalId, M as refusesFinalSnapshot, Ma as failedStageNote, Mi as buildDockerImage, Mn as isReadableOrphanRecord, Mo as safeStringify, Mr as createSecretMasker, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as globMatches, Ni as resolveDockerContextDirectory, Nn as isReadableResourceEntry, Nr as dynamicReferenceTokens, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as ambientCredentialConfig, Oi as readBootstrapMarkerBody, On as displayLogicalId, Oo as markNonRetryable, Or as STATE_SOURCED_CROSS_GENERATION_RULES, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as processStackMessages, Pi as describeDockerCapturedOutput, Pn as malformedExportNamesWarning, Pr as errorCauseChain, Pt as IntrinsicFunctionResolver, Q as red, Qa as CdkdError, Qi as Synthesizer, Qn as refuseMalformedOrphanRecords, Qr as buildLockContentionMessage, Qt as configBooleanRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as nullPrototypeRecord, Ri as finchSecretArgvRefusal, Rn as malformedOrphanRecordsWarning, Rr as markSameGenerationBag, Rt as coerceParameterTypedValue, S as computeParameterTaint, Sa as decodeListingKey, Si as BOOTSTRAP_MARKER_PREFIX, Sn as INTRINSIC_KEYS, So as pasteableCommand, Sr as findSilentDropProperties, St as compositeIdSeparatorRefusal, T as resourcesNamingDeclaredParameter, Ta as canonicalizeRegion, Ti as getBootstrapMarkerKey, Tn as UNREADABLE_ORPHANS_CONTAINER_ROW, To as isRetryableTransientError, Tr as DagBuilder, Tt as createMaskedRetryLogger, U as coerceWarmThroughput$1, Ua as resolveAssemblyPath, Ui as partitionSensitiveEnv, Un as malformedOutputsWarning, Ur as recordMaskOnlyValuesIn, Ut as parameterTypeMayLoseSecretIdentity, V as renderStatefulReason, Va as displayAssemblyPath, Vi as isDockerClientEnvKey, Vn as malformedOrphansWarning, Vr as pathCrossesDottedKey, Vt as isNamelessDynamicReferenceError, W as isWarmThroughputDecrease, Wi as redactDockerArgvValues, Wn as malformedRenderedContainersWarning, Wr as recoverMaskedOutput, Wt as refStateLookupFromResource, X as gray, Xa as setAwsClients, Xi as AssetManifestLoader, Xn as refuseDivergentRecordRegionForDestroy, Xr as UNREPRODUCIBLE_LOCK_CLAUSE, Xt as coerceCfnBoolean, Y as cyan, Ya as runWithStackAwsClients, Yi as stripControlChars, Yn as previewableOrphanRecords, Yr as rebuildClientForBucketRegion, Yt as assertRegionMatch, Z as green, Zi as getDockerImageBySourceHash, Zn as refuseMalformedNestedChildOutputs, Zr as buildForceUnlockCommand, Zt as coerceCfnInteger, _ as bagHoldsSecretExpression, _a as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, _i as buildAssetRedirectMap, _n as AWS_CREDENTIAL_ENV_KEYS, _o as SynthesisError, _r as safeRegion, _t as startInterruptWatch, a as DeploymentEventsStore, aa as resolveSkipPrefix, ai as hasReadableExportSet, an as requireConfigString, ao as LocalInvokeBuildError$1, ar as refuseMalformedResourceAttributesForOrphan, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as producerCoordinateKey, bi as rewriteTemplateAssetReferences, bn as envCredentialsAreAssumedRole, bo as normalizeAwsError, br as unreadableOrphanRecords, bt as ccProtectionRegistryTypes, c as replayFailedOperations, ca as resolveUseCdkBootstrapAssets, ci as importableOutputKeys, cn as classifyReplaySecretRegion, co as MalformedProducerRecordRefusalError, cr as refuseMalformedResourcePropertiesForOrphan, ct as IAMRoleProvider, d as updatePartialMessage, da as ssmResolvedValueType, di as orphansAfterRollback, dn as s3BucketArn, do as ProvisioningError, dr as repairMalformedOrphanRecordsForReadOnly, dt as ProviderRegistry, ea as getDefaultStateBucketName, ei as formatLockExpiry, en as configStringRefusal, eo as CrossAccountSecretRefusalError, er as refuseMalformedOrphans, et as collectDeclaredOutputNames, f as updatePartialReason, fa as CFN_TEMPLATE_BODY_LIMIT, fi as orphansCarriedFrom, fn as s3BucketDomainName, fo as ResourceTimeoutError, fr as repairMalformedOrphansForReadOnly, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as uploadCfnTemplate, gi as WorkGraph, gn as applyRoleArnIfSet, gr as repairMalformedResourcesForReadOnly, gt as isInterruptedWaitError, h as IMPLICIT_DELETE_DEPENDENCIES, ha as findLargeInlineResources, hi as stringifyValue, hn as s3BucketWebsiteUrl, ho as StackTerminationProtectionError, hr as repairMalformedResourcePropertiesForReadOnly, ht as interruptWatchListenerCount, i as DeploymentEventsReader, ia as resolveCaptureObservedState, ii as exportNamesCarriedFrom, in as requireConfigObject, io as IntrinsicResolutionRefusalError, ir as refuseMalformedOutputsForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as AssemblyReader, ji as buildDenyExternalAccessPolicy, jn as hasReadableResources, jo as describeAwsFailure, jr as carriesSecretMask, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as clientDefaultsFor, ki as validateAssetBucketName, kn as hasReadableOrphans, ko as markRedactedCause, kr as STATE_SOURCED_READBACK_RULES, kt as deleteIndeterminateGuards, l as replayRollback, la as stateBucketExistenceConfirmed, li as importableOutputs, ln as producerRegionsFromState, lo as NestedStackChildDirectDestroyError, lr as refuseMalformedResourcesForDestroy, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as MIGRATE_TMP_PREFIX, mi as AssetPublisher, mn as s3BucketRegionalDomainName, mo as StackHasActiveImportsError, mr as repairMalformedResourceEntriesForReadOnly, mt as endCommandInterruptScope, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveApp, ni as DEFAULT_STATE_PREFIX, nn as replayWarn, no as DeployCancelledError, nr as refuseMalformedOrphansForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as resolveStateBucketWithDefault, oi as hasReasonlessBaselineRefusal, on as definedAttributes, oo as LocalStartServiceError, or as refuseMalformedResourceEntries, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as CFN_TEMPLATE_URL_LIMIT, pi as shouldRetainResource, pn as s3BucketDualStackDomainName, po as ResourceUpdateNotSupportedError, pr as repairMalformedOutputsForReadOnly, pt as beginCommandInterruptScope, q as formatResourceLine, qa as getAwsClients, qi as warnFinchArgvExposure, qn as malformedResourcesWarning, qr as LockManager, qt as normalizeAwsTagsToCfn, r as DeployEngine, ra as resolveAutoAssetStorage, ri as describeRegionValueKind, rn as requireConfigArray, ro as DynamicReferenceRegionAmbiguousError, rr as refuseMalformedOutputs, rt as isExportAliasCollision, s as planRollback, sa as resolveStateBucketWithDefaultAndSource, si as hasUnverifiableParameterRefusal, sn as stringifyIfAssigned, sr as refuseMalformedResourceEntriesForOrphan, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as getLegacyStateBucketName, ti as CUSTOM_RESOURCE_RESPONSE_PREFIX, tn as readConfigString, tr as refuseMalformedOrphansForDestroy, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as warnDeprecatedNoPrefixCliFlag, ui as isReadableBag, un as withSharedDrainBudget, uo as PartialFailureError, ur as refuseMalformedState, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as injectiveKey, vi as createAssetRedirectResolver, vn as applyCallerIdentityCredentials, vr as safeStackName, vt as CloudControlProvider, w as reachableDivergentParameters, wa as PARTITION_TABLE, wi as ensureAssetStorage, wn as STATE_RESOURCES_MALFORMED, wo as isMarkedNonRetryable, wr as withRetry, wt as packCompositeId, x as bindingSkippedOutputs, xa as producerRecordKey, xi as AssetModeResolver, xn as DiffCalculator, xo as withErrorHandling, xr as findActionableSilentDrops, xt as compositeIdFormatMessage, y as keptWholeReasonText, ya as injectiveKeyPrefix, yi as loadPublishableAssetManifest, yn as callerEnvCredentials, yr as unpreviewableOrphanRecords, yt as slowCcOperationTimeoutMs, z as isStatefulRecreateTargetForReplace, za as ownValue, zi as formatDockerLoginError, zn as malformedOrphanRowsKeptWarning, zr as maskSecretsInError, zt as getAccountInfo } from "./deploy-engine-Czuf7jgT.js";
1
+ import { $ as yellow, $a as CdkdError, $i as synthesisStatusMessage, $n as refuseMalformedOrphanRecordsForDestroy, $r as forceQuitRecoveryClause, $t as configIntegerRefusal, A as createPreDeleteFinalSnapshot, Aa as credentialFingerprint, Ai as validateContainerRepoName, An as hasReadableOutputs, Ao as markRedactedCause, Ar as TEMPLATE_SOURCED_RULES, At as deleteSkipReason, B as isStatefulRecreateTargetSync, Ba as absoluteAssemblyPathEscape, Bi as getDockerCmd, Bn as malformedOrphansRefusalMessage, Br as maskSecretsInText, Bt as isImpossibleEmptyStoredAttribute, C as namesAnyDeclaredParameter, Ca as expectedOwnerParam, Ci as assertAssetBucketRegion, Cn as STATE_REGION_DIVERGED, Co as pasteableCommand, Cr as describeTypeWithThrottleRetry, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as ambientClientDefaults, Di as parseBootstrapMarker, Dn as deployRefusesOrphanRowsReason, Do as isThrottlingError, Dr as STATE_SOURCED_BASELINE_RULES, Dt as maskerOrIdentity, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as derivePartitionAndUrlSuffix, Ei as isCrossRegionRedirect, En as UNREADABLE_RESOURCES_MAP_ROW, Eo as isRetryableTransientError, Er as TemplateParser, Et as maskDeep, F as extractDeploymentEventError, Fa as defineOwnKey, Fi as describeDockerExecFailure, Fn as malformedExportSourceWarning, Fr as identityKeyFor, Ft as carriesDynamicReference, G as toCfnInteger, Gi as runDockerForeground, Gn as malformedResourceEntriesWarning, Gr as redactSecretsForState, Gt as isSettledInstanceState, H as WARM_THROUGHPUT_MEMBERS, Ha as displayAssemblyPath, Hi as isMalformedEnvKey, Hn as malformedOutputsRefusalMessage, Hr as recordMaskOnlyValue, Ht as isUnboundTemplateParameter, I as makeSiblingClaimReader, Ia as hasOwnKey, Ii as describeDockerFailure, In as malformedLocalOutputsWarning, Ir as isSingleDynamicReferenceToken, It as carriesFetchableDynamicReference, J as bold, Ja as getAwsClients, Ji as escapeRegExp, Jn as malformedStateRefusalMessage, Jr as S3StateBackend, Jt as resolveExplicitPhysicalId, K as toFiniteNumber, Ka as resolveBucketRegion, Ki as runDockerStreaming, Kn as malformedResourcePropertiesWarning, Kr as scrubResourceRecord, Kt as WAFv2WebACLProvider, L as planOrphanAdoption, La as hasPlainPrototype, Li as dockerSpawnEnvWithSensitive, Ln as malformedOrphanRecordsRefusalMessage, Lr as isUncertifiedBaselineMaskPosition, Lt as cfnRefValueFromPhysicalId, M as refusesFinalSnapshot, Ma as failedStageNote, Mi as buildDockerImage, Mn as isReadableOrphanRecord, Mo as describeAwsFailure, Mr as createSecretMasker, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as globMatches, Ni as resolveDockerContextDirectory, Nn as isReadableResourceEntry, No as safeStringify, Nr as dynamicReferenceTokens, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as ambientCredentialConfig, Oi as readBootstrapMarkerBody, On as displayLogicalId, Oo as isTransientServerError, Or as STATE_SOURCED_CROSS_GENERATION_RULES, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as processStackMessages, Pi as describeDockerCapturedOutput, Pn as malformedExportNamesWarning, Pr as errorCauseChain, Pt as IntrinsicFunctionResolver, Q as red, Qi as Synthesizer, Qn as refuseMalformedOrphanRecords, Qr as buildLockContentionMessage, Qt as configBooleanRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as nullPrototypeRecord, Ri as finchSecretArgvRefusal, Rn as malformedOrphanRecordsWarning, Rr as markSameGenerationBag, Rt as coerceParameterTypedValue, S as computeParameterTaint, Sa as decodeListingKey, Si as BOOTSTRAP_MARKER_PREFIX, Sn as INTRINSIC_KEYS, So as withErrorHandling, Sr as findSilentDropProperties, St as compositeIdSeparatorRefusal, T as resourcesNamingDeclaredParameter, Ta as canonicalizeRegion, Ti as getBootstrapMarkerKey, Tn as UNREADABLE_ORPHANS_CONTAINER_ROW, To as isMarkedNonRetryable, Tr as DagBuilder, Tt as createMaskedRetryLogger, U as coerceWarmThroughput$1, Ua as renderAssemblyPathEscape, Ui as partitionSensitiveEnv, Un as malformedOutputsWarning, Ur as recordMaskOnlyValuesIn, Ut as parameterTypeMayLoseSecretIdentity, V as renderStatefulReason, Va as describeFileReadFailure, Vi as isDockerClientEnvKey, Vn as malformedOrphansWarning, Vr as pathCrossesDottedKey, Vt as isNamelessDynamicReferenceError, W as isWarmThroughputDecrease, Wa as resolveAssemblyPath, Wi as redactDockerArgvValues, Wn as malformedRenderedContainersWarning, Wr as recoverMaskedOutput, Wt as refStateLookupFromResource, X as gray, Xa as runWithStackAwsClients, Xi as AssetManifestLoader, Xn as refuseDivergentRecordRegionForDestroy, Xr as UNREPRODUCIBLE_LOCK_CLAUSE, Xt as coerceCfnBoolean, Y as cyan, Ya as resetAwsClients, Yi as stripControlChars, Yn as previewableOrphanRecords, Yr as rebuildClientForBucketRegion, Yt as assertRegionMatch, Z as green, Za as setAwsClients, Zi as getDockerImageBySourceHash, Zn as refuseMalformedNestedChildOutputs, Zr as buildForceUnlockCommand, Zt as coerceCfnInteger, _ as bagHoldsSecretExpression, _a as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, _i as buildAssetRedirectMap, _n as AWS_CREDENTIAL_ENV_KEYS, _r as safeRegion, _t as startInterruptWatch, a as DeploymentEventsStore, aa as resolveSkipPrefix, ai as hasReadableExportSet, an as requireConfigString, ao as IntrinsicResolutionRefusalError, ar as refuseMalformedResourceAttributesForOrphan, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as producerCoordinateKey, bi as rewriteTemplateAssetReferences, bn as envCredentialsAreAssumedRole, br as unreadableOrphanRecords, bt as ccProtectionRegistryTypes, c as replayFailedOperations, ca as resolveUseCdkBootstrapAssets, ci as importableOutputKeys, cn as classifyReplaySecretRegion, cr as refuseMalformedResourcePropertiesForOrphan, ct as IAMRoleProvider, d as updatePartialMessage, da as ssmResolvedValueType, di as orphansAfterRollback, dn as s3BucketArn, do as PartialFailureError, dr as repairMalformedOrphanRecordsForReadOnly, dt as ProviderRegistry, ea as getDefaultStateBucketName, ei as formatLockExpiry, en as configStringRefusal, er as refuseMalformedOrphans, et as collectDeclaredOutputNames, f as updatePartialReason, fa as CFN_TEMPLATE_BODY_LIMIT, fi as orphansCarriedFrom, fn as s3BucketDomainName, fo as ProvisioningError, fr as repairMalformedOrphansForReadOnly, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as uploadCfnTemplate, gi as WorkGraph, gn as applyRoleArnIfSet, go as StackTerminationProtectionError, gr as repairMalformedResourcesForReadOnly, gt as isInterruptedWaitError, h as IMPLICIT_DELETE_DEPENDENCIES, ha as findLargeInlineResources, hi as stringifyValue, hn as s3BucketWebsiteUrl, ho as StackHasActiveImportsError, hr as repairMalformedResourcePropertiesForReadOnly, ht as interruptWatchListenerCount, i as DeploymentEventsReader, ia as resolveCaptureObservedState, ii as exportNamesCarriedFrom, in as requireConfigObject, io as DynamicReferenceRegionAmbiguousError, ir as refuseMalformedOutputsForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as AssemblyReader, ji as buildDenyExternalAccessPolicy, jn as hasReadableResources, jo as retryClassificationText, jr as carriesSecretMask, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as clientDefaultsFor, ki as validateAssetBucketName, kn as hasReadableOrphans, ko as markNonRetryable, kr as STATE_SOURCED_READBACK_RULES, kt as deleteIndeterminateGuards, l as replayRollback, la as stateBucketExistenceConfirmed, li as importableOutputs, ln as producerRegionsFromState, lo as MalformedProducerRecordRefusalError, lr as refuseMalformedResourcesForDestroy, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as MIGRATE_TMP_PREFIX, mi as AssetPublisher, mn as s3BucketRegionalDomainName, mo as ResourceUpdateNotSupportedError, mr as repairMalformedResourceEntriesForReadOnly, mt as endCommandInterruptScope, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveApp, ni as DEFAULT_STATE_PREFIX, nn as replayWarn, nr as refuseMalformedOrphansForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as resolveStateBucketWithDefault, oi as hasReasonlessBaselineRefusal, on as definedAttributes, oo as LocalInvokeBuildError$1, or as refuseMalformedResourceEntries, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as CFN_TEMPLATE_URL_LIMIT, pi as shouldRetainResource, pn as s3BucketDualStackDomainName, po as ResourceTimeoutError, pr as repairMalformedOutputsForReadOnly, pt as beginCommandInterruptScope, q as formatResourceLine, qa as AwsClients, qi as warnFinchArgvExposure, qn as malformedResourcesWarning, qr as LockManager, qt as normalizeAwsTagsToCfn, r as DeployEngine, ra as resolveAutoAssetStorage, ri as describeRegionValueKind, rn as requireConfigArray, ro as DeployCancelledError, rr as refuseMalformedOutputs, rt as isExportAliasCollision, s as planRollback, sa as resolveStateBucketWithDefaultAndSource, si as hasUnverifiableParameterRefusal, sn as stringifyIfAssigned, so as LocalStartServiceError, sr as refuseMalformedResourceEntriesForOrphan, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as getLegacyStateBucketName, ti as CUSTOM_RESOURCE_RESPONSE_PREFIX, tn as readConfigString, to as CrossAccountSecretRefusalError, tr as refuseMalformedOrphansForDestroy, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as warnDeprecatedNoPrefixCliFlag, ui as isReadableBag, un as withSharedDrainBudget, uo as NestedStackChildDirectDestroyError, ur as refuseMalformedState, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as injectiveKey, vi as createAssetRedirectResolver, vn as applyCallerIdentityCredentials, vo as SynthesisError, vr as safeStackName, vt as CloudControlProvider, w as reachableDivergentParameters, wa as PARTITION_TABLE, wi as ensureAssetStorage, wn as STATE_RESOURCES_MALFORMED, wo as shellQuote, wr as withRetry, wt as packCompositeId, x as bindingSkippedOutputs, xa as producerRecordKey, xi as AssetModeResolver, xn as DiffCalculator, xo as normalizeAwsError, xr as findActionableSilentDrops, xt as compositeIdFormatMessage, y as keptWholeReasonText, ya as injectiveKeyPrefix, yi as loadPublishableAssetManifest, yn as callerEnvCredentials, yr as unpreviewableOrphanRecords, yt as slowCcOperationTimeoutMs, z as isStatefulRecreateTargetForReplace, za as ownValue, zi as formatDockerLoginError, zn as malformedOrphanRowsKeptWarning, zr as maskSecretsInError, zt as getAccountInfo } from "./deploy-engine-BZps_IKn.js";
2
2
  import { C as displayAwsMessage, D as isPasteableIdent, E as displayStackName, O as truncateCodePoints, 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-Bt0RGDfb.js";
3
3
  import { n as awsClientDefaults, s as ambientRegion } from "./aws-client-defaults-jISU4PHo.js";
4
- import { t as getCdkdVersion } from "./version-BI33Emlj.js";
5
- import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-CXNAEgyw.js";
4
+ import { t as getCdkdVersion } from "./version-BkoR4hMq.js";
5
+ import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-Dbqbr89e.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";
@@ -3073,7 +3073,7 @@ function validateRecreateTargets(input) {
3073
3073
  if (MULTI_REGION_RECREATE_BLOCKED_TYPES.has(resourceType)) blockedMultiRegionTargets.push(target);
3074
3074
  if (resourceType === NESTED_STACK_RESOURCE_TYPE$1 || templateResource.Type === NESTED_STACK_RESOURCE_TYPE$1) blockedNestedStackTargets.push(target);
3075
3075
  if (direction === "to-cc-api") {
3076
- const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, EMPTY_ALLOW_SET$1);
3076
+ const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, EMPTY_ALLOW_SET$1, recordedResource.properties, { unresolvedAs: "changed" });
3077
3077
  for (const { property } of actionableDrops) {
3078
3078
  const allowKey = `${resourceType}:${property}`;
3079
3079
  if (input.allowUnsupportedProperties.has(allowKey)) ambiguousIntent.push({
@@ -3084,7 +3084,7 @@ function validateRecreateTargets(input) {
3084
3084
  }
3085
3085
  if (recordedResource.provisionedBy === "cc-api") blockedAlreadyCcApi.push(target);
3086
3086
  } else {
3087
- const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, input.allowUnsupportedProperties);
3087
+ const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, input.allowUnsupportedProperties, recordedResource.properties, { unresolvedAs: "changed" });
3088
3088
  for (const { property } of actionableDrops) ambiguousIntentSdk.push({
3089
3089
  logicalId,
3090
3090
  resourceType,
@@ -8600,6 +8600,16 @@ function noRecordedRegionCause() {
8600
8600
  remedy: "This record predates cdkd's region-keyed state layout. Re-deploy the stack to write a record that carries its region, or confirm the bucket's location yourself, to have the guard run on the next destroy."
8601
8601
  };
8602
8602
  }
8603
+ /**
8604
+ * A lifecycle rule's `Id` as the warnings print it (go-to-k/cdkd#3617). The id
8605
+ * is template-chosen and free-form, so it renders through `displayIdent` --
8606
+ * bare when plain, otherwise one JSON string -- rather than inside cdkd's own
8607
+ * quotes, which a `'` in it would close. An absent or empty id is named in
8608
+ * words.
8609
+ */
8610
+ function shownLifecycleRuleId(id) {
8611
+ return id === void 0 || id === null || id === "" ? "(no Id)" : displayIdent(id);
8612
+ }
8603
8613
  var S3BucketProvider = class S3BucketProvider {
8604
8614
  s3Client;
8605
8615
  logger = getLogger().child("S3BucketProvider");
@@ -8901,7 +8911,7 @@ var S3BucketProvider = class S3BucketProvider {
8901
8911
  if (coerceCfnBoolean(rule["ExpiredObjectDeleteMarker"]) === true) {
8902
8912
  const exp = sdkRule.Expiration;
8903
8913
  if (!(exp?.["Days"] !== void 0 || exp?.["Date"] !== void 0)) sdkRule.Expiration = { ExpiredObjectDeleteMarker: true };
8904
- else this.logger.warn(`Lifecycle rule '${displaySafe(rule["Id"] ?? "<unnamed>")}' on ${displaySafe(bucketName)} sets ExpiredObjectDeleteMarker alongside an expiration Days/Date; S3 forbids combining them, so the delete-marker cleanup was not applied.`);
8914
+ else this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(rule["Id"])} on ${displaySafe(bucketName)} sets ExpiredObjectDeleteMarker alongside an expiration Days/Date; S3 forbids combining them, so the delete-marker cleanup was not applied.`);
8905
8915
  }
8906
8916
  const nve = isPlainObject$2(rule["NoncurrentVersionExpiration"]) ? rule["NoncurrentVersionExpiration"] : void 0;
8907
8917
  const legacyNveDays = rule["NoncurrentVersionExpirationInDays"];
@@ -8917,7 +8927,7 @@ var S3BucketProvider = class S3BucketProvider {
8917
8927
  });
8918
8928
  const nvts = rule["NoncurrentVersionTransitions"];
8919
8929
  const singularNvt = rule["NoncurrentVersionTransition"];
8920
- const allNvts = mergeLegacySingular(nvts, singularNvt, (sc) => this.logger.warn(`Lifecycle rule '${displaySafe(rule["Id"] ?? "<unnamed>")}' on ${displaySafe(bucketName)} declares both NoncurrentVersionTransitions and the legacy NoncurrentVersionTransition for storage class ${displaySafe(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
8930
+ const allNvts = mergeLegacySingular(nvts, singularNvt, (sc) => this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(rule["Id"])} on ${displaySafe(bucketName)} declares both NoncurrentVersionTransitions and the legacy NoncurrentVersionTransition for storage class ${displaySafe(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
8921
8931
  if (allNvts.length > 0) sdkRule.NoncurrentVersionTransitions = allNvts.map(toSdkNvt);
8922
8932
  const toSdkTransition = (t) => ({
8923
8933
  Days: t["TransitionInDays"] ?? t["Days"],
@@ -8926,7 +8936,7 @@ var S3BucketProvider = class S3BucketProvider {
8926
8936
  });
8927
8937
  const transitions = rule["Transitions"];
8928
8938
  const singularTransition = rule["Transition"];
8929
- const allTransitions = mergeLegacySingular(transitions, singularTransition, (sc) => this.logger.warn(`Lifecycle rule '${displaySafe(rule["Id"] ?? "<unnamed>")}' on ${displaySafe(bucketName)} declares both Transitions and the legacy Transition for storage class ${displaySafe(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
8939
+ const allTransitions = mergeLegacySingular(transitions, singularTransition, (sc) => this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(rule["Id"])} on ${displaySafe(bucketName)} declares both Transitions and the legacy Transition for storage class ${displaySafe(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
8930
8940
  if (allTransitions.length > 0) sdkRule.Transitions = allTransitions.map(toSdkTransition);
8931
8941
  const abort = isPlainObject$2(rule["AbortIncompleteMultipartUpload"]) ? rule["AbortIncompleteMultipartUpload"] : void 0;
8932
8942
  if (abort) sdkRule.AbortIncompleteMultipartUpload = { DaysAfterInitiation: abort["DaysAfterInitiation"] };
@@ -21135,23 +21145,29 @@ var DynamoDBTableProvider = class {
21135
21145
  * CALLER-BLIND, decided rather than overlooked (PR review). A TEMPLATE-borne
21136
21146
  * `{0, 0}` warn-skips here while `create()` fails loudly on the same value,
21137
21147
  * which reads like the "loud failure for a quiet lie" trade the adopted-index
21138
- * arm below forbids. It stands for three reasons:
21139
- *
21140
- * - The discriminator that EXISTS does not separate the callers that matter.
21141
- * `ResourceProvider.update` DOES take an optional `UpdateContext` — an
21142
- * earlier draft of this comment claimed the signature carries no context
21143
- * at all, which is simply false (`s3-bucket-provider.ts` consumes it
21144
- * today) — but its one field, `desiredFromAwsReadback`, is set ONLY by
21145
- * `cdkd drift --revert` (`src/cli/commands/drift.ts`). The rollback
21146
- * executor's revert arms deliberately pass NO context: their desired bag
21147
- * is `previousState.properties`, a TEMPLATE recorded earlier, so they are
21148
- * indistinguishable from an ordinary template deploy — and THAT is the
21149
- * pair this decision turns on. Knowing the value came from a readback
21150
- * would not license throwing on the other two.
21151
- * - With the caller unknowable, the repo's rule for the UPDATE path is
21152
- * WARN-never-throw (issues #1545 / #1552): the desired bag here can BE a
21153
- * historical cdkd state record, and a refusal would make the table
21154
- * un-updatable and un-rollbackable with no template-side remedy.
21148
+ * arm below forbids. It was decided for three reasons; the first no longer
21149
+ * holds as written (see its own bullet), the other two still do:
21150
+ *
21151
+ * - When this was decided, no discriminator separated the callers that
21152
+ * matter. `ResourceProvider.update` takes an optional `UpdateContext`, and
21153
+ * `desiredFromAwsReadback` on it is set ONLY by `cdkd drift --revert`
21154
+ * (`src/cli/commands/drift.ts`). The rollback executor's revert arms DO
21155
+ * pass a context (a `maskSecrets` capability, issue #1932) but never set
21156
+ * that flag: their desired bag is `previousState.properties`, a TEMPLATE
21157
+ * recorded earlier. At the time they were therefore indistinguishable
21158
+ * from an ordinary template deploy — and THAT is the pair this decision
21159
+ * turns on. (An earlier revision said the revert arms "pass NO context",
21160
+ * which stopped being true with #1932 — issue #1999.) Since issue #3141
21161
+ * they ALSO set `UpdateContext.replayingState`, so the caller is now
21162
+ * knowable: the per-index `OnDemandThroughput` refusal in `update()` gates
21163
+ * on exactly that pair of flags (the go-to-k/cdkd#3401 review). This arm
21164
+ * was not re-decided when that became possible; splitting it the same way
21165
+ * would turn a template-path warn-skip into a refusal, a behaviour change
21166
+ * that needs its own review rather than a comment edit (issue #3728).
21167
+ * - The repo's general rule for the UPDATE path is WARN-never-throw (issues
21168
+ * #1545 / #1552): the desired bag here can BE a historical cdkd state
21169
+ * record, and a refusal would make the table un-updatable and
21170
+ * un-rollbackable with no template-side remedy.
21155
21171
  * - The lie is bounded and self-surfacing. AWS never accepted `{0, 0}` at
21156
21172
  * create either, so no live table can be holding it; and where the value
21157
21173
  * would actually matter — a PROVISIONED table, whose indexes hold a real
@@ -31657,9 +31673,10 @@ var EC2Provider = class {
31657
31673
  * narrowing here the template's extra keys read as an ADDED property on the
31658
31674
  * next deploy — and every destination key is create-only in the registry
31659
31675
  * schema, so the diff would classify a REPLACEMENT and the engine's
31660
- * replacement create (which passes no context, and so gets no
31661
- * `onMultipleDestinations` downgrade) would hit the #1566 refusal. A
31662
- * previously-green no-op deploy would start failing.
31676
+ * replacement create (whose context carries a `maskSecrets` capability but
31677
+ * never `replayingState`, and so gets no `onMultipleDestinations`
31678
+ * downgrade) would hit the #1566 refusal. A previously-green no-op deploy
31679
+ * would start failing.
31663
31680
  *
31664
31681
  * Shares `narrowRouteDestinations` with the provisioning path so the two
31665
31682
  * cannot disagree about which key survives.
@@ -31668,8 +31685,8 @@ var EC2Provider = class {
31668
31685
  * half for the same reason: `IpProtocol` is create-only on that type in the
31669
31686
  * registry schema, so normalizing state alone would make the template's
31670
31687
  * original value read as a changed immutable property — a REPLACEMENT, whose
31671
- * create passes no context and so gets no `onUnusable` downgrade, turning a
31672
- * previously-green no-op deploy into a hard failure. Normalizing BOTH sides
31688
+ * create never sets `replayingState` and so gets no `onUnusable` downgrade,
31689
+ * turning a previously-green no-op deploy into a hard failure. Normalizing BOTH sides
31673
31690
  * is also what keeps the fix correct for records written BEFORE it existed,
31674
31691
  * which still carry the un-narrowed value.
31675
31692
  */
@@ -51256,6 +51273,40 @@ const GLUE_TABLE_ID_FORMAT = {
51256
51273
  segments: ["databaseName", "tableName"]
51257
51274
  };
51258
51275
  /**
51276
+ * Decode an `AWS::Glue::Table` physicalId `<databaseName>|<tableName>`.
51277
+ *
51278
+ * The separator is unescaped (issue #1672), so a bare split of an id whose
51279
+ * table name carries a `|` returns a DIFFERENT table — `mydb|a|b` splits to
51280
+ * `mydb.a`, both halves non-empty, and a delete of it would hit the wrong
51281
+ * table. Such ids exist: a state-replay create warns and packs one anyway, and
51282
+ * binaries before the #1719 refusal recorded them. The recorded `DatabaseName`
51283
+ * disambiguates the id without re-deriving the identity from the bag: it is
51284
+ * used only when the id starts with it, and the table name is the remainder.
51285
+ *
51286
+ * `bags` are tried in order, so pass the one describing what was DEPLOYED
51287
+ * first. With no usable anchor only an id with exactly one separator decodes;
51288
+ * anything longer is ambiguous and returns `undefined`, the malformed-id arm
51289
+ * every caller already has.
51290
+ */
51291
+ function decodeTableId(physicalId, ...bags) {
51292
+ for (const bag of bags) {
51293
+ const databaseName = bag?.["DatabaseName"];
51294
+ if (typeof databaseName !== "string" || databaseName === "") continue;
51295
+ if (!physicalId.startsWith(`${databaseName}|`)) continue;
51296
+ const tableName = physicalId.slice(databaseName.length + 1);
51297
+ if (tableName !== "") return {
51298
+ databaseName,
51299
+ tableName
51300
+ };
51301
+ }
51302
+ const parts = physicalId.split("|");
51303
+ if (parts.length !== 2 || !parts[0] || !parts[1]) return void 0;
51304
+ return {
51305
+ databaseName: parts[0],
51306
+ tableName: parts[1]
51307
+ };
51308
+ }
51309
+ /**
51259
51310
  * Read a template-borne value that is about to be forwarded to a Glue read
51260
51311
  * API as a string.
51261
51312
  *
@@ -51585,8 +51636,9 @@ var GlueProvider = class {
51585
51636
  }
51586
51637
  async updateTable(logicalId, physicalId, resourceType, properties, previousProperties) {
51587
51638
  this.logger.debug(`Updating Glue Table ${logicalId}: ${physicalId}`);
51588
- const [databaseName, tableName] = physicalId.split("|");
51589
- if (!databaseName || !tableName) throw new ProvisioningError(compositeIdFormatMessage(GLUE_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
51639
+ const decoded = decodeTableId(physicalId, previousProperties, properties);
51640
+ if (!decoded) throw new ProvisioningError(compositeIdFormatMessage(GLUE_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
51641
+ const { databaseName, tableName } = decoded;
51590
51642
  const tableInput = properties["TableInput"];
51591
51643
  if (!tableInput) throw new ProvisioningError(`TableInput is required for Glue Table update ${logicalId}`, resourceType, logicalId, physicalId);
51592
51644
  const catalogId = properties["CatalogId"];
@@ -51621,11 +51673,12 @@ var GlueProvider = class {
51621
51673
  }
51622
51674
  async deleteTable(logicalId, physicalId, resourceType, properties, context) {
51623
51675
  this.logger.debug(`Deleting Glue Table ${logicalId}: ${physicalId}`);
51624
- const [databaseName, tableName] = physicalId.split("|");
51625
- if (!databaseName || !tableName) {
51676
+ const decoded = decodeTableId(physicalId, properties);
51677
+ if (!decoded) {
51626
51678
  this.logger.warn(compositeIdFormatMessage(GLUE_TABLE_ID_FORMAT, logicalId, physicalId, { skipping: true }));
51627
51679
  return compositeIdSkipResult();
51628
51680
  }
51681
+ const { databaseName, tableName } = decoded;
51629
51682
  const target = deleteCatalogId(properties);
51630
51683
  if (target.declaredButUnusable) this.logger.debug(`Glue Table ${logicalId}: CatalogId is not a usable value (likely an unresolved intrinsic), so DeleteTable targets ${describeCatalog(target.catalogId)}.`);
51631
51684
  try {
@@ -51897,9 +51950,12 @@ var GlueProvider = class {
51897
51950
  * downgrades through the shared `replayWarn`, since a reverse-replacement
51898
51951
  * re-create reads a STATE record the user cannot edit from the template.
51899
51952
  * - UPDATE passes a warn callback UNCONDITIONALLY (the `updateRoute`
51900
- * precedent — `update()` has no context, so it cannot tell a template
51901
- * push from the state-borne bag `drift --revert` and the rollback revert
51902
- * arm hand it), and then RETAINS the PREVIOUS side's block, which is why
51953
+ * precedent, decided when `update()` could not tell a template push
51954
+ * from the state-borne bag `drift --revert` and the rollback revert arm
51955
+ * hand it — since issue #3141 `UpdateContext.replayingState` plus
51956
+ * `desiredFromAwsReadback` can, and this arm was not re-decided — issue
51957
+ * #3728), and
51958
+ * then RETAINS the PREVIOUS side's block, which is why
51903
51959
  * `previousDatabaseInput` is threaded in. Omitting instead would ERASE a
51904
51960
  * live resource link, because `UpdateDatabase` replaces `DatabaseInput`
51905
51961
  * wholesale — the #1612 "UPDATE retains the previous value" row, reached
@@ -52112,7 +52168,7 @@ var GlueProvider = class {
52112
52168
  const catalogId = catalogIdForApi(properties?.["CatalogId"]);
52113
52169
  switch (resourceType) {
52114
52170
  case "AWS::Glue::Database": return this.readDatabase(physicalId, catalogId);
52115
- case "AWS::Glue::Table": return this.readTable(physicalId, catalogId);
52171
+ case "AWS::Glue::Table": return this.readTable(physicalId, catalogId, properties);
52116
52172
  default: return;
52117
52173
  }
52118
52174
  }
@@ -52175,9 +52231,10 @@ var GlueProvider = class {
52175
52231
  if (db.Name !== void 0) result["DatabaseName"] = db.Name;
52176
52232
  return result;
52177
52233
  }
52178
- async readTable(physicalId, catalogId) {
52179
- const [databaseName, tableName] = physicalId.split("|");
52180
- if (!databaseName || !tableName) return void 0;
52234
+ async readTable(physicalId, catalogId, properties) {
52235
+ const decoded = decodeTableId(physicalId, properties);
52236
+ if (!decoded) return void 0;
52237
+ const { databaseName, tableName } = decoded;
52181
52238
  let table;
52182
52239
  try {
52183
52240
  table = (await this.getClient().send(new GetTableCommand({
@@ -52421,8 +52478,19 @@ var GlueWorkflowProvider = class {
52421
52478
  }
52422
52479
  return null;
52423
52480
  }
52481
+ /**
52482
+ * The workflow ARN `GetTags` needs. The partition is derived from the
52483
+ * client's region (issue #1815): the literal `arn:aws:` is structurally valid
52484
+ * everywhere, so in `aws-cn` / `aws-us-gov` nothing rejected it — `GetTags`
52485
+ * was simply aimed at an ARN naming no workflow, and the best-effort catch
52486
+ * below reads a failure there as EMPTY tags. A commercial region still derives to `aws`,
52487
+ * so commercial output is unchanged byte for byte.
52488
+ */
52424
52489
  async buildWorkflowArn(workflowName) {
52425
- return `arn:aws:glue:${await this.getRegion()}:${await this.getAccountId()}:workflow/${workflowName}`;
52490
+ const region = await this.getRegion();
52491
+ const account = await this.getAccountId();
52492
+ const { partition } = derivePartitionAndUrlSuffix(region);
52493
+ return `arn:${partition}:glue:${region}:${account}:workflow/${workflowName}`;
52426
52494
  }
52427
52495
  async getRegion() {
52428
52496
  return await this.getClient().config.region() || this.providerRegion || "us-east-1";
@@ -52640,8 +52708,18 @@ function findIcebergTableInputKey(properties) {
52640
52708
  * must never call `this.create()` from inside its own `update()` the way ACM /
52641
52709
  * IAM / Lambda-permission / SNS-subscription do: those internal re-creates
52642
52710
  * forward `update()`'s `properties` — a STATE record during a rollback replay —
52643
- * and `update()` has no context parameter to carry the flag, so this refusal
52644
- * would fire on a replay with no way to detect it.
52711
+ * and pass no `CreateContext`, so this refusal would fire on a replay with no
52712
+ * way to detect it. (`update()` DOES take a context — an `UpdateContext` since
52713
+ * issue #1732 — and since issue #3141 that context carries its own
52714
+ * `replayingState`, set by the rollback executor's two revert arms. So the
52715
+ * information now reaches `update()`; what is missing is a re-create that
52716
+ * builds a `CreateContext` from it, and none of those providers does. An
52717
+ * earlier revision said `update()` had "no context parameter to carry the
52718
+ * flag" — issue #1999.) Were GlueProvider ever to re-create inside `update()`,
52719
+ * it would have to forward a replay signal into that `create()` —
52720
+ * `context.replayingState` on the rollback path — and decide separately what
52721
+ * this refusal means for the `desiredFromAwsReadback` bag `cdkd drift --revert`
52722
+ * hands it, since that path sets no `replayingState`.
52645
52723
  *
52646
52724
  * **Known bypass: the sticky Cloud Control route.** This is a GlueProvider
52647
52725
  * pre-flight, so it only runs on the SDK route. When a table's state record
@@ -52747,11 +52825,22 @@ function cleanCfnObject(obj) {
52747
52825
  }
52748
52826
  /**
52749
52827
  * Build the ARN for a Glue resource. Used by tag-fetch via
52750
- * `GetTagsCommand` which only accepts an ARN. Account id falls back
52751
- * to STS when not provided.
52828
+ * `GetTagsCommand` which only accepts an ARN, and by the Job / Crawler /
52829
+ * Trigger `applyTagDiff` as the `TagResource` / `UntagResource` target.
52830
+ * Account id falls back to STS when not provided.
52831
+ *
52832
+ * The partition is derived from the region (issue #1815). A hardcoded
52833
+ * `arn:aws:` is structurally valid everywhere, so in `aws-cn` / `aws-us-gov`
52834
+ * nothing rejected it: the tag MUTATION was aimed at an ARN naming no
52835
+ * resource, and the drift read's best-effort `GetTags` read the failure as
52836
+ * empty tags. A commercial region still derives to `aws`, so commercial output
52837
+ * is unchanged byte for byte.
52752
52838
  */
52753
52839
  async function buildGlueResourceArn(client, stsClient, resource, name, accountId) {
52754
- return `arn:aws:glue:${await client.config.region() || ambientRegion() || "us-east-1"}:${accountId ?? await resolveAccountId(stsClient)}:${resource}/${name}`;
52840
+ const region = await client.config.region() || ambientRegion() || "us-east-1";
52841
+ const account = accountId ?? await resolveAccountId(stsClient);
52842
+ const { partition } = derivePartitionAndUrlSuffix(region);
52843
+ return `arn:${partition}:glue:${region}:${account}:${resource}/${name}`;
52755
52844
  }
52756
52845
  async function resolveAccountId(stsClient) {
52757
52846
  const identity = await stsClient.send(new GetCallerIdentityCommand({}));
@@ -65583,13 +65672,13 @@ var NestedStackProvider = class {
65583
65672
  try {
65584
65673
  raw = fs.readFileSync(templatePath, "utf-8");
65585
65674
  } catch (err) {
65586
- throw new Error(`Failed to read nested template at ${displayAssemblyPath(templatePath)}: ${displaySafe(err instanceof Error ? err.message : String(err))}`);
65675
+ throw new Error(`Failed to read nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
65587
65676
  }
65588
65677
  let template;
65589
65678
  try {
65590
65679
  template = JSON.parse(raw);
65591
65680
  } catch (err) {
65592
- throw new Error(`Failed to parse nested template at ${displayAssemblyPath(templatePath)}: ${displaySafe(err instanceof Error ? err.message : String(err))}`);
65681
+ throw new Error(`Failed to parse nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
65593
65682
  }
65594
65683
  const grandchildTemplates = this.indexGrandchildTemplates(template, templatePath);
65595
65684
  if (assetRedirect) {
@@ -68503,12 +68592,12 @@ function readNestedTemplate(templatePath) {
68503
68592
  try {
68504
68593
  raw = fs.readFileSync(templatePath, "utf-8");
68505
68594
  } catch (err) {
68506
- throw new Error(`Failed to read nested template at ${templatePath}: ${err instanceof Error ? err.message : String(err)}`);
68595
+ throw new Error(`Failed to read nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
68507
68596
  }
68508
68597
  try {
68509
68598
  return JSON.parse(raw);
68510
68599
  } catch (err) {
68511
- throw new Error(`Failed to parse nested template at ${templatePath}: ${err instanceof Error ? err.message : String(err)}`);
68600
+ throw new Error(`Failed to parse nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
68512
68601
  }
68513
68602
  }
68514
68603
  /**
@@ -68527,9 +68616,9 @@ function indexNestedChildTemplates(template, templatePath) {
68527
68616
  if (resource?.Type !== "AWS::CloudFormation::Stack") continue;
68528
68617
  const assetPath = resource.Metadata?.["aws:asset:path"];
68529
68618
  if (typeof assetPath !== "string" || assetPath.length === 0) continue;
68530
- if (isAbsoluteCrossPlatform(assetPath)) throw new Error(`Nested stack '${displaySafe(logicalId)}' has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which is absolute. CDK emits relative asset paths for nested templates; an absolute path indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to load.`);
68619
+ if (isAbsoluteCrossPlatform(assetPath)) throw new Error(`Nested stack ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which is absolute. CDK emits relative asset paths for nested templates; an absolute path indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to load.`);
68531
68620
  const resolved = resolveAssemblyPath(dir, assetPath);
68532
- if (!resolved.contained) throw new Error(`Nested stack '${displaySafe(logicalId)}' has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`);
68621
+ if (!resolved.contained) throw new Error(`Nested stack ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`);
68533
68622
  result[logicalId] = resolved.path;
68534
68623
  }
68535
68624
  return result;
@@ -68685,7 +68774,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
68685
68774
  const tokenParameterNames = new Set(Object.entries(parameters ?? {}).filter(([, value]) => carriesDynamicReference(value)).map(([name]) => name));
68686
68775
  for (const name of tokenParameterNames) {
68687
68776
  const declaredType = (template.Parameters?.[name])?.Type;
68688
- if (typeof declaredType === "string" && parameterTypeMayLoseSecretIdentity(declaredType)) logger.warn(`Stack ${stripControlChars(stackName)}: parameter '${stripControlChars(name)}' is declared 'Type: ${stripControlChars(declaredType)}' and is fed a secret dynamic reference. 'cdkd deploy' refuses this when the coercion actually destroys the plaintext (a comma-bearing secret in a list-typed parameter) — declare it 'Type: String' — and this diff compares the unresolved reference, shaped by the declared type only where that keeps every part of it a string.`);
68777
+ if (typeof declaredType === "string" && parameterTypeMayLoseSecretIdentity(declaredType)) logger.warn(`Stack ${displayStackName(stackName)}: parameter ${displayIdent(name)} is declared Type: ${displayIdent(declaredType)} and is fed a secret dynamic reference. 'cdkd deploy' refuses this when the coercion actually destroys the plaintext (a comma-bearing secret in a list-typed parameter) — declare it 'Type: String' — and this diff compares the unresolved reference, shaped by the declared type only where that keeps every part of it a string.`);
68689
68778
  }
68690
68779
  try {
68691
68780
  const userParameters = {};
@@ -68701,7 +68790,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
68701
68790
  }
68702
68791
  parametersBound = true;
68703
68792
  } catch (error) {
68704
- logger.debug(`Diff parameter binding for stack ${stackName} is partial: ${error instanceof Error ? error.message : String(error)}`);
68793
+ logger.debug(`Diff parameter binding for stack ${displayStackName(stackName)} is partial: ${error instanceof Error ? error.message : String(error)}`);
68705
68794
  }
68706
68795
  let effectiveTemplate = template;
68707
68796
  let conditions;
@@ -68716,7 +68805,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
68716
68805
  });
68717
68806
  effectiveTemplate = new TemplateParser().filterResourcesByCondition(template, conditions);
68718
68807
  } catch (error) {
68719
- logger.debug(`Diff condition evaluation for stack ${stackName} skipped: ${error instanceof Error ? error.message : String(error)}`);
68808
+ logger.debug(`Diff condition evaluation for stack ${displayStackName(stackName)} skipped: ${error instanceof Error ? error.message : String(error)}`);
68720
68809
  }
68721
68810
  const resolveFn = (value) => intrinsicResolver.resolve(value, {
68722
68811
  template: effectiveTemplate,
@@ -68929,10 +69018,10 @@ async function buildDiffTree(args) {
68929
69018
  if (resource?.Type !== "AWS::CloudFormation::Stack") continue;
68930
69019
  templateChildIds.add(logicalId);
68931
69020
  const childTemplatePath = nestedTemplates[logicalId];
68932
- if (!childTemplatePath) throw new Error(`Nested template file not found for ${NESTED_STACK_RESOURCE_TYPE} '${logicalId}' under stack '${stackName}'. Verify the synth output emits Metadata['aws:asset:path'] on this resource (CDK 2.x cdk.NestedStack does so by default), then re-run synth.`);
69021
+ if (!childTemplatePath) throw new Error(`Nested template file not found for ${NESTED_STACK_RESOURCE_TYPE} ${displayIdent(logicalId)} under stack ${displayStackName(stackName)}. Verify the synth output emits Metadata['aws:asset:path'] on this resource (CDK 2.x cdk.NestedStack does so by default), then re-run synth.`);
68933
69022
  const childStackName = `${stackName}~${logicalId}`;
68934
69023
  const resolvedChildPath = path.resolve(childTemplatePath);
68935
- if (ancestorTemplatePaths?.has(resolvedChildPath) === true) throw new Error(`Nested stack '${displaySafe(logicalId)}' under stack '${displaySafe(stackName)}' resolves to nested template ${displayAssemblyPath(resolvedChildPath)}, which is already being diffed higher up the same nesting chain. Its Metadata['aws:asset:path'] closes a cycle; CDK emits an acyclic nested template tree, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to diff.`);
69024
+ if (ancestorTemplatePaths?.has(resolvedChildPath) === true) throw new Error(`Nested stack ${displayIdent(logicalId)} under stack ${displayStackName(stackName)} resolves to nested template ${displayAssemblyPath(resolvedChildPath)}, which is already being diffed higher up the same nesting chain. Its Metadata['aws:asset:path'] closes a cycle; CDK emits an acyclic nested template tree, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to diff.`);
68936
69025
  const childAncestorTemplatePaths = new Set(ancestorTemplatePaths ?? []).add(resolvedChildPath);
68937
69026
  const childTemplate = readNestedTemplate(childTemplatePath);
68938
69027
  if (assetRedirect) rewriteTemplateAssetReferences(childTemplate, assetRedirect);
@@ -69028,7 +69117,7 @@ function collectCcApiRoutes(template, state) {
69028
69117
  if (!resource) continue;
69029
69118
  if (resource.Type === "AWS::CDK::Metadata") continue;
69030
69119
  if (resource.Type === "AWS::CloudFormation::Stack") continue;
69031
- const drops = findActionableSilentDrops(resource.Type, resource.Properties, EMPTY_ALLOW_SET);
69120
+ const drops = findActionableSilentDrops(resource.Type, resource.Properties, EMPTY_ALLOW_SET, state.resources[logicalId]?.properties);
69032
69121
  if (drops.length > 0) {
69033
69122
  hits.set(logicalId, drops.map((d) => d.property));
69034
69123
  continue;
@@ -69246,7 +69335,7 @@ function renderChangeLines(changes, logFn, ccApiRoutes, adoptedOrphans) {
69246
69335
  logFn(` [~] ${logicalId} (${change.resourceType})${annotateAdoption(logicalId)}${annotateRouting(logicalId)}`);
69247
69336
  if (change.propertyChanges && change.propertyChanges.length > 0) for (const propChange of change.propertyChanges) {
69248
69337
  const requiresReplace = propChange.requiresReplacement ? " [requires replacement]" : "";
69249
- const propagated = propChange.replacementPropagated ? " [replacement propagated]" : "";
69338
+ const propagated = propChange.replacementPropagated ? " [replacement propagated]" : propChange.inPlacePropagated ? " [attribute propagated]" : "";
69250
69339
  const indent = " ";
69251
69340
  const [oldFiltered, newFiltered] = stripUnchangedValuePair(propChange.oldValue, propChange.newValue);
69252
69341
  const oldStr = renderDiffValue(propChange.oldValue, oldFiltered, indent, false);
@@ -69672,7 +69761,7 @@ function describeFailure(err) {
69672
69761
  * thing the paragraph above rejects.
69673
69762
  */
69674
69763
  function scrubStacksFailedError(failures) {
69675
- return new ScrubRefusalError(`${failures.length} stack(s) could not be scrubbed: ${failures.map((f) => f.stackName).join(", ")}. Each one's reason was logged as it happened — see the 'Scrub of <stack> failed:' line above for it.`, "SCRUB_STACKS_FAILED");
69764
+ return new ScrubRefusalError(`${failures.length} stack(s) could not be scrubbed: ${failures.map((f) => displayStackName(f.stackName)).join(", ")}. Each one's reason was logged as it happened — see the 'Scrub of <stack> failed:' line above for it.`, "SCRUB_STACKS_FAILED");
69676
69765
  }
69677
69766
  /**
69678
69767
  * Which of `entries` this stack's post-scrub `outputs` bag disagrees with.
@@ -69751,8 +69840,8 @@ function planExportIndexRepair(entries, stackName, producerRegion, outputs) {
69751
69840
  */
69752
69841
  function exportIndexIncompleteError(unwritten, unreadable, dryRun) {
69753
69842
  const parts = [dryRun ? "no state written (--dry-run)" : "state.json complete"];
69754
- if (unwritten.length > 0) parts.push(`${unwritten.length} exports index entr${unwritten.length === 1 ? "y" : "ies"} unwritten (${unwritten.map((u) => `${u.shown} in ${u.region}`).join(", ")})`);
69755
- if (unreadable.length > 0) parts.push(`${unreadable.length} region(s) whose exports index could not be read (${unreadable.map((u) => `${u.region}: ${u.reason}`).join("; ")})`);
69843
+ if (unwritten.length > 0) parts.push(`${unwritten.length} exports index entr${unwritten.length === 1 ? "y" : "ies"} unwritten (${unwritten.map((u) => `${u.shown} in ${displayIdent(u.region)}`).join(", ")})`);
69844
+ if (unreadable.length > 0) parts.push(`${unreadable.length} region(s) whose exports index could not be read (${unreadable.map((u) => `${displayIdent(u.region)}: ${u.reason}`).join("; ")})`);
69756
69845
  return new ScrubRefusalError(`${parts.join("; ")}. Re-run the same command once the cause is cleared: each entry is written only while its value differs from the producer's state.outputs, so a re-run writes the remainder and leaves the rest alone.`, "SCRUB_EXPORT_INDEX_INCOMPLETE");
69757
69846
  }
69758
69847
  /**
@@ -69983,6 +70072,7 @@ async function scrubCommand(stacks, options) {
69983
70072
  const indexUnwritten = [];
69984
70073
  const indexUnreadable = [];
69985
70074
  for (const stack of targetStacks) {
70075
+ const shownStack = displayStackName(stack.stackName);
69986
70076
  const stackRegion = stack.region || region;
69987
70077
  let scrubbed;
69988
70078
  try {
@@ -69994,7 +70084,7 @@ async function scrubCommand(stacks, options) {
69994
70084
  });
69995
70085
  } catch (err) {
69996
70086
  failures.push({ stackName: stack.stackName });
69997
- logger.error(`Scrub of ${stack.stackName} failed: ${describeFailure(err)}`);
70087
+ logger.error(`Scrub of ${shownStack} failed: ${describeFailure(err)}`);
69998
70088
  if (err instanceof Error && err.stack) logger.debug("Stack trace:", err.stack);
69999
70089
  continue;
70000
70090
  }
@@ -70007,8 +70097,8 @@ async function scrubCommand(stacks, options) {
70007
70097
  const named = (exportName) => {
70008
70098
  const shown = scrubbed.exportNameDisplay(exportName);
70009
70099
  switch (shown.kind) {
70010
- case "safe": return `'${shown.text}'`;
70011
- case "masked": return `(masked: "${shown.text}")`;
70100
+ case "safe": return displayIdent(shown.text);
70101
+ case "masked": return `(masked: ${displayIdent(shown.text)})`;
70012
70102
  case "withheld": return "(name withheld: it holds a secret this run recorded)";
70013
70103
  }
70014
70104
  };
@@ -70019,14 +70109,14 @@ async function scrubCommand(stacks, options) {
70019
70109
  });
70020
70110
  for (const finding of repair.findings) if (finding.kind === "converge") {
70021
70111
  indexConverged++;
70022
- if (!options.dryRun && unwrittenNames.has(finding.exportName)) logger.warn(`Exports index entry ${named(finding.exportName)} (${stackRegion}) differs from ${stack.stackName}'s state.outputs and could NOT be written — it keeps the value it holds.`);
70112
+ if (!options.dryRun && unwrittenNames.has(finding.exportName)) logger.warn(`Exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) differs from ${shownStack}'s state.outputs and could NOT be written — it keeps the value it holds.`);
70023
70113
  else {
70024
70114
  totalIndexEntriesConverged++;
70025
- logger.info(`${options.dryRun ? "Would converge" : "Converged"} exports index entry ${named(finding.exportName)} (${stackRegion}) to ${stack.stackName}'s state.outputs value.`);
70115
+ logger.info(`${options.dryRun ? "Would converge" : "Converged"} exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) to ${shownStack}'s state.outputs value.`);
70026
70116
  }
70027
70117
  } else {
70028
70118
  totalIndexEntriesAbsent++;
70029
- logger.warn(`Exports index entry ${named(finding.exportName)} (${stackRegion}) is published by ${stack.stackName}, whose state.outputs has no key of that name — nothing was written for it and it keeps the value it holds. Redeploy ${stack.stackName} to rewrite the index from its own outputs.`);
70119
+ logger.warn(`Exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) is published by ${shownStack}, whose state.outputs has no key of that name — nothing was written for it and it keeps the value it holds. Redeploy ${shownStack} to rewrite the index from its own outputs.`);
70030
70120
  }
70031
70121
  } catch (err) {
70032
70122
  if (err instanceof ScrubIndexInvariantError) throw err;
@@ -70036,28 +70126,28 @@ async function scrubCommand(stacks, options) {
70036
70126
  region: stackRegion,
70037
70127
  reason
70038
70128
  });
70039
- logger.error(`Exports index for ${stackRegion} could not be read (first seen while scrubbing ${stack.stackName}): ${reason}`);
70129
+ logger.error(`Exports index for ${displayIdent(stackRegion)} could not be read (first seen while scrubbing ${shownStack}): ${reason}`);
70040
70130
  }
70041
70131
  }
70042
70132
  if (scrubbed.recordsChanged > 0) {
70043
70133
  totalStacksScrubbed++;
70044
- logger.info(`${options.dryRun ? "Would scrub" : "Scrubbed"} ${scrubbed.recordsChanged} resource record(s) in ${stack.stackName}`);
70045
- } else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${stack.stackName}`);
70134
+ logger.info(`${options.dryRun ? "Would scrub" : "Scrubbed"} ${scrubbed.recordsChanged} resource record(s) in ${shownStack}`);
70135
+ } else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${shownStack}`);
70046
70136
  if (scrubbed.malformedResources) malformedRecords.push(stack.stackName);
70047
70137
  if (scrubbed.malformedOutputs) malformedOutputRecords.push(stack.stackName);
70048
70138
  if (scrubbed.malformedOrphans || scrubbed.malformedOrphanRows) malformedOrphanRecords.push(stack.stackName);
70049
70139
  if (scrubbed.unverifiableLeaves > 0) {
70050
70140
  totalStacksWithUnverifiableLeaves++;
70051
- logger.warn(`${scrubbed.unverifiableLeaves} scan(s) in ${stack.stackName} were ABANDONED mid-value because a {{resolve:...}} reference could not be resolved (see the warnings above). The resolver stops at the first failing token, so a real secret after it in the same value recorded no needle — this stack is not reported clean. The count is per abandoned SCAN, not per secret: one record can contribute more than once (an output whose Export.Name and Value both abandon), and one abandoned scan can hide several unexamined leaves.`);
70141
+ logger.warn(`${scrubbed.unverifiableLeaves} scan(s) in ${shownStack} were ABANDONED mid-value because a {{resolve:...}} reference could not be resolved (see the warnings above). The resolver stops at the first failing token, so a real secret after it in the same value recorded no needle — this stack is not reported clean. The count is per abandoned SCAN, not per secret: one record can contribute more than once (an output whose Export.Name and Value both abandon), and one abandoned scan can hide several unexamined leaves.`);
70052
70142
  }
70053
70143
  if (scrubbed.unverifiableProducerRecords > 0) damagedProducerStacks.push(stack.stackName);
70054
70144
  if (scrubbed.unverifiableReads > 0) {
70055
70145
  totalStacksWithUnverifiableReads++;
70056
- logger.warn(`${scrubbed.unverifiableReads} cross-stack read(s) in ${stack.stackName} could NOT be verified (see the warnings above for which, and why) — so this stack is not reported clean.`);
70146
+ logger.warn(`${scrubbed.unverifiableReads} cross-stack read(s) in ${shownStack} could NOT be verified (see the warnings above for which, and why) — so this stack is not reported clean.`);
70057
70147
  }
70058
70148
  if (scrubbed.secretBearingKeys > 0) {
70059
70149
  totalStacksWithUnscrubbableKeys++;
70060
- logger.warn(`${scrubbed.secretBearingKeys} output KEY(s) in ${stack.stackName} hold plaintext and CANNOT be scrubbed — rename the Export.Name and redeploy (see the warning above).`);
70150
+ logger.warn(`${scrubbed.secretBearingKeys} output KEY(s) in ${shownStack} hold plaintext and CANNOT be scrubbed — rename the Export.Name and redeploy (see the warning above).`);
70061
70151
  }
70062
70152
  }
70063
70153
  for (const [indexRegion, store] of exportIndexStores) {
@@ -70071,7 +70161,7 @@ async function scrubCommand(stacks, options) {
70071
70161
  region: indexRegion,
70072
70162
  reason
70073
70163
  });
70074
- logger.error(`Exports index for ${indexRegion} could not be read for the coverage report: ${reason}`);
70164
+ logger.error(`Exports index for ${displayIdent(indexRegion)} could not be read for the coverage report: ${reason}`);
70075
70165
  continue;
70076
70166
  }
70077
70167
  if (!entries) continue;
@@ -70079,7 +70169,7 @@ async function scrubCommand(stacks, options) {
70079
70169
  const unexamined = [...entries.keys()].filter((name) => !examined.has(name));
70080
70170
  if (unexamined.length === 0) continue;
70081
70171
  totalIndexEntriesUnexamined += unexamined.length;
70082
- logger.info(`Exports index (${indexRegion}): ${unexamined.length} entr${unexamined.length === 1 ? "y is" : "ies are"} published by a producer this run did not scrub, so nothing here read ${unexamined.length === 1 ? "its" : "their"} value. Coverage composes across the apps sharing this bucket and region — run each app's own cdkd scrub to reach its entries.`);
70172
+ logger.info(`Exports index (${displayIdent(indexRegion)}): ${unexamined.length} entr${unexamined.length === 1 ? "y is" : "ies are"} published by a producer this run did not scrub, so nothing here read ${unexamined.length === 1 ? "its" : "their"} value. Coverage composes across the apps sharing this bucket and region — run each app's own cdkd scrub to reach its entries.`);
70083
70173
  }
70084
70174
  if (totalStacksScrubbed === 0 && totalStacksWithUnscrubbableKeys === 0 && totalStacksWithUnverifiableReads === 0 && totalStacksWithUnverifiableLeaves === 0 && totalIndexEntriesConverged === 0 && indexUnwritten.length === 0 && indexUnreadable.length === 0 && malformedRecords.length === 0 && malformedOutputRecords.length === 0 && malformedOrphanRecords.length === 0) {
70085
70175
  if (failures.length === 0) {
@@ -70370,8 +70460,8 @@ var ScrubResolvers = class {
70370
70460
  * Never the resolved value: nothing has been resolved for this reference, and
70371
70461
  * the expression is the same string `state.json` already stores in the clear.
70372
70462
  */
70373
- function regionAmbiguousScrubSecretError(origin, stackName, secretName, foreignProducerRegions, stackRegion) {
70374
- return new ScrubRefusalError(`Scrub of ${stackName} cannot re-resolve the secret reference '${secretName}' in ${origin}: the reference carries no region of its own, and this stack read across a region boundary (producer region(s) on record: ${foreignProducerRegions.join(", ")}), so it may have been resolved in one of those rather than in '${stackRegion}'. A secret of the same name in two regions is two independent values, so scrub would look for the WRONG plaintext — leaving the real one in state while reporting the stack clean, and using the foreign value as a needle that can rewrite an unrelated literal. Refusing instead. Spell the reference as a full ARN, which names its region and is resolved there, then re-run 'cdkd scrub'.`, "SCRUB_SECRET_REGION_AMBIGUOUS");
70463
+ function regionAmbiguousScrubSecretError(origin, stackName, secretName, foreignProducerRegions, stackRegion, secrets) {
70464
+ return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} cannot re-resolve the secret reference ${maskedIdent(secretName, secrets)} in ${origin}: the reference carries no region of its own, and this stack read across a region boundary (producer region(s) on record: ${foreignProducerRegions.map((r) => displayIdent(r)).join(", ")}), so it may have been resolved in one of those rather than in ${displayIdent(stackRegion)}. A secret of the same name in two regions is two independent values, so scrub would look for the WRONG plaintext — leaving the real one in state while reporting the stack clean, and using the foreign value as a needle that can rewrite an unrelated literal. Refusing instead. Spell the reference as a full ARN, which names its region and is resolved there, then re-run 'cdkd scrub'.`, "SCRUB_SECRET_REGION_AMBIGUOUS");
70375
70465
  }
70376
70466
  /**
70377
70467
  * The refusal a `named-region` reference raises when its OWN region cannot
@@ -70389,7 +70479,7 @@ function regionAmbiguousScrubSecretError(origin, stackName, secretName, foreignP
70389
70479
  * into, so a value recorded a moment earlier in this very leaf is covered.
70390
70480
  */
70391
70481
  function unresolvableForeignScrubSecretError(origin, stackName, secretName, region, cause, secrets) {
70392
- return new ScrubRefusalError(`Scrub of ${stackName} could not resolve the secret reference '${secretName}' in ${origin} in the region its ARN names ('${region}'): ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than resolving it in the stack's own region, which would look for a different secret's value and report the stack clean over state that still holds the plaintext.`, "SCRUB_CROSS_REGION_SECRET_UNRESOLVED");
70482
+ return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} could not resolve the secret reference ${maskedIdent(secretName, secrets)} in ${origin} in the region its ARN names (${displayIdent(region)}): ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than resolving it in the stack's own region, which would look for a different secret's value and report the stack clean over state that still holds the plaintext.`, "SCRUB_CROSS_REGION_SECRET_UNRESOLVED");
70393
70483
  }
70394
70484
  /**
70395
70485
  * The literal that OPENS a dynamic reference. Used as the CHEAP pre-filter that
@@ -70537,17 +70627,18 @@ function isAssembledSecretReference(leaf, secretTokens) {
70537
70627
  * together out of a plaintext is not.
70538
70628
  */
70539
70629
  async function resolveForeignRegionTokens(leaf, stackName, ctx) {
70630
+ const shownStackName = displayStackName(stackName);
70540
70631
  const tokens = dynamicReferenceTokens(leaf);
70541
70632
  if (isAssembledSecretReference(leaf, tokens.filter(isSecretReferenceToken))) return leaf;
70542
70633
  const verdicts = tokens.map((token) => [token, classifyReplaySecretRegion(token, ctx.stackRegion, ctx.producerRegions)]);
70543
- for (const [, verdict] of verdicts) if (verdict.kind === "ambiguous") throw regionAmbiguousScrubSecretError(ctx.origin, stackName, verdict.secretName, verdict.foreignProducerRegions, ctx.stackRegion);
70634
+ for (const [, verdict] of verdicts) if (verdict.kind === "ambiguous") throw regionAmbiguousScrubSecretError(ctx.origin, stackName, verdict.secretName, verdict.foreignProducerRegions, ctx.stackRegion, ctx.recordedSecretValues);
70544
70635
  if (!verdicts.some(([, verdict]) => verdict.kind === "named-region")) return leaf;
70545
70636
  const localTokens = [];
70546
70637
  let out = "";
70547
70638
  let cursor = 0;
70548
70639
  for (const [token, verdict] of verdicts) {
70549
70640
  const at = leaf.indexOf(token, cursor);
70550
- if (at < 0) throw new ScrubRefusalError(`Scrub of ${stackName} could not locate a scanned dynamic reference in ${ctx.origin}, in the value it was scanned from. Refusing rather than resolving it in '${ctx.stackRegion}', which would be the wrong region for a reference that names another one. This is an internal invariant failure — please report it with the resource type and property path.`, "SCRUB_SECRET_TOKEN_SCAN_MISMATCH");
70641
+ if (at < 0) throw new ScrubRefusalError(`Scrub of ${shownStackName} could not locate a scanned dynamic reference in ${ctx.origin}, in the value it was scanned from. Refusing rather than resolving it in ${displayIdent(ctx.stackRegion)}, which would be the wrong region for a reference that names another one. This is an internal invariant failure — please report it with the resource type and property path.`, "SCRUB_SECRET_TOKEN_SCAN_MISMATCH");
70551
70642
  out += leaf.slice(cursor, at);
70552
70643
  if (verdict.kind === "named-region") {
70553
70644
  const resolver = ctx.resolvers.forRegion(verdict.region);
@@ -70568,7 +70659,7 @@ async function resolveForeignRegionTokens(leaf, stackName, ctx) {
70568
70659
  }
70569
70660
  out += leaf.slice(cursor);
70570
70661
  const surviving = dynamicReferenceTokens(out);
70571
- if (surviving.length !== localTokens.length || surviving.some((token, i) => token !== localTokens[i])) throw new ScrubRefusalError(`Scrub of ${stackName} refused ${ctx.origin}: resolving a cross-region secret reference produced a value that is itself dynamic-reference shaped, which the stack's own resolver would then resolve as if it were a reference of this stack's. Refusing rather than passing it on.`, "SCRUB_SECRET_RESOLUTION_REINTRODUCED_TOKEN");
70662
+ if (surviving.length !== localTokens.length || surviving.some((token, i) => token !== localTokens[i])) throw new ScrubRefusalError(`Scrub of ${shownStackName} refused ${ctx.origin}: resolving a cross-region secret reference produced a value that is itself dynamic-reference shaped, which the stack's own resolver would then resolve as if it were a reference of this stack's. Refusing rather than passing it on.`, "SCRUB_SECRET_RESOLUTION_REINTRODUCED_TOKEN");
70572
70663
  return out;
70573
70664
  }
70574
70665
  /**
@@ -70875,7 +70966,7 @@ function effectiveIntrinsicKey(node) {
70875
70966
  * can carry one, and the map is the same one this pass records into.
70876
70967
  */
70877
70968
  function unresolvableCrossStackReadError(origin, stackName, intrinsic, path, cause, secrets) {
70878
- return new ScrubRefusalError(`Scrub of ${stackName} could not resolve the ${intrinsic} in ${origin}${path ? ` at ${path}` : ""}: ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than continuing: the value that reference carries may be a secret, and scrub would then have no plaintext to look for — reporting the stack clean over state that still holds it. Deploy the producer stack (or correct the reference) and re-run 'cdkd scrub'.`, "SCRUB_CROSS_STACK_READ_UNRESOLVED");
70969
+ return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} could not resolve the ${intrinsic} in ${origin}${path ? ` at ${maskedIdent(path, secrets)}` : ""}: ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than continuing: the value that reference carries may be a secret, and scrub would then have no plaintext to look for — reporting the stack clean over state that still holds it. Deploy the producer stack (or correct the reference) and re-run 'cdkd scrub'.`, "SCRUB_CROSS_STACK_READ_UNRESOLVED");
70879
70970
  }
70880
70971
  /**
70881
70972
  * The two sentences the plaintext-producer refusal is built from: what the
@@ -70919,8 +71010,10 @@ function unresolvableCrossStackReadError(origin, stackName, intrinsic, path, cau
70919
71010
  function scrubRefusalWording(verdict, loggedExportKey, loggedProducerStack, loggedVia) {
70920
71011
  const chain = dedupePreservingOrder(loggedVia, "first");
70921
71012
  const chainRoot = chain[chain.length - 1];
70922
- const through = chain.length > 1 ? ` (through ${chain.slice(0, -1).map((s) => `'${s}'`).join(", ")})` : "";
70923
- const templateClaim = verdict.kind === "declared" ? `declares '${loggedExportKey}' from a {{resolve:...}} expression` : verdict.kind === "chained" ? chainRoot !== void 0 ? `publishes '${loggedExportKey}' by RE-EXPORTING a value that '${chainRoot}' declares from a {{resolve:...}} expression${through}` : `publishes '${loggedExportKey}' by RE-EXPORTING a value another stack of this app declares from a {{resolve:...}} expression` : chainRoot !== void 0 ? `publishes at least one output that RE-EXPORTS a value '${chainRoot}' declares from a {{resolve:...}} expression${through} (this run could not match '${loggedExportKey}' to a declared output, so it cannot say which)` : `publishes at least one output from a {{resolve:...}} expression (this run could not match '${loggedExportKey}' to a declared output, so it cannot say which)`;
71013
+ const shownKey = displayIdent(loggedExportKey);
71014
+ const shownRoot = chainRoot === void 0 ? void 0 : displayStackName(chainRoot);
71015
+ const through = chain.length > 1 ? ` (through ${chain.slice(0, -1).map((s) => displayStackName(s)).join(", ")})` : "";
71016
+ const templateClaim = verdict.kind === "declared" ? `declares ${shownKey} from a {{resolve:...}} expression` : verdict.kind === "chained" ? chainRoot !== void 0 ? `publishes ${shownKey} by RE-EXPORTING a value that ${shownRoot} declares from a {{resolve:...}} expression${through}` : `publishes ${shownKey} by RE-EXPORTING a value another stack of this app declares from a {{resolve:...}} expression` : chainRoot !== void 0 ? `publishes at least one output that RE-EXPORTS a value ${shownRoot} declares from a {{resolve:...}} expression${through} (this run could not match ${shownKey} to a declared output, so it cannot say which)` : `publishes at least one output from a {{resolve:...}} expression (this run could not match ${shownKey} to a declared output, so it cannot say which)`;
70924
71017
  const scrubOrder = dedupePreservingOrder([...chain].reverse().concat(loggedProducerStack), "last");
70925
71018
  const remedyCommands = scrubOrder.map((name) => `Scrub with: ${pasteableCommand("cdkd scrub", [{
70926
71019
  value: name,
@@ -70993,7 +71086,7 @@ function plaintextProducerCrossStackReadError(origin, stackName, intrinsic, path
70993
71086
  const loggedExportKey = maskSecretsInText(exportKey, secrets);
70994
71087
  const loggedProducerStack = maskSecretsInText(producerStack, secrets);
70995
71088
  const { templateClaim, remedy, remedyCommands } = scrubRefusalWording(verdict, loggedExportKey, loggedProducerStack, verdict.via.map((s) => maskSecretsInText(s, secrets)));
70996
- return new ScrubRefusalError(`Scrub of ${stackName} resolved the ${intrinsic} in ${origin}${path ? ` at ${path}` : ""} to a PLAINTEXT value: the producer stack '${loggedProducerStack}' ${templateClaim}, but its own state still stores the resolved plaintext rather than that expression. scrub has no expression to write in this stack's place, so it cannot redact the imported secret and must not report this stack clean. ${remedy}, then re-run scrub for this stack — the read will then return the expression and this stack is scrubbed normally.\n${remedyCommands.join("\n")}\nThen re-run: ${pasteableCommand("cdkd scrub", [{
71089
+ return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} resolved the ${intrinsic} in ${origin}${path ? ` at ${maskedIdent(path, secrets)}` : ""} to a PLAINTEXT value: the producer stack ${displayStackName(loggedProducerStack)} ${templateClaim}, but its own state still stores the resolved plaintext rather than that expression. scrub has no expression to write in this stack's place, so it cannot redact the imported secret and must not report this stack clean. ${remedy}, then re-run scrub for this stack — the read will then return the expression and this stack is scrubbed normally.\n${remedyCommands.join("\n")}\nThen re-run: ${pasteableCommand("cdkd scrub", [{
70997
71090
  value: stackName,
70998
71091
  hole: "stack",
70999
71092
  opts: { patternMatched: true }
@@ -71445,6 +71538,16 @@ function isNamelessDynamicReferenceFailure(err) {
71445
71538
  return isNamelessDynamicReferenceError(err);
71446
71539
  }
71447
71540
  /**
71541
+ * An assembly-chosen NAME (a logical id, a property or output name, a property
71542
+ * path, a secret reference's name) rendered into scrub's prose: MASKED FIRST,
71543
+ * then bounded (go-to-k/cdkd#3638). `displayIdent` JSON-escapes, blanks
71544
+ * non-ASCII and cuts at 255, any of which would stop a recorded plaintext
71545
+ * embedded in the name from matching a mask that ran over the rendered text.
71546
+ */
71547
+ function maskedIdent(value, secrets) {
71548
+ return displayIdent(maskSecretsInText(value, secrets));
71549
+ }
71550
+ /**
71448
71551
  * The per-record line each counting site prints. Deliberately ONE SHORT
71449
71552
  * SENTENCE, and that is a fix rather than a style choice: the first cut emitted
71450
71553
  * a ~440-character paragraph PER RECORD at default verbosity, and the arm it
@@ -71459,11 +71562,9 @@ function isNamelessDynamicReferenceFailure(err) {
71459
71562
  * it through `maskSecretsInText`, and a resolver error echoes what it was
71460
71563
  * handed — which, after `pinCrossRegionSecrets`, can be a foreign plaintext.
71461
71564
  *
71462
- * RESIDUAL on the `subject` the call sites pass. They compose
71463
- * `maskSecretsInText(... displaySafe(id) ...)` — sanitise, then mask — and
71464
- * `displaySafe` REPLACES a control character with a space rather than deleting
71465
- * it, so it cannot JOIN a split needle (the go-to-k/cdkd#2874 direction) but it
71466
- * can BREAK one, and it leaves `U+200B`-`U+200D` / `U+FEFF` untouched. A secret
71565
+ * The `subject` the call sites pass renders each name through
71566
+ * {@link maskedIdent} — masked, then bounded — so bounding cannot break a needle.
71567
+ * RESIDUAL: the mask sees only what this run has recorded SO FAR, and a secret
71467
71568
  * would have to sit inside a template logical id or Outputs key to be reachable,
71468
71569
  * which is why `secretSafeKeyDisplay` is not used here — that one is for RESOLVED
71469
71570
  * state-bag keys. Recorded rather than closed: go-to-k/cdkd#3178 security review.
@@ -71850,6 +71951,7 @@ var SharedEntriesSecrets = class extends Map {
71850
71951
  */
71851
71952
  function makeCrossStackPrePass(deps) {
71852
71953
  const { stackName, resolver, producerTemplates, findings, logger } = deps;
71954
+ const shownStackName = displayStackName(stackName);
71853
71955
  const exportOwners = buildExportOwnerIndex(producerTemplates);
71854
71956
  const verdicts = /* @__PURE__ */ new Map();
71855
71957
  /**
@@ -72004,26 +72106,27 @@ function makeCrossStackPrePass(deps) {
72004
72106
  */
72005
72107
  const storedProducerValue = async (producer, backend, nodeCanRefuse) => {
72006
72108
  if (!backend) return void 0;
72109
+ const shownProducer = displayStackName(maskSecretsInText(producer.stack, secrets));
72007
72110
  let loaded;
72008
72111
  try {
72009
72112
  loaded = await backend.getState(producer.stack, producer.region);
72010
72113
  } catch (err) {
72011
- logger.debug(`Scrub of ${stackName}: could not re-read producer '${maskSecretsInText(producer.stack, secrets)}' (${producer.region}) to classify its stored value: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`);
72114
+ logger.debug(`Scrub of ${shownStackName}: could not re-read producer ${shownProducer} (${displayIdent(producer.region)}) to classify its stored value: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`);
72012
72115
  return;
72013
72116
  }
72014
72117
  const outputs = loaded?.state?.outputs;
72015
72118
  if (outputs !== void 0 && !isReadableBag(outputs)) {
72016
72119
  if (!nodeCanRefuse) {
72017
- logger.debug(`Scrub of ${stackName}: producer '${maskSecretsInText(producer.stack, secrets)}' (${producer.region}) has no readable 'outputs' map, and this position cannot refuse.`);
72120
+ logger.debug(`Scrub of ${shownStackName}: producer ${shownProducer} (${displayIdent(producer.region)}) has no readable 'outputs' map, and this position cannot refuse.`);
72018
72121
  return;
72019
72122
  }
72020
72123
  const seenKey = producerRecordKey(producer.stack, producer.region);
72021
72124
  if (!warnedDamagedProducers.has(seenKey)) {
72022
72125
  warnedDamagedProducers.add(seenKey);
72023
- const detail = `the stored value of producer '${maskSecretsInText(producer.stack, secrets)}' (${producer.region}), whose 'outputs' map cannot be read`;
72126
+ const detail = `the stored value of producer ${shownProducer} (${displayIdent(producer.region)}), whose 'outputs' map cannot be read`;
72024
72127
  findings.unverifiable.push(detail);
72025
72128
  findings.damagedProducerRecords.push(detail);
72026
- logger.warn(`Scrub of ${stackName}: producer '${maskSecretsInText(producer.stack, secrets)}' (${producer.region}) has no readable 'outputs' map, so its stored value could NOT be classified — this run cannot tell whether it still holds plaintext for the value ${stackName} imports from it. ${stackName} is scrubbed for everything else. Repair that record and scrub it first.`);
72129
+ logger.warn(`Scrub of ${shownStackName}: producer ${shownProducer} (${displayIdent(producer.region)}) has no readable 'outputs' map, so its stored value could NOT be classified — this run cannot tell whether it still holds plaintext for the value ${shownStackName} imports from it. ${shownStackName} is scrubbed for everything else. Repair that record and scrub it first.`);
72027
72130
  }
72028
72131
  return;
72029
72132
  }
@@ -72037,60 +72140,60 @@ function makeCrossStackPrePass(deps) {
72037
72140
  recordedImports: [],
72038
72141
  recordedOutputReads: []
72039
72142
  };
72040
- const where = `${key} in ${origin}${path ? ` at ${path}` : ""}`;
72143
+ const where = `${key} in ${origin}${path ? ` at ${maskedIdent(path, secrets)}` : ""}`;
72041
72144
  try {
72042
72145
  await resolver.resolve({ [key]: node[key] }, probe);
72043
72146
  } catch (err) {
72044
72147
  if (!nodeCanRefuse) {
72045
- logger.debug(`Scrub of ${stackName}: ${where} could not be resolved, and this position cannot refuse: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`);
72148
+ logger.debug(`Scrub of ${shownStackName}: ${where} could not be resolved, and this position cannot refuse: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`);
72046
72149
  return;
72047
72150
  }
72048
72151
  if (isByDesignRefusal(err)) {
72049
72152
  const detail = `${where}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`;
72050
72153
  findings.unverifiable.push(detail);
72051
- logger.warn(`Scrub of ${stackName} cannot verify ${detail} — cdkd declines this read by design, so no re-run can change it. The rest of the stack is still scrubbed; this stack is NOT reported clean.`);
72154
+ logger.warn(`Scrub of ${shownStackName} cannot verify ${detail} — cdkd declines this read by design, so no re-run can change it. The rest of the stack is still scrubbed; this stack is NOT reported clean.`);
72052
72155
  return;
72053
72156
  }
72054
72157
  if (isMalformedProducerRefusal(err)) {
72055
72158
  const detail = `${where}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`;
72056
72159
  findings.unverifiable.push(detail);
72057
72160
  findings.damagedProducerRecords.push(detail);
72058
- logger.warn(`Scrub of ${stackName} cannot verify ${detail} — the PRODUCER's state record is malformed or truncated, so this run cannot tell whether that producer still holds the plaintext. The rest of the stack is still scrubbed; this stack is NOT reported clean. Repair the producer's record and scrub it first, then re-run.`);
72161
+ logger.warn(`Scrub of ${shownStackName} cannot verify ${detail} — the PRODUCER's state record is malformed or truncated, so this run cannot tell whether that producer still holds the plaintext. The rest of the stack is still scrubbed; this stack is NOT reported clean. Repair the producer's record and scrub it first, then re-run.`);
72059
72162
  return;
72060
72163
  }
72061
72164
  throw unresolvableCrossStackReadError(origin, stackName, key, path, err, secrets);
72062
72165
  }
72063
72166
  const producer = recordedProducer(key, probe);
72064
72167
  if (!producer) {
72065
- logger.debug(`Scrub of ${stackName}: ${where} resolved, but the resolver recorded no cdkd cross-stack read for it — the value came from a CloudFormation fallback or a cross-account arm that records nothing, so scrub cannot name a producer to classify. Not classified as a plaintext producer.`);
72168
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved, but the resolver recorded no cdkd cross-stack read for it — the value came from a CloudFormation fallback or a cross-account arm that records nothing, so scrub cannot name a producer to classify. Not classified as a plaintext producer.`);
72066
72169
  return;
72067
72170
  }
72068
- const loggedKey = maskSecretsInText(producer.key, secrets);
72069
- const loggedStack = maskSecretsInText(producer.stack, secrets);
72171
+ const loggedKey = displayIdent(maskSecretsInText(producer.key, secrets));
72172
+ const loggedStack = displayStackName(maskSecretsInText(producer.stack, secrets));
72070
72173
  if (!producerTemplates.has(producer.stack)) {
72071
- logger.debug(`Scrub of ${stackName}: ${where} resolved through producer '${loggedStack}' (${producer.region}), which is not a stack of this app — scrub has no template to classify export '${loggedKey}' with. Not classified as a plaintext producer.`);
72174
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack} (${displayIdent(producer.region)}), which is not a stack of this app — scrub has no template to classify export ${loggedKey} with. Not classified as a plaintext producer.`);
72072
72175
  return;
72073
72176
  }
72074
72177
  const verdict = secretExpressionVerdict(producer.stack, producer.key);
72075
72178
  if (verdict.kind === "no") {
72076
- logger.debug(`Scrub of ${stackName}: ${where} resolved through producer '${loggedStack}', whose template declares no {{resolve:...}} expression for '${loggedKey}' and no re-export chain reaching one. Not classified as a plaintext producer.`);
72179
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack}, whose template declares no {{resolve:...}} expression for ${loggedKey} and no re-export chain reaching one. Not classified as a plaintext producer.`);
72077
72180
  return;
72078
72181
  }
72079
72182
  const stored = await storedProducerValue(producer, context.stateBackend, nodeCanRefuse);
72080
72183
  if (!stored) {
72081
- logger.debug(`Scrub of ${stackName}: ${where} resolved through producer '${loggedStack}' (${producer.region}), whose state record could not be read or does not carry the key '${loggedKey}' — cannot classify, so this is not classified as a plaintext producer.`);
72184
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack} (${displayIdent(producer.region)}), whose state record could not be read or does not carry the key ${loggedKey} — cannot classify, so this is not classified as a plaintext producer.`);
72082
72185
  return;
72083
72186
  }
72084
72187
  if (carriesDynamicReference(stored.stored)) {
72085
- logger.debug(`Scrub of ${stackName}: ${where} resolved through producer '${loggedStack}', whose stored value for '${loggedKey}' already carries a {{resolve:...}} expression — the producer is scrubbed and there is nothing wrong with this read.`);
72188
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack}, whose stored value for ${loggedKey} already carries a {{resolve:...}} expression — the producer is scrubbed and there is nothing wrong with this read.`);
72086
72189
  return;
72087
72190
  }
72088
72191
  if (storedValueCarriesNoPlaintext(stored.stored)) {
72089
- logger.debug(`Scrub of ${stackName}: ${where} resolved through producer '${loggedStack}', whose stored value for that key carries no text — nothing to redact, so this is not classified as a plaintext producer.`);
72192
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack}, whose stored value for that key carries no text — nothing to redact, so this is not classified as a plaintext producer.`);
72090
72193
  return;
72091
72194
  }
72092
72195
  if (!nodeCanRefuse) {
72093
- logger.debug(`Scrub of ${stackName}: ${where} resolved to a plaintext from unscrubbed producer '${loggedStack}', and this position cannot refuse.`);
72196
+ logger.debug(`Scrub of ${shownStackName}: ${where} resolved to a plaintext from unscrubbed producer ${loggedStack}, and this position cannot refuse.`);
72094
72197
  return;
72095
72198
  }
72096
72199
  throw plaintextProducerCrossStackReadError(origin, stackName, key, path, producer.stack, producer.key, verdict, secrets);
@@ -72147,6 +72250,7 @@ function makeCrossStackPrePass(deps) {
72147
72250
  */
72148
72251
  async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72149
72252
  const { logger } = opts;
72253
+ const shownStack = displayStackName(stack.stackName);
72150
72254
  const acquired = !opts.dryRun;
72151
72255
  if (acquired) await lockManager.acquireLockWithRetry(stack.stackName, region, void 0, "scrub");
72152
72256
  const perResourceSecrets = /* @__PURE__ */ new Map();
@@ -72232,7 +72336,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72232
72336
  try {
72233
72337
  const loaded = await stateBackend.getState(stack.stackName, region);
72234
72338
  if (!loaded) {
72235
- logger.debug(`No state for ${stack.stackName} (${region}) — skipping`);
72339
+ logger.debug(`No state for ${shownStack} (${displayIdent(region)}) — skipping`);
72236
72340
  return {
72237
72341
  recordsChanged: 0,
72238
72342
  secretsFound: 0,
@@ -72285,7 +72389,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72285
72389
  try {
72286
72390
  parameters = await resolver.resolveParameters(stack.template);
72287
72391
  } catch (err) {
72288
- logger.debug(`Parameter resolution skipped for ${stack.stackName}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
72392
+ logger.debug(`Parameter resolution skipped for ${shownStack}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
72289
72393
  }
72290
72394
  const resolverStateBackend = memoizeCrossStackStateReads(stateBackend);
72291
72395
  const resolverContext = (recordedSecretValues) => ({
@@ -72309,7 +72413,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72309
72413
  try {
72310
72414
  conditions = await resolver.evaluateConditions(resolverContext(outputSecrets));
72311
72415
  } catch (err) {
72312
- logger.debug(`Condition evaluation skipped for ${stack.stackName}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
72416
+ logger.debug(`Condition evaluation skipped for ${shownStack}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
72313
72417
  }
72314
72418
  const templateResources = stack.template.Resources ?? {};
72315
72419
  const templateOutputs = stack.template.Outputs ?? {};
@@ -72329,10 +72433,10 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72329
72433
  producerRegions,
72330
72434
  resolvers,
72331
72435
  recordedSecretValues,
72332
- origin: `resource '${logicalId}'`
72436
+ origin: `resource ${maskedIdent(logicalId, recordedSecretValues)}`
72333
72437
  });
72334
72438
  const resourceContext = resolverContext(recordedSecretValues);
72335
- await resolveCrossStackReads(resolveInput, resourceContext, `resource '${logicalId}'`);
72439
+ await resolveCrossStackReads(resolveInput, resourceContext, `resource ${maskedIdent(logicalId, recordedSecretValues)}`);
72336
72440
  const bagKeys = resolveInput !== null && typeof resolveInput === "object" && !Array.isArray(resolveInput) ? Object.keys(resolveInput) : void 0;
72337
72441
  const intrinsicShapedBag = bagKeys?.some((k) => RESOLVER_DISPATCH_KEYS.has(k)) ?? false;
72338
72442
  const resolveUnits = bagKeys && !intrinsicShapedBag ? Object.entries(resolveInput) : [["", resolveInput]];
@@ -72343,16 +72447,16 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72343
72447
  ...resourceContext,
72344
72448
  abandonedResolutions: abandoned
72345
72449
  });
72346
- reportAbandonedBag(abandoned, propertyName ? `resource '${displaySafe(logicalId)}' property '${displaySafe(propertyName)}'` : `resource '${displaySafe(logicalId)}'`, recordedSecretValues, `${displaySafe(logicalId)}${propertyName ? `.${displaySafe(propertyName)}` : ""}`);
72450
+ reportAbandonedBag(abandoned, propertyName ? `resource ${maskedIdent(logicalId, recordedSecretValues)} property ${maskedIdent(propertyName, recordedSecretValues)}` : `resource ${maskedIdent(logicalId, recordedSecretValues)}`, recordedSecretValues, `${maskedIdent(logicalId, recordedSecretValues)}${propertyName ? `.${maskedIdent(propertyName, recordedSecretValues)}` : ""}`);
72347
72451
  } catch (err) {
72348
72452
  if (isRegionAmbiguousRefusal(err) || isNamelessDynamicReferenceFailure(err)) throw err;
72349
72453
  const leafVerdict = abandonedScanVerdict(propertyValue, err);
72350
72454
  if (leafVerdict !== "silent") {
72351
72455
  if (leafVerdict === "count") unverifiableLeaves++;
72352
72456
  else ungateableAbandonedScans++;
72353
- logger.warn(maskSecretsInText(abandonedScanWarning(propertyName ? `resource '${displaySafe(logicalId)}' property '${displaySafe(propertyName)}'` : `resource '${displaySafe(logicalId)}'`, leafVerdict), recordedSecretValues));
72457
+ logger.warn(maskSecretsInText(abandonedScanWarning(propertyName ? `resource ${maskedIdent(logicalId, recordedSecretValues)} property ${maskedIdent(propertyName, recordedSecretValues)}` : `resource ${maskedIdent(logicalId, recordedSecretValues)}`, leafVerdict), recordedSecretValues));
72354
72458
  }
72355
- logger.debug(maskSecretsInText(`Resolution of ${displaySafe(logicalId)}${propertyName ? `.${displaySafe(propertyName)}` : ""} during scrub was partial: ${err instanceof Error ? err.message : String(err)}`, recordedSecretValues));
72459
+ logger.debug(maskSecretsInText(`Resolution of ${maskedIdent(logicalId, recordedSecretValues)}${propertyName ? `.${maskedIdent(propertyName, recordedSecretValues)}` : ""} during scrub was partial: ${err instanceof Error ? err.message : String(err)}`, recordedSecretValues));
72356
72460
  }
72357
72461
  }
72358
72462
  perResourceTemplateProps.set(logicalId, templateResource.Properties);
@@ -72369,7 +72473,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72369
72473
  producerRegions,
72370
72474
  resolvers,
72371
72475
  recordedSecretValues,
72372
- origin: `orphan record '${record.logicalId}'`
72476
+ origin: `orphan record ${maskedIdent(record.logicalId, recordedSecretValues)}`
72373
72477
  });
72374
72478
  const orphanContext = resolverContext(recordedSecretValues);
72375
72479
  for (const [bagName, bagValue] of Object.entries(resolveInput)) {
@@ -72379,16 +72483,16 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72379
72483
  ...orphanContext,
72380
72484
  abandonedResolutions: abandoned
72381
72485
  });
72382
- reportAbandonedBag(abandoned, `orphan record '${displaySafe(record.logicalId)}' ${bagName}`, recordedSecretValues, `orphan record ${displaySafe(record.logicalId)} ${bagName}`);
72486
+ reportAbandonedBag(abandoned, `orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName}`, recordedSecretValues, `orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName}`);
72383
72487
  } catch (err) {
72384
72488
  if (isRegionAmbiguousRefusal(err) || isNamelessDynamicReferenceFailure(err)) throw err;
72385
72489
  const leafVerdict = abandonedScanVerdict(bagValue, err);
72386
72490
  if (leafVerdict !== "silent") {
72387
72491
  if (leafVerdict === "count") unverifiableLeaves++;
72388
72492
  else ungateableAbandonedScans++;
72389
- logger.warn(maskSecretsInText(abandonedScanWarning(`orphan record '${displaySafe(record.logicalId)}' ${bagName}`, leafVerdict), recordedSecretValues));
72493
+ logger.warn(maskSecretsInText(abandonedScanWarning(`orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName}`, leafVerdict), recordedSecretValues));
72390
72494
  }
72391
- logger.debug(maskSecretsInText(`Resolution of orphan record ${displaySafe(record.logicalId)} ${bagName} during scrub was partial: ${err instanceof Error ? err.message : String(err)}`, recordedSecretValues));
72495
+ logger.debug(maskSecretsInText(`Resolution of orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName} during scrub was partial: ${err instanceof Error ? err.message : String(err)}`, recordedSecretValues));
72392
72496
  }
72393
72497
  }
72394
72498
  }
@@ -72404,10 +72508,10 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72404
72508
  producerRegions,
72405
72509
  resolvers,
72406
72510
  recordedSecretValues: nameSecrets,
72407
- origin: `Export.Name of output '${name}'`
72511
+ origin: `Export.Name of output ${maskedIdent(name, nameSecrets)}`
72408
72512
  });
72409
72513
  const nameContext = resolverContext(nameSecrets);
72410
- await resolveCrossStackReads(nameSource, nameContext, `Export.Name of output '${name}'`, { canRefuse: !isOutputSuppressed(name, output, conditions, state.outputs ?? {}) });
72514
+ await resolveCrossStackReads(nameSource, nameContext, `Export.Name of output ${maskedIdent(name, nameSecrets)}`, { canRefuse: !isOutputSuppressed(name, output, conditions, state.outputs ?? {}) });
72411
72515
  try {
72412
72516
  exportName = await resolver.resolve(nameSource, nameContext);
72413
72517
  } catch (err) {
@@ -72416,14 +72520,14 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72416
72520
  if (leafVerdict !== "silent") {
72417
72521
  if (leafVerdict === "count") unverifiableLeaves++;
72418
72522
  else ungateableAbandonedScans++;
72419
- logger.warn(maskSecretsInText(abandonedScanWarning(`the Export.Name of output '${displaySafe(name)}'`, leafVerdict), outputSecrets));
72523
+ logger.warn(maskSecretsInText(abandonedScanWarning(`the Export.Name of output ${maskedIdent(name, outputSecrets)}`, leafVerdict), outputSecrets));
72420
72524
  }
72421
72525
  nameFailed = true;
72422
72526
  nameError = err;
72423
72527
  }
72424
72528
  if (nameFailed) {
72425
72529
  outputsSourceUntrusted = true;
72426
- logger.warn(`Export.Name of output ${name} could not be resolved during scrub (${maskSecretsInText(nameError instanceof Error ? nameError.message : String(nameError), outputSecrets)}) — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
72530
+ logger.warn(`Export.Name of output ${maskedIdent(name, outputSecrets)} could not be resolved during scrub (${maskSecretsInText(nameError instanceof Error ? nameError.message : String(nameError), outputSecrets)}) — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
72427
72531
  }
72428
72532
  }
72429
72533
  if (declaredExportName !== void 0 && typeof exportName !== "string") outputsSourceUntrusted = true;
@@ -72431,7 +72535,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72431
72535
  if (typeof exportName === "string" && !exportNameUnresolved) accountedOutputKeys.add(exportName);
72432
72536
  if (exportNameUnresolved) {
72433
72537
  outputsSourceUntrusted = true;
72434
- logger.warn(`Export.Name of output ${name} did not fully resolve during scrub — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
72538
+ logger.warn(`Export.Name of output ${maskedIdent(name, outputSecrets)} did not fully resolve during scrub — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
72435
72539
  } else if (typeof exportName === "string" && isExportAliasCollision(exportName, name, declaredOutputNames)) {
72436
72540
  ambiguousKeys.add(exportName);
72437
72541
  collisions.push([name, exportName]);
@@ -72448,26 +72552,26 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72448
72552
  producerRegions,
72449
72553
  resolvers,
72450
72554
  recordedSecretValues: outputSecrets,
72451
- origin: `output '${name}'`
72555
+ origin: `output ${maskedIdent(name, outputSecrets)}`
72452
72556
  });
72453
72557
  const valueContext = resolverContext(outputSecrets);
72454
- await resolveCrossStackReads(valueSource, valueContext, `output '${name}'`, { canRefuse: !isOutputSuppressed(name, output, conditions, state.outputs ?? {}) });
72558
+ await resolveCrossStackReads(valueSource, valueContext, `output ${maskedIdent(name, outputSecrets)}`, { canRefuse: !isOutputSuppressed(name, output, conditions, state.outputs ?? {}) });
72455
72559
  const abandonedOutput = [];
72456
72560
  try {
72457
72561
  await resolver.resolve(valueSource, {
72458
72562
  ...valueContext,
72459
72563
  abandonedResolutions: abandonedOutput
72460
72564
  });
72461
- reportAbandonedBag(abandonedOutput, `output '${displaySafe(name)}'`, outputSecrets, `output ${displaySafe(name)}`);
72565
+ reportAbandonedBag(abandonedOutput, `output ${maskedIdent(name, outputSecrets)}`, outputSecrets, `output ${maskedIdent(name, outputSecrets)}`);
72462
72566
  } catch (err) {
72463
72567
  if (isRegionAmbiguousRefusal(err) || isNamelessDynamicReferenceFailure(err)) throw err;
72464
72568
  const leafVerdict = abandonedScanVerdict(valueSource, err);
72465
72569
  if (leafVerdict !== "silent") {
72466
72570
  if (leafVerdict === "count") unverifiableLeaves++;
72467
72571
  else ungateableAbandonedScans++;
72468
- logger.warn(maskSecretsInText(abandonedScanWarning(`output '${displaySafe(name)}'`, leafVerdict), outputSecrets));
72572
+ logger.warn(maskSecretsInText(abandonedScanWarning(`output ${maskedIdent(name, outputSecrets)}`, leafVerdict), outputSecrets));
72469
72573
  }
72470
- logger.debug(`Resolution of output ${name} during scrub was partial: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
72574
+ logger.debug(`Resolution of output ${maskedIdent(name, outputSecrets)} during scrub was partial: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
72471
72575
  }
72472
72576
  }
72473
72577
  });
@@ -72580,7 +72684,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72580
72684
  throw maskSecretsInError(err, allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets));
72581
72685
  } finally {
72582
72686
  if (acquired) await lockManager.releaseLock(stack.stackName, region).catch((err) => {
72583
- logger.warn(`Failed to release lock for ${stack.stackName}: ${err instanceof Error ? err.message : String(err)}`);
72687
+ logger.warn(`Failed to release lock for ${shownStack}: ${err instanceof Error ? err.message : String(err)}`);
72584
72688
  });
72585
72689
  }
72586
72690
  }
@@ -86366,7 +86470,7 @@ var AttributeFetcher = class {
86366
86470
  const orphan = this.orphans[orphanLogicalId];
86367
86471
  const bag = orphan.attributes;
86368
86472
  if (bag !== void 0 && !isReadableBag(bag)) {
86369
- 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.`);
86473
+ this.logger.warn(`--force: state.attributes of ${displayIdent(orphanLogicalId)} is not a readable map, so it is not consulted for ${displayIdent(attribute)}; leaving the original intrinsic in place.`);
86370
86474
  return {
86371
86475
  ok: false,
86372
86476
  reason: `${reason}; the state.attributes cache is not a readable map`
@@ -88372,7 +88476,7 @@ async function resolveImportedProperties(stackState, template, region, stateBack
88372
88476
  if (divergentParameters !== void 0 && divergentParameters.size > 0) try {
88373
88477
  parameterTaint = computeParameterTaint(template, new Map(entries.map(([logicalId, resource]) => [logicalId, resource.properties])), divergentParameters);
88374
88478
  } catch (err) {
88375
- logger.debug(`observed-baseline parameter-dependence walk failed for '${displaySafe(stackState.stackName)}': ${err instanceof Error ? err.name : typeof err} — refusing every baseline in the stack fail-closed.`);
88479
+ logger.debug(`observed-baseline parameter-dependence walk failed for ${displayStackName(stackState.stackName)}: ${err instanceof Error ? err.name : typeof err} — refusing every baseline in the stack fail-closed.`);
88376
88480
  const all = new Set(entries.map(([logicalId]) => logicalId));
88377
88481
  parameterTaint = {
88378
88482
  refused: all,
@@ -88425,8 +88529,8 @@ async function resolveImportedProperties(stackState, template, region, stateBack
88425
88529
  const refusedHere = [...parameterTaint.refused].filter((id) => inState.has(id));
88426
88530
  const unreadable = refusedHere.filter((id) => parameterTaint.unclassifiable.has(id));
88427
88531
  if (refusedHere.length > 0) {
88428
- const named = [...parameterTaint.parametersHit].sort().map((name) => displaySafe(name));
88429
- logger.warn(`${refusedHere.length} resource(s) in '${displaySafe(stackState.stackName)}' depend, directly or through another resource's attributes, on template parameter(s) whose deployed CloudFormation value could not be proven equal to the template 'Default' 'cdkd import' binds` + (named.length > 0 ? ` (${named.join(", ")})` : "") + (unreadable.length > 0 ? ` — ${unreadable.length} of them because their properties could not be checked for such a dependence` : "") + ". Their recorded properties hold the 'Default', NOT the deployed value, and no observed drift baseline was captured for them by this import (the live value may be a secret this import cannot position a redaction for). Review 'cdkd diff' before the next 'cdkd deploy'.");
88532
+ const named = [...parameterTaint.parametersHit].sort().map((name) => displayIdent(name));
88533
+ logger.warn(`${refusedHere.length} resource(s) in ${displayStackName(stackState.stackName)} depend, directly or through another resource's attributes, on template parameter(s) whose deployed CloudFormation value could not be proven equal to the template 'Default' 'cdkd import' binds` + (named.length > 0 ? ` (${named.join(", ")})` : "") + (unreadable.length > 0 ? ` — ${unreadable.length} of them because their properties could not be checked for such a dependence` : "") + ". Their recorded properties hold the 'Default', NOT the deployed value, and no observed drift baseline was captured for them by this import (the live value may be a secret this import cannot position a redaction for). Review 'cdkd diff' before the next 'cdkd deploy'.");
88430
88534
  }
88431
88535
  }
88432
88536
  return unsafeObservedBaselineLogicalIds;
@@ -89048,9 +89152,9 @@ function indexGrandchildTemplatePaths(childTemplate, childTemplatePath) {
89048
89152
  if (resource.Type !== "AWS::CloudFormation::Stack") continue;
89049
89153
  const assetPath = resource.Metadata?.["aws:asset:path"];
89050
89154
  if (typeof assetPath !== "string" || assetPath.length === 0) continue;
89051
- if (path.isAbsolute(assetPath)) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack '${displaySafe(grandLogicalId)}' has Metadata['aws:asset:path']='${displaySafe(assetPath)}' which is absolute. CDK emits relative asset paths for nested templates.`);
89155
+ if (path.isAbsolute(assetPath)) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which is absolute. CDK emits relative asset paths for nested templates.`);
89052
89156
  const resolved = resolveAssemblyPath(dir, assetPath);
89053
- if (!resolved.contained) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack '${displaySafe(grandLogicalId)}' has Metadata['aws:asset:path']='${displaySafe(assetPath)}' which ${renderAssemblyPathEscape(resolved, dir)}`);
89157
+ if (!resolved.contained) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`);
89054
89158
  result[grandLogicalId] = resolved.path;
89055
89159
  }
89056
89160
  return result;
@@ -95028,7 +95132,7 @@ async function resolveOne(entry, secretsClient, ssmClient) {
95028
95132
  switch (shape.kind) {
95029
95133
  case "secrets-manager": return resolveSecretsManager(entry, shape, secretsClient);
95030
95134
  case "ssm": return resolveSsm(entry, shape, ssmClient);
95031
- case "unknown": throw new EcsSecretsResolutionError(`Container '${displayIdent(entry.containerName)}' secret '${displayIdent(entry.name)}' references an unsupported ValueFrom shape ${displayIdent(arn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}. Expected Secrets Manager ARN (optionally with :<json-key>::) or SSM Parameter ARN.`);
95135
+ case "unknown": throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} references an unsupported ValueFrom shape ${displayIdent(arn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}. Expected Secrets Manager ARN (optionally with :<json-key>::) or SSM Parameter ARN.`);
95032
95136
  }
95033
95137
  }
95034
95138
  /**
@@ -95061,20 +95165,20 @@ async function resolveSecretsManager(entry, shape, client) {
95061
95165
  try {
95062
95166
  secretString = (await client.send(new GetSecretValueCommand({ SecretId: shape.baseArn }))).SecretString;
95063
95167
  } catch (err) {
95064
- throw new EcsSecretsResolutionError(`Failed to resolve Secrets Manager secret for container '${displayIdent(entry.containerName)}' / env '${displayIdent(entry.name)}' (${displayIdent(shape.baseArn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
95168
+ throw new EcsSecretsResolutionError(`Failed to resolve Secrets Manager secret for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)} (${displayIdent(shape.baseArn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
95065
95169
  }
95066
- if (secretString === void 0) throw new EcsSecretsResolutionError(`Secrets Manager returned no SecretString for container '${displayIdent(entry.containerName)}' / env '${displayIdent(entry.name)}' (${displayIdent(shape.baseArn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}). Binary secrets are not supported.`);
95170
+ if (secretString === void 0) throw new EcsSecretsResolutionError(`Secrets Manager returned no SecretString for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)} (${displayIdent(shape.baseArn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}). Binary secrets are not supported.`);
95067
95171
  if (shape.jsonKey === void 0) return secretString;
95068
95172
  let parsed;
95069
95173
  try {
95070
95174
  parsed = JSON.parse(secretString);
95071
95175
  } catch (err) {
95072
95176
  const kind = err instanceof Error ? err.name : "unknown";
95073
- throw new EcsSecretsResolutionError(`Container '${displayIdent(entry.containerName)}' secret '${displayIdent(entry.name)}' specified json-key '${displaySafe(shape.jsonKey)}' but the secret value is not valid JSON (${displayIdent(kind)}). The parser detail is withheld because it would echo the secret plaintext.`);
95177
+ throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} specified json-key ${displayIdent(shape.jsonKey)} but the secret value is not valid JSON (${displayIdent(kind)}). The parser detail is withheld because it would echo the secret plaintext.`);
95074
95178
  }
95075
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new EcsSecretsResolutionError(`Container '${displayIdent(entry.containerName)}' secret '${displayIdent(entry.name)}' specified json-key '${displaySafe(shape.jsonKey)}' but the secret root is not a JSON object.`);
95179
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} specified json-key ${displayIdent(shape.jsonKey)} but the secret root is not a JSON object.`);
95076
95180
  const value = parsed[shape.jsonKey];
95077
- if (value === void 0) throw new EcsSecretsResolutionError(`Container '${displayIdent(entry.containerName)}' secret '${displayIdent(entry.name)}' specified json-key '${displaySafe(shape.jsonKey)}' but no such key exists in the secret JSON.`);
95181
+ if (value === void 0) throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} specified json-key ${displayIdent(shape.jsonKey)} but no such key exists in the secret JSON.`);
95078
95182
  return typeof value === "string" ? value : JSON.stringify(value);
95079
95183
  }
95080
95184
  async function resolveSsm(entry, shape, client) {
@@ -95083,11 +95187,11 @@ async function resolveSsm(entry, shape, client) {
95083
95187
  Name: shape.name,
95084
95188
  WithDecryption: true
95085
95189
  }))).Parameter?.Value;
95086
- if (value === void 0) throw new EcsSecretsResolutionError(`SSM parameter '${displayIdent(shape.name, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}' returned no Value for container '${displayIdent(entry.containerName)}' / env '${displayIdent(entry.name)}'.`);
95190
+ if (value === void 0) throw new EcsSecretsResolutionError(`SSM parameter ${displayIdent(shape.name, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })} returned no Value for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)}.`);
95087
95191
  return value;
95088
95192
  } catch (err) {
95089
95193
  if (err instanceof EcsSecretsResolutionError) throw err;
95090
- throw new EcsSecretsResolutionError(`Failed to resolve SSM parameter for container '${displayIdent(entry.containerName)}' / env '${displayIdent(entry.name)}' (${displayIdent(shape.name, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
95194
+ throw new EcsSecretsResolutionError(`Failed to resolve SSM parameter for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)} (${displayIdent(shape.name, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
95091
95195
  }
95092
95196
  }
95093
95197
 
@@ -95500,7 +95604,7 @@ async function prepareOneImage(task, container, options) {
95500
95604
  tag,
95501
95605
  ...task.stack.assetOutdir !== void 0 && { assetOutdir: task.stack.assetOutdir },
95502
95606
  ...options.platformOverride !== void 0 && { platform: options.platformOverride },
95503
- wrapError: (stderr) => new LocalInvokeBuildError$1(`docker build failed for ECS container '${displaySafe(container.name)}' (${asset.source.directory !== void 0 ? displayAssemblyPath(asset.source.directory) : asset.source.executable ? redactDockerArgvValues(asset.source.executable).join(" ") : void 0}): ${displaySafe(stderr)}`)
95607
+ wrapError: (stderr) => new LocalInvokeBuildError$1(`docker build failed for ECS container ${displayIdent(container.name)} (${asset.source.directory !== void 0 ? displayAssemblyPath(asset.source.directory) : asset.source.executable ? redactDockerArgvValues(asset.source.executable).join(" ") : void 0}): ${displaySafe(stderr)}`)
95504
95608
  });
95505
95609
  if (actualTag !== tag) {
95506
95610
  const tagArgs = [
@@ -95511,7 +95615,7 @@ async function prepareOneImage(task, container, options) {
95511
95615
  try {
95512
95616
  await runDockerStreaming(tagArgs);
95513
95617
  } catch (err) {
95514
- throw new LocalInvokeBuildError$1(`docker tag failed re-tagging '${displaySafe(actualTag)}' → '${displaySafe(tag)}' for ECS container '${displaySafe(container.name)}': ${displaySafe(describeDockerFailure(err, tagArgs))}`);
95618
+ throw new LocalInvokeBuildError$1(`docker tag failed re-tagging ${displayIdent(actualTag)} → ${displayIdent(tag)} for ECS container ${displayIdent(container.name)}: ${displaySafe(describeDockerFailure(err, tagArgs))}`);
95515
95619
  }
95516
95620
  }
95517
95621
  return tag;
@@ -99040,4 +99144,4 @@ function buildProgram() {
99040
99144
 
99041
99145
  //#endregion
99042
99146
  export { buildProgram };
99043
- //# sourceMappingURL=program-CQ_Y14q1.js.map
99147
+ //# sourceMappingURL=program-BALgPCWL.js.map