@go-to-k/cdkd 0.291.17 → 0.291.18

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 findLargeInlineResources, $n as repairMalformedOutputsForReadOnly, $r as WorkGraph, $t as replayWarn, A as createPreDeleteFinalSnapshot, Aa as setAwsClients, Ai as runDockerStreaming, An as malformedOrphansRefusalMessage, Ar as scrubResourceRecord, At as isTerminationProtectionPropagationError, B as isStatefulRecreateTargetSync, Ba as LocalStartServiceError, Bi as resolveApp, Bn as refuseMalformedNestedChildOutputs, Br as DEFAULT_STATE_PREFIX, Bt as parameterTypeMayLoseSecretIdentity, C as namesAnyDeclaredParameter, Ca as resolveAssemblyPath, Ci as formatDockerLoginError, Cn as hasReadableOutputs, Cr as maskSecretsInError, Ct as CloudControlProvider, D as PRE_DELETE_SNAPSHOT_TYPES, Da as getAwsClients, Di as partitionSensitiveEnv, Dn as malformedExportSourceWarning, Dr as recordMaskOnlyValuesIn, Dt as deleteSkipReason, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as AwsClients, Ei as isMalformedEnvKey, En as malformedExportNamesWarning, Er as recordMaskOnlyValue, Et as deleteIndeterminateGuards, F as extractDeploymentEventError, Fi as getDockerImageBySourceHash, Fn as malformedResourceEntriesWarning, Fr as buildForceUnlockCommand, Ft as coerceParameterTypedValue, G as toCfnInteger, Ga as ProvisioningError, Gi as resolveStateBucketWithDefaultAndSource, Gn as refuseMalformedOutputsForDestroy, Gr as importableOutputKeys, Gt as resolveExplicitPhysicalId, H as WARM_THROUGHPUT_MEMBERS, Ha as MalformedProducerRecordRefusalError, Hi as resolveCaptureObservedState, Hn as refuseMalformedOrphansForDestroy, Hr as hasReadableExportSet, Ht as isSettledInstanceState, I as makeSiblingClaimReader, Ia as DeployCancelledError, Ii as Synthesizer, In as malformedResourcePropertiesWarning, Ir as buildLockContentionMessage, It as getAccountInfo, J as bold, Ja as StackHasActiveImportsError, Ji as warnDeprecatedNoPrefixCliFlag, Jn as refuseMalformedResourceEntriesForOrphan, Jr as orphansAfterRollback, Jt as coerceCfnInteger, K as toFiniteNumber, Ka as ResourceTimeoutError, Ki as resolveUseCdkBootstrapAssets, Kn as refuseMalformedResourceAttributesForOrphan, Kr as importableOutputs, Kt as assertRegionMatch, L as planOrphanAdoption, La as DynamicReferenceRegionAmbiguousError, Li as synthesisStatusMessage, Ln as malformedResourcesWarning, Lr as forceQuitRecoveryClause, Lt as isImpossibleEmptyStoredAttribute, M as refusesFinalSnapshot, Ma as CdkdError, Mi as escapeRegExp, Mn as malformedOutputsRefusalMessage, Mr as S3StateBackend, Mt as carriesDynamicReference, N as unsupportedFinalSnapshotError, Ni as stripControlChars, Nn as malformedOutputsWarning, Nr as rebuildClientForBucketRegion, Nt as carriesFetchableDynamicReference, O as buildFinalSnapshotIdentifier, Oa as resetAwsClients, Oi as redactDockerArgvValues, On as malformedLocalOutputsWarning, Or as recoverMaskedOutput, Ot as isWaitAbandonedError, P as makeCanonicalizePropertiesFn, Pa as CrossAccountSecretRefusalError, Pi as AssetManifestLoader, Pn as malformedRenderedContainersWarning, Pr as UNREPRODUCIBLE_LOCK_CLAUSE, Pt as cfnRefValueFromPhysicalId, Q as red, Qi as MIGRATE_TMP_PREFIX, Qn as repairMalformedOrphansForReadOnly, Qr as stringifyValue, Qt as readConfigString, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as IntrinsicResolutionRefusalError, Ri as getDefaultStateBucketName, Rn as malformedStateRefusalMessage, Rr as formatLockExpiry, Rt as isNamelessDynamicReferenceError, S as computeParameterTaint, Sa as renderAssemblyPathEscape, Si as finchSecretArgvRefusal, Sn as hasReadableOrphans, Sr as markSameGenerationBag, St as startInterruptWatch, T as resourcesNamingDeclaredParameter, Ta as resolveBucketRegion, Ti as isDockerClientEnvKey, Tn as isReadableResourceEntry, Tr as pathCrossesDottedKey, Tt as UNSPECIFIED_SKIP_REASON, U as coerceWarmThroughput$1, Ua as NestedStackChildDirectDestroyError, Ui as resolveSkipPrefix, Un as refuseMalformedOrphansForOrphan, Ur as hasReasonlessBaselineRefusal, Ut as WAFv2WebACLProvider, V as renderStatefulReason, Vi as resolveAutoAssetStorage, Vn as refuseMalformedOrphans, Vr as exportNamesCarriedFrom, Vt as refStateLookupFromResource, W as isWarmThroughputDecrease, Wa as PartialFailureError, Wi as resolveStateBucketWithDefault, Wn as refuseMalformedOutputs, Wr as hasUnverifiableParameterRefusal, Wt as normalizeAwsTagsToCfn, X as gray, Xi as CFN_TEMPLATE_BODY_LIMIT, Xn as refuseMalformedResourcesForDestroy, Xr as shouldRetainResource, Xt as configIntegerRefusal, Y as cyan, Ya as StackTerminationProtectionError, Yi as ssmResolvedValueType, Yn as refuseMalformedResourcePropertiesForOrphan, Yr as orphansCarriedFrom, Yt as configBooleanRefusal, Z as green, Za as SynthesisError, Zi as CFN_TEMPLATE_URL_LIMIT, Zn as refuseMalformedState, Zr as AssetPublisher, Zt as configStringRefusal, _ as bagHoldsSecretExpression, _a as hasPlainPrototype, _i as resolveDockerContextDirectory, _n as INTRINSIC_KEYS, _r as dynamicReferenceTokens, _t as maskerOrIdentity, a as DeploymentEventsStore, aa as producerRecordKey, ai as BOOTSTRAP_MARKER_PREFIX, an as withSharedDrainBudget, ao as isRetryableTransientError, ar as findActionableSilentDrops, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as absoluteAssemblyPathEscape, bi as describeDockerFailure, bn as UNREADABLE_RESOURCES_MAP_ROW, br as isSingleDynamicReferenceToken, bt as interruptWatchListenerCount, c as replayFailedOperations, ca as PARTITION_TABLE, ci as getBootstrapMarkerKey, cn as s3BucketDualStackDomainName, co as markNonRetryable, cr as withRetry, ct as IAMRoleProvider, d as updatePartialMessage, da as AssemblyReader, di as readBootstrapMarkerBody, dn as applyRoleArnIfSet, do as describeAwsFailure, dr as STATE_SOURCED_BASELINE_RULES, dt as definedAttributes, ea as uploadCfnTemplate, ei as buildAssetRedirectMap, en as requireConfigArray, eo as normalizeAwsError, er as repairMalformedResourceEntriesForReadOnly, et as collectDeclaredOutputNames, f as updatePartialReason, fa as failedStageNote, fi as validateAssetBucketName, fn as AWS_CREDENTIAL_ENV_KEYS, fo as safeStringify, fr as STATE_SOURCED_CROSS_GENERATION_RULES, ft as stringifyIfAssigned, g as computeImplicitDeleteEdges, ga as hasOwnKey, gi as buildDockerImage, gn as DiffCalculator, gr as createSecretMasker, gt as maskDeep, h as IMPLICIT_DELETE_DEPENDENCIES, ha as defineOwnKey, hi as assertCdkLocalDockerContextContained, hn as envCredentialsAreAssumedRole, hr as carriesSecretMask, ht as createMaskedRetryLogger, i as DeploymentEventsReader, ia as producerCoordinateKey, ii as AssetModeResolver, in as producerRegionsFromState, io as isMarkedNonRetryable, ir as safeStackName, it as secretBearing, j as isFinalSnapshotError, ji as warnFinchArgvExposure, jn as malformedOrphansWarning, jr as LockManager, jt as IntrinsicFunctionResolver, k as ccRoutedFinalSnapshotError, ka as runWithStackAwsClients, ki as runDockerForeground, kn as malformedOrphanRecordsWarning, kr as redactSecretsForState, kt as disableInstanceApiTermination, l as replayRollback, la as canonicalizeRegion, li as isCrossRegionRedirect, ln as s3BucketRegionalDomainName, lo as markRedactedCause, lr as DagBuilder, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as processStackMessages, mi as buildDenyExternalAccessPolicy, mn as callerEnvCredentials, mr as TEMPLATE_SOURCED_RULES, mt as wouldReturnToSdkProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as injectiveKey, ni as loadPublishableAssetManifest, nn as requireConfigString, no as pasteableCommand, nr as repairMalformedResourcesForReadOnly, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as decodeListingKey, oi as assertAssetBucketRegion, on as s3BucketArn, oo as isThrottlingError, or as findSilentDropProperties, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as globMatches, pi as validateContainerRepoName, pn as applyCallerIdentityCredentials, pr as STATE_SOURCED_READBACK_RULES, pt as ProviderRegistry, q as formatResourceLine, qa as ResourceUpdateNotSupportedError, qi as stateBucketExistenceConfirmed, qn as refuseMalformedResourceEntries, qr as isReadableBag, qt as coerceCfnBoolean, r as DeployEngine, ra as injectiveKeyPrefix, ri as rewriteTemplateAssetReferences, rn as classifyReplaySecretRegion, ro as shellQuote, rr as safeRegion, rt as isExportAliasCollision, s as planRollback, sa as expectedOwnerParam, si as ensureAssetStorage, sn as s3BucketDomainName, so as isTransientServerError, sr as describeTypeWithThrottleRetry, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, ti as createAssetRedirectResolver, tn as requireConfigObject, to as withErrorHandling, tr as repairMalformedResourcePropertiesForReadOnly, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as derivePartitionAndUrlSuffix, ui as parseBootstrapMarker, un as s3BucketWebsiteUrl, uo as retryClassificationText, ur as TemplateParser, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as nullPrototypeRecord, vi as describeDockerCapturedOutput, vn as STATE_RESOURCES_MALFORMED, vr as errorCauseChain, vt as beginCommandInterruptScope, w as reachableDivergentParameters, wi as getDockerCmd, wn as hasReadableResources, wr as maskSecretsInText, wt as slowCcOperationTimeoutMs, x as bindingSkippedOutputs, xa as displayAssemblyPath, xi as dockerSpawnEnvWithSensitive, xn as displayLogicalId, xr as isUncertifiedBaselineMaskPosition, xt as isInterruptedWaitError, y as keptWholeReasonText, ya as ownValue, yi as describeDockerExecFailure, yn as UNREADABLE_ORPHANS_CONTAINER_ROW, yr as identityKeyFor, yt as endCommandInterruptScope, z as isStatefulRecreateTargetForReplace, za as LocalInvokeBuildError$1, zi as getLegacyStateBucketName, zn as refuseDivergentRecordRegionForDestroy, zr as CUSTOM_RESOURCE_RESPONSE_PREFIX, zt as isUnboundTemplateParameter } from "./deploy-engine-xxVOQPPr.js";
2
- import { C as displayAwsMessage, D as truncateCodePoints, E as isPasteableIdent, S as UNRENDERABLE, T as displaySafe, _ as withSkipPrefix, b as SECRET_REF_MAX_CODE_POINTS, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS } from "./logger-GASr9bAF.js";
1
+ import { $ as yellow, $a as NestedStackChildDirectDestroyError, $i as resolveSkipPrefix, $n as refuseMalformedOutputsForDestroy, $r as hasReadableExportSet, $t as readConfigString, A as createPreDeleteFinalSnapshot, Aa as absoluteAssemblyPathEscape, Ai as describeDockerFailure, An as malformedExportSourceWarning, Ar as identityKeyFor, At as disableInstanceApiTermination, B as isStatefulRecreateTargetSync, Ba as setAwsClients, Bi as runDockerStreaming, Bn as malformedResourceEntriesWarning, Br as redactSecretsForState, Bt as isUnboundTemplateParameter, C as namesAnyDeclaredParameter, Ca as globMatches, Ci as validateAssetBucketName, Cn as displayLogicalId, Cr as STATE_SOURCED_CROSS_GENERATION_RULES, Ct as CloudControlProvider, D as PRE_DELETE_SNAPSHOT_TYPES, Da as hasPlainPrototype, Di as resolveDockerContextDirectory, Dn as isReadableOrphanRecord, Dr as createSecretMasker, Dt as deleteIndeterminateGuards, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as hasOwnKey, Ei as buildDockerImage, En as hasReadableResources, Er as carriesSecretMask, Et as UNSPECIFIED_SKIP_REASON, F as extractDeploymentEventError, Fa as resolveBucketRegion, Fi as isDockerClientEnvKey, Fn as malformedOrphansRefusalMessage, Fr as maskSecretsInText, Ft as cfnRefValueFromPhysicalId, G as toCfnInteger, Gi as getDockerImageBySourceHash, Gn as refuseDivergentRecordRegionForDestroy, Gr as UNREPRODUCIBLE_LOCK_CLAUSE, Gt as normalizeAwsTagsToCfn, H as WARM_THROUGHPUT_MEMBERS, Ha as CdkdError, Hi as escapeRegExp, Hn as malformedResourcesWarning, Hr as LockManager, Ht as refStateLookupFromResource, I as makeSiblingClaimReader, Ia as AwsClients, Ii as isMalformedEnvKey, In as malformedOrphansWarning, Ir as pathCrossesDottedKey, It as coerceParameterTypedValue, J as bold, Ja as IntrinsicResolutionRefusalError, Ji as getDefaultStateBucketName, Jn as refuseMalformedOrphanRecordsForDestroy, Jr as forceQuitRecoveryClause, Jt as coerceCfnBoolean, K as toFiniteNumber, Ka as DeployCancelledError, Ki as Synthesizer, Kn as refuseMalformedNestedChildOutputs, Kr as buildForceUnlockCommand, Kt as resolveExplicitPhysicalId, L as planOrphanAdoption, La as getAwsClients, Li as partitionSensitiveEnv, Ln as malformedOutputsRefusalMessage, Lr as recordMaskOnlyValue, Lt as getAccountInfo, M as refusesFinalSnapshot, Ma as renderAssemblyPathEscape, Mi as finchSecretArgvRefusal, Mn as malformedOrphanRecordsRefusalMessage, Mr as isUncertifiedBaselineMaskPosition, Mt as IntrinsicFunctionResolver, N as unsupportedFinalSnapshotError, Na as resolveAssemblyPath, Ni as formatDockerLoginError, Nn as malformedOrphanRecordsWarning, Nr as markSameGenerationBag, Nt as carriesDynamicReference, O as buildFinalSnapshotIdentifier, Oa as nullPrototypeRecord, Oi as describeDockerCapturedOutput, On as isReadableResourceEntry, Or as dynamicReferenceTokens, Ot as deleteSkipReason, P as makeCanonicalizePropertiesFn, Pi as getDockerCmd, Pn as malformedOrphanRowsKeptWarning, Pr as maskSecretsInError, Pt as carriesFetchableDynamicReference, Q as red, Qa as MalformedProducerRecordRefusalError, Qi as resolveCaptureObservedState, Qn as refuseMalformedOutputs, Qr as exportNamesCarriedFrom, Qt as configStringRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as resetAwsClients, Ri as redactDockerArgvValues, Rn as malformedOutputsWarning, Rr as recordMaskOnlyValuesIn, Rt as isImpossibleEmptyStoredAttribute, S as computeParameterTaint, Sa as failedStageNote, Si as readBootstrapMarkerBody, Sn as deployRefusesOrphanRowsReason, So as safeStringify, Sr as STATE_SOURCED_BASELINE_RULES, St as startInterruptWatch, T as resourcesNamingDeclaredParameter, Ta as defineOwnKey, Ti as buildDenyExternalAccessPolicy, Tn as hasReadableOutputs, Tr as TEMPLATE_SOURCED_RULES, Tt as ccProtectionRegistryTypes, U as coerceWarmThroughput$1, Ui as stripControlChars, Un as malformedStateRefusalMessage, Ur as S3StateBackend, Ut as isSettledInstanceState, V as renderStatefulReason, Vi as warnFinchArgvExposure, Vn as malformedResourcePropertiesWarning, Vr as scrubResourceRecord, Vt as parameterTypeMayLoseSecretIdentity, W as isWarmThroughputDecrease, Wa as CrossAccountSecretRefusalError, Wi as AssetManifestLoader, Wn as previewableOrphanRecords, Wr as rebuildClientForBucketRegion, Wt as WAFv2WebACLProvider, X as gray, Xa as LocalStartServiceError, Xi as resolveApp, Xn as refuseMalformedOrphansForDestroy, Xr as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xt as configBooleanRefusal, Y as cyan, Ya as LocalInvokeBuildError$1, Yi as getLegacyStateBucketName, Yn as refuseMalformedOrphans, Yr as formatLockExpiry, Yt as coerceCfnInteger, Z as green, Zi as resolveAutoAssetStorage, Zn as refuseMalformedOrphansForOrphan, Zr as DEFAULT_STATE_PREFIX, Zt as configIntegerRefusal, _ as bagHoldsSecretExpression, _a as expectedOwnerParam, _i as assertAssetBucketRegion, _n as DiffCalculator, _o as isTransientServerError, _r as findSilentDropProperties, _t as maskerOrIdentity, a as DeploymentEventsStore, aa as ssmResolvedValueType, ai as orphansAfterRollback, an as producerRegionsFromState, ao as StackTerminationProtectionError, ar as refuseMalformedState, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as derivePartitionAndUrlSuffix, bi as isCrossRegionRedirect, bn as UNREADABLE_ORPHANS_CONTAINER_ROW, bo as retryClassificationText, br as DagBuilder, bt as interruptWatchListenerCount, c as replayFailedOperations, ca as MIGRATE_TMP_PREFIX, ci as AssetPublisher, cn as s3BucketDomainName, cr as repairMalformedOutputsForReadOnly, ct as IAMRoleProvider, d as updatePartialMessage, da as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, di as buildAssetRedirectMap, dn as s3BucketWebsiteUrl, do as withErrorHandling, dr as repairMalformedResourcesForReadOnly, dt as definedAttributes, ea as resolveStateBucketWithDefault, ei as hasReasonlessBaselineRefusal, en as replayWarn, eo as PartialFailureError, er as refuseMalformedResourceAttributesForOrphan, et as collectDeclaredOutputNames, f as updatePartialReason, fa as injectiveKey, fi as createAssetRedirectResolver, fn as applyRoleArnIfSet, fo as pasteableCommand, fr as safeRegion, ft as stringifyIfAssigned, g as computeImplicitDeleteEdges, ga as decodeListingKey, gi as BOOTSTRAP_MARKER_PREFIX, gn as envCredentialsAreAssumedRole, go as isThrottlingError, gr as findActionableSilentDrops, gt as maskDeep, h as IMPLICIT_DELETE_DEPENDENCIES, ha as producerRecordKey, hi as AssetModeResolver, hn as callerEnvCredentials, ho as isRetryableTransientError, hr as unreadableOrphanRecords, ht as createMaskedRetryLogger, i as DeploymentEventsReader, ia as warnDeprecatedNoPrefixCliFlag, ii as isReadableBag, in as classifyReplaySecretRegion, io as StackHasActiveImportsError, ir as refuseMalformedResourcesForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as displayAssemblyPath, ji as dockerSpawnEnvWithSensitive, jn as malformedLocalOutputsWarning, jr as isSingleDynamicReferenceToken, jt as isTerminationProtectionPropagationError, k as ccRoutedFinalSnapshotError, ka as ownValue, ki as describeDockerExecFailure, kn as malformedExportNamesWarning, kr as errorCauseChain, kt as isWaitAbandonedError, l as replayRollback, la as findLargeInlineResources, li as stringifyValue, ln as s3BucketDualStackDomainName, lr as repairMalformedResourceEntriesForReadOnly, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as producerCoordinateKey, mi as rewriteTemplateAssetReferences, mn as applyCallerIdentityCredentials, mo as isMarkedNonRetryable, mr as unpreviewableOrphanRecords, mt as wouldReturnToSdkProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveUseCdkBootstrapAssets, ni as importableOutputKeys, nn as requireConfigObject, no as ResourceTimeoutError, nr as refuseMalformedResourceEntriesForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as CFN_TEMPLATE_BODY_LIMIT, oi as orphansCarriedFrom, on as withSharedDrainBudget, or as repairMalformedOrphanRecordsForReadOnly, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as injectiveKeyPrefix, pi as loadPublishableAssetManifest, pn as AWS_CREDENTIAL_ENV_KEYS, po as shellQuote, pr as safeStackName, pt as ProviderRegistry, q as formatResourceLine, qa as DynamicReferenceRegionAmbiguousError, qi as synthesisStatusMessage, qn as refuseMalformedOrphanRecords, qr as buildLockContentionMessage, qt as assertRegionMatch, r as DeployEngine, ra as stateBucketExistenceConfirmed, ri as importableOutputs, rn as requireConfigString, ro as ResourceUpdateNotSupportedError, rr as refuseMalformedResourcePropertiesForOrphan, rt as isExportAliasCollision, s as planRollback, sa as CFN_TEMPLATE_URL_LIMIT, si as shouldRetainResource, sn as s3BucketArn, so as SynthesisError, sr as repairMalformedOrphansForReadOnly, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as resolveStateBucketWithDefaultAndSource, ti as hasUnverifiableParameterRefusal, tn as requireConfigArray, to as ProvisioningError, tr as refuseMalformedResourceEntries, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as uploadCfnTemplate, ui as WorkGraph, un as s3BucketRegionalDomainName, uo as normalizeAwsError, ur as repairMalformedResourcePropertiesForReadOnly, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as PARTITION_TABLE, vi as ensureAssetStorage, vn as INTRINSIC_KEYS, vo as markNonRetryable, vr as describeTypeWithThrottleRetry, vt as beginCommandInterruptScope, w as reachableDivergentParameters, wa as processStackMessages, wi as validateContainerRepoName, wn as hasReadableOrphans, wr as STATE_SOURCED_READBACK_RULES, wt as slowCcOperationTimeoutMs, x as bindingSkippedOutputs, xa as AssemblyReader, xi as parseBootstrapMarker, xn as UNREADABLE_RESOURCES_MAP_ROW, xo as describeAwsFailure, xr as TemplateParser, xt as isInterruptedWaitError, y as keptWholeReasonText, ya as canonicalizeRegion, yi as getBootstrapMarkerKey, yn as STATE_RESOURCES_MALFORMED, yo as markRedactedCause, yr as withRetry, yt as endCommandInterruptScope, z as isStatefulRecreateTargetForReplace, za as runWithStackAwsClients, zi as runDockerForeground, zn as malformedRenderedContainersWarning, zr as recoverMaskedOutput, zt as isNamelessDynamicReferenceError } from "./deploy-engine-BwDlgFRs.js";
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-DMRkEtU2.js";
5
- import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-CHM7_WdJ.js";
4
+ import { t as getCdkdVersion } from "./version-CJkb2usU.js";
5
+ import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-DR5gOGbi.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";
@@ -284,6 +284,51 @@ function describeStateKey(key, suffix = STATE_FILE_SUFFIX, knownPrefix) {
284
284
  */
285
285
  const STATE_KEY_MAX_CODE_POINTS = STACK_REF_MAX_CODE_POINTS + 64;
286
286
 
287
+ //#endregion
288
+ //#region src/provisioning/remove-protection-types.ts
289
+ /**
290
+ * The resource types whose SDK provider's `delete()` flips a protection flag
291
+ * off under `DeleteContext.removeProtection` (issue
292
+ * [#2660](https://github.com/go-to-k/cdkd/issues/2660)).
293
+ *
294
+ * This is the ONE list the `--remove-protection` help strings render from, on
295
+ * `cdkd destroy` and `cdkd state destroy`. The Cloud Control half comes from
296
+ * {@link ccProtectionRegistryTypes}. Both copies of the help were hand-written
297
+ * before, and two types the providers honour (`AWS::EMR::Cluster`,
298
+ * `AWS::DynamoDB::GlobalTable`) were missing from both.
299
+ *
300
+ * `tests/unit/provisioning/remove-protection-types.test.ts` binds this list to
301
+ * the provider tree in both directions: each type's registered provider reads
302
+ * `removeProtection`, and each provider file that reads it registers at least
303
+ * one type here. A new provider gaining the flip fails that test until its type
304
+ * is added.
305
+ */
306
+ const SDK_REMOVE_PROTECTION_TYPES = [
307
+ "AWS::Logs::LogGroup",
308
+ "AWS::RDS::DBInstance",
309
+ "AWS::RDS::DBCluster",
310
+ "AWS::DocDB::DBCluster",
311
+ "AWS::Neptune::DBCluster",
312
+ "AWS::Neptune::DBInstance",
313
+ "AWS::DynamoDB::Table",
314
+ "AWS::DynamoDB::GlobalTable",
315
+ "AWS::EC2::Instance",
316
+ "AWS::Cognito::UserPool",
317
+ "AWS::AutoScaling::AutoScalingGroup",
318
+ "AWS::ElasticLoadBalancingV2::LoadBalancer",
319
+ "AWS::EMR::Cluster"
320
+ ];
321
+ /** Every type `--remove-protection` covers: the SDK list, then the Cloud Control registry. */
322
+ function removeProtectionTypes() {
323
+ return [...SDK_REMOVE_PROTECTION_TYPES, ...ccProtectionRegistryTypes()];
324
+ }
325
+ /** The types as the help prints them: `A, B, and C`. */
326
+ function removeProtectionTypeList() {
327
+ const types = removeProtectionTypes();
328
+ if (types.length < 2) return types.join("");
329
+ return `${types.slice(0, -1).join(", ")}, and ${types[types.length - 1]}`;
330
+ }
331
+
287
332
  //#endregion
288
333
  //#region src/cli/options.ts
289
334
  /**
@@ -1127,7 +1172,7 @@ function effectiveAssumeRoleArn(logicalId, opt) {
1127
1172
  */
1128
1173
  const destroyOptions = [
1129
1174
  new Option("-f, --force", "Do not ask for confirmation before destroying the stacks").default(false),
1130
- new Option("--remove-protection", "Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DocDB::DBCluster, AWS::Neptune::DBCluster, AWS::Neptune::DBInstance, AWS::DynamoDB::Table, AWS::EC2::Instance, AWS::Cognito::UserPool, AWS::AutoScaling::AutoScalingGroup, AWS::ElasticLoadBalancingV2::LoadBalancer, AWS::DSQL::Cluster, AWS::NeptuneGraph::Graph, AWS::SMSVOICE::ProtectConfiguration, AWS::VerifiedPermissions::PolicyStore, AWS::EKS::Cluster, AWS::RDS::GlobalCluster, and AWS::DocDB::GlobalCluster.").default(false),
1175
+ new Option("--remove-protection", `Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on ${removeProtectionTypeList()}.`).default(false),
1131
1176
  allowUnsupportedTypesOption
1132
1177
  ];
1133
1178
  /**
@@ -2392,12 +2437,12 @@ function countDeployableResources(template) {
2392
2437
  */
2393
2438
  function resolveVerboseTemplatePath(outputDir, stackName) {
2394
2439
  const resolved = resolveAssemblyPath(outputDir, `${stackName}.template.json`);
2395
- if (!resolved.contained) throw new SynthesisError(`Stack '${displaySafe(stackName)}' would write its template to a path that ${renderAssemblyPathEscape(resolved, outputDir, "write it")}`);
2440
+ if (!resolved.contained) throw new SynthesisError(`Stack ${displayStackName(stackName)} would write its template to a path that ${renderAssemblyPathEscape(resolved, outputDir, "write it")}`);
2396
2441
  let linked = false;
2397
2442
  try {
2398
2443
  linked = lstatSync(resolved.path).isSymbolicLink();
2399
2444
  } catch {}
2400
- if (linked) throw new SynthesisError(`Stack '${displaySafe(stackName)}' would write its template over a symbolic link at ${displayAssemblyPath(resolved.path)}. cdkd writes a stack's template as a regular file beside the assembly; a symbolic link there redirects the write to wherever it points, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to write it.`);
2445
+ if (linked) throw new SynthesisError(`Stack ${displayStackName(stackName)} would write its template over a symbolic link at ${displayAssemblyPath(resolved.path)}. cdkd writes a stack's template as a regular file beside the assembly; a symbolic link there redirects the write to wherever it points, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to write it.`);
2401
2446
  return resolved.path;
2402
2447
  }
2403
2448
  /**
@@ -3789,15 +3834,16 @@ function findNestedTemplateTreeDefect(nestedTemplates, ancestorTemplatePaths = [
3789
3834
  /** Hops rendered in full before the middle of a long chain is elided. */
3790
3835
  const MAX_RENDERED_HOPS = 8;
3791
3836
  /**
3792
- * `'A' (/x/a.json) -> 'B' (/x/b.json)`. Every interpolation goes through
3793
- * `displaySafe`: this text exists FOR a hand-modified assembly, so a logical id
3837
+ * `A (/x/a.json) -> B (/x/b.json)`. The logical id renders through
3838
+ * `displayIdent` and the path through `displayAssemblyPath`, each supplying its
3839
+ * own boundary: this text exists FOR a hand-modified assembly, so a logical id
3794
3840
  * (a template key) and a path (derived from `aws:asset:path`) are both
3795
3841
  * attacker-controlled, and a bare `Error` message is not sanitized downstream.
3796
3842
  * A long chain keeps both ends, since the entry row and the closing row are
3797
3843
  * the two a reader needs.
3798
3844
  */
3799
3845
  function renderChain(chain) {
3800
- const hop = (h) => `'${displaySafe(h.logicalId)}' (${displayAssemblyPath(h.templatePath)})`;
3846
+ const hop = (h) => `${displayIdent(h.logicalId)} (${displayAssemblyPath(h.templatePath)})`;
3801
3847
  if (chain.length <= MAX_RENDERED_HOPS) return chain.map(hop).join(" -> ");
3802
3848
  const keep = MAX_RENDERED_HOPS / 2;
3803
3849
  return [
@@ -3815,21 +3861,19 @@ function renderNestedTemplateTreeDefect(defect, stackName, action) {
3815
3861
  const owner = (chain) => {
3816
3862
  const ids = chain.slice(0, -1).map((h) => h.logicalId);
3817
3863
  const keep = MAX_RENDERED_HOPS / 2;
3818
- const shown = ids.length <= MAX_RENDERED_HOPS ? ids : [
3819
- ...ids.slice(0, keep),
3820
- `...${ids.length - 8} more...`,
3821
- ...ids.slice(-4)
3822
- ];
3823
- return displaySafe([stackName, ...shown].join("~"));
3864
+ if (ids.length <= MAX_RENDERED_HOPS) return displayStackName([stackName, ...ids].join("~"));
3865
+ const head = displayStackName([stackName, ...ids.slice(0, keep)].join("~"));
3866
+ const tail = displayStackName(ids.slice(-4).join("~"));
3867
+ return `${head}~...${ids.length - 8} more...~${tail}`;
3824
3868
  };
3825
3869
  if (defect.kind === "cycle") {
3826
3870
  const closing = defect.chain[defect.chain.length - 1];
3827
- return `The nested template tree under stack '${displaySafe(stackName)}' contains a cycle: ${renderChain(defect.chain)}. Nested stack '${displaySafe(closing.logicalId)}' (declared in stack '${owner(defect.chain)}') resolves to a template that is already on that nesting chain, so its Metadata['aws:asset:path'] closes a cycle. ${provenance}`;
3871
+ return `The nested template tree under stack ${displayStackName(stackName)} contains a cycle: ${renderChain(defect.chain)}. Nested stack ${displayIdent(closing.logicalId)} (declared in stack ${owner(defect.chain)}) resolves to a template that is already on that nesting chain, so its Metadata['aws:asset:path'] closes a cycle. ${provenance}`;
3828
3872
  }
3829
- if (defect.kind === "too-large") return `The nested template tree under stack '${displaySafe(stackName)}' has more than ${MAX_ROWS_FOLLOWED} nested-stack rows to follow (the walk stopped at ${renderChain(defect.chain)}). That is far beyond any CDK-generated assembly. Symlinked directories can give one template file many paths, which multiplies the tree without ever repeating on one chain. Refusing to ${action}.`;
3830
- if (defect.kind === "too-deep") return `The nested template tree under stack '${displaySafe(stackName)}' nests more than ${512} levels deep: ${renderChain(defect.chain)}. No tree that deep can deploy, because each level lengthens the child's state key and S3 caps a key at 1024 bytes. ${provenance}`;
3831
- if (defect.kind === "escaping-path") return `The nested template tree under stack '${displaySafe(stackName)}' has nested stack '${displaySafe(defect.logicalId)}' (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which ${renderAssemblyPathEscape(defect.escape, defect.dir, action)}`;
3832
- return `The nested template tree under stack '${displaySafe(stackName)}' has nested stack '${displaySafe(defect.logicalId)}' (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which is absolute. ${provenance}`;
3873
+ if (defect.kind === "too-large") return `The nested template tree under stack ${displayStackName(stackName)} has more than ${MAX_ROWS_FOLLOWED} nested-stack rows to follow (the walk stopped at ${renderChain(defect.chain)}). That is far beyond any CDK-generated assembly. Symlinked directories can give one template file many paths, which multiplies the tree without ever repeating on one chain. Refusing to ${action}.`;
3874
+ if (defect.kind === "too-deep") return `The nested template tree under stack ${displayStackName(stackName)} nests more than ${512} levels deep: ${renderChain(defect.chain)}. No tree that deep can deploy, because each level lengthens the child's state key and S3 caps a key at 1024 bytes. ${provenance}`;
3875
+ if (defect.kind === "escaping-path") return `The nested template tree under stack ${displayStackName(stackName)} has nested stack ${displayIdent(defect.logicalId)} (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which ${renderAssemblyPathEscape(defect.escape, defect.dir, action)}`;
3876
+ return `The nested template tree under stack ${displayStackName(stackName)} has nested stack ${displayIdent(defect.logicalId)} (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which is absolute. ${provenance}`;
3833
3877
  }
3834
3878
 
3835
3879
  //#endregion
@@ -4598,8 +4642,8 @@ var ExportIndexStore = class {
4598
4642
  */
4599
4643
  warnOnForeignOverwrite(existing, exportName, stackName, producerRegion) {
4600
4644
  if (!existing || existing.producerStack === stackName) return;
4601
- const safeName = displaySafe(exportName);
4602
- this.logger.warn(`Export '${safeName}' is published by both '${existing.producerStack}' (${existing.producerRegion}) and '${stackName}' (${producerRegion}); the exports index keeps the latest writer, so an Fn::ImportValue on it binds to whichever deployed last. CloudFormation refuses a second producer of the same export name — rename one of the two exports. (If '${existing.producerStack}' predates cdkd's state schema v9, this is its stale entry for a plain output of that name, and its next deploy clears it.)`);
4645
+ const theirs = displayStackName(existing.producerStack);
4646
+ this.logger.warn(`Export ${displayIdent(exportName)} is published by both ${theirs} (${displayIdent(existing.producerRegion)}) and ${displayStackName(stackName)} (${displayIdent(producerRegion)}); the exports index keeps the latest writer, so an Fn::ImportValue on it binds to whichever deployed last. CloudFormation refuses a second producer of the same export name — rename one of the two exports. (If ${theirs} predates cdkd's state schema v9, this is its stale entry for a plain output of that name, and its next deploy clears it.)`);
4603
4647
  }
4604
4648
  async applyPatch(exportName, entry, requireOwner) {
4605
4649
  await this.ensureLoaded();
@@ -4607,7 +4651,7 @@ var ExportIndexStore = class {
4607
4651
  if (requireOwner) {
4608
4652
  const current = this.loadState.entries.get(exportName);
4609
4653
  if (!current || current.producerStack !== requireOwner.producerStack || current.producerRegion !== requireOwner.producerRegion) {
4610
- this.logger.warn(`Exports index entry ownership changed under a patch; refusing to write it. Expected producer '${displaySafe(requireOwner.producerStack)}' (${displaySafe(requireOwner.producerRegion)}), found ${current ? `'${displaySafe(current.producerStack)}' (${displaySafe(current.producerRegion)})` : "no entry"}.`);
4654
+ this.logger.warn(`Exports index entry ownership changed under a patch; refusing to write it. Expected producer ${displayStackName(requireOwner.producerStack)} (${displayIdent(requireOwner.producerRegion)}), found ${current ? `${displayStackName(current.producerStack)} (${displayIdent(current.producerRegion)})` : "no entry"}.`);
4611
4655
  return false;
4612
4656
  }
4613
4657
  }
@@ -5862,10 +5906,10 @@ var IAMInstanceProfileProvider = class {
5862
5906
  async import(input) {
5863
5907
  const explicit = resolveExplicitPhysicalId(input, "InstanceProfileName");
5864
5908
  if (explicit) try {
5865
- await this.iamClient.send(new GetInstanceProfileCommand({ InstanceProfileName: explicit }));
5909
+ const resp = await this.iamClient.send(new GetInstanceProfileCommand({ InstanceProfileName: explicit }));
5866
5910
  return {
5867
5911
  physicalId: explicit,
5868
- attributes: {}
5912
+ attributes: definedAttributes({ Arn: resp.InstanceProfile?.Arn })
5869
5913
  };
5870
5914
  } catch (err) {
5871
5915
  if (err instanceof NoSuchEntityException) return null;
@@ -7199,10 +7243,10 @@ var IAMUserGroupProvider = class {
7199
7243
  async importUser(input) {
7200
7244
  const explicit = resolveExplicitPhysicalId(input, "UserName");
7201
7245
  if (explicit) try {
7202
- await this.iamClient.send(new GetUserCommand({ UserName: explicit }));
7246
+ const resp = await this.iamClient.send(new GetUserCommand({ UserName: explicit }));
7203
7247
  return {
7204
7248
  physicalId: explicit,
7205
- attributes: {}
7249
+ attributes: definedAttributes({ Arn: resp.User?.Arn })
7206
7250
  };
7207
7251
  } catch (err) {
7208
7252
  if (err instanceof NoSuchEntityException) return null;
@@ -7213,10 +7257,10 @@ var IAMUserGroupProvider = class {
7213
7257
  async importGroup(input) {
7214
7258
  const explicit = resolveExplicitPhysicalId(input, "GroupName");
7215
7259
  if (explicit) try {
7216
- await this.iamClient.send(new GetGroupCommand({ GroupName: explicit }));
7260
+ const resp = await this.iamClient.send(new GetGroupCommand({ GroupName: explicit }));
7217
7261
  return {
7218
7262
  physicalId: explicit,
7219
- attributes: {}
7263
+ attributes: definedAttributes({ Arn: resp.Group?.Arn })
7220
7264
  };
7221
7265
  } catch (err) {
7222
7266
  if (err instanceof NoSuchEntityException) return null;
@@ -13868,6 +13912,29 @@ function isSnsTopicArnList(value) {
13868
13912
  */
13869
13913
  const LAMBDA_CLEANUP_DELETE_MAX_ATTEMPTS = 3;
13870
13914
  /**
13915
+ * Refuse `CodeSigningConfigArn` / `RuntimeManagementConfig` on a
13916
+ * container-image function (`PackageType: Image`), BEFORE any Lambda call.
13917
+ * AWS rejects both there with `InvalidParameterValueException`: the image
13918
+ * carries its own runtime, so there are no runtime-management controls, and
13919
+ * Lambda code signing does not apply to images (issue
13920
+ * [#1894](https://github.com/go-to-k/cdkd/issues/1894)). The READ side skips
13921
+ * the matching `Get*` calls for the same reason (see `readCurrentState`). Without it the create either
13922
+ * fails on `CreateFunction` (code signing) or creates the function, fails the
13923
+ * post-create `PutRuntimeManagementConfig` and deletes it again; the update
13924
+ * fails part-way through on the Put.
13925
+ *
13926
+ * Unconditional, including on a rollback replay (`replayingState`): AWS
13927
+ * rejects the combination every time, so no state record can carry it and a
13928
+ * downgraded warning could only report success over a call that then fails
13929
+ * (the `.claude/rules/provider-replay-and-refusals.md` exception).
13930
+ */
13931
+ function refuseImageFunctionUnsupported(logicalId, resourceType, properties, physicalId) {
13932
+ if (properties["PackageType"] !== "Image") return;
13933
+ const declared = [properties["CodeSigningConfigArn"] !== void 0 ? "CodeSigningConfigArn" : void 0, properties["RuntimeManagementConfig"] !== void 0 ? "RuntimeManagementConfig" : void 0].filter((key) => key !== void 0);
13934
+ if (declared.length === 0) return;
13935
+ throw markNonRetryable(new ProvisioningError(`Lambda function ${logicalId} is a container-image function (PackageType: Image), and AWS rejects ${declared.join(" and ")} on one: an image carries its own runtime and Lambda code signing does not apply to images. Remove ${declared.length === 1 ? "it" : "them"} from the function's properties.`, resourceType, logicalId, physicalId));
13936
+ }
13937
+ /**
13871
13938
  * Pick the inline-code filename for a Lambda runtime.
13872
13939
  *
13873
13940
  * CloudFormation's `Code.ZipFile` auto-zips inline code into a file named
@@ -13962,6 +14029,7 @@ var LambdaFunctionProvider = class {
13962
14029
  const role = properties["Role"];
13963
14030
  if (!code) throw new ProvisioningError(`Code is required for Lambda function ${logicalId}`, resourceType, logicalId);
13964
14031
  if (!role) throw new ProvisioningError(`Role is required for Lambda function ${logicalId}`, resourceType, logicalId);
14032
+ refuseImageFunctionUnsupported(logicalId, resourceType, properties);
13965
14033
  try {
13966
14034
  let tags;
13967
14035
  if (properties["Tags"]) {
@@ -14112,6 +14180,7 @@ var LambdaFunctionProvider = class {
14112
14180
  const mask = maskerOrIdentity(context?.maskSecrets);
14113
14181
  const debug = (message) => this.logger.debug(mask(message));
14114
14182
  this.logger.debug(`Updating Lambda function ${logicalId}: ${physicalId}`);
14183
+ refuseImageFunctionUnsupported(logicalId, resourceType, properties, physicalId);
14115
14184
  try {
14116
14185
  const configFields = [
14117
14186
  "Role",
@@ -27953,10 +28022,17 @@ var SSMParameterProvider = class {
27953
28022
  if (explicit) {
27954
28023
  this.refuseUnwritableParameterId(input, explicit);
27955
28024
  try {
27956
- const arn = (await this.ssmClient.send(new GetParameterCommand({ Name: explicit }))).Parameter?.ARN;
28025
+ const resp = await this.ssmClient.send(new GetParameterCommand({ Name: explicit }));
28026
+ const arn = resp.Parameter?.ARN;
28027
+ const declared = input.properties?.["Value"];
28028
+ const literalValue = typeof declared === "string" && !declared.includes("{{resolve:");
27957
28029
  return {
27958
28030
  physicalId: explicit,
27959
- attributes: { ...arn !== void 0 && { Arn: arn } }
28031
+ attributes: definedAttributes({
28032
+ Type: resp.Parameter?.Type,
28033
+ ...literalValue && { Value: resp.Parameter?.Value },
28034
+ Arn: arn
28035
+ })
27960
28036
  };
27961
28037
  } catch (err) {
27962
28038
  if (err instanceof ParameterNotFound) return null;
@@ -28701,6 +28777,39 @@ var EventBridgeBusProvider = class {
28701
28777
  }
28702
28778
  };
28703
28779
 
28780
+ //#endregion
28781
+ //#region src/utils/ipv4-cidr.ts
28782
+ /**
28783
+ * Return the host-bit-cleared form of an IPv4 CIDR (`100.68.0.18/18` ->
28784
+ * `100.68.0.0/18`), or `undefined` when the input is not an IPv4 CIDR at all
28785
+ * (an IPv6 CIDR, a `pl-…` prefix-list id, or anything malformed).
28786
+ *
28787
+ * AWS rewrites a non-canonical CIDR on `CreateRoute`, so a route id that
28788
+ * spells the template's CIDR can differ from the destination AWS reports
28789
+ * (issue #1771). `EC2Provider`'s import compares through this (issue #3661).
28790
+ * `src/cli/commands/export.ts` still carries a private copy of the same
28791
+ * function; fold it onto this one once the open PR holding that file lands.
28792
+ */
28793
+ function canonicalizeIpv4Cidr$1(value) {
28794
+ const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(value);
28795
+ if (!match) return void 0;
28796
+ const octets = [
28797
+ match[1],
28798
+ match[2],
28799
+ match[3],
28800
+ match[4]
28801
+ ].map(Number);
28802
+ const prefixLength = Number(match[5]);
28803
+ if (prefixLength > 32 || octets.some((octet) => octet > 255)) return void 0;
28804
+ const network = ((octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]) >>> 0 & (prefixLength === 0 ? 0 : 4294967295 << 32 - prefixLength >>> 0)) >>> 0;
28805
+ return `${[
28806
+ network >>> 24,
28807
+ network >>> 16 & 255,
28808
+ network >>> 8 & 255,
28809
+ network & 255
28810
+ ].join(".")}/${prefixLength}`;
28811
+ }
28812
+
28704
28813
  //#endregion
28705
28814
  //#region src/provisioning/providers/idempotency-token.ts
28706
28815
  /**
@@ -30225,12 +30334,16 @@ var EC2Provider = class {
30225
30334
  try {
30226
30335
  const ingressRules = properties["SecurityGroupIngress"];
30227
30336
  const egressRules = properties["SecurityGroupEgress"];
30228
- const firstRejection = (await Promise.allSettled([
30229
- this.applyTags(groupId, properties, logicalId),
30230
- this.authorizeInlineIngress(groupId, ingressRules),
30231
- this.applyInlineEgress(groupId, egressRules)
30232
- ])).find((r) => r.status === "rejected");
30233
- if (firstRejection) throw firstRejection.reason;
30337
+ let firstRejection;
30338
+ const recordRejection = (branch) => branch.catch((error) => {
30339
+ firstRejection ??= { error };
30340
+ });
30341
+ await Promise.all([
30342
+ recordRejection(this.applyTags(groupId, properties, logicalId)),
30343
+ recordRejection(this.authorizeInlineIngress(groupId, ingressRules)),
30344
+ recordRejection(this.applyInlineEgress(groupId, egressRules))
30345
+ ]);
30346
+ if (firstRejection !== void 0) throw firstRejection.error;
30234
30347
  } catch (innerError) {
30235
30348
  try {
30236
30349
  await this.ec2Client.send(new DeleteSecurityGroupCommand({ GroupId: groupId }));
@@ -31572,12 +31685,14 @@ var EC2Provider = class {
31572
31685
  * id, and records cdkd's composite `<groupId>|<ipProtocol>|<fromPort>|<toPort>`
31573
31686
  * plus the rule id as the `Id` attribute (issue #1761).
31574
31687
  *
31575
- * The remaining EC2 types this provider creates (RouteTable, Route,
31576
- * InternetGateway, VPCGatewayAttachment, NetworkAcl, NetworkAclEntry,
31577
- * SubnetRouteTableAssociation, SubnetNetworkAclAssociation, Instance) return
31578
- * `null` — Routes and associations are derived from their parent, and the
31579
- * typical adoption story is "find the VPC, cdkd reconstructs the rest at
31580
- * deploy time".
31688
+ * - RouteTable, Route, InternetGateway, VPCGatewayAttachment, NetworkAcl,
31689
+ * NetworkAclEntry, SubnetRouteTableAssociation, SubnetNetworkAclAssociation,
31690
+ * Instance (issue #3661) — they used to return `null` on the premise that
31691
+ * cdkd reconstructs them at deploy time, which `--migrate-from-cloudformation`
31692
+ * breaks: the CloudFormation stack is retired with them live, and the
31693
+ * re-create duplicates or conflicts. VPCGatewayAttachment and
31694
+ * NetworkAclEntry rebuild cdkd's composite from the template, since
31695
+ * CloudFormation's id for them does not carry it.
31581
31696
  *
31582
31697
  * There is no `aws:cdk:path` tag lookup: AWS rejects `aws:`-prefixed tag
31583
31698
  * writes, so that tag never exists on a real resource and a
@@ -31587,7 +31702,7 @@ var EC2Provider = class {
31587
31702
  * physical-name property instead.
31588
31703
  */
31589
31704
  async import(input) {
31590
- if (input.knownPhysicalId) return this.verifyExplicit(input.logicalId, input.resourceType, input.knownPhysicalId);
31705
+ if (input.knownPhysicalId) return this.verifyExplicit(input.logicalId, input.resourceType, input.knownPhysicalId, input.properties ?? {});
31591
31706
  return null;
31592
31707
  }
31593
31708
  /**
@@ -32150,17 +32265,23 @@ var EC2Provider = class {
32150
32265
  }
32151
32266
  }
32152
32267
  }
32153
- async verifyExplicit(logicalId, resourceType, physicalId) {
32268
+ async verifyExplicit(logicalId, resourceType, physicalId, properties) {
32154
32269
  try {
32155
32270
  switch (resourceType) {
32156
32271
  case "AWS::EC2::VPC": return (await this.ec2Client.send(new DescribeVpcsCommand({ VpcIds: [physicalId] }))).Vpcs?.[0] ? {
32157
32272
  physicalId,
32158
32273
  attributes: {}
32159
32274
  } : null;
32160
- case "AWS::EC2::Subnet": return (await this.ec2Client.send(new DescribeSubnetsCommand({ SubnetIds: [physicalId] }))).Subnets?.[0] ? {
32161
- physicalId,
32162
- attributes: {}
32163
- } : null;
32275
+ case "AWS::EC2::Subnet": {
32276
+ const subnet = (await this.ec2Client.send(new DescribeSubnetsCommand({ SubnetIds: [physicalId] }))).Subnets?.[0];
32277
+ return subnet ? {
32278
+ physicalId,
32279
+ attributes: definedAttributes({
32280
+ SubnetId: physicalId,
32281
+ AvailabilityZone: subnet.AvailabilityZone
32282
+ })
32283
+ } : null;
32284
+ }
32164
32285
  case "AWS::EC2::SecurityGroup": {
32165
32286
  const group = (await this.ec2Client.send(new DescribeSecurityGroupsCommand({ GroupIds: [physicalId] }))).SecurityGroups?.[0];
32166
32287
  if (!group) return null;
@@ -32233,6 +32354,125 @@ var EC2Provider = class {
32233
32354
  }
32234
32355
  };
32235
32356
  }
32357
+ case "AWS::EC2::RouteTable":
32358
+ if (!/^rtb-[0-9a-f]+$/.test(physicalId)) return null;
32359
+ return (await this.ec2Client.send(new DescribeRouteTablesCommand({ RouteTableIds: [physicalId] }))).RouteTables?.[0] ? {
32360
+ physicalId,
32361
+ attributes: { RouteTableId: physicalId }
32362
+ } : null;
32363
+ case "AWS::EC2::InternetGateway":
32364
+ if (!/^igw-[0-9a-f]+$/.test(physicalId)) return null;
32365
+ return (await this.ec2Client.send(new DescribeInternetGatewaysCommand({ InternetGatewayIds: [physicalId] }))).InternetGateways?.[0] ? {
32366
+ physicalId,
32367
+ attributes: { InternetGatewayId: physicalId }
32368
+ } : null;
32369
+ case "AWS::EC2::NetworkAcl":
32370
+ if (!/^acl-[0-9a-f]+$/.test(physicalId)) return null;
32371
+ return (await this.ec2Client.send(new DescribeNetworkAclsCommand({ NetworkAclIds: [physicalId] }))).NetworkAcls?.[0] ? {
32372
+ physicalId,
32373
+ attributes: { Id: physicalId }
32374
+ } : null;
32375
+ case "AWS::EC2::Route": {
32376
+ const [routeTableId, destination, ...rest] = physicalId.split("|");
32377
+ if (rest.length > 0 || !routeTableId || !destination) return null;
32378
+ if (!/^rtb-[0-9a-f]+$/.test(routeTableId)) return null;
32379
+ const resp = await this.ec2Client.send(new DescribeRouteTablesCommand({ RouteTableIds: [routeTableId] }));
32380
+ const wanted = canonicalizeIpv4Cidr$1(destination) ?? destination;
32381
+ return resp.RouteTables?.[0]?.Routes?.some((r) => r.DestinationCidrBlock !== void 0 && (canonicalizeIpv4Cidr$1(r.DestinationCidrBlock) ?? r.DestinationCidrBlock) === wanted || r.DestinationIpv6CidrBlock === destination || r.DestinationPrefixListId === destination) ? {
32382
+ physicalId,
32383
+ attributes: {}
32384
+ } : null;
32385
+ }
32386
+ case "AWS::EC2::VPCGatewayAttachment": {
32387
+ const segments = physicalId.split("|");
32388
+ if (segments.length !== 2) return null;
32389
+ if (segments.includes("VGW") || properties["VpnGatewayId"] !== void 0) return null;
32390
+ const vpcId = segments.find((seg) => /^vpc-[0-9a-f]+$/.test(seg)) ?? (typeof properties["VpcId"] === "string" ? properties["VpcId"] : void 0);
32391
+ if (!vpcId || !/^vpc-[0-9a-f]+$/.test(vpcId)) return null;
32392
+ const declared = segments.find((seg) => /^igw-[0-9a-f]+$/.test(seg)) ?? (typeof properties["InternetGatewayId"] === "string" ? properties["InternetGatewayId"] : void 0);
32393
+ if (declared !== void 0 && !/^igw-[0-9a-f]+$/.test(declared)) return null;
32394
+ const gateway = (await this.ec2Client.send(new DescribeInternetGatewaysCommand(declared ? { InternetGatewayIds: [declared] } : { Filters: [{
32395
+ Name: "attachment.vpc-id",
32396
+ Values: [vpcId]
32397
+ }] }))).InternetGateways?.find((g) => g.Attachments?.some((a) => a.VpcId === vpcId && ["available", "attached"].includes(String(a.State))));
32398
+ if (!gateway?.InternetGatewayId) return null;
32399
+ const attachmentSegments = [{
32400
+ name: "internetGatewayId",
32401
+ value: gateway.InternetGatewayId
32402
+ }, {
32403
+ name: "vpcId",
32404
+ value: vpcId
32405
+ }];
32406
+ const refusal = compositeIdSeparatorRefusal(resourceType, logicalId, attachmentSegments);
32407
+ if (refusal !== void 0) {
32408
+ this.logger.warn(`${refusal} Skipping import.`);
32409
+ return null;
32410
+ }
32411
+ return {
32412
+ physicalId: packCompositeId(resourceType, logicalId, attachmentSegments),
32413
+ attributes: {}
32414
+ };
32415
+ }
32416
+ case "AWS::EC2::NetworkAclEntry": {
32417
+ const own = /^(acl-[0-9a-f]+)\|(\d+)\|(true|false)$/.exec(physicalId);
32418
+ const networkAclId = own ? own[1] : typeof properties["NetworkAclId"] === "string" ? properties["NetworkAclId"] : void 0;
32419
+ const ruleNumber = own ? Number(own[2]) : Number(properties["RuleNumber"]);
32420
+ const egress = own ? own[3] === "true" : properties["Egress"] === true || properties["Egress"] === "true";
32421
+ if (!networkAclId || !/^acl-[0-9a-f]+$/.test(networkAclId)) return null;
32422
+ if (!Number.isInteger(ruleNumber)) return null;
32423
+ if (!(await this.ec2Client.send(new DescribeNetworkAclsCommand({ NetworkAclIds: [networkAclId] }))).NetworkAcls?.[0]?.Entries?.find((e) => e.RuleNumber === ruleNumber && (e.Egress ?? false) === egress)) return null;
32424
+ const entrySegments = [
32425
+ {
32426
+ name: "networkAclId",
32427
+ value: networkAclId
32428
+ },
32429
+ {
32430
+ name: "ruleNumber",
32431
+ value: ruleNumber
32432
+ },
32433
+ {
32434
+ name: "egress",
32435
+ value: egress
32436
+ }
32437
+ ];
32438
+ const refusal = compositeIdSeparatorRefusal(resourceType, logicalId, entrySegments);
32439
+ if (refusal !== void 0) {
32440
+ this.logger.warn(`${refusal} Skipping import.`);
32441
+ return null;
32442
+ }
32443
+ return {
32444
+ physicalId: packCompositeId(resourceType, logicalId, entrySegments),
32445
+ attributes: {}
32446
+ };
32447
+ }
32448
+ case "AWS::EC2::SubnetRouteTableAssociation":
32449
+ if (!/^rtbassoc-[0-9a-f]+$/.test(physicalId)) return null;
32450
+ return (await this.ec2Client.send(new DescribeRouteTablesCommand({ Filters: [{
32451
+ Name: "association.route-table-association-id",
32452
+ Values: [physicalId]
32453
+ }] }))).RouteTables?.[0] ? {
32454
+ physicalId,
32455
+ attributes: {}
32456
+ } : null;
32457
+ case "AWS::EC2::SubnetNetworkAclAssociation":
32458
+ if (!/^aclassoc-[0-9a-f]+$/.test(physicalId)) return null;
32459
+ return (await this.ec2Client.send(new DescribeNetworkAclsCommand({ Filters: [{
32460
+ Name: "association.association-id",
32461
+ Values: [physicalId]
32462
+ }] }))).NetworkAcls?.[0] ? {
32463
+ physicalId,
32464
+ attributes: { AssociationId: physicalId }
32465
+ } : null;
32466
+ case "AWS::EC2::Instance": {
32467
+ if (!/^i-[0-9a-f]+$/.test(physicalId)) return null;
32468
+ const instance = (await this.ec2Client.send(new DescribeInstancesCommand({ InstanceIds: [physicalId] }))).Reservations?.[0]?.Instances?.[0];
32469
+ const state = instance?.State?.Name;
32470
+ if (!instance || state === "terminated" || state === "shutting-down") return null;
32471
+ return {
32472
+ physicalId,
32473
+ attributes: describedInstanceAttributes(physicalId, instance)
32474
+ };
32475
+ }
32236
32476
  default: return null;
32237
32477
  }
32238
32478
  } catch (error) {
@@ -35799,13 +36039,28 @@ var CloudFrontOAIProvider = class {
35799
36039
  *
35800
36040
  * Users adopting an existing OAI should pass
35801
36041
  * `--resource <logicalId>=<oaiId>` (e.g. `E1ABCDEF123456`).
36042
+ *
36043
+ * The override is read back (issue #3627): `S3CanonicalUserId` is the
36044
+ * attribute an S3 bucket policy grants the OAI by, `create()` records it,
36045
+ * and the resolver cannot build it from the id. Returns `null` when no OAI
36046
+ * exists behind the id.
35802
36047
  */
35803
36048
  async import(input) {
35804
- if (input.knownPhysicalId) return {
36049
+ if (!input.knownPhysicalId) return null;
36050
+ let resp;
36051
+ try {
36052
+ resp = await this.cloudFrontClient.send(new GetCloudFrontOriginAccessIdentityCommand({ Id: input.knownPhysicalId }));
36053
+ } catch (err) {
36054
+ if (err instanceof NoSuchCloudFrontOriginAccessIdentity) return null;
36055
+ throw err;
36056
+ }
36057
+ return {
35805
36058
  physicalId: input.knownPhysicalId,
35806
- attributes: { Id: input.knownPhysicalId }
36059
+ attributes: definedAttributes({
36060
+ Id: input.knownPhysicalId,
36061
+ S3CanonicalUserId: resp.CloudFrontOriginAccessIdentity?.S3CanonicalUserId
36062
+ })
35807
36063
  };
35808
- return null;
35809
36064
  }
35810
36065
  };
35811
36066
 
@@ -37933,20 +38188,24 @@ var AgentCoreEvaluatorProvider = class {
37933
38188
  */
37934
38189
  async import(input) {
37935
38190
  if (!input.knownPhysicalId) return null;
37936
- if (input.knownPhysicalId.includes(":evaluator/")) return {
37937
- physicalId: input.knownPhysicalId,
37938
- attributes: {
37939
- EvaluatorArn: input.knownPhysicalId,
37940
- EvaluatorId: evaluatorIdFromArn(input.knownPhysicalId)
37941
- }
37942
- };
37943
- const response = await this.client.send(new GetEvaluatorCommand({ evaluatorId: input.knownPhysicalId }));
38191
+ const isArn = input.knownPhysicalId.includes(":evaluator/");
38192
+ let response;
38193
+ try {
38194
+ response = await this.client.send(new GetEvaluatorCommand({ evaluatorId: evaluatorIdFromArn(input.knownPhysicalId) }));
38195
+ } catch (err) {
38196
+ if (err instanceof ResourceNotFoundException$6) return null;
38197
+ throw err;
38198
+ }
38199
+ const evaluatorArn = isArn ? input.knownPhysicalId : response.evaluatorArn;
38200
+ if (!evaluatorArn) return null;
37944
38201
  return {
37945
- physicalId: response.evaluatorArn,
37946
- attributes: {
37947
- EvaluatorArn: response.evaluatorArn,
37948
- EvaluatorId: response.evaluatorId ?? input.knownPhysicalId
37949
- }
38202
+ physicalId: evaluatorArn,
38203
+ attributes: definedAttributes({
38204
+ EvaluatorArn: evaluatorArn,
38205
+ EvaluatorId: response.evaluatorId ?? evaluatorIdFromArn(input.knownPhysicalId),
38206
+ Status: response.status,
38207
+ CreatedAt: response.createdAt?.toISOString()
38208
+ })
37950
38209
  };
37951
38210
  }
37952
38211
  };
@@ -40340,6 +40599,30 @@ const LOAD_BALANCER_ATTRIBUTE_DEFAULTS = {
40340
40599
  /** @see LOAD_BALANCER_ATTRIBUTE_DEFAULTS — same rule, Listener key table. */
40341
40600
  const LISTENER_ATTRIBUTE_DEFAULTS = { "routing.http.response.server.enabled": "true" };
40342
40601
  /**
40602
+ * The attribute map a load balancer records, shared by `create()` and
40603
+ * `import()` (issue #3627).
40604
+ */
40605
+ function loadBalancerAttributes(lb, lbArn) {
40606
+ return definedAttributes({
40607
+ DNSName: lb.DNSName,
40608
+ CanonicalHostedZoneID: lb.CanonicalHostedZoneId,
40609
+ LoadBalancerArn: lbArn,
40610
+ LoadBalancerFullName: lbArn.split("/").slice(1).join("/"),
40611
+ LoadBalancerName: lb.LoadBalancerName
40612
+ });
40613
+ }
40614
+ /**
40615
+ * The attribute map a target group records, shared by `create()`,
40616
+ * `update()` and `import()` (issue #3627).
40617
+ */
40618
+ function targetGroupAttributes(tg, tgArn) {
40619
+ return definedAttributes({
40620
+ TargetGroupArn: tgArn,
40621
+ TargetGroupFullName: tgArn.split(":").pop(),
40622
+ TargetGroupName: tg.TargetGroupName
40623
+ });
40624
+ }
40625
+ /**
40343
40626
  * AWS ELBv2 Provider
40344
40627
  *
40345
40628
  * Implements resource provisioning for ELBv2 resources:
@@ -40597,13 +40880,7 @@ var ELBv2Provider = class {
40597
40880
  }
40598
40881
  return {
40599
40882
  physicalId: lbArn,
40600
- attributes: {
40601
- DNSName: lb.DNSName,
40602
- CanonicalHostedZoneID: lb.CanonicalHostedZoneId,
40603
- LoadBalancerArn: lbArn,
40604
- LoadBalancerFullName: lbArn.split("/").slice(1).join("/"),
40605
- LoadBalancerName: lb.LoadBalancerName
40606
- }
40883
+ attributes: loadBalancerAttributes(lb, lbArn)
40607
40884
  };
40608
40885
  } catch (error) {
40609
40886
  const cause = error instanceof Error ? error : void 0;
@@ -40840,11 +41117,7 @@ var ELBv2Provider = class {
40840
41117
  }
40841
41118
  return {
40842
41119
  physicalId: tgArn,
40843
- attributes: {
40844
- TargetGroupArn: tgArn,
40845
- TargetGroupFullName: tgArn.split(":").pop()?.replace("targetgroup/", ""),
40846
- TargetGroupName: tg.TargetGroupName
40847
- }
41120
+ attributes: targetGroupAttributes(tg, tgArn)
40848
41121
  };
40849
41122
  } catch (error) {
40850
41123
  const cause = error instanceof Error ? error : void 0;
@@ -40922,11 +41195,7 @@ var ELBv2Provider = class {
40922
41195
  return {
40923
41196
  physicalId,
40924
41197
  wasReplaced: false,
40925
- attributes: {
40926
- TargetGroupArn: physicalId,
40927
- TargetGroupFullName: physicalId.split(":").pop()?.replace("targetgroup/", ""),
40928
- TargetGroupName: tg?.TargetGroupName
40929
- }
41198
+ attributes: targetGroupAttributes(tg ?? {}, physicalId)
40930
41199
  };
40931
41200
  } catch (error) {
40932
41201
  const cause = error instanceof Error ? error : void 0;
@@ -41587,10 +41856,10 @@ var ELBv2Provider = class {
41587
41856
  }
41588
41857
  async importLoadBalancer(input) {
41589
41858
  if (input.knownPhysicalId) try {
41590
- const resp = await this.getClient().send(new DescribeLoadBalancersCommand({ LoadBalancerArns: [input.knownPhysicalId] }));
41591
- return resp.LoadBalancers?.[0]?.LoadBalancerArn ? {
41592
- physicalId: resp.LoadBalancers[0].LoadBalancerArn,
41593
- attributes: {}
41859
+ const lb = (await this.getClient().send(new DescribeLoadBalancersCommand({ LoadBalancerArns: [input.knownPhysicalId] }))).LoadBalancers?.[0];
41860
+ return lb?.LoadBalancerArn ? {
41861
+ physicalId: lb.LoadBalancerArn,
41862
+ attributes: loadBalancerAttributes(lb, lb.LoadBalancerArn)
41594
41863
  } : null;
41595
41864
  } catch (err) {
41596
41865
  if (this.isNotFoundError(err)) return null;
@@ -41600,10 +41869,10 @@ var ELBv2Provider = class {
41600
41869
  }
41601
41870
  async importTargetGroup(input) {
41602
41871
  if (input.knownPhysicalId) try {
41603
- const resp = await this.getClient().send(new DescribeTargetGroupsCommand({ TargetGroupArns: [input.knownPhysicalId] }));
41604
- return resp.TargetGroups?.[0]?.TargetGroupArn ? {
41605
- physicalId: resp.TargetGroups[0].TargetGroupArn,
41606
- attributes: {}
41872
+ const tg = (await this.getClient().send(new DescribeTargetGroupsCommand({ TargetGroupArns: [input.knownPhysicalId] }))).TargetGroups?.[0];
41873
+ return tg?.TargetGroupArn ? {
41874
+ physicalId: tg.TargetGroupArn,
41875
+ attributes: targetGroupAttributes(tg, tg.TargetGroupArn)
41607
41876
  } : null;
41608
41877
  } catch (err) {
41609
41878
  if (this.isNotFoundError(err)) return null;
@@ -49306,10 +49575,14 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
49306
49575
  }
49307
49576
  async importServiceResource(input) {
49308
49577
  if (input.knownPhysicalId) try {
49309
- await this.getClient().send(new GetServiceCommand({ Id: input.knownPhysicalId }));
49578
+ const resp = await this.getClient().send(new GetServiceCommand({ Id: input.knownPhysicalId }));
49310
49579
  return {
49311
49580
  physicalId: input.knownPhysicalId,
49312
- attributes: {}
49581
+ attributes: definedAttributes({
49582
+ Id: input.knownPhysicalId,
49583
+ Arn: resp.Service?.Arn,
49584
+ Name: resp.Service?.Name
49585
+ })
49313
49586
  };
49314
49587
  } catch (err) {
49315
49588
  if (err instanceof ServiceNotFound) return null;
@@ -56618,7 +56891,10 @@ var EFSProvider = class {
56618
56891
  const ap = (await this.getClient().send(new DescribeAccessPointsCommand({ AccessPointId: input.knownPhysicalId }))).AccessPoints?.[0];
56619
56892
  return ap?.AccessPointId ? {
56620
56893
  physicalId: ap.AccessPointId,
56621
- attributes: {}
56894
+ attributes: definedAttributes({
56895
+ Arn: ap.AccessPointArn,
56896
+ AccessPointId: ap.AccessPointId
56897
+ })
56622
56898
  } : null;
56623
56899
  } catch (err) {
56624
56900
  if (err instanceof AccessPointNotFound) return null;
@@ -64395,6 +64671,7 @@ async function runDestroyForStack(stackName, state, ctx) {
64395
64671
  const regionForState = state.region ?? ctx.baseRegion;
64396
64672
  refuseMalformedResourcesForDestroy(state, stackName, regionForState);
64397
64673
  refuseMalformedOrphansForDestroy(state, stackName, regionForState);
64674
+ refuseMalformedOrphanRecordsForDestroy(state, stackName, regionForState);
64398
64675
  refuseDivergentRecordRegionForDestroy(state, stackName, regionForState, ctx.divergentBodyRegion);
64399
64676
  const resourceCount = Object.keys(state.resources).length;
64400
64677
  const orphanCount = (state.orphans ?? []).length;
@@ -64448,6 +64725,7 @@ async function runDestroyForStack(stackName, state, ctx) {
64448
64725
  if (recheck) {
64449
64726
  refuseMalformedResourcesForDestroy(recheck.state, stackName, regionForState);
64450
64727
  refuseMalformedOrphansForDestroy(recheck.state, stackName, regionForState);
64728
+ refuseMalformedOrphanRecordsForDestroy(recheck.state, stackName, regionForState);
64451
64729
  }
64452
64730
  const recheckResources = recheck ? Object.keys(recheck.state.resources).length : 0;
64453
64731
  const recheckOrphans = recheck ? (recheck.state.orphans ?? []).length : 0;
@@ -64472,13 +64750,13 @@ async function runDestroyForStack(stackName, state, ctx) {
64472
64750
  if (consumers.length > 0) throw new StackHasActiveImportsError(stackName, regionForState, consumers);
64473
64751
  }
64474
64752
  logger.info(`\nResources to be deleted (${resourceCount}):`);
64475
- for (const [logicalId, resource] of Object.entries(state.resources)) logger.info(` - ${logicalId} (${resource.resourceType})`);
64753
+ for (const [logicalId, resource] of Object.entries(state.resources)) logger.info(` - ${displaySafe(logicalId)} (${displaySafe(resource.resourceType)})`);
64476
64754
  const protectedCount = ctx.removeProtection ? countProtectedResources(state) : 0;
64477
64755
  const orphansAtDestroy = state.orphans ?? [];
64478
64756
  if (orphansAtDestroy.length > 0) {
64479
64757
  logger.info(`\n${orphansAtDestroy.length} resource(s) are still in AWS from an earlier failed deploy. cdkd left them there because their DeletionPolicy is Retain (CDK's RemovalPolicy.RETAIN), and has been tracking them so a later deploy of this stack could adopt them back instead of colliding with their names.`);
64480
64758
  logger.info("Destroying this stack deletes that record. The resources stay in AWS, may continue to incur charges, and cdkd will no longer know about them:");
64481
- for (const entry of orphansAtDestroy) logger.info(` - ${entry.logicalId} (${entry.state.resourceType}) ${entry.state.physicalId}`);
64759
+ for (const entry of orphansAtDestroy) logger.info(` - ${displaySafe(entry.logicalId)} (${displaySafe(entry.state.resourceType)}) ${displaySafe(entry.state.physicalId)}`);
64482
64760
  }
64483
64761
  if (!ctx.skipConfirmation) {
64484
64762
  if (process.stdin.isTTY !== true) throw new CdkdError(`The destroy confirmation prompt for stack "${stackName}" cannot run in a non-interactive environment. Pass --yes / -y to confirm the destroy (cdkd destroy also accepts -f / --force), or run the command from a real terminal.`, "NON_INTERACTIVE_CONFIRM");
@@ -65158,7 +65436,7 @@ var NestedStackProvider = class {
65158
65436
  const ctx = this.requireContext();
65159
65437
  this.requireDeployContext(ctx, "create");
65160
65438
  const childTemplatePath = ctx.nestedTemplates[logicalId];
65161
- if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack '${displaySafe(logicalId)}' under parent '${displaySafe(ctx.parentStackName)}'. Verify the synth output emits Metadata['aws:asset:path'] on this resource (CDK 2.x cdk.NestedStack does so by default).`);
65439
+ if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack ${displayIdent(logicalId)} under parent ${displayStackName(ctx.parentStackName)}. Verify the synth output emits Metadata['aws:asset:path'] on this resource (CDK 2.x cdk.NestedStack does so by default).`);
65162
65440
  this.refuseMalformedNestedTemplateTree(ctx, logicalId, childTemplatePath);
65163
65441
  const { template: childTemplate, grandchildTemplates } = this.readChildTemplate(childTemplatePath, ctx.assetRedirect);
65164
65442
  const childStackName = this.deriveChildStackName(ctx.parentStackName, logicalId);
@@ -65178,7 +65456,7 @@ var NestedStackProvider = class {
65178
65456
  const ctx = this.requireContext();
65179
65457
  this.requireDeployContext(ctx, "update");
65180
65458
  const childTemplatePath = ctx.nestedTemplates[logicalId];
65181
- if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack '${displaySafe(logicalId)}' on update.`);
65459
+ if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack ${displayIdent(logicalId)} on update.`);
65182
65460
  this.refuseMalformedNestedTemplateTree(ctx, logicalId, childTemplatePath);
65183
65461
  const { template: childTemplate, grandchildTemplates } = this.readChildTemplate(childTemplatePath, ctx.assetRedirect);
65184
65462
  const childStackName = this.deriveChildStackName(ctx.parentStackName, logicalId);
@@ -65250,7 +65528,7 @@ var NestedStackProvider = class {
65250
65528
  }
65251
65529
  }
65252
65530
  async getAttribute(_physicalId, _resourceType, attributeName) {
65253
- throw new Error(`AWS::CloudFormation::Stack: attribute '${displaySafe(attributeName)}' is not in the recorded Outputs map. Only 'Outputs.<Key>' references to declared Output names on the child template are supported.`);
65531
+ throw new Error(`AWS::CloudFormation::Stack: attribute ${displayIdent(attributeName)} is not in the recorded Outputs map. Only 'Outputs.<Key>' references to declared Output names on the child template are supported.`);
65254
65532
  }
65255
65533
  async runChildDeploy(parentCtx, logicalId, childStackName, childRegion, childTemplate, childParameters, grandchildTemplates) {
65256
65534
  const inheritedSecrets = getCurrentResourceSecrets();
@@ -65301,7 +65579,7 @@ var NestedStackProvider = class {
65301
65579
  */
65302
65580
  async readChildOutputsAsAttributes(ctx, childStackName, childRegion) {
65303
65581
  const childStateData = await ctx.stateBackend.getState(childStackName, childRegion);
65304
- if (!childStateData) throw new Error(`Child stack state '${displaySafe(childStackName)}' not found after deploy — NestedStackProvider invariant violated.`);
65582
+ if (!childStateData) throw new Error(`Child stack state ${displayStackName(childStackName)} not found after deploy — NestedStackProvider invariant violated.`);
65305
65583
  refuseMalformedNestedChildOutputs(childStateData.state, childStackName, childRegion);
65306
65584
  const attributes = this.buildOutputsAttributes(childStateData.state.outputs ?? {});
65307
65585
  const noEchoAttributeNames = [];
@@ -65404,7 +65682,7 @@ var NestedStackProvider = class {
65404
65682
  * points at `[2]` rather than at the whole parameter.
65405
65683
  */
65406
65684
  refuseNonScalarParameter(k, offender, where) {
65407
- throw new Error(`NestedStackProvider: child Parameter '${displaySafe(k)}'${where} resolved to a non-scalar value (type=${offender === null ? "null" : typeof offender}). Parameters must be scalars (string / number / boolean), or an ARRAY of them from a list-typed parameter, by the time they reach the provider — an unresolved intrinsic here means IntrinsicFunctionResolver upstream did not handle the value, which is a bug. Surface the unresolved input rather than silently coercing to '[object Object]'.`);
65685
+ throw new Error(`NestedStackProvider: child Parameter ${displayIdent(k)}${where} resolved to a non-scalar value (type=${offender === null ? "null" : typeof offender}). Parameters must be scalars (string / number / boolean), or an ARRAY of them from a list-typed parameter, by the time they reach the provider — an unresolved intrinsic here means IntrinsicFunctionResolver upstream did not handle the value, which is a bug. Surface the unresolved input rather than silently coercing to '[object Object]'.`);
65408
65686
  }
65409
65687
  /**
65410
65688
  * The child template as the child engine deploys it, plus the grandchild
@@ -65447,9 +65725,9 @@ var NestedStackProvider = class {
65447
65725
  const dir = path.dirname(childTemplatePath);
65448
65726
  const result = Object.create(null);
65449
65727
  for (const { logicalId: grandLogicalId, assetPath } of listNestedTemplateRows(childTemplate)) {
65450
- if (isAbsoluteCrossPlatform$1(assetPath)) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack '${displaySafe(grandLogicalId)}' 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.`));
65728
+ if (isAbsoluteCrossPlatform$1(assetPath)) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack ${displayIdent(grandLogicalId)} 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.`));
65451
65729
  const resolved = resolveAssemblyPath(dir, assetPath);
65452
- if (!resolved.contained) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack '${displaySafe(grandLogicalId)}' has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`));
65730
+ if (!resolved.contained) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`));
65453
65731
  result[grandLogicalId] = resolved.path;
65454
65732
  }
65455
65733
  return result;
@@ -68566,13 +68844,10 @@ async function computeStackDiff(currentState, template, region, stackName, state
68566
68844
  let stateForDiff = currentState;
68567
68845
  const unreadableOrphans = [];
68568
68846
  if (currentState.orphans?.length && options.previewOrphanAdoption) {
68569
- const readableOrphans = currentState.orphans.filter((record) => {
68570
- if (isReadableResourceEntry(record?.state)) return true;
68571
- const id = record?.logicalId;
68572
- unreadableOrphans.push(typeof id === "string" ? id : "");
68573
- return false;
68574
- });
68575
- if (unreadableOrphans.length > 0) logger.warn(malformedOrphanRecordsWarning(stackName, region, unreadableOrphans));
68847
+ for (const id of unpreviewableOrphanRecords(currentState)) unreadableOrphans.push(id);
68848
+ const readableOrphans = previewableOrphanRecords(currentState);
68849
+ if (unreadableOrphans.length > 0) logger.warn(malformedOrphanRecordsWarning(stackName, region, unreadableOrphans, false));
68850
+ let reportedByTheAdoptedPropertiesArm = [];
68576
68851
  const plan = await options.previewOrphanAdoption({
68577
68852
  ...currentState,
68578
68853
  orphans: readableOrphans
@@ -68589,11 +68864,18 @@ async function computeStackDiff(currentState, template, region, stackName, state
68589
68864
  }
68590
68865
  };
68591
68866
  const tornAdopted = repairMalformedResourcePropertiesForReadOnly(stateForDiff);
68867
+ reportedByTheAdoptedPropertiesArm = tornAdopted;
68592
68868
  if (tornAdopted.length > 0) {
68593
68869
  logger.warn(malformedResourcePropertiesWarning(stackName, region, tornAdopted));
68594
68870
  deployRefusals.push(deployRefusesPropertiesReason(tornAdopted));
68595
68871
  }
68596
68872
  }
68873
+ const alreadyReported = new Set(reportedByTheAdoptedPropertiesArm);
68874
+ const previewedRowsTheDeployRefuses = readableOrphans.filter((record) => !isReadableOrphanRecord(record)).map((record) => record.logicalId).filter((logicalId) => !alreadyReported.has(logicalId));
68875
+ if (previewedRowsTheDeployRefuses.length > 0) {
68876
+ logger.warn(malformedOrphanRowsKeptWarning(stackName, region, previewedRowsTheDeployRefuses));
68877
+ deployRefusals.push(deployRefusesOrphanRowsReason(previewedRowsTheDeployRefuses));
68878
+ }
68597
68879
  }
68598
68880
  const changes = await diffCalculator.calculateDiff(stateForDiff, effectiveTemplate, resolveFn, canonicalizeProperties);
68599
68881
  const changedLogicalIds = new Set([...changes.values()].filter((c) => c.changeType !== "NO_CHANGE").map((c) => c.logicalId));
@@ -69869,7 +70151,7 @@ async function scrubCommand(stacks, options) {
69869
70151
  } else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${stack.stackName}`);
69870
70152
  if (scrubbed.malformedResources) malformedRecords.push(stack.stackName);
69871
70153
  if (scrubbed.malformedOutputs) malformedOutputRecords.push(stack.stackName);
69872
- if (scrubbed.malformedOrphans) malformedOrphanRecords.push(stack.stackName);
70154
+ if (scrubbed.malformedOrphans || scrubbed.malformedOrphanRows) malformedOrphanRecords.push(stack.stackName);
69873
70155
  if (scrubbed.unverifiableLeaves > 0) {
69874
70156
  totalStacksWithUnverifiableLeaves++;
69875
70157
  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.`);
@@ -70565,7 +70847,7 @@ function malformedRecordsAuditedError(stackNames, outputStackNames, orphanStackN
70565
70847
  const parts = [];
70566
70848
  if (stackNames.length > 0) parts.push(`${stackNames.length} stack(s) were audited with an EMPTY resource set because their state record has no readable 'resources' map: ${safeNames(stackNames)}. The report above describes their outputs only — nothing is known about their resources, so this run cannot certify them clean.`);
70567
70849
  if (outputStackNames.length > 0) parts.push(`${outputStackNames.length} stack(s) were audited with an EMPTY outputs bag because their state record has no readable 'outputs' map: ${safeNames(outputStackNames)}. The report above describes their resources only — nothing is known about the values their outputs hold, and those values are what the exports index republishes to consumer stacks, so this run cannot certify them clean.`);
70568
- if (orphanStackNames.length > 0) parts.push(`${orphanStackNames.length} stack(s) were audited with an EMPTY orphan list because their state record has no readable 'orphans' list: ${safeNames(orphanStackNames)}. Nothing is known about resources an earlier failed deploy may have left live in AWS for them, so this run cannot certify them clean.`);
70850
+ if (orphanStackNames.length > 0) parts.push(`${orphanStackNames.length} stack(s) were audited with an INCOMPLETE orphan list because their state record has no readable 'orphans' list, or a record inside it that no reader can use: ${safeNames(orphanStackNames)}. Whichever it was, the warning above names it per stack. Nothing is known about the resources those records describe — resources an earlier failed deploy may have left live in AWS — so this run cannot certify them clean.`);
70569
70851
  return new ScrubRefusalError(`${parts.join(" ")} See the warnings above for the record to inspect.`, STATE_RESOURCES_MALFORMED);
70570
70852
  }
70571
70853
  /**
@@ -71977,9 +72259,23 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
71977
72259
  const outputSecrets = /* @__PURE__ */ new Map();
71978
72260
  /**
71979
72261
  * Needles derived from each rollback-orphan record's OWN recorded bag
71980
- * (issue go-to-k/cdkd#2943), keyed by logical id — per-record for the same
71981
- * reason `perResourceSecrets` is per-resource: one record's secret must not
71982
- * rewrite another's coinciding literal.
72262
+ * (issue go-to-k/cdkd#2943) — per-record for the same reason
72263
+ * `perResourceSecrets` is per-resource: one record's secret must not rewrite
72264
+ * another's coinciding literal.
72265
+ *
72266
+ * Keyed by the row's INDEX in `orphans`, never by its `logicalId`
72267
+ * (go-to-k/cdkd#3500 security review). Two rows sharing an id are a MALFORMED
72268
+ * record — no cdkd writer produces one, since `orphansAfterRollback` keeps one
72269
+ * row per id — and both arms of this command meet it before this map is read:
72270
+ * a real run refuses the record and `--dry-run` drops every such row
72271
+ * (go-to-k/cdkd#3643). The index keying stays as defense in depth, because it
72272
+ * is still the only identity that cannot collide: on an id key the second row's
72273
+ * empty map REPLACED the first row's filled one. Both halves broke: the first
72274
+ * row's needles left the union that the rewrite and the error boundary read, and
72275
+ * its own lookup returned the OTHER row's map, so where two rows resolve one
72276
+ * plaintext through different expressions the wrong expression was written. The
72277
+ * index is the only identity the collecting loop and the rewrite can agree on,
72278
+ * since both walk `state.orphans` in order and neither reorders it.
71983
72279
  */
71984
72280
  const orphanSecrets = /* @__PURE__ */ new Map();
71985
72281
  const prePassFindings = {
@@ -72069,12 +72365,22 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72069
72365
  }
72070
72366
  } else if (!hasReadableOutputs(state)) throw new ScrubRefusalError(malformedOutputsRefusalMessage(stack.stackName, region), STATE_RESOURCES_MALFORMED);
72071
72367
  let malformedOrphans;
72368
+ let malformedOrphanRows;
72072
72369
  if (opts.dryRun) {
72073
72370
  if (repairMalformedOrphansForReadOnly(state)) {
72074
72371
  malformedOrphans = true;
72075
72372
  logger.warn(malformedOrphansWarning(stack.stackName, region));
72076
72373
  }
72374
+ const droppedRows = repairMalformedOrphanRecordsForReadOnly(state);
72375
+ if (droppedRows.length > 0) {
72376
+ malformedOrphanRows = true;
72377
+ logger.warn(malformedOrphanRecordsWarning(stack.stackName, region, droppedRows, true));
72378
+ }
72077
72379
  } else if (!hasReadableOrphans(state)) throw new ScrubRefusalError(malformedOrphansRefusalMessage(stack.stackName, region), STATE_RESOURCES_MALFORMED);
72380
+ else {
72381
+ const unreadableRows = unreadableOrphanRecords(state);
72382
+ if (unreadableRows.length > 0) throw new ScrubRefusalError(malformedOrphanRecordsRefusalMessage(stack.stackName, region, unreadableRows), STATE_RESOURCES_MALFORMED);
72383
+ }
72078
72384
  const perResourceTemplateProps = /* @__PURE__ */ new Map();
72079
72385
  const outputsTemplateSource = {};
72080
72386
  const resolvers = new ScrubResolvers(region);
@@ -72157,9 +72463,9 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72157
72463
  }
72158
72464
  perResourceTemplateProps.set(logicalId, templateResource.Properties);
72159
72465
  }
72160
- for (const record of state.orphans ?? []) {
72466
+ for (const [orphanIndex, record] of (state.orphans ?? []).entries()) {
72161
72467
  const recordedSecretValues = /* @__PURE__ */ new Map();
72162
- orphanSecrets.set(record.logicalId, recordedSecretValues);
72468
+ orphanSecrets.set(String(orphanIndex), recordedSecretValues);
72163
72469
  const resolveInput = await pinCrossRegionSecrets({
72164
72470
  properties: record.state.properties,
72165
72471
  attributes: record.state.attributes ?? {},
@@ -72292,6 +72598,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72292
72598
  ...malformedResources ? { malformedResources } : {},
72293
72599
  ...malformedOutputs ? { malformedOutputs } : {},
72294
72600
  ...malformedOrphans ? { malformedOrphans } : {},
72601
+ ...malformedOrphanRows ? { malformedOrphanRows } : {},
72295
72602
  outputs: state.outputs,
72296
72603
  exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
72297
72604
  };
@@ -72310,8 +72617,8 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72310
72617
  if (JSON.stringify(scrubbed) !== JSON.stringify(record)) recordsChanged++;
72311
72618
  newResources[logicalId] = scrubbed;
72312
72619
  }
72313
- const newOrphans = (state.orphans ?? []).map((record) => {
72314
- const own = orphanSecrets.get(record.logicalId);
72620
+ const newOrphans = (state.orphans ?? []).map((record, orphanIndex) => {
72621
+ const own = orphanSecrets.get(String(orphanIndex));
72315
72622
  const needles = new Map(allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets));
72316
72623
  for (const [plaintext, expression] of own ?? []) needles.set(plaintext, expression);
72317
72624
  if (needles.size === 0) return record;
@@ -72371,6 +72678,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
72371
72678
  ...malformedResources ? { malformedResources } : {},
72372
72679
  ...malformedOutputs ? { malformedOutputs } : {},
72373
72680
  ...malformedOrphans ? { malformedOrphans } : {},
72681
+ ...malformedOrphanRows ? { malformedOrphanRows } : {},
72374
72682
  outputs: newOutputs,
72375
72683
  exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
72376
72684
  };
@@ -82939,7 +83247,7 @@ async function stateDestroyCommand(stackArgs, options) {
82939
83247
  * Create the `state destroy` subcommand.
82940
83248
  */
82941
83249
  function createStateDestroyCommand() {
82942
- const cmd = new Command("destroy").description("Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'.").argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).option("--remove-protection", "Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DocDB::DBCluster, AWS::Neptune::DBCluster, AWS::Neptune::DBInstance, AWS::DynamoDB::Table, AWS::EC2::Instance, AWS::Cognito::UserPool, AWS::AutoScaling::AutoScalingGroup, AWS::ElasticLoadBalancingV2::LoadBalancer, AWS::DSQL::Cluster, AWS::NeptuneGraph::Graph, AWS::SMSVOICE::ProtectConfiguration, AWS::VerifiedPermissions::PolicyStore, AWS::EKS::Cluster, AWS::RDS::GlobalCluster, and AWS::DocDB::GlobalCluster.", false).addOption(stackRegionOption$1()).addHelpText("after", [
83250
+ const cmd = new Command("destroy").description("Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'.").argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).option("--remove-protection", `Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers ${removeProtectionTypeList()}.`, false).addOption(stackRegionOption$1()).addHelpText("after", [
82943
83251
  "",
82944
83252
  "Examples:",
82945
83253
  " cdkd state destroy MyStack",
@@ -83887,6 +84195,7 @@ async function rollbackCommand(stackArg, options) {
83887
84195
  const baseState = stateData.state;
83888
84196
  refuseMalformedState(baseState, stackName, region);
83889
84197
  refuseMalformedOrphans(baseState, stackName, region);
84198
+ refuseMalformedOrphanRecords(baseState, stackName, region);
83890
84199
  const stateResources = { ...baseState.resources };
83891
84200
  const mintedOrphans = [];
83892
84201
  const orphanLogicalIds = new Set(options.orphan ?? []);
@@ -84546,23 +84855,45 @@ function createEventsPruneCommand() {
84546
84855
  * The two dual-stack forms carry a FIXED suffix, so their check is that literal
84547
84856
  * rather than the region's partition suffix — the TIGHTEST available check for
84548
84857
  * them, not a relaxation: `on.aws` is an AWS-owned domain, so unlike a captured
84549
- * suffix it cannot be substituted by a host someone else owns. They are
84550
- * accepted for ANY region rather than only the partitions AWS documents them
84551
- * in, deliberately: under-accepting is precisely the issue #1764 failure (a
84552
- * cdkd table lagging AWS made a GENUINE registry classify as public), and the
84553
- * suffix being AWS-owned means the widening cannot point a `docker login`
84554
- * anywhere but AWS.
84555
- */
84858
+ * suffix it cannot be substituted by a host someone else owns.
84859
+ *
84860
+ * The three non-plain forms are accepted only for a region in the `aws` /
84861
+ * `aws-us-gov` partitions (issue #3670):
84862
+ *
84863
+ * - `on.aws` is the dual-stack DNS of those two partitions; the others serve
84864
+ * dual-stack under their own suffixes, which this table does not list.
84865
+ * - AWS's own endpoint data (botocore `endpoints.json`, service `ecr`) carries
84866
+ * the `fips-dkr-<region>` registry endpoints in those two partitions only;
84867
+ * `aws-cn`, the ISO partitions and `aws-eusc` list none. So
84868
+ * `<acct>.dkr.ecr-fips.cn-north-1.amazonaws.com.cn` is not a host AWS serves
84869
+ * either, although its suffix is the region's own.
84870
+ *
84871
+ * Such a host is refused rather than handed a `docker login`. An earlier
84872
+ * revision accepted `on.aws` for any region, reasoning that under-accepting
84873
+ * repeats the issue #1764 failure; that trade stops paying once the pull path
84874
+ * logs in to whatever host the reference names. The partition, not the six
84875
+ * FIPS regions, is the unit, so a new FIPS region in those partitions is not
84876
+ * refused before AWS documents it.
84877
+ *
84878
+ * `cdkd gc` builds its pattern from the LABELS and suffixes only and ignores
84879
+ * `partitions`, deliberately: over-matching there only ever KEEPS an asset.
84880
+ */
84881
+ const COMMERCIAL_AND_GOVCLOUD = ["aws", "aws-us-gov"];
84556
84882
  const ECR_REGISTRY_HOST_FORMS = [
84557
84883
  { labels: "dkr.ecr" },
84558
- { labels: "dkr.ecr-fips" },
84884
+ {
84885
+ labels: "dkr.ecr-fips",
84886
+ partitions: COMMERCIAL_AND_GOVCLOUD
84887
+ },
84559
84888
  {
84560
84889
  labels: "dkr-ecr",
84561
- fixedUrlSuffix: "on.aws"
84890
+ fixedUrlSuffix: "on.aws",
84891
+ partitions: COMMERCIAL_AND_GOVCLOUD
84562
84892
  },
84563
84893
  {
84564
84894
  labels: "dkr-ecr-fips",
84565
- fixedUrlSuffix: "on.aws"
84895
+ fixedUrlSuffix: "on.aws",
84896
+ partitions: COMMERCIAL_AND_GOVCLOUD
84566
84897
  }
84567
84898
  ];
84568
84899
  /**
@@ -84686,6 +85017,17 @@ function ecrRegistryHostPattern(segments) {
84686
85017
  * MESSAGE was written for the #1764 partition-gap case and now over-claims for a
84687
85018
  * form/suffix mispairing (`amazonaws.com` IS `us-east-1`'s partition suffix).
84688
85019
  * `src/local/ecs-task-resolver.ts` owns that wording; recorded on issue #1846.
85020
+ *
85021
+ * `<r>` above is a commercial region. Issue #3670 then scoped the three
85022
+ * non-plain forms to the `aws` / `aws-us-gov` partitions, flipping more
85023
+ * verdicts: `<a>.dkr-ecr[-fips].<r>.on.aws` and `<a>.dkr.ecr-fips.<r>.S` for an
85024
+ * `aws-cn`, ISO or `aws-eusc` `<r>` went from `p=ok d=f` to `p=und d=TRUE`, a
85025
+ * form / partition mispairing reported like the form / suffix ones. The same
85026
+ * issue added the region-SHAPE guard ({@link AWS_REGION_ID}), which refuses a
85027
+ * service-name "region" such as `s3` at both entry points. That guard also
85028
+ * flips the diagnostic the other way for such a label: `<a>.dkr.ecr.s3.F` went
85029
+ * from `p=und d=TRUE` to `p=und d=f`. A region-shaped label no partition knows
85030
+ * (`nz-north-1`) went from `p=ok d=f` to `p=und d=TRUE`.
84689
85031
  */
84690
85032
  const ECR_URI_HOST_REGEX = new RegExp(`^(\\d{12})\\.(${ECR_HOST_FORMS_LONGEST_FIRST.map((form) => escapeRegExp(form.labels)).join("|")})\\.([^.]+)\\.([^/]+)/`, "i");
84691
85033
  /**
@@ -84746,6 +85088,54 @@ const CANONICAL_REGION_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
84746
85088
  */
84747
85089
  const CANONICAL_URL_SUFFIX = /^[A-Za-z0-9][A-Za-z0-9.-]*$/;
84748
85090
  /**
85091
+ * `<letters>(-<letters or digits>)+-<number>`: the generic shape every AWS
85092
+ * region id has had. A label matching it but not {@link AWS_REGION_ID} is a
85093
+ * region cdkd does not know yet, reported by the diagnostic rather than
85094
+ * silenced; `s3`, `lambda-url` and `s3-external-1` do not match it (the first
85095
+ * segment must be letters only).
85096
+ */
85097
+ const GENERIC_REGION_SHAPE = /^[a-z]+(?:-[a-z0-9]+)+-\d+$/;
85098
+ /**
85099
+ * The SHAPE of an AWS region id, tested on the folded region AFTER the charset
85100
+ * guard above (issue #3670).
85101
+ *
85102
+ * The charset guard admits any `[A-Za-z0-9-]` label, so a SERVICE-name label
85103
+ * parsed as a region: `<acct>.dkr.ecr.s3.amazonaws.com` yielded the region
85104
+ * `s3`, whose partition falls back to commercial, so the suffix matched and the
85105
+ * host became a `docker login` target. Only TLS stopped the token there. A
85106
+ * region id is one of the partitions' region patterns, so anything else is not
85107
+ * a registry host this module recognizes.
85108
+ *
85109
+ * One alternative per partition, transcribed from each partition's
85110
+ * `regionRegex` in AWS's own endpoint data (botocore `partitions.json`, which
85111
+ * `@aws-sdk/util-endpoints` vendors), with `\w+` spelled `[a-z0-9]+`. That is
85112
+ * the same set once the charset guard has refused `_` and the fold has
85113
+ * lower-cased the segment:
85114
+ *
85115
+ * - `aws`: `^(us|eu|ap|sa|ca|me|af|il|mx)-\w+-\d+$`
85116
+ * - `aws-cn`: `^cn-\w+-\d+$`
85117
+ * - `aws-us-gov`: `^us-gov-\w+-\d+$`
85118
+ * - `aws-iso` / `-iso-b` / `-iso-e` / `-iso-f`: `^us-iso-`, `^us-isob-`,
85119
+ * `^eu-isoe-`, `^us-isof-`, each followed by `\w+-\d+`
85120
+ * - `aws-eusc`: `^eusc-(de)-\w+-\d+$`, widened here to any `eusc-<cc>-` country
85121
+ * code for the reason `PARTITION_TABLE` (`src/utils/aws-partition.ts`) gives
85122
+ * for its own broader `eusc-` prefix: a future sovereign-cloud country falling
85123
+ * through is the failure, and no other partition's regions begin `eusc-`.
85124
+ *
85125
+ * A future partition with a new prefix is refused until it is added here, the
85126
+ * same way `derivePartitionAndUrlSuffix` has to learn its suffix.
85127
+ */
85128
+ const AWS_REGION_ID = new RegExp("^(?:" + [
85129
+ "(?:us|eu|ap|sa|ca|me|af|il|mx)-[a-z0-9]+-\\d+",
85130
+ "cn-[a-z0-9]+-\\d+",
85131
+ "us-gov-[a-z0-9]+-\\d+",
85132
+ "us-iso-[a-z0-9]+-\\d+",
85133
+ "us-isob-[a-z0-9]+-\\d+",
85134
+ "eu-isoe-[a-z0-9]+-\\d+",
85135
+ "us-isof-[a-z0-9]+-\\d+",
85136
+ "eusc-[a-z]+-[a-z0-9]+-\\d+"
85137
+ ].join("|") + ")$");
85138
+ /**
84749
85139
  * The ONE case-normalization boundary of this module (issue #1786).
84750
85140
  *
84751
85141
  * DNS is case-INSENSITIVE, so `US-ISO-EAST-1.amazonaws.com` and
@@ -84790,11 +85180,21 @@ function matchEcrRegistryHost(imageUri) {
84790
85180
  const form = ECR_HOST_FORM_BY_LABELS.get(m[2].toLowerCase());
84791
85181
  if (!form) return void 0;
84792
85182
  const region = m[3].toLowerCase();
85183
+ if (!AWS_REGION_ID.test(region)) {
85184
+ if (!GENERIC_REGION_SHAPE.test(region)) return void 0;
85185
+ return {
85186
+ accountId: m[1],
85187
+ region,
85188
+ suffix: m[4].toLowerCase(),
85189
+ expectedSuffix: void 0
85190
+ };
85191
+ }
85192
+ const partition = derivePartitionAndUrlSuffix(region);
84793
85193
  return {
84794
85194
  accountId: m[1],
84795
85195
  region,
84796
85196
  suffix: m[4].toLowerCase(),
84797
- expectedSuffix: (form.fixedUrlSuffix ?? derivePartitionAndUrlSuffix(region).urlSuffix).toLowerCase()
85197
+ expectedSuffix: form.partitions && !form.partitions.includes(partition.partition) ? void 0 : (form.fixedUrlSuffix ?? partition.urlSuffix).toLowerCase()
84798
85198
  };
84799
85199
  }
84800
85200
  /**
@@ -84824,7 +85224,7 @@ function matchEcrRegistryHost(imageUri) {
84824
85224
  function parseEcrRegistryHost(imageUri) {
84825
85225
  const m = matchEcrRegistryHost(imageUri);
84826
85226
  if (!m) return void 0;
84827
- if (m.suffix !== m.expectedSuffix) return void 0;
85227
+ if (m.expectedSuffix === void 0 || m.suffix !== m.expectedSuffix) return void 0;
84828
85228
  return {
84829
85229
  accountId: m.accountId,
84830
85230
  region: m.region
@@ -86504,7 +86904,7 @@ async function orphanCommand(pathArgs, options) {
86504
86904
  const stackInfo = resolved.stack;
86505
86905
  const orphanLogicalIds = resolved.logicalIds;
86506
86906
  const { region: targetRegion, recordRegion } = await pickStackRegion(stateBackend, stackInfo.stackName, stackInfo.region, options.stackRegion);
86507
- logger.info(`Target: ${displaySafe(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })}); orphaning ${orphanLogicalIds.length} resource(s): ${displaySafeList(orphanLogicalIds)}`);
86907
+ logger.info(`Target: ${displayStackName(stackInfo.stackName)} (${displayIdent(targetRegion)}); orphaning ${orphanLogicalIds.length} resource(s): ${displaySafeList(orphanLogicalIds)}`);
86508
86908
  const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
86509
86909
  const recovery = {
86510
86910
  profile: options.profile,
@@ -86521,7 +86921,7 @@ async function orphanCommand(pathArgs, options) {
86521
86921
  }
86522
86922
  try {
86523
86923
  const stateData = await stateBackend.getState(stackInfo.stackName, targetRegion);
86524
- if (!stateData) throw new Error(`No state found for stack '${displaySafe(stackInfo.stackName)}' (${displaySafe(targetRegion, { asciiOnly: true })}). Nothing to orphan. (Did the stack get deployed?)`);
86924
+ if (!stateData) throw new Error(`No state found for stack ${displayStackName(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })}). Nothing to orphan. (Did the stack get deployed?)`);
86525
86925
  const { state, etag, migrationPending } = stateData;
86526
86926
  refuseMalformedState(state, stackInfo.stackName, recordRegion, recovery);
86527
86927
  refuseMalformedOutputs(state, stackInfo.stackName, recordRegion, recovery);
@@ -86532,7 +86932,7 @@ async function orphanCommand(pathArgs, options) {
86532
86932
  const missing = orphanLogicalIds.filter((id) => !Object.hasOwn(state.resources, id));
86533
86933
  if (missing.length > 0) {
86534
86934
  const have = displayIdentList(Object.keys(state.resources), ", ");
86535
- throw new Error(`Resource(s) not in state for stack '${displaySafe(stackInfo.stackName)}' (${displaySafe(targetRegion, { asciiOnly: true })}): ${displayIdentList(missing, ", ")}.\nAvailable logical IDs: ${have}`);
86935
+ throw new Error(`Resource(s) not in state for stack ${displayStackName(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })}): ${displayIdentList(missing, ", ")}.\nAvailable logical IDs: ${have}`);
86536
86936
  }
86537
86937
  const providerRegistry = new ProviderRegistry();
86538
86938
  registerAllProviders(providerRegistry);
@@ -86551,7 +86951,7 @@ async function orphanCommand(pathArgs, options) {
86551
86951
  return;
86552
86952
  }
86553
86953
  if (!options.yes && !options.force) {
86554
- if (!await confirmPrompt$1(`Orphan ${orphanLogicalIds.length} resource(s) from cdkd state for ${displaySafe(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })})? AWS resources will NOT be deleted.`)) {
86954
+ if (!await confirmPrompt$1(`Orphan ${orphanLogicalIds.length} resource(s) from cdkd state for ${displayStackName(stackInfo.stackName)} (${displayIdent(targetRegion)})? AWS resources will NOT be deleted.`)) {
86555
86955
  logger.info("Orphan cancelled.");
86556
86956
  return;
86557
86957
  }
@@ -86560,7 +86960,7 @@ async function orphanCommand(pathArgs, options) {
86560
86960
  expectedEtag: etag,
86561
86961
  ...migrationPending && { migrateLegacy: true }
86562
86962
  });
86563
- logger.info(`Orphaned ${orphanLogicalIds.length} resource(s) from state: ${displaySafe(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })}). AWS resources are still in AWS; cdkd will no longer manage them.`);
86963
+ logger.info(`Orphaned ${orphanLogicalIds.length} resource(s) from state: ${displayStackName(stackInfo.stackName)} (${displayIdent(targetRegion)}). AWS resources are still in AWS; cdkd will no longer manage them.`);
86564
86964
  } finally {
86565
86965
  if (!options.dryRun) await lockManager.releaseLock(stackInfo.stackName, targetRegion).catch((err) => {
86566
86966
  logger.warn(`Failed to release lock: ${displayAwsMessage(err instanceof Error ? err.message : String(err))}`);
@@ -86599,12 +86999,12 @@ function resolveConstructPaths(paths, stacks) {
86599
86999
  throw new Error(`Construct path '${p}': stack '${head}' not found in synthesized app. Available: ${available}`);
86600
87000
  }
86601
87001
  if (stack === void 0) stack = candidate;
86602
- else if (stack.stackName !== candidate.stackName) throw new Error(`All construct paths must reference the same stack. Got '${displaySafe(stack.stackName)}' and '${displaySafe(candidate.stackName)}'. Run 'cdkd orphan' once per stack.`);
87002
+ else if (stack.stackName !== candidate.stackName) throw new Error(`All construct paths must reference the same stack. Got ${displayStackName(stack.stackName)} and ${displayStackName(candidate.stackName)}. Run 'cdkd orphan' once per stack.`);
86603
87003
  const index = buildCdkPathIndex(candidate.template);
86604
87004
  const matches = resolveCdkPathToLogicalIds(p, index);
86605
87005
  if (matches.length === 0) {
86606
87006
  const available = displayIdentList([...index.keys()].sort(), "\n ");
86607
- throw new Error(`Construct path '${p}' not found in template for stack '${displaySafe(candidate.stackName)}'.\nAvailable paths:\n ${available}`);
87007
+ throw new Error(`Construct path '${p}' not found in template for stack ${displayStackName(candidate.stackName)}.\nAvailable paths:\n ${available}`);
86608
87008
  }
86609
87009
  for (const { logicalId } of matches) if (!logicalIds.includes(logicalId)) logicalIds.push(logicalId);
86610
87010
  }
@@ -86631,12 +87031,12 @@ async function pickStackRegion(stateBackend, stackName, synthRegion, flag) {
86631
87031
  region: synthRegion,
86632
87032
  recordRegion: synthRegion
86633
87033
  };
86634
- throw new Error(`No state found for stack '${displaySafe(stackName)}'. Run 'cdkd state list' to see available stacks.`);
87034
+ throw new Error(`No state found for stack ${displayStackName(stackName)}. Run 'cdkd state list' to see available stacks.`);
86635
87035
  }
86636
87036
  if (flag) {
86637
87037
  if (!refs.find((r) => r.region === flag)) {
86638
87038
  const seen = displayRegionList(refs);
86639
- throw new Error(`No state found for stack '${displaySafe(stackName)}' in region '${flag}'. Available regions: ${seen}.`);
87039
+ throw new Error(`No state found for stack ${displayStackName(stackName)} in region ${displayIdent(flag)}. Available regions: ${seen}.`);
86640
87040
  }
86641
87041
  return {
86642
87042
  region: flag,
@@ -86657,7 +87057,7 @@ async function pickStackRegion(stateBackend, stackName, synthRegion, flag) {
86657
87057
  };
86658
87058
  }
86659
87059
  const regions = displayRegionList(refs);
86660
- throw new Error(`Stack '${displaySafe(stackName)}' has state in multiple regions: ${regions}. Re-run with --stack-region <region> to disambiguate.`);
87060
+ throw new Error(`Stack ${displayStackName(stackName)} has state in multiple regions: ${regions}. Re-run with --stack-region <region> to disambiguate.`);
86661
87061
  }
86662
87062
  function printRewriteSummary(rewrites, orphanLogicalIds) {
86663
87063
  const logger = getLogger();
@@ -87303,7 +87703,10 @@ async function importCommand(stackArg, options) {
87303
87703
  const existingState = existingResult?.state ?? null;
87304
87704
  if (existingState) refuseMalformedState(existingState, stackInfo.stackName, targetRegion);
87305
87705
  if (existingState) refuseMalformedOutputs(existingState, stackInfo.stackName, targetRegion);
87306
- if (existingState) refuseMalformedOrphans(existingState, stackInfo.stackName, targetRegion);
87706
+ if (existingState) {
87707
+ refuseMalformedOrphans(existingState, stackInfo.stackName, targetRegion);
87708
+ refuseMalformedOrphanRecords(existingState, stackInfo.stackName, targetRegion);
87709
+ }
87307
87710
  const existingEtag = existingResult?.etag;
87308
87711
  const migrationPending = existingResult?.migrationPending ?? false;
87309
87712
  if (existingState) {
@@ -89657,12 +90060,12 @@ function resolveAssetCodeDirectory(opts) {
89657
90060
  if (isAbsolute(assetPath)) {
89658
90061
  const absolute = resolve(assetPath);
89659
90062
  const escape = absoluteAssemblyPathEscape(assetOutdir, absolute);
89660
- if (escape !== void 0) getLogger().warn(`Lambda '${displaySafe(logicalId)}' has an absolute Metadata['aws:asset:path'] pointing outside the assembly: ${displayAssemblyPath(absolute)}` + (escape.escape === "symlink" ? ` (through a symbolic link to ${displayAssemblyPath(escape.realPath)})` : "") + ". cdkd will bind-mount that directory into the container read-only, where the code in this assembly can read it. This is what cdk synth --no-staging emits, and is expected for it; if you did not synthesize with that flag, treat this assembly as untrusted.");
90063
+ if (escape !== void 0) getLogger().warn(`Lambda ${displayIdent(logicalId)} has an absolute Metadata['aws:asset:path'] pointing outside the assembly: ${displayAssemblyPath(absolute)}` + (escape.escape === "symlink" ? ` (through a symbolic link to ${displayAssemblyPath(escape.realPath)})` : "") + ". cdkd will bind-mount that directory into the container read-only, where the code in this assembly can read it. This is what cdk synth --no-staging emits, and is expected for it; if you did not synthesize with that flag, treat this assembly as untrusted.");
89661
90064
  return absolute;
89662
90065
  }
89663
90066
  const resolved = resolveAssemblyPath(manifestDir, assetPath, { containWithin: assetOutdir });
89664
90067
  if (!resolved.contained && resolved.escape === "lexical" && resolved.path === resolve(assetOutdir)) return resolved.path;
89665
- if (!resolved.contained) throw wrapError(`Lambda '${displaySafe(logicalId)}' has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, assetOutdir, "mount it")}`);
90068
+ if (!resolved.contained) throw wrapError(`Lambda ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, assetOutdir, "mount it")}`);
89666
90069
  return resolved.path;
89667
90070
  }
89668
90071
  /**
@@ -89691,9 +90094,8 @@ function resolveAssetCodeDirectory(opts) {
89691
90094
  * `process.cwd()` survives only for a `StackInfo` carrying NEITHER field, where
89692
90095
  * base and bound coincide again.
89693
90096
  *
89694
- * Exported for `local-start-api.ts`'s copy of the caller, for the Docker
89695
- * context check the ECS emulator commands run over cdk-local's `StackInfo`
89696
- * (which is why it takes only the two fields it reads), and for unit testing.
90097
+ * Exported for `local-start-api.ts`'s copy of the caller, and for unit
90098
+ * testing.
89697
90099
  */
89698
90100
  function assetPathDirs(stack) {
89699
90101
  const manifestDir = stack.assetManifestPath ? dirname(stack.assetManifestPath) : stack.assetOutdir ?? process.cwd();
@@ -89719,7 +90121,7 @@ function assetPathDirs(stack) {
89719
90121
  */
89720
90122
  function resolveAssetCodePath$1(stack, logicalId, resource) {
89721
90123
  const assetPath = resource.Metadata?.["aws:asset:path"];
89722
- if (typeof assetPath !== "string" || assetPath.length === 0) throw new LocalInvokeResolutionError(`Lambda '${displaySafe(logicalId)}' has no Metadata['aws:asset:path']. cdkd local invoke needs this hint to find the local asset directory. Re-synthesize the app (without \`--output <stale-dir>\`) and retry.`);
90124
+ if (typeof assetPath !== "string" || assetPath.length === 0) throw new LocalInvokeResolutionError(`Lambda ${displayIdent(logicalId)} has no Metadata['aws:asset:path']. cdkd local invoke needs this hint to find the local asset directory. Re-synthesize the app (without \`--output <stale-dir>\`) and retry.`);
89723
90125
  const { manifestDir, assetOutdir } = assetPathDirs(stack);
89724
90126
  const abs = resolveAssetCodeDirectory({
89725
90127
  manifestDir,
@@ -89728,7 +90130,7 @@ function resolveAssetCodePath$1(stack, logicalId, resource) {
89728
90130
  assetOutdir,
89729
90131
  logicalId
89730
90132
  });
89731
- if (!existsSync(abs) || !statSync(abs).isDirectory()) throw new LocalInvokeResolutionError(`Lambda '${displaySafe(logicalId)}' asset directory ${displayAssemblyPath(abs)} does not exist or is not a directory. Re-synthesize the app and retry.`);
90133
+ if (!existsSync(abs) || !statSync(abs).isDirectory()) throw new LocalInvokeResolutionError(`Lambda ${displayIdent(logicalId)} asset directory ${displayAssemblyPath(abs)} does not exist or is not a directory. Re-synthesize the app and retry.`);
89732
90134
  return abs;
89733
90135
  }
89734
90136
  /**
@@ -90751,7 +91153,7 @@ function parseContainerImage(raw, containerName, taskLogicalId, resources, _stac
90751
91153
  account: ecrHost.accountId,
90752
91154
  region: ecrHost.region
90753
91155
  };
90754
- if (looksLikeEcrHostWithForeignSuffix(substituted)) getLogger().child("ecs-task-resolver").debug(`Image '${substituted}' has an ECR host shape but a URL suffix that does not belong to its region's partition; treating it as a public image (no docker login).`);
91156
+ if (looksLikeEcrHostWithForeignSuffix(substituted)) getLogger().child("ecs-task-resolver").debug(`Image '${substituted}' has an ECR host shape, but that host form and suffix are not an ECR registry endpoint for its region; treating it as a public image (no docker login).`);
90755
91157
  return {
90756
91158
  kind: "public",
90757
91159
  uri: substituted
@@ -91334,24 +91736,17 @@ const SENSITIVE_ENV_KEYS = /* @__PURE__ */ new Set([
91334
91736
  * boundary, so a local-invoke build failure still surfaces with cdkd's exit code
91335
91737
  * / branding. `architectureToPlatform` is a pure helper (re-exported directly).
91336
91738
  *
91337
- * The build context is CONTAINED twice, against one REQUIRED `assetOutdir`
91338
- * bound (issue [#3503](https://github.com/go-to-k/cdkd/issues/3503)). The
91339
- * engine refuses an escaping `source.directory` itself since cdk-local 0.149.3,
91340
- * and the bound is FORWARDED to it: without one the engine narrows to the
91341
- * manifest directory and refuses a `cdk.Stage` image's `../asset.<hash>`
91342
- * (issue [#3597](https://github.com/go-to-k/cdkd/issues/3597)). cdkd still
91343
- * refuses first, because the engine's refusal quotes the manifest value in a
91344
- * boundary the value itself can close (go-to-k/cdk-local#758); once that
91345
- * ships, go-to-k/cdkd#3652 drops cdkd's copy.
91739
+ * The build context is CONTAINED by the engine, against the REQUIRED
91740
+ * `assetOutdir` bound this shim forwards (issues
91741
+ * [#3503](https://github.com/go-to-k/cdkd/issues/3503),
91742
+ * [#3597](https://github.com/go-to-k/cdkd/issues/3597)): without one the
91743
+ * engine narrows to the manifest directory and refuses a `cdk.Stage` image's
91744
+ * `../asset.<hash>`. The engine refuses an escaping `source.directory` before
91745
+ * it spawns anything, and renders the value display-safe since cdk-local
91746
+ * 0.149.4, so cdkd carries no copy of the check (go-to-k/cdkd#3652).
91346
91747
  * See cdk-local's `src/local/docker-image-builder.ts`.
91347
91748
  */
91348
91749
  async function buildContainerImage$1(asset, cdkOutDir, options) {
91349
- assertCdkLocalDockerContextContained({
91350
- manifestDir: cdkOutDir,
91351
- source: asset.source,
91352
- assetOutdir: options.assetOutdir,
91353
- wrapError: (message) => new LocalInvokeBuildError$1(`Refusing to build the container image: ${message}`)
91354
- });
91355
91750
  try {
91356
91751
  return await buildContainerImage(asset, cdkOutDir, options);
91357
91752
  } catch (e) {
@@ -91362,10 +91757,6 @@ async function buildContainerImage$1(asset, cdkOutDir, options) {
91362
91757
 
91363
91758
  //#endregion
91364
91759
  //#region src/local/ecr-puller.ts
91365
- /** The URL suffix an ECR registry host uses in `region`'s partition (issue #1758). */
91366
- function ecrUrlSuffix(region) {
91367
- return derivePartitionAndUrlSuffix(region).urlSuffix;
91368
- }
91369
91760
  /**
91370
91761
  * Lower-case the REGISTRY HOST of an image reference and leave the repository
91371
91762
  * path and tag byte-identical.
@@ -91485,12 +91876,8 @@ function isCredentialFresh(creds) {
91485
91876
  * pass to `docker run`: the input with its registry HOST lower-cased and
91486
91877
  * its repository path + tag untouched (issue #1801). That is the SAME
91487
91878
  * spelling `docker pull` / `docker image inspect` were handed here, and
91488
- * the same one the DERIVED `docker login` endpoint names — an
91489
- * AWS-reported `proxyEndpoint` still wins over that fallback (it can be
91490
- * a VPC-endpoint host), which is correct: AWS names the endpoint its own
91491
- * token authenticates, and it reports it lower-cased. That precedence holds
91492
- * only for the PLAIN host form: a FIPS or dual-stack pull logs in to its own
91493
- * host, since `proxyEndpoint` always names the plain one (issue #1855).
91879
+ * the same one the `docker login` endpoint names, on every host form
91880
+ * (issues #1855 / #3670).
91494
91881
  */
91495
91882
  async function pullEcrImage(imageUri, options) {
91496
91883
  const logger = getLogger().child("ecr-puller");
@@ -91594,18 +91981,21 @@ async function assumeRoleForEcr(roleArn, callerRegion, logger) {
91594
91981
  }
91595
91982
  /**
91596
91983
  * Authenticate the local docker daemon against the target ECR registry.
91597
- * Mirrors `DockerAssetPublisher.ecrLogin` but stays in this module so the
91598
- * local-invoke path doesn't depend on the publisher's larger surface area.
91599
- *
91600
- * The login endpoint must name the host the PULL targets (issue #1855):
91601
- * docker's credential store is keyed on the hostname verbatim, so a login to
91602
- * the plain host followed by a pull from a FIPS or dual-stack host sends no
91603
- * credentials (`no basic auth credentials`). `GetAuthorizationToken` reports
91604
- * the PLAIN host as its `proxyEndpoint`, so that value, and the derived
91605
- * fallback, are used only when the pull targets the plain form; every other
91606
- * form logs in to `registryHost` itself. The token is registry-scoped, not
91607
- * host-scoped: measured against real ECR, one token authenticated `/v2/` on
91608
- * all four host forms `ECR_REGISTRY_HOST_FORMS` lists.
91984
+ * Kept apart from `DockerAssetPublisher.ecrLogin`, and it no longer mirrors it:
91985
+ * the publisher still prefers `proxyEndpoint`, which is right only because it
91986
+ * pushes to the CALLER's own registry, while a pull here can name any account
91987
+ * and any host form, so this one always logs in to the pull host.
91988
+ *
91989
+ * The login endpoint is ALWAYS the host the PULL targets (issues #1855 /
91990
+ * #3670): docker's credential store is keyed on the hostname verbatim, so a
91991
+ * login to any other host leaves the pull with no credentials (`no basic auth
91992
+ * credentials`). `GetAuthorizationToken`'s `proxyEndpoint` is therefore NOT
91993
+ * used. The request carries no `registryIds`, so it names the CALLER's default
91994
+ * registry on the plain host: the wrong host for a FIPS or dual-stack pull, and
91995
+ * the wrong ACCOUNT for a cross-account plain pull made on the caller's own
91996
+ * credentials (a repository-policy grant, no `--ecr-role-arn`). The token is
91997
+ * principal-scoped, not host-scoped: measured against real ECR, one token
91998
+ * authenticated `/v2/` on all four host forms `ECR_REGISTRY_HOST_FORMS` lists.
91609
91999
  */
91610
92000
  async function ecrLogin(client, target) {
91611
92001
  const { accountId, region, registryHost } = target;
@@ -91614,8 +92004,7 @@ async function ecrLogin(client, target) {
91614
92004
  if (!authData?.authorizationToken) throw new LocalInvokeBuildError$1("Failed to get ECR authorization token");
91615
92005
  const [username, password] = Buffer.from(authData.authorizationToken, "base64").toString().split(":");
91616
92006
  if (!username || password === void 0) throw new LocalInvokeBuildError$1("ECR authorization token has unexpected shape (missing username/password)");
91617
- const plainHost = `${accountId}.dkr.ecr.${region}.${ecrUrlSuffix(region)}`;
91618
- const endpoint = registryHost === plainHost ? authData.proxyEndpoint || `https://${plainHost}` : `https://${registryHost}`;
92007
+ const endpoint = `https://${registryHost}`;
91619
92008
  const loginArgs = [
91620
92009
  "login",
91621
92010
  "--username",
@@ -93864,7 +94253,7 @@ function resolveImageLambda(args) {
93864
94253
  */
93865
94254
  function resolveAssetCodePath(stack, logicalId, resource) {
93866
94255
  const assetPath = resource.Metadata?.["aws:asset:path"];
93867
- if (typeof assetPath !== "string" || assetPath.length === 0) throw new Error(`Lambda '${displaySafe(logicalId)}' has no Metadata['aws:asset:path']. cdkd local start-api needs this hint to find the local asset directory. Re-synthesize the app and retry.`);
94256
+ if (typeof assetPath !== "string" || assetPath.length === 0) throw new Error(`Lambda ${displayIdent(logicalId)} has no Metadata['aws:asset:path']. cdkd local start-api needs this hint to find the local asset directory. Re-synthesize the app and retry.`);
93868
94257
  const { manifestDir, assetOutdir } = assetPathDirs(stack);
93869
94258
  return resolveAssetCodeDirectory({
93870
94259
  manifestDir,
@@ -95793,134 +96182,6 @@ function createLocalRunTaskCommand() {
95793
96182
  return cmd;
95794
96183
  }
95795
96184
 
95796
- //#endregion
95797
- //#region src/cli/commands/emulator-docker-context.ts
95798
- /**
95799
- * Decorate an `EmulatorStrategy` so every Docker image asset the bundled
95800
- * engine could build for this run is containment-checked BEFORE it builds one
95801
- * (issue [#3503](https://github.com/go-to-k/cdkd/issues/3503)).
95802
- *
95803
- * `cdkd local start-service` / `start-alb` hand the whole run to cdk-local's
95804
- * `runEcsServiceEmulator`, which reads each stack's asset manifest itself —
95805
- * for an ECS container image and for an ALB Lambda target's container image
95806
- * alike. Since cdk-local 0.149.3 the engine refuses an escaping
95807
- * `source.directory` at each build and each `--watch` soft reload
95808
- * (go-to-k/cdkd#3597). This check stays in front of it, for the whole
95809
- * assembly at once, because the engine's refusal quotes the assembly-chosen
95810
- * value in a boundary the value can close (go-to-k/cdk-local#758);
95811
- * go-to-k/cdkd#3652 removes it once that ships.
95812
- *
95813
- * `resolveBoots` is the seam because the engine calls it after every synth —
95814
- * at boot, and again on every `--watch` reload — and before any image is
95815
- * built on either path. A refusal at boot fails the command; on a reload the
95816
- * engine logs it and keeps the previous replicas serving, which is the
95817
- * fail-closed outcome.
95818
- *
95819
- * Every stack with a manifest is checked, not only the booted targets' stacks:
95820
- * which stack a target resolves to is decided inside the engine, and the ALB
95821
- * front door builds Lambda images from stacks no ECS boot names. An escaping
95822
- * `source.directory` is never something a real `cdk synth` writes, so
95823
- * refusing one anywhere in the assembly costs a legitimate run nothing, and
95824
- * `cdkd deploy` refuses the same assembly.
95825
- */
95826
- function containEmulatorDockerContexts(strategy) {
95827
- return {
95828
- ...strategy,
95829
- resolveBoots: (stacks, chosenTargets) => {
95830
- assertEmulatorDockerContextsContained(stacks);
95831
- return strategy.resolveBoots(stacks, chosenTargets);
95832
- }
95833
- };
95834
- }
95835
- /**
95836
- * The check itself, over the manifests the engine will read. Exported for
95837
- * unit testing.
95838
- *
95839
- * It reads the SAME file the engine does — `<manifest dir>/<stackName>.assets.json`,
95840
- * not `assetManifestPath` verbatim — and refuses a `stackName` that would
95841
- * carry that filename out of the manifest directory, as cdkd's own
95842
- * `AssetManifestLoader.loadManifest` does.
95843
- *
95844
- * A manifest that is absent, unreadable or not JSON is skipped: the engine
95845
- * reads it again and reports that failure itself, before building anything.
95846
- */
95847
- function assertEmulatorDockerContextsContained(stacks) {
95848
- for (const stack of stacks) {
95849
- if (!stack.assetManifestPath) continue;
95850
- const dirs = assetPathDirs(stack);
95851
- const { manifestDir } = dirs;
95852
- const assetOutdir = stack.assetOutdir === void 0 || stack.assetOutdir === "" ? dirs.assetOutdir : engineAssemblyRoot(stack.assetOutdir);
95853
- const manifestFile = resolveAssemblyPath(manifestDir, `${stack.stackName}.assets.json`);
95854
- if (!manifestFile.contained) throw new LocalInvokeBuildError$1(`Refusing to build container images: the asset manifest for stack '${displaySafe(stack.stackName)}' ${renderAssemblyPathEscape(manifestFile, manifestDir)}`);
95855
- const dockerImages = readDockerImages(manifestFile.path);
95856
- for (const [assetId, asset] of Object.entries(dockerImages)) {
95857
- const source = asset?.source;
95858
- if (source === null || typeof source !== "object") continue;
95859
- const { directory } = source;
95860
- if (typeof directory !== "string") continue;
95861
- assertCdkLocalDockerContextContained({
95862
- manifestDir,
95863
- source,
95864
- assetOutdir,
95865
- wrapError: (message) => new LocalInvokeBuildError$1(`Refusing to build container image asset '${displaySafe(assetId)}' of stack '${displaySafe(stack.stackName)}': ${message}`)
95866
- });
95867
- }
95868
- }
95869
- }
95870
- /**
95871
- * The containment bound the ENGINE itself uses for a stack it synthesized: its
95872
- * `assetOutdir`, climbed to the parent assembly when `--app` names a
95873
- * `cdk.Stage` sub-assembly. cdk-local enumerates no Stage stacks from an app
95874
- * root, so `--app cdk.out/assembly-<Stage>` is the only way these commands run
95875
- * a Stage, and its assets are staged one level up as `../asset.<hash>`.
95876
- *
95877
- * A copy of cdk-local's `assemblyRootOf` (not exported by the package): climb
95878
- * only while the directory is named `assembly-*` AND its parent's
95879
- * `manifest.json` declares it as a `cdk:cloud-assembly` artifact, and WARN
95880
- * whenever a climb happens, since the predicate is read from the tree being
95881
- * judged. Deleted with this module by go-to-k/cdkd#3652.
95882
- */
95883
- function engineAssemblyRoot(outdir) {
95884
- let dir = resolve(outdir);
95885
- let climbed = false;
95886
- for (;;) {
95887
- if (!basename(dir).startsWith("assembly-")) break;
95888
- const parent = dirname(dir);
95889
- if (parent === dir || !parentDeclaresNestedAssembly(parent, basename(dir))) break;
95890
- dir = parent;
95891
- climbed = true;
95892
- }
95893
- if (!climbed) return outdir;
95894
- if (!warnedDerivedRoots.has(dir)) {
95895
- warnedDerivedRoots.add(dir);
95896
- getLogger().warn(`${displayAssemblyPath(outdir)} is a cdk.Stage sub-assembly, so cdkd is treating its parent ${displayAssemblyPath(dir)} as the assembly root when it checks Docker build contexts — that is where cdk synth stages a Stage's assets. Everything under that parent is now inside the containment bound, including siblings of the directory you named.`);
95897
- }
95898
- return dir;
95899
- }
95900
- const warnedDerivedRoots = /* @__PURE__ */ new Set();
95901
- function parentDeclaresNestedAssembly(parent, child) {
95902
- try {
95903
- const artifacts = JSON.parse(readFileSync(join(parent, "manifest.json"), "utf-8")).artifacts;
95904
- if (artifacts === null || typeof artifacts !== "object") return false;
95905
- return Object.values(artifacts).some((a) => {
95906
- const art = a;
95907
- return art?.type === "cdk:cloud-assembly" && art.properties?.directoryName === child;
95908
- });
95909
- } catch {
95910
- return false;
95911
- }
95912
- }
95913
- function readDockerImages(manifestPath) {
95914
- let parsed;
95915
- try {
95916
- parsed = JSON.parse(readFileSync(manifestPath, "utf-8"));
95917
- } catch {
95918
- return {};
95919
- }
95920
- const dockerImages = parsed?.dockerImages;
95921
- return dockerImages !== null && typeof dockerImages === "object" ? dockerImages : {};
95922
- }
95923
-
95924
96185
  //#endregion
95925
96186
  //#region src/cli/commands/local-start-service.ts
95926
96187
  /**
@@ -95948,17 +96209,6 @@ function serviceStrategy() {
95948
96209
  };
95949
96210
  }
95950
96211
  /**
95951
- * The `EmulatorStrategy` `cdkd local start-service` runs with:
95952
- * {@link serviceStrategy}, decorated by `containEmulatorDockerContexts` so the
95953
- * engine's own Docker builds are containment-checked (issue
95954
- * [#3503](https://github.com/go-to-k/cdkd/issues/3503)). A NAMED seam for the
95955
- * same reason `buildAlbEmulatorStrategy` is one: inline in the action, the
95956
- * decorator was deletable at its only call site.
95957
- */
95958
- function buildServiceEmulatorStrategy() {
95959
- return containEmulatorDockerContexts(serviceStrategy());
95960
- }
95961
- /**
95962
96212
  * `cdkl start-service <Stack/Service>...` — run one or more `AWS::ECS::Service`
95963
96213
  * resources locally as a long-running emulator. Spins up DesiredCount task
95964
96214
  * replicas per service (clamped by --max-tasks) using the same per-task
@@ -95971,7 +96221,7 @@ function buildServiceEmulatorStrategy() {
95971
96221
  */
95972
96222
  function createLocalStartServiceCommand() {
95973
96223
  const cmd = new Command("start-service").description("Run one or more AWS::ECS::Service resources locally as a long-running emulator. Spins up DesiredCount task replicas per service (clamped by --max-tasks) using the same per-task docker network + metadata sidecar pattern as `cdkd local run-task`, then keeps each replica running and restarts it on exit per --restart-policy. ^C tears every replica + sidecar + network down. Each <target> accepts a CDK display path (MyStack/MyService) or stack-qualified logical ID (MyStack:MyServiceXYZ); single-stack apps may omit the stack prefix. When two or more <target>s are supplied, every service is booted into a shared Cloud Map / Service Connect registry so peer services discover each other via docker --add-host overlay (Issue #460). Omit <targets> in an interactive terminal to multi-select the ECS services from a list.").argument("[targets...]", "One or more CDK display paths or stack-qualified logical IDs of the AWS::ECS::Service resources to run (omit to multi-select interactively in a TTY)").addOption(new Option("--from-state", "Read cdkd's S3 state for the target stack and substitute Ref / Fn::GetAtt / Fn::Sub / Fn::ImportValue / Fn::GetStackOutput intrinsics in container images, environment variables, secrets, role ARNs, and volumes. Mutually exclusive with --from-cfn-stack.").default(false)).addOption(new Option("--state-bucket <bucket>", "S3 bucket for --from-state. Falls back to CDKD_STATE_BUCKET env or cdk.json context.cdkd.stateBucket.")).addOption(new Option("--state-prefix <prefix>", "S3 key prefix for --from-state state files.").default("cdkd")).action(withErrorHandling(async (targets, options) => {
95974
- await runEcsServiceEmulator(targets, options, buildServiceEmulatorStrategy(), cdkdExtraStateProviders);
96224
+ await runEcsServiceEmulator(targets, options, serviceStrategy(), cdkdExtraStateProviders);
95975
96225
  }));
95976
96226
  addStartServiceSpecificOptions(cmd);
95977
96227
  return adoptDeprecatedRegionFlag(addCommonEcsServiceOptions(cmd));
@@ -96903,12 +97153,12 @@ async function resolveAgentCoreCodeImage(resolved, code, options, architecture,
96903
97153
  const manifest = await loader.loadManifest(cdkOutDir, resolved.stack.stackName);
96904
97154
  const fileAssets = manifest ? loader.getFileAssets(manifest) : void 0;
96905
97155
  const asset = fileAssets ? fileAssets.get(code.codeAssetHash) ?? findFileAssetByObjectKey(fileAssets, code.codeAssetHash) : void 0;
96906
- if (!asset) throw new CdkdError(`AgentCore Runtime '${displaySafe(resolved.logicalId)}' code bundle (asset ${displaySafe(code.codeAssetHash)}) was not found in the cdk.out asset manifest. ${getEmbedConfig().cliName} invoke-agentcore runs a local from-source build of a fromCodeAsset bundle — re-synthesize the app so the asset is staged in cdk.out and retry. (A fromS3 bundle is downloaded from S3 instead; this runtime has no literal Code.S3.Bucket.)`, "LOCAL_INVOKE_AGENTCORE_CODE_ASSET_NOT_FOUND");
97156
+ if (!asset) throw new CdkdError(`AgentCore Runtime ${displayIdent(resolved.logicalId)} code bundle (asset ${displaySafe(code.codeAssetHash)}) was not found in the cdk.out asset manifest. ${getEmbedConfig().cliName} invoke-agentcore runs a local from-source build of a fromCodeAsset bundle — re-synthesize the app so the asset is staged in cdk.out and retry. (A fromS3 bundle is downloaded from S3 instead; this runtime has no literal Code.S3.Bucket.)`, "LOCAL_INVOKE_AGENTCORE_CODE_ASSET_NOT_FOUND");
96907
97157
  const sourceDir = loader.getAssetSourcePath(cdkOutDir, asset, {
96908
97158
  assetOutdir: assemblyDir,
96909
97159
  sink: "read that directory and build a local image from it"
96910
97160
  });
96911
- if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) throw new CdkdError(`AgentCore Runtime '${displaySafe(resolved.logicalId)}' code bundle source ${displayAssemblyPath(sourceDir)} does not exist or is not a directory. Re-synthesize the app and retry.`, "LOCAL_INVOKE_AGENTCORE_CODE_SOURCE_MISSING");
97161
+ if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) throw new CdkdError(`AgentCore Runtime ${displayIdent(resolved.logicalId)} code bundle source ${displayAssemblyPath(sourceDir)} does not exist or is not a directory. Re-synthesize the app and retry.`, "LOCAL_INVOKE_AGENTCORE_CODE_SOURCE_MISSING");
96912
97162
  return buildAgentCoreCodeImage({
96913
97163
  sourceDir,
96914
97164
  runtime: code.runtime,
@@ -97660,8 +97910,7 @@ function warnUnresolvedLambdaTargetEnv(strategy, options) {
97660
97910
  }
97661
97911
  /**
97662
97912
  * The `EmulatorStrategy` `cdkd local start-alb` runs with: cdk-local's ALB
97663
- * strategy, decorated by {@link warnUnresolvedLambdaTargetEnv} and then by
97664
- * `containEmulatorDockerContexts` (issue go-to-k/cdkd#3503).
97913
+ * strategy, decorated by {@link warnUnresolvedLambdaTargetEnv}.
97665
97914
  *
97666
97915
  * Extracted from the command's action for ONE reason, and it is the finding
97667
97916
  * that produced it: with the composition written inline in the `.action(...)`
@@ -97681,7 +97930,7 @@ function warnUnresolvedLambdaTargetEnv(strategy, options) {
97681
97930
  * can satisfy reads as coverage while providing none.
97682
97931
  */
97683
97932
  function buildAlbEmulatorStrategy(options) {
97684
- return containEmulatorDockerContexts(warnUnresolvedLambdaTargetEnv(albStrategy(options), options));
97933
+ return warnUnresolvedLambdaTargetEnv(albStrategy(options), options);
97685
97934
  }
97686
97935
  /**
97687
97936
  * `cdkl start-alb <Stack/Alb>` — Issue #86 v1. Names an
@@ -98819,4 +99068,4 @@ function buildProgram() {
98819
99068
 
98820
99069
  //#endregion
98821
99070
  export { buildProgram };
98822
- //# sourceMappingURL=program-hXXls0hg.js.map
99071
+ //# sourceMappingURL=program-DxyHPT8E.js.map