@go-to-k/cdkd 0.296.25 → 0.296.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/README.md +7 -2
  2. package/dist/{asg-provider-CdG5Zd57.js → asg-provider-BiMLPagi.js} +3 -3
  3. package/dist/{asg-provider-CdG5Zd57.js.map → asg-provider-BiMLPagi.js.map} +1 -1
  4. package/dist/cli.js +2 -2
  5. package/dist/{deploy-engine-Dyj0tnOa.js → deploy-engine-DC4Yblxp.js} +11 -10
  6. package/dist/deploy-engine-DC4Yblxp.js.map +1 -0
  7. package/dist/{iam-policy-targets-BoZuWtxK.js → iam-policy-targets-B61e5_Sk.js} +2 -2
  8. package/dist/{iam-policy-targets-BoZuWtxK.js.map → iam-policy-targets-B61e5_Sk.js.map} +1 -1
  9. package/dist/{iam-role-provider-ByH7w-1n.js → iam-role-provider-BA2eujXF.js} +3 -3
  10. package/dist/{iam-role-provider-ByH7w-1n.js.map → iam-role-provider-BA2eujXF.js.map} +1 -1
  11. package/dist/index.js +3 -3
  12. package/dist/{neptune-provider-daz11aIJ.js → neptune-provider-DME95IcZ.js} +3 -3
  13. package/dist/{neptune-provider-daz11aIJ.js.map → neptune-provider-DME95IcZ.js.map} +1 -1
  14. package/dist/{program-GmKPVK8p.js → program-BwNb3_Ot.js} +354 -48
  15. package/dist/program-BwNb3_Ot.js.map +1 -0
  16. package/dist/{provider-classes-N6aXDqij.js → provider-classes-BcSDENeH.js} +97 -20
  17. package/dist/provider-classes-BcSDENeH.js.map +1 -0
  18. package/dist/{rds-provider-DTLTlRGL.js → rds-provider-iouJXdXX.js} +3 -3
  19. package/dist/{rds-provider-DTLTlRGL.js.map → rds-provider-iouJXdXX.js.map} +1 -1
  20. package/dist/{version-DImm5uUz.js → version-Cs9QbaaH.js} +2 -2
  21. package/dist/{version-DImm5uUz.js.map → version-Cs9QbaaH.js.map} +1 -1
  22. package/package.json +10 -3
  23. package/dist/deploy-engine-Dyj0tnOa.js.map +0 -1
  24. package/dist/program-GmKPVK8p.js.map +0 -1
  25. package/dist/provider-classes-N6aXDqij.js.map +0 -1
@@ -1,9 +1,9 @@
1
1
  import { a as runWithStackAwsClients, i as resetAwsClients, o as setAwsClients, t as AwsClients } from "./aws-clients-CnmtbrxD.js";
2
2
  import { A as UNRENDERABLE, B as stringifyJsonPayload, D as SAFE_MSG_ALTERED_CHAR, F as displayStackName, I as isPasteableIdent, M as displayAwsMessage, N as displayIdent, O as SECRET_REF_MAX_CODE_POINTS, P as displaySafe, R as plainIdentOr, T as withStackName, V as truncateCodePoints, _ as derivesPatternBName, a as getLogger, f as getLiveRenderer, h as PATTERN_B_RESOURCE_TYPES, j as cutMarker, k as STACK_REF_MAX_CODE_POINTS, l as runStackBuffered, m as PATTERN_B_NAME_PROPERTIES, o as isStdoutReservedForPayload, p as PATTERN_B_NAME_OPTIONS, r as safeStringify, s as reserveStdoutForPayload, t as describeAwsFailure, v as explicitNamePropertyFor, w as withSkipPrefix, y as generateResourceName, z as safeMsg } from "./aws-failure-text-BaWeCWRz.js";
3
- import { $t as AccountIdUnavailableError, An as commandHole, Bn as setPasteableRunFlags, D as VALUE_NOT_SHOWN, E as assertRegionMatch, En as TIMEOUT_FLAG_RESOURCE_TYPE, Fn as plainOrDescribed, Ft as buildLockContentionMessage, G as runDeleteAttempt, Gt as producerCoordinateKey, Ht as DEFAULT_STATE_PREFIX, In as quotedOrDescribed, It as forceQuitRecoveryClause, Jt as withPasteableAwsProfile, Kt as producerRecordKey, Ln as shellBoundedDisplay, Lt as formatLockExpiry, Mn as isInertUnquoted, Nn as pasteableCommand, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE_WHY, P as remedyLogicalId, Pt as buildForceUnlockCommand, Qn as isAmbiguousOutcomeError, Qt as credentialFingerprint, Rn as shellQuote, Rt as formatLockOperation, T as RESOURCE_NOT_FOUND, Tn as withErrorHandling, Ut as injectiveKey, Vn as setPasteableVerbFlags, Vt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xt as ambientCredentialConfig, Yt as ambientClientDefaults, Z as isAwsCliLiteral, Zt as clientDefaultsFor, _n as ResourceUpdateNotSupportedError, an as DeployCancelledError, ar as isThrottlingError, cn as LocalInvokeBuildError$1, er as isRetryableTransientError, fn as MalformedProducerRecordRefusalError, ft as logicalIdShown, gn as ResourceTimeoutError, hn as ProvisioningError, ir as isMarkedNonRetryable, it as isInterruptedWaitError, ln as LocalStartServiceError, mn as PartialFailureError, mt as resourceTypeShown, n as RESOLVED_PREVIOUS_PRINCIPAL_KEYS, nr as retryClassificationText, nt as endCommandInterruptScope, on as DynamicReferenceRegionAmbiguousError, or as markNonRetryable, pn as NestedStackChildDirectDestroyError, qt as setPasteableAwsProfile, rn as CrossAccountSecretRefusalError, rt as interruptWatchListenerCount, s as readRecordedPrincipals, sn as IntrinsicResolutionRefusalError, t as IAM_PRINCIPAL_NAME, tn as CdkdError, tr as isTransientServerError, tt as beginCommandInterruptScope, vn as StackHasActiveImportsError, wn as normalizeAwsError, xn as SynthesisError, yn as StackTerminationProtectionError, zn as withheldTargetClause, zt as formatLockOwner } from "./iam-policy-targets-BoZuWtxK.js";
3
+ import { $t as AccountIdUnavailableError, An as commandHole, Bn as setPasteableRunFlags, D as VALUE_NOT_SHOWN, E as assertRegionMatch, En as TIMEOUT_FLAG_RESOURCE_TYPE, Fn as plainOrDescribed, Ft as buildLockContentionMessage, G as runDeleteAttempt, Gt as producerCoordinateKey, Ht as DEFAULT_STATE_PREFIX, In as quotedOrDescribed, It as forceQuitRecoveryClause, Jt as withPasteableAwsProfile, Kt as producerRecordKey, Ln as shellBoundedDisplay, Lt as formatLockExpiry, Mn as isInertUnquoted, Nn as pasteableCommand, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, On as SHELL_ACTIVE_WHY, P as remedyLogicalId, Pt as buildForceUnlockCommand, Qn as isAmbiguousOutcomeError, Qt as credentialFingerprint, Rn as shellQuote, Rt as formatLockOperation, T as RESOURCE_NOT_FOUND, Tn as withErrorHandling, Ut as injectiveKey, Vn as setPasteableVerbFlags, Vt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xt as ambientCredentialConfig, Yt as ambientClientDefaults, Z as isAwsCliLiteral, Zt as clientDefaultsFor, _n as ResourceUpdateNotSupportedError, an as DeployCancelledError, ar as isThrottlingError, cn as LocalInvokeBuildError$1, er as isRetryableTransientError, fn as MalformedProducerRecordRefusalError, ft as logicalIdShown, gn as ResourceTimeoutError, hn as ProvisioningError, ir as isMarkedNonRetryable, it as isInterruptedWaitError, ln as LocalStartServiceError, mn as PartialFailureError, mt as resourceTypeShown, n as RESOLVED_PREVIOUS_PRINCIPAL_KEYS, nr as retryClassificationText, nt as endCommandInterruptScope, on as DynamicReferenceRegionAmbiguousError, or as markNonRetryable, pn as NestedStackChildDirectDestroyError, qt as setPasteableAwsProfile, rn as CrossAccountSecretRefusalError, rt as interruptWatchListenerCount, s as readRecordedPrincipals, sn as IntrinsicResolutionRefusalError, t as IAM_PRINCIPAL_NAME, tn as CdkdError, tr as isTransientServerError, tt as beginCommandInterruptScope, vn as StackHasActiveImportsError, wn as normalizeAwsError, xn as SynthesisError, yn as StackTerminationProtectionError, zn as withheldTargetClause, zt as formatLockOwner } from "./iam-policy-targets-B61e5_Sk.js";
4
4
  import { n as awsClientDefaults, r as getAssumedRoleCredentials, u as formatAuthority } from "./aws-client-defaults-D0q0z4dG.js";
5
- import { $ as green, $a as describeTypeWithThrottleRetry, $i as refuseMalformedResourceAttributesForOrphan, $o as TEMPLATE_SOURCED_RULES, $r as carriesDynamicReference, $s as runDockerStreaming, $t as updatePartialReason, A as readProtection, Aa as findReplacedReadersOfRecreateTargets, Ac as derivePartitionAndUrlSuffix, Ai as malformedOrphanRecordsRefusalMessage, An as collectPublishedOutputNames, Ao as maskSecretsInError, Ar as producerRegionsFromState, As as ensureAssetStorage, At as destroyStackRecordsView, Bc as describeFileReadFailure, Bi as malformedResourcesWarning, Bo as inheritNestedStackParameterAssociations, Br as callerEnvCredentials, Bs as describeDockerCapturedOutput, Bt as recheckFailedPlan, C as noEchoComparisonForTemplate, Ca as withheldAccountClause, Cc as findLargeInlineResources, Ci as isReadableResourceEntry, Cn as secretSafeKeyDisplay, Co as logOnlyValueCount, Cs as buildAssetRedirectMap, Ct as journaledOrphanLines, D as PROTECTION_PROPERTY_BY_TYPE, Dc as expectedOwnerParam, Di as malformedLocalOutputsWarning, Dn as isWholeDynamicReferenceValue, Do as shareLogOnlyValues, Dr as IntrinsicFunctionResolver, Ds as AssetModeResolver, Dt as replayFailedOperations, E as recordedProtectionNote, Ea as unwrittenCreateOnlyReplacement, Ec as decodeListingKey, Ei as malformedExportSourceWarning, En as exportNameSecretExposure, Eo as recordLogOnlyValue, Er as INTRINSIC_KEYS, Es as rewriteTemplateAssetReferences, Et as sameJournaledOrphans, Fa as renderStatefulReason, Fc as hasOwnKey, Fi as malformedOutputsRefusalMessage, Fn as maskingRetryLogger, Fo as DYNAMIC_REFERENCE_TOKEN_SCAN, Fr as explicitRoleArnOrThrow, Fs as validateAssetBucketName, Ft as demoteSupersededOrphans, Gc as resolveBucketRegion, Go as recordMaskOnlyValue, Gs as formatDockerLoginError, Gt as findNestedStackTypeChanges, Hc as renderAssemblyPathEscape, Hi as malformedStateRefusalMessage, Hs as describeDockerFailure, Ht as replacementNeverSwapped, Ic as hasPlainPrototype, Ii as malformedOutputsWarning, In as constructPathOf, Io as dynamicReferenceTokens, Ir as isIamRoleArn, Is as validateContainerRepoName, It as isJournaledOrphan, J as formatResourceLine, Ji as refuseMalformedOrphans, Jo as recordProvenPublicExpression, Jr as coerceParameterTypedValue, Js as isMalformedEnvKey, Ki as refuseMalformedOrphanRecords, Ko as recordMaskOnlyValuesIn, Ks as getDockerCmd, Lc as nullPrototypeRecord, Li as malformedRenderedContainersWarning, Ln as findDestructiveChanges, Lo as isUncertifiedBaselineMaskPosition, Lr as sendableAssumeRoleCommand, Ls as buildDenyExternalAccessPolicy, Lt as isReplacementOrphan, Ma as MULTI_REGION_RECREATE_BLOCKED_TYPES, Mc as StageLoadError, Mi as malformedOrphanRowsKeptWarning, Mn as bindingSkippedOutputs, Mo as markSameGenerationBag, Mr as applyRoleArnIfSet, Ms as isCrossRegionRedirect, Mt as withStackRecords, Na as isStatefulRecreateTargetForReplace, Nc as processStackMessages, Ni as malformedOrphansRefusalMessage, Nn as DEFAULT_RESOURCE_TIMEOUT_MS, No as redactSecretsForState, Nr as assertFlagRoleArn, Ns as parseBootstrapMarker, Nt as removeProtectionTypeList, O as isProtectionValueActive, Oa as NO_CC_HANDLERS_REASON, Oc as PARTITION_TABLE, Oi as malformedLocalResourceEntriesWarning, On as noEchoParameterValueSeed, Oo as createSecretMasker, Or as poisonRenderedSpellingsCollidingIn, Os as BOOTSTRAP_MARKER_PREFIX, Ot as replayRollback, Pa as isStatefulRecreateTargetSync, Pc as defineOwnKey, Pi as malformedOrphansWarning, Pn as DEFAULT_RESOURCE_WARN_AFTER_MS, Po as scrubResourceRecord, Pr as assertSendableRoleArn, Ps as readBootstrapMarkerBody, Pt as recordAfterRollbackUpdate, Q as gray, Qa as templateResourceTypes, Qi as refuseMalformedOutputsForDestroy, Qo as STATE_SOURCED_READBACK_RULES, Qr as isImpossibleEmptyStoredAttribute, Qs as runDockerForeground, Qt as updatePartialMessage, Rc as ownValue, Ri as malformedResourceEntriesWarning, Rn as formatDestructiveChange, Ro as pathCrossesDottedKey, Rr as AWS_CREDENTIAL_ENV_KEYS, Rs as buildDockerImage, Rt as planFailedOps, S as noEchoAttributeNamesOf, Sa as unreadableResourceEntries, Sc as MIGRATE_TMP_PREFIX, Si as isReadableOrphanRecord, Sn as secretBearingStateKeyWarning, So as literalSplitDelimitersOf, Ss as WorkGraph, St as isHandledOrphan, T as recordedProtectionEvidence, Tc as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Ti as malformedExportNamesWarning, Tn as exportNameNoEchoParameters, To as recordLogOnlyParameterValue, Tr as DiffCalculator, Ts as loadPublishableAssetManifest, Tt as makeForeignHolderScan, Uc as resolveAssemblyPath, Ui as previewableOrphanRecords, Un as withCreateTokenLedger, Uo as carriesSecretMask, Us as dockerSpawnEnvWithSensitive, Ut as resolveReplacementOldType, Vc as displayAssemblyPath, Vi as malformedScrubResourceEntriesRefusalMessage, Vn as ledgerForStack, Vo as recordNestedStackParameterExpressions, Vr as envCredentialsAreAssumedRole, Vs as describeDockerExecFailure, Vt as recordUnderIdIsNotOwn, Wi as refuseDivergentRecordRegionForDestroy, Wo as provenPublicValue, Ws as finchSecretArgvRefusal, Wt as orphanDeleteNeedsIdentity, X as bold, Xi as refuseMalformedOrphansForOrphan, Xo as STATE_SOURCED_BASELINE_RULES, Xr as parameterTypeMayLoseSecretIdentity, Xs as redactDockerArgvValues, Y as createReadOnlyAttributeHealerFactory, Yi as refuseMalformedOrphansForDestroy, Yo as wholeStringLeavesOf, Yr as isUnboundTemplateParameter, Ys as partitionSensitiveEnv, Z as cyan, Za as prefetchCreateOnlyPropertyPaths, Zi as refuseMalformedOutputs, Zo as STATE_SOURCED_CROSS_GENERATION_RULES, Zr as getAccountInfo, Zs as redactedDockerCause, _ as makeCanonicalizePropertiesFn, _a as repairMalformedResourceEntriesForReadOnly, _c as stateBucketExistenceConfirmed, _i as deployRefusesOrphanRowsReason, _n as extractDeploymentEventError, _o as valueAtCoordinate, _r as isWaitAbandonedError, _s as orphansCarriedFrom, _t as withNestedRevertRun, a as findNestedTemplateTreeDefect, aa as refuseMalformedResourceEntriesForOrphan, ac as Synthesizer, ai as isStalePlaceholderArnAttribute, an as stateSecretNameNeedles, ao as TemplateParser, ar as TemplateNoEchoReresolver, as as rebuildClientForBucketRegion, at as resourcesNamingDeclaredParameter, b as serviceTokenBlockingReason, ba as unpreviewableOrphanRecords, bc as CFN_TEMPLATE_BODY_LIMIT, bi as hasReadableOutputs, bn as exportAliasCollisionScrubWarning, bo as createUnionSecretMasker, bs as isSensitiveAttributeName, bt as deleteJournaledOrphans, c as renderNestedTemplateTreeDefect, ca as refuseMalformedResourcePropertiesForExport, cc as getLegacyStateBucketName, ci as withSharedDrainBudget, cn as buildFinalSnapshotIdentifier, co as maskAtCoordinates, cs as describeRegionValueKind, ct as NESTED_PENDING_PARENT_REASON, d as conditionInputsFrom, da as refuseMalformedResourcesForDestroy, dc as resolveAutoAssetStorage, di as JSON_LISTING_HOLE_VALUE, dn as effectiveDeletionPolicy, do as maskedLeafCoordinatesOf, dr as slowCcOperationTimeoutMs, ds as hasReasonlessBaselineRefusal, dt as dropSettledNestedJournals, ea as refuseMalformedResourceEntries, ec as warnFinchArgvExposure, ei as carriesFetchableDynamicReference, en as completedReplayEntries, eo as withRetry, er as CC_BROKEN_REASON, es as WHOLE_DYNAMIC_REFERENCE_PATTERN, et as red, f as parentSuppliedValues, fa as refuseMalformedResourcesForExport, fc as resolveCaptureObservedState, fi as STATE_REGION_DIVERGED, fn as isFinalSnapshotError, fo as noEchoLeavesOf, fs as hasUnverifiableParameterRefusal, g as mergeNoChangeOutputs, ga as repairMalformedOutputsForReadOnly, gc as resolveUseCdkBootstrapAssets, gi as accountArgs, gn as DeploymentEventsStore, go as readsNoEchoSource, gs as orphansAfterRollback, gt as revertedNestedRowIds, h as keptWholeReasonText, ha as repairMalformedOrphansForReadOnly, hc as resolveStateBucketWithDefaultAndSource, hi as UNREADABLE_RESOURCES_MAP_ROW, hn as DeploymentEventsReader, ho as readbackPathFor, hr as deleteSkipReason, hs as isReadableBag, i as childTemplateLoader, ia as refuseMalformedResourceEntriesForImportSave, ic as getDockerImageBySourceHash, ii as cfnRefValueFromPhysicalId, in as secretNamePrintingBag, io as DagBuilder, ir as wouldReturnToSdkProvider, is as S3StateBackend, it as reachableDivergentParameters, ja as shownType, jc as AssemblyReader, ji as malformedOrphanRecordsWarning, jn as isExportAliasCollision, jo as maskSecretsInText, jr as regionLessSecretName, js as getBootstrapMarkerKey, k as perType, ka as hasNoCloudControlHandlers, kc as canonicalizeRegion, ki as malformedLocalResourcesWarning, kn as collectDeclaredOutputNames, ko as errorCauseChain, kr as classifyReplaySecretRegion, ks as assertAssetBucketRegion, l as templateIdentity, la as refuseMalformedResourcePropertiesForOrphan, lc as loadCdkJson, li as parameterInputsFor, ln as ccRoutedFinalSnapshotError, lo as maskReadbackAtCoordinates, lr as withPrintingSecrets, ls as exportNamesCarriedFrom, lt as displacedOpClause, m as isSecretBearingReferenceString, ma as repairMalformedOrphanRecordsForReadOnly, mc as resolveStateBucketWithDefault, mi as UNREADABLE_ORPHANS_CONTAINER_ROW, mn as unsupportedFinalSnapshotError, mr as deleteIndeterminateGuards, ms as importableOutputs, mt as recordDisplacedSkips, n as IMPLICIT_DELETE_DEPENDENCIES, na as refuseMalformedResourceEntriesForDestroy, nc as stripControlChars, ni as keepsSecretReferenceToken, nn as maskEventTextWithBoundBags, nr as ccBrokenReason, ns as LockManager, nt as computeParameterTaint, o as isAbsoluteAssetPath, oa as refuseMalformedResourcePropertiesForDestroy, oc as synthesisStatusMessage, oi as refStateLookupFromResource, on as ATOMIC_FINAL_SNAPSHOT_TYPES, oo as canonicalCoordinates, or as readsNoEchoDeleteValues, os as splitImportedOps, ot as makeSiblingClaimReader, p as readRecordedConditionVerdicts, pa as refuseMalformedState, pc as resolveSkipPrefix, pi as STATE_RESOURCES_MALFORMED, pn as refusesFinalSnapshot, po as noEchoOutputsComparison, pr as UNSPECIFIED_SKIP_REASON, ps as importableOutputKeys, pt as nestedChildStackName$1, qi as refuseMalformedOrphanRecordsForDestroy, qo as recordNoEchoAttributeValues, qs as isDockerClientEnvKey, qt as inheritProducerRegions, r as computeImplicitDeleteEdges, ra as refuseMalformedResourceEntriesForImport, rc as AssetManifestLoader, ri as AWS_NO_VALUE, rn as orphanRecordsPrintingBag, rr as isCustomResource, rs as isLockInfoExpired, rt as namesAnyDeclaredParameter, s as listNestedTemplateRows, sa as refuseMalformedResourcePropertiesForDrift, sc as getDefaultStateBucketName, sn as PRE_DELETE_SNAPSHOT_TYPES, so as isMarkedCoordinate, sr as isCustomResourceType$1, ss as acceptedCreateOnlyDropsOf, st as planOrphanAdoption, t as DeployEngine, ta as refuseMalformedResourceEntriesForDeploy, tc as escapeRegExp, ti as isNamelessDynamicReferenceError, tn as journaledOrphanPrintingBag, tr as ProviderRegistry, ts as isSingleDynamicReferenceToken, tt as yellow, u as conditionFingerprint, ua as refuseMalformedResourcesForDeploy, uc as resolveApp, un as createPreDeleteFinalSnapshot, uo as maskWholeValue, ur as CloudControlProvider, us as hasReadableExportSet, ut as displacedPhysicalIdShown, v as deferredServiceTokenWarning, va as repairMalformedResourcePropertiesForReadOnly, vc as warnDeprecatedNoPrefixCliFlag, vi as displayLogicalId, vn as WITHHELD_NAME_DISPLAY, vo as liveMatchesUnresolvedTokenFrame, vs as shouldRetainResource, w as noEchoParameterNamesOf, wa as findActionableSilentDrops, wc as uploadCfnTemplate, wi as malformedDriftResourcePropertiesWarning, wn as carriedExportAliasExposure, wo as printingCorpusOf, ws as createAssetRedirectResolver, wt as loadJournaledOrphans, x as withResourceDeadline, xa as unreadableOrphanRecords, xc as CFN_TEMPLATE_URL_LIMIT, xi as hasReadableResources, xn as secretBearing, xo as hasMaskableValues, xs as stringifyValue, xt as dropFailedHint, y as findServiceTokenRefusals, ya as repairMalformedResourcesForReadOnly, yc as ssmResolvedValueType, yi as hasReadableOrphans, yn as displayTextOrWithheld, yo as carryLogOnlyValues, ys as AssetPublisher, yt as withNestedStackContext, zc as absoluteAssemblyPathEscape, zi as malformedResourcePropertiesWarning, zn as RollbackInlinePolicyWriters, zo as identityKeyFor, zr as applyCallerIdentityCredentials, zs as resolveDockerContextDirectory, zt as planRollback } from "./deploy-engine-Dyj0tnOa.js";
6
- import { t as getCdkdVersion } from "./version-DImm5uUz.js";
5
+ import { $ as gray, $a as templateResourceTypes, $i as refuseMalformedOutputsForDestroy, $o as STATE_SOURCED_BASELINE_RULES, $r as isImpossibleEmptyStoredAttribute, $s as redactDockerArgvValues, $t as updatePartialMessage, A as perType, Aa as hasNoCloudControlHandlers, Ac as expectedOwnerParam, Ai as malformedLocalResourcesWarning, An as collectDeclaredOutputNames, Ao as createSecretMasker, Ar as classifyReplaySecretRegion, As as AssetModeResolver, Bc as nullPrototypeRecord, Bi as malformedResourcePropertiesWarning, Bn as RollbackInlinePolicyWriters, Bo as pathCrossesDottedKey, Br as applyCallerIdentityCredentials, Bs as buildDenyExternalAccessPolicy, Bt as planRollback, C as noEchoComparisonForTemplate, Ca as unreadableResourceEntries, Cc as CFN_TEMPLATE_BODY_LIMIT, Ci as isReadableOrphanRecord, Cn as secretBearingStateKeyWarning, Co as hasMaskableValues, Cs as isSensitiveAttributeName, Ct as isHandledOrphan, D as recordedProtectionNote, Da as unwrittenCreateOnlyReplacement, Dc as uploadCfnTemplate, Di as malformedExportSourceWarning, Dn as exportNameSecretExposure, Do as recordLogOnlyParameterValue, Dr as INTRINSIC_KEYS, Ds as createAssetRedirectResolver, Dt as sameJournaledOrphans, E as recordedProtectionEvidence, Ec as findLargeInlineResources, Ei as malformedExportNamesWarning, En as exportNameNoEchoParameters, Eo as printingCorpusOf, Er as DiffCalculator, Es as buildAssetRedirectMap, Et as makeForeignHolderScan, Fa as isStatefulRecreateTargetSync, Fc as StageLoadError, Fi as malformedOrphansWarning, Fn as DEFAULT_RESOURCE_WARN_AFTER_MS, Fo as redactSecretsForState, Fr as assertSendableRoleArn, Fs as isCrossRegionRedirect, Ft as recordAfterRollbackUpdate, Gc as renderAssemblyPathEscape, Gi as refuseDivergentRecordRegionForDestroy, Go as carriesSecretMask, Gs as describeDockerFailure, Gt as orphanDeleteNeedsIdentity, Hc as absoluteAssemblyPathEscape, Hi as malformedScrubResourceEntriesRefusalMessage, Hn as ledgerForStack, Ho as inheritNestedStackParameterAssociations, Hr as envCredentialsAreAssumedRole, Hs as resolveDockerContextDirectory, Ht as recordUnderIdIsNotOwn, Ia as renderStatefulReason, Ic as processStackMessages, Ii as malformedOutputsRefusalMessage, In as maskingRetryLogger, Io as scrubResourceRecord, Ir as explicitRoleArnOrThrow, Is as parseBootstrapMarker, It as demoteSupersededOrphans, Jc as resolveBucketRegion, Ji as refuseMalformedOrphanRecordsForDestroy, Jo as recordMaskOnlyValuesIn, Js as formatDockerLoginError, Jt as inheritProducerRegions, Kc as resolveAssemblyPath, Ko as provenPublicValue, Ks as dockerSpawnEnvWithSensitive, Kt as findNestedStackTypeChanges, Lc as defineOwnKey, Li as malformedOutputsWarning, Ln as constructPathOf, Lo as DYNAMIC_REFERENCE_TOKEN_SCAN, Lr as isIamRoleArn, Ls as readBootstrapMarkerBody, Lt as isJournaledOrphan, Ma as shownType, Mc as canonicalizeRegion, Mi as malformedOrphanRecordsWarning, Mn as isExportAliasCollision, Mo as maskSecretsInError, Mr as regionLessSecretName, Ms as assertAssetBucketRegion, Na as MULTI_REGION_RECREATE_BLOCKED_TYPES, Nc as derivePartitionAndUrlSuffix, Ni as malformedOrphanRowsKeptWarning, Nn as bindingSkippedOutputs, No as maskSecretsInText, Nr as applyRoleArnIfSet, Ns as ensureAssetStorage, Nt as withStackRecords, O as PROTECTION_PROPERTY_BY_TYPE, Oc as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Oi as malformedLocalOutputsWarning, On as isWholeDynamicReferenceValue, Oo as recordLogOnlyValue, Or as IntrinsicFunctionResolver, Os as loadPublishableAssetManifest, Ot as replayFailedOperations, Pa as isStatefulRecreateTargetForReplace, Pc as AssemblyReader, Pi as malformedOrphansRefusalMessage, Pn as DEFAULT_RESOURCE_TIMEOUT_MS, Po as markSameGenerationBag, Pr as assertFlagRoleArn, Ps as getBootstrapMarkerKey, Pt as removeProtectionTypeList, Q as cyan, Qa as prefetchCreateOnlyPropertyPaths, Qi as refuseMalformedOutputs, Qo as wholeStringLeavesOf, Qr as getAccountInfo, Qs as partitionSensitiveEnv, Rc as hasOwnKey, Ri as malformedRenderedContainersWarning, Rn as findDestructiveChanges, Ro as dynamicReferenceTokens, Rr as sendableAssumeRoleCommand, Rs as validateAssetBucketName, Rt as isReplacementOrphan, S as noEchoAttributeNamesOf, Sa as unreadableOrphanRecords, Sc as ssmResolvedValueType, Si as hasReadableResources, Sn as secretBearing, So as createUnionSecretMasker, Ss as AssetPublisher, St as dropFailedHint, T as noEchoParameterNamesOf, Ta as findActionableSilentDrops, Tc as MIGRATE_TMP_PREFIX, Ti as malformedDriftResourcePropertiesWarning, Tn as carriedExportAliasExposure, To as logOnlyValueCount, Ts as WorkGraph, Tt as loadJournaledOrphans, Uc as describeFileReadFailure, Ui as malformedStateRefusalMessage, Uo as recordNestedStackParameterExpressions, Us as describeDockerCapturedOutput, Ut as replacementNeverSwapped, Vc as ownValue, Vi as malformedResourcesWarning, Vo as identityKeyFor, Vr as callerEnvCredentials, Vs as buildDockerImage, Vt as recheckFailedPlan, Wc as displayAssemblyPath, Wi as previewableOrphanRecords, Wn as withCreateTokenLedger, Ws as describeDockerExecFailure, Wt as resolveReplacementOldType, X as createReadOnlyAttributeHealerFactory, Xi as refuseMalformedOrphansForDestroy, Xo as recordNoEchoParameterFreshValue, Xr as isUnboundTemplateParameter, Xs as isDockerClientEnvKey, Y as formatResourceLine, Yi as refuseMalformedOrphans, Yo as recordNoEchoAttributeValues, Yr as coerceParameterTypedValue, Ys as getDockerCmd, Z as bold, Zi as refuseMalformedOrphansForOrphan, Zo as recordProvenPublicExpression, Zr as parameterTypeMayLoseSecretIdentity, Zs as isMalformedEnvKey, _ as makeCanonicalizePropertiesFn, _a as repairMalformedOutputsForReadOnly, _c as resolveStateBucketWithDefault, _i as accountArgs, _n as DeploymentEventsStore, _o as readbackPathFor, _s as importableOutputs, _t as revertedNestedRowIds, a as findNestedTemplateTreeDefect, aa as refuseMalformedResourceEntriesForImportSave, ac as stripControlChars, ai as cfnRefValueFromPhysicalId, an as secretNamePrintingBag, ao as DagBuilder, ar as wouldReturnToSdkProvider, as as LockManager, at as reachableDivergentParameters, b as serviceTokenBlockingReason, ba as repairMalformedResourcesForReadOnly, bc as stateBucketExistenceConfirmed, bi as hasReadableOrphans, bn as displayTextOrWithheld, bo as liveMatchesUnresolvedTokenFrame, bs as orphansCarriedFrom, bt as withNestedStackContext, c as renderNestedTemplateTreeDefect, ca as refuseMalformedResourcePropertiesForDrift, cc as Synthesizer, cn as PRE_DELETE_SNAPSHOT_TYPES, co as isMarkedCoordinate, cr as isCustomResourceType$1, cs as rebuildClientForBucketRegion, ct as planOrphanAdoption, d as conditionInputsFrom, da as refuseMalformedResourcesForDeploy, dc as getLegacyStateBucketName, dn as createPreDeleteFinalSnapshot, do as maskWholeValue, dr as CloudControlProvider, ds as describeRegionValueKind, dt as displacedPhysicalIdShown, ea as refuseMalformedResourceAttributesForOrphan, ec as redactedDockerCause, ei as carriesDynamicReference, en as updatePartialReason, eo as describeTypeWithThrottleRetry, es as STATE_SOURCED_CROSS_GENERATION_RULES, et as green, f as parentSuppliedValues, fa as refuseMalformedResourcesForDestroy, fc as loadCdkJson, fi as JSON_LISTING_HOLE_VALUE, fn as effectiveDeletionPolicy, fo as maskedLeafCoordinatesOf, fr as slowCcOperationTimeoutMs, fs as exportNamesCarriedFrom, ft as dropSettledNestedJournals, g as mergeNoChangeOutputs, ga as repairMalformedOrphansForReadOnly, gc as resolveSkipPrefix, gi as UNREADABLE_RESOURCES_MAP_ROW, gn as DeploymentEventsReader, gr as deleteSkipReason, gs as importableOutputKeys, h as keptWholeReasonText, ha as repairMalformedOrphanRecordsForReadOnly, hc as resolveCaptureObservedState, hi as UNREADABLE_ORPHANS_CONTAINER_ROW, hn as unsupportedFinalSnapshotError, ho as noEchoOutputsComparison, hr as deleteIndeterminateGuards, hs as hasUnverifiableParameterRefusal, ht as recordDisplacedSkips, i as childTemplateLoader, ia as refuseMalformedResourceEntriesForImport, ic as escapeRegExp, ii as AWS_NO_VALUE, in as orphanRecordsPrintingBag, ir as isCustomResource, is as isSingleDynamicReferenceToken, it as namesAnyDeclaredParameter, j as readProtection, ja as findReplacedReadersOfRecreateTargets, jc as PARTITION_TABLE, ji as malformedOrphanRecordsRefusalMessage, jn as collectPublishedOutputNames, jo as errorCauseChain, jr as producerRegionsFromState, js as BOOTSTRAP_MARKER_PREFIX, jt as destroyStackRecordsView, k as isProtectionValueActive, ka as NO_CC_HANDLERS_REASON, kc as decodeListingKey, ki as malformedLocalResourceEntriesWarning, kn as noEchoParameterValueSeed, ko as shareLogOnlyValues, kr as poisonRenderedSpellingsCollidingIn, ks as rewriteTemplateAssetReferences, kt as replayRollback, l as templateIdentity, la as refuseMalformedResourcePropertiesForExport, lc as synthesisStatusMessage, li as withSharedDrainBudget, ln as buildFinalSnapshotIdentifier, lo as maskAtCoordinates, ls as splitImportedOps, lt as NESTED_PENDING_PARENT_REASON, m as isSecretBearingReferenceString, ma as refuseMalformedState, mc as resolveAutoAssetStorage, mi as STATE_RESOURCES_MALFORMED, mn as refusesFinalSnapshot, mo as noEchoLeavesOf, mr as UNSPECIFIED_SKIP_REASON, ms as hasReasonlessBaselineRefusal, mt as nestedChildStackName$1, n as IMPLICIT_DELETE_DEPENDENCIES, na as refuseMalformedResourceEntriesForDeploy, nc as runDockerStreaming, ni as isNamelessDynamicReferenceError, nn as journaledOrphanPrintingBag, nr as ProviderRegistry, ns as TEMPLATE_SOURCED_RULES, nt as yellow, o as isAbsoluteAssetPath, oa as refuseMalformedResourceEntriesForOrphan, oc as AssetManifestLoader, oi as isStalePlaceholderArnAttribute, on as stateSecretNameNeedles, oo as TemplateParser, or as TemplateNoEchoReresolver, os as isLockInfoExpired, ot as resourcesNamingDeclaredParameter, p as readRecordedConditionVerdicts, pa as refuseMalformedResourcesForExport, pc as resolveApp, pi as STATE_REGION_DIVERGED, pn as isFinalSnapshotError, po as noEchoCoordinatesOf, ps as hasReadableExportSet, qi as refuseMalformedOrphanRecords, qo as recordMaskOnlyValue, qs as finchSecretArgvRefusal, r as computeImplicitDeleteEdges, ra as refuseMalformedResourceEntriesForDestroy, rc as warnFinchArgvExposure, ri as keepsSecretReferenceToken, rn as maskEventTextWithBoundBags, rr as ccBrokenReason, rs as WHOLE_DYNAMIC_REFERENCE_PATTERN, rt as computeParameterTaint, s as listNestedTemplateRows, sa as refuseMalformedResourcePropertiesForDestroy, sc as getDockerImageBySourceHash, si as refStateLookupFromResource, sn as ATOMIC_FINAL_SNAPSHOT_TYPES, so as canonicalCoordinates, sr as readsNoEchoDeleteValues, ss as S3StateBackend, st as makeSiblingClaimReader, t as DeployEngine, ta as refuseMalformedResourceEntries, tc as runDockerForeground, ti as carriesFetchableDynamicReference, tn as completedReplayEntries, to as withRetry, tr as CC_BROKEN_REASON, ts as STATE_SOURCED_READBACK_RULES, tt as red, u as conditionFingerprint, ua as refuseMalformedResourcePropertiesForOrphan, uc as getDefaultStateBucketName, ui as parameterInputsFor, un as ccRoutedFinalSnapshotError, uo as maskReadbackAtCoordinates, ur as withPrintingSecrets, us as acceptedCreateOnlyDropsOf, ut as displacedOpClause, v as deferredServiceTokenWarning, va as repairMalformedResourceEntriesForReadOnly, vc as resolveStateBucketWithDefaultAndSource, vi as deployRefusesOrphanRowsReason, vn as extractDeploymentEventError, vo as readsNoEchoSource, vr as isWaitAbandonedError, vs as isReadableBag, vt as withNestedRevertRun, w as noEchoExactEchoLeavesOf, wa as withheldAccountClause, wc as CFN_TEMPLATE_URL_LIMIT, wi as isReadableResourceEntry, wn as secretSafeKeyDisplay, wo as literalSplitDelimitersOf, ws as stringifyValue, wt as journaledOrphanLines, x as withResourceDeadline, xa as unpreviewableOrphanRecords, xc as warnDeprecatedNoPrefixCliFlag, xi as hasReadableOutputs, xn as exportAliasCollisionScrubWarning, xo as carryLogOnlyValues, xs as shouldRetainResource, xt as deleteJournaledOrphans, y as findServiceTokenRefusals, ya as repairMalformedResourcePropertiesForReadOnly, yc as resolveUseCdkBootstrapAssets, yi as displayLogicalId, yn as WITHHELD_NAME_DISPLAY, yo as valueAtCoordinate, ys as orphansAfterRollback, zc as hasPlainPrototype, zi as malformedResourceEntriesWarning, zn as formatDestructiveChange, zo as isUncertifiedBaselineMaskPosition, zr as AWS_CREDENTIAL_ENV_KEYS, zs as validateContainerRepoName, zt as planFailedOps } from "./deploy-engine-DC4Yblxp.js";
6
+ import { t as getCdkdVersion } from "./version-Cs9QbaaH.js";
7
7
  import { randomBytes, randomUUID } from "node:crypto";
8
8
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetObjectCommand, HeadBucketCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, NotFound, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutBucketVersioningCommand, PutObjectCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
9
9
  import { GetRoleCommand, GetUserCommand } from "@aws-sdk/client-iam";
@@ -242,7 +242,7 @@ function parsePinCcApiToken(value, previous) {
242
242
  }
243
243
  const pinCcApiOption = new Option("--pin-cc-api <logicalId>", "Keep the named resource (by CloudFormation logical id) on the Cloud Control route in this deploy, declining the automatic return to the SDK Provider that a type-level sdk-coverage exemption would otherwise apply to a resource recorded as provisionedBy: cc-api. Repeatable — pass the flag once per resource. Has no effect on a resource already on the SDK path, and does not override an exemption admitted because Cloud Control cannot manage the type.").argParser(parsePinCcApiToken);
244
244
  const recreateViaSdkProviderOption = new Option("--recreate-via-sdk-provider <logicalId>", "Destroy + recreate the named resource (by CloudFormation logical id) via cdkd's SDK Provider in this deploy, so a resource currently sticky on provisionedBy: cc-api flips back to provisionedBy: sdk. Used after a #609 backfill release adds SDK coverage for a type the user originally needed CC for (e.g. Lambda LoggingConfig). Repeatable — pass the flag once per resource. Per-resource opt-in. Stateful resource types refuse unless --force-stateful-recreation is ALSO passed.").argParser(parseRecreateViaSdkProviderToken);
245
- const forceStatefulRecreationOption = new Option("--force-stateful-recreation", "Confirm a data-losing destroy + recreate of a stateful resource. Required whenever a replacement target is a stateful type on the --recreate-via-cc-api / --recreate-via-sdk-provider pre-flight, with --replace, AND on the paths a plain deploy reaches with no flag: a template immutable-property change, and an in-place update the provisioning layer rejects. Stateful types are databases, filesystems, KMS keys, table / vector storage, source repositories, and more; docs/cli-deploy-safety.md carries the full list. S3 buckets and log groups are the conditional cases: at pre-flight, a non-empty bucket, or a log group with retention, with log streams, or whose emptiness the probe could not settle; mid-deploy, ANY bucket or log group, because the emptiness probe cannot run there. The two probes differ on failure — the bucket fails open, the log group closed. Destroy + recreate loses ALL data in the resource — no automatic data migration. Full opt-in for CI use: --recreate-via-cc-api '<id>' --force-stateful-recreation --yes.").default(false);
245
+ const forceStatefulRecreationOption = new Option("--force-stateful-recreation", "Confirm a data-losing destroy + recreate of a stateful resource. Required whenever a replacement target is a stateful type on the --recreate-via-cc-api / --recreate-via-sdk-provider pre-flight, with --replace, AND on the paths a plain deploy reaches with no flag: a template immutable-property change, and an in-place update the provisioning layer rejects. Stateful types are databases, filesystems, KMS keys, table / vector storage, source repositories, and more; https://cdkd.dev/cli-deploy-safety/ carries the full list. S3 buckets and log groups are the conditional cases: at pre-flight, a non-empty bucket, or a log group with retention, with log streams, or whose emptiness the probe could not settle; mid-deploy, ANY bucket or log group, because the emptiness probe cannot run there. The two probes differ on failure — the bucket fails open, the log group closed. Destroy + recreate loses ALL data in the resource — no automatic data migration. Full opt-in for CI use: --recreate-via-cc-api '<id>' --force-stateful-recreation --yes.").default(false);
246
246
  const replaceOption = new Option("--replace", "Replace (DELETE + CREATE) a resource whose in-place update is rejected because an immutable property changed and AWS exposes no update API for it (e.g. Lambda LayerVersion content, EFS AccessPoint, ECS TaskDefinition, ApiGatewayV2 immutable fields). Without this flag such a change fails the deploy. Stateful types (RDS / DynamoDB / EFS / any S3 bucket / any Logs log group / etc.) ALSO require --force-stateful-recreation since the replacement is a data-losing DELETE + CREATE — mid-deploy neither emptiness probe can run, so both conditional types count as stateful there.").default(false);
247
247
  const useCdkBootstrapAssetsOption = new Option("--use-cdk-bootstrap-assets", "Publish assets to the CDK bootstrap bucket/repo named by the asset manifest verbatim, skipping the cdkd asset-storage redirection even when this region is opted in via 'cdkd bootstrap'. For apps deployed via both CloudFormation and cdkd during a migration window. Per-app pin: cdk.json context.cdkd.useCdkBootstrapAssets. Also suppresses the legacy-mode 'cdk gc' notice.").default(false);
248
248
  const strictGetattOption = new Option("--strict-getatt", "Fail the deploy on ANY Fn::GetAtt that falls back to the physical ID because cdkd cannot construct the attribute (default: warn and use the physical ID, hard-failing only when the fallback is knowably wrong — an *Arn attribute with a non-ARN value or a *Url attribute with a non-http(s) value). Also fails the deploy when a stack Output cannot be resolved (default: warn and store no value).").default(false);
@@ -2396,7 +2396,7 @@ function collectCrossStackRefs(node, onRef) {
2396
2396
  //#region src/provisioning/register-providers.ts
2397
2397
  let providerClasses;
2398
2398
  function loadProviderClasses() {
2399
- providerClasses ??= import("./provider-classes-N6aXDqij.js");
2399
+ providerClasses ??= import("./provider-classes-BcSDENeH.js");
2400
2400
  return providerClasses;
2401
2401
  }
2402
2402
  function registerAllProviders(registry, classes) {
@@ -5621,12 +5621,13 @@ function planExportIndexRepair(entries, stackName, producerRegion, outputs) {
5621
5621
  continue;
5622
5622
  }
5623
5623
  const stateValue = outputs[exportName];
5624
- if (!carriesDynamicReference(stateValue)) continue;
5624
+ if (!carriesDynamicReference(stateValue) && !carriesSecretMask(stateValue)) continue;
5625
5625
  if (JSON.stringify(entry.value) === JSON.stringify(stateValue)) continue;
5626
5626
  findings.push({
5627
5627
  kind: "converge",
5628
5628
  exportName,
5629
- stateValue
5629
+ stateValue,
5630
+ entryValue: entry.value
5630
5631
  });
5631
5632
  }
5632
5633
  return {
@@ -5713,9 +5714,9 @@ async function saveScrubbedState(stateBackend, stackName, region, state, loaded)
5713
5714
  try {
5714
5715
  survives = await stateBackend.getRawObject(legacyKey) !== null;
5715
5716
  } catch (err) {
5716
- throw new ScrubRefusalError(safeMsg`${displayStackName(stackName)} was rewritten to the region-scoped state key, ` + safeMsg`but whether its legacy key ${legacyKey} still holds the pre-scrub record ` + safeMsg`could not be verified (${describeAwsFailure(err).detail}). ` + "Check that key yourself and, if it exists, delete it (aws s3api delete-object --bucket <state-bucket> --key <that key>), then purge its earlier versions as docs/cli-scrub.md describes. A re-run will not check it again.", "SCRUB_LEGACY_STATE_KEY_UNVERIFIED");
5717
+ throw new ScrubRefusalError(safeMsg`${displayStackName(stackName)} was rewritten to the region-scoped state key, ` + safeMsg`but whether its legacy key ${legacyKey} still holds the pre-scrub record ` + safeMsg`could not be verified (${describeAwsFailure(err).detail}). ` + "Check that key yourself and, if it exists, delete it (aws s3api delete-object --bucket <state-bucket> --key <that key>), then purge its earlier versions as https://cdkd.dev/cli-scrub/#what-a-real-run-removes-and-what-it-cannot describes. A re-run will not check it again.", "SCRUB_LEGACY_STATE_KEY_UNVERIFIED");
5717
5718
  }
5718
- if (survives) throw new ScrubRefusalError(safeMsg`${displayStackName(stackName)} was rewritten to the region-scoped state key, ` + safeMsg`but its legacy key ${legacyKey} could not be deleted and still holds the ` + "pre-scrub record as its CURRENT object. Delete it (aws s3api delete-object --bucket <state-bucket> --key <that key>), then purge its earlier versions as docs/cli-scrub.md describes.", "SCRUB_LEGACY_STATE_KEY_SURVIVES");
5719
+ if (survives) throw new ScrubRefusalError(safeMsg`${displayStackName(stackName)} was rewritten to the region-scoped state key, ` + safeMsg`but its legacy key ${legacyKey} could not be deleted and still holds the ` + "pre-scrub record as its CURRENT object. Delete it (aws s3api delete-object --bucket <state-bucket> --key <that key>), then purge its earlier versions as https://cdkd.dev/cli-scrub/#what-a-real-run-removes-and-what-it-cannot describes.", "SCRUB_LEGACY_STATE_KEY_SURVIVES");
5719
5720
  }
5720
5721
  } finally {
5721
5722
  if (mayHaveWritten) await stateBackend.purgeNoncurrentVersions(stateHistoryKeys(stateBackend, stackName, region, loaded.migrationPending), { objectDescription: SCRUBBED_STATE_OBJECT_DESCRIPTION });
@@ -6084,16 +6085,17 @@ async function scrubCommand(stacks, options) {
6084
6085
  const absentNamed = (exportName, entryValue) => /[^A-Za-z0-9]/.test(exportName) ? "(name withheld: an export name, which may carry a secret)" : named(exportName, entryValue);
6085
6086
  const named = (exportName, alsoMask) => renderStateKeyForLine(scrubbed.exportNameDisplay(exportName, alsoMask), "it may carry a secret");
6086
6087
  const unwrittenNames = new Set(repair.unwritten);
6088
+ const entryValueOf = new Map(repair.findings.map((finding) => [finding.exportName, finding.entryValue]));
6087
6089
  for (const exportName of repair.unwritten) indexUnwritten.push({
6088
6090
  region: stackRegion,
6089
- shown: named(exportName)
6091
+ shown: named(exportName, entryValueOf.get(exportName))
6090
6092
  });
6091
6093
  for (const finding of repair.findings) if (finding.kind === "converge") {
6092
6094
  indexConverged++;
6093
- if (!options.dryRun && unwrittenNames.has(finding.exportName)) logger.warn(`Exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) differs from ${shownStack}'s state.outputs and could NOT be written — it keeps the value it holds.`);
6095
+ if (!options.dryRun && unwrittenNames.has(finding.exportName)) logger.warn(`Exports index entry ${named(finding.exportName, finding.entryValue)} (${displayIdent(stackRegion)}) differs from ${shownStack}'s state.outputs and could NOT be written — it keeps the value it holds.`);
6094
6096
  else {
6095
6097
  totalIndexEntriesConverged++;
6096
- logger.info(`${options.dryRun ? "Would converge" : "Converged"} exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) to ${shownStack}'s state.outputs value.`);
6098
+ logger.info(`${options.dryRun ? "Would converge" : "Converged"} exports index entry ${named(finding.exportName, finding.entryValue)} (${displayIdent(stackRegion)}) to ${shownStack}'s state.outputs value.`);
6097
6099
  }
6098
6100
  } else {
6099
6101
  totalIndexEntriesAbsent++;
@@ -7339,6 +7341,10 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7339
7341
  const collisions = [];
7340
7342
  let outputsSourceUntrusted = false;
7341
7343
  let everyExportAliasReproduced = true;
7344
+ const conditionalNameParameters = new Set(nestedInput?.noEchoConditionalParameters ?? []);
7345
+ const noEchoNameParameters = /* @__PURE__ */ new Set([...noEchoParameterNamesOf(stack.template), ...(nestedInput?.noEchoParameters ?? []).filter((name) => !conditionalNameParameters.has(name))]);
7346
+ const declaredAliasOf = /* @__PURE__ */ new Map();
7347
+ const noEchoNameSeed = noEchoParameterValueSeed(stack.template.Parameters, parameters, inheritedSecrets);
7342
7348
  const nestedRowParameters = /* @__PURE__ */ new Map();
7343
7349
  await withSharedDrainBudget(async () => {
7344
7350
  for (const logicalId of Object.keys(state.resources ?? {})) {
@@ -7470,7 +7476,9 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7470
7476
  const exportNameUnresolved = declaredExportName !== void 0 && typeof exportName === "string" && isUnresolvedValue(exportName, templateUsesSub(declaredExportName));
7471
7477
  if (typeof exportName === "string" && !exportNameUnresolved) accountedOutputKeys.add(exportName);
7472
7478
  const literalCollision = typeof declaredExportName === "string" && isExportAliasCollision(declaredExportName, name, declaredOutputNames);
7473
- if (declaredExportName !== void 0 && !literalCollision && !(typeof exportName === "string" && !exportNameUnresolved && isReadableBag(state.outputs) && Object.hasOwn(state.outputs, exportName) && (knownExportNamesOf(state.exportNames)?.has(exportName) ?? (typeof declaredExportName === "string" || !declaredOutputNames.has(exportName))))) everyExportAliasReproduced = false;
7479
+ const refusedForNoEcho = declaredExportName !== void 0 && !JSON.stringify(declaredExportName).includes("\"Fn::If\"") && (typeof exportName === "string" && !exportNameUnresolved && carriedExportAliasExposure(exportName, outputSecrets, noEchoNameSeed) !== void 0 || readsNoEchoSource(declaredExportName, { parameters: noEchoNameParameters }));
7480
+ if (typeof exportName === "string" && !exportNameUnresolved) declaredAliasOf.set(name, exportName);
7481
+ if (declaredExportName !== void 0 && !literalCollision && !refusedForNoEcho && !(typeof exportName === "string" && !exportNameUnresolved && isReadableBag(state.outputs) && Object.hasOwn(state.outputs, exportName) && (knownExportNamesOf(state.exportNames)?.has(exportName) ?? (typeof declaredExportName === "string" || !declaredOutputNames.has(exportName))))) everyExportAliasReproduced = false;
7474
7482
  if (exportNameUnresolved) {
7475
7483
  outputsSourceUntrusted = true;
7476
7484
  logger.warn(`Export.Name of output ${maskedIdent(name, outputSecrets)} did not fully resolve during scrub — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
@@ -7521,6 +7529,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7521
7529
  secretBearingKeys.push(key);
7522
7530
  logger.warn(secretBearingStateKeyWarning(stack.stackName, display));
7523
7531
  }
7532
+ const noEchoPlans = planScrubNoEcho(state, stack.template, perResourceTemplateProps, conditions, nestedInput?.noEchoParameters ?? [], nestedInput?.noEchoConditionalParameters ?? []);
7524
7533
  const nestedChildren = [];
7525
7534
  const nestedRowIds = /* @__PURE__ */ new Set();
7526
7535
  for (const [logicalId, resource] of Object.entries(templateResources)) if (resource?.Type === NESTED_STACK_TYPE$1) nestedRowIds.add(logicalId);
@@ -7553,7 +7562,14 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7553
7562
  stackName: childStackName,
7554
7563
  input: {
7555
7564
  parameters,
7556
- inheritedSecrets: perResourceSecrets.get(logicalId) ?? /* @__PURE__ */ new Map()
7565
+ inheritedSecrets: perResourceSecrets.get(logicalId) ?? /* @__PURE__ */ new Map(),
7566
+ ...(() => {
7567
+ const filled = noEchoFilledRowParameters(templateResources[logicalId]?.Properties, noEchoPlans.sources, noEchoPlans.needleSources);
7568
+ return {
7569
+ noEchoParameters: filled.names,
7570
+ ...filled.conditional.length > 0 && { noEchoConditionalParameters: filled.conditional }
7571
+ };
7572
+ })()
7557
7573
  }
7558
7574
  });
7559
7575
  }
@@ -7586,8 +7602,9 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7586
7602
  const needles = new Map([...allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets), ...outputSecrets]);
7587
7603
  return JSON.stringify(redactSecretsForState(value, needles)) !== JSON.stringify(value);
7588
7604
  };
7605
+ const noEchoPublicTokens = /* @__PURE__ */ new Set([region, stack.stackName]);
7589
7606
  const totalSecrets = outputSecrets.size + [...perResourceSecrets.values()].reduce((n, m) => n + m.size, 0) + [...orphanSecrets.values()].reduce((n, m) => n + m.size, 0);
7590
- if (totalSecrets === 0) {
7607
+ if (totalSecrets === 0 && !noEchoPlans.changesAny) {
7591
7608
  emitAbandonedScanNotes();
7592
7609
  return {
7593
7610
  ...await purgeExaminedHistory(loaded.migrationPending),
@@ -7621,8 +7638,11 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7621
7638
  properties: redactSecretsForState(record.properties, ownSecrets, templateProps, TEMPLATE_SOURCED_RULES)
7622
7639
  } : record;
7623
7640
  const scrubbed = secrets || templateProps ? scrubResourceRecord(positioned, ownSecrets, void 0, STATE_SOURCED_CROSS_GENERATION_RULES) : record;
7624
- if (JSON.stringify(scrubbed) !== JSON.stringify(record)) recordsChanged++;
7625
- newResources[logicalId] = scrubbed;
7641
+ const plan = noEchoPlans.byLogicalId.get(logicalId);
7642
+ const migrationNeedles = scrubMigrationNeedles(plan, noEchoPublicTokens);
7643
+ const written = applyScrubNoEcho(migrationNeedles === void 0 ? scrubbed : scrubResourceRecord(scrubbed, migrationNeedles, void 0, STATE_SOURCED_CROSS_GENERATION_RULES), record, plan);
7644
+ if (JSON.stringify(written) !== JSON.stringify(record)) recordsChanged++;
7645
+ newResources[logicalId] = written;
7626
7646
  }
7627
7647
  const newOrphans = (state.orphans ?? []).map((record, orphanIndex) => {
7628
7648
  const own = orphanSecrets.get(String(orphanIndex));
@@ -7667,9 +7687,9 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7667
7687
  const producer = list === "imports" ? `producer ${displayStackName(maskSecretsInText(entry.sourceStack, crossStackNeedles))}, ` : "";
7668
7688
  logger.warn(safeMsg`Scrub of ${shownStack}: state.${list}[${index}] (${producer}${displayIdent(String(entry.sourceRegion))}) ` + "holds a cross-stack read name in plaintext that has the shape of a secret-bearing read in today's template but not the secret's current value — most likely a value from before the secret was ROTATED. Scrub cannot repair it (it matches only the current value) and does not print it; treat that earlier value as exposed. A deploy " + safeMsg`that updates ${shownStack} rewrites this list from the reads it performs.`);
7669
7689
  }
7670
- const redactedOutputs = redactUnaccountedOutputs(outputSecrets.size > 0 ? redactSecretsForState(state.outputs, outputSecrets, outputsSourceUntrusted ? void 0 : outputsTemplateSource, TEMPLATE_SOURCED_RULES) : state.outputs, state.outputs, accountedOutputKeys, allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets));
7690
+ const noEchoMaskedOutputs = maskScrubNoEchoOutputs(redactUnaccountedOutputs(outputSecrets.size > 0 ? redactSecretsForState(state.outputs, outputSecrets, outputsSourceUntrusted ? void 0 : outputsTemplateSource, TEMPLATE_SOURCED_RULES) : state.outputs, state.outputs, accountedOutputKeys, allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets)), noEchoPlans.outputKeys, new Set(Object.keys(stack.template.Outputs ?? {})), declaredAliasOf);
7671
7691
  emitAbandonedScanNotes();
7672
- let newOutputs = redactedOutputs;
7692
+ let newOutputs = noEchoMaskedOutputs;
7673
7693
  let newExportNames = state.exportNames;
7674
7694
  let droppedOutputKeys = 0;
7675
7695
  let keptReadOutputKeys = 0;
@@ -7677,11 +7697,11 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7677
7697
  let droppedOutputReadersUnverified = false;
7678
7698
  const droppedDisplayCorpus = /* @__PURE__ */ new Map();
7679
7699
  const withheldOutputKeys = /* @__PURE__ */ new Set();
7680
- if (isReadableBag(state.outputs) && isReadableBag(redactedOutputs)) {
7700
+ if (isReadableBag(state.outputs) && isReadableBag(noEchoMaskedOutputs)) {
7681
7701
  const stored = state.outputs;
7682
7702
  const plan = planUnnamedOutputDrop({
7683
7703
  stored,
7684
- rewritten: redactedOutputs,
7704
+ rewritten: noEchoMaskedOutputs,
7685
7705
  accountedKeys: accountedOutputKeys,
7686
7706
  reportedKeys: new Set(secretBearingKeys),
7687
7707
  exportNames: state.exportNames,
@@ -7715,7 +7735,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
7715
7735
  }
7716
7736
  if (dropping.size > 0) {
7717
7737
  droppedOutputKeys = dropping.size;
7718
- newOutputs = Object.fromEntries(Object.entries(redactedOutputs).filter(([key]) => !dropping.has(key)));
7738
+ newOutputs = Object.fromEntries(Object.entries(noEchoMaskedOutputs).filter(([key]) => !dropping.has(key)));
7719
7739
  if (Array.isArray(state.exportNames)) newExportNames = state.exportNames.filter((name) => !(typeof name === "string" && dropping.has(name)));
7720
7740
  logger.info(safeMsg`${opts.dryRun ? "Would drop" : "Dropped"} ${dropping.size} output key(s) from ` + safeMsg`${shownStack} that its template no longer declares: ${shownKeys(dropping)}. ` + "Their values are not printed: scrub could not identify them as a secret's plaintext, and left beside the references it writes, cdkd diff would print them. A deploy of today's template does not write them either.");
7721
7741
  }
@@ -7798,6 +7818,179 @@ function createScrubCommand() {
7798
7818
  cmd.action(withErrorHandling(scrubCommand));
7799
7819
  return cmd;
7800
7820
  }
7821
+ function planScrubNoEcho(state, template, templateProps, conditions, passedParameters = [], conditionalParameters = []) {
7822
+ const byLogicalId = /* @__PURE__ */ new Map();
7823
+ const parameters = /* @__PURE__ */ new Set([...noEchoParameterNamesOf(template), ...passedParameters]);
7824
+ const resources = state.resources ?? {};
7825
+ const declared = /* @__PURE__ */ new Map();
7826
+ for (const [id, record] of Object.entries(resources)) declared.set(id, new Set(noEchoAttributeNamesOf(record) ?? []));
7827
+ const sources = {
7828
+ parameters,
7829
+ attributeIsNoEcho: (id, attribute) => declared.get(id)?.has(attribute) === true,
7830
+ ...Object.keys(conditions).length > 0 && { conditions }
7831
+ };
7832
+ const persisted = (value) => carriesSecretMask(value) || typeof value === "string" && isSingleDynamicReferenceToken(value);
7833
+ const templateResources = template.Resources ?? {};
7834
+ const eligible = Object.entries(resources).filter(([logicalId, record]) => templateProps.has(logicalId) && Object.hasOwn(templateResources, logicalId) && templateResources[logicalId]?.Type === record.resourceType);
7835
+ const positionFrom = (params, names) => {
7836
+ const from = {
7837
+ ...sources,
7838
+ parameters: params,
7839
+ attributeIsNoEcho: (id, attribute) => names.get(id)?.has(attribute) === true
7840
+ };
7841
+ const leavesOf = /* @__PURE__ */ new Map();
7842
+ for (let round = 0; round <= eligible.length; round++) {
7843
+ let grew = false;
7844
+ for (const [logicalId, record] of eligible) {
7845
+ const own = noEchoLeavesOf(record);
7846
+ const leaves = canonicalCoordinates(own ?? noEchoCoordinatesOf(templateProps.get(logicalId), record.properties, from));
7847
+ leavesOf.set(logicalId, leaves);
7848
+ for (const [name, attribute] of Object.entries(record.attributes ?? {})) {
7849
+ if (attribute === record.physicalId || persisted(attribute)) continue;
7850
+ const echoes = leaves.some((coordinate) => coordinate[0] === name && JSON.stringify(valueAtCoordinate(record.properties, coordinate)) === JSON.stringify(attribute));
7851
+ const recordNames = names.get(logicalId);
7852
+ if (echoes && !recordNames.has(name)) {
7853
+ recordNames.add(name);
7854
+ grew = true;
7855
+ }
7856
+ }
7857
+ }
7858
+ if (!grew) break;
7859
+ }
7860
+ return leavesOf;
7861
+ };
7862
+ const leavesOf = positionFrom(parameters, declared);
7863
+ const conditional = new Set(conditionalParameters);
7864
+ const needleParameters = new Set([...parameters].filter((name) => !conditional.has(name)));
7865
+ const needleDeclared = conditional.size === 0 ? declared : new Map(Object.entries(resources).map(([id, record]) => [id, new Set(noEchoAttributeNamesOf(record) ?? [])]));
7866
+ const needleLeavesOf = conditional.size === 0 ? leavesOf : positionFrom(needleParameters, needleDeclared);
7867
+ let changesAny = false;
7868
+ for (const [logicalId, record] of eligible) {
7869
+ const leaves = leavesOf.get(logicalId) ?? [];
7870
+ const attributeNames = [...declared.get(logicalId) ?? []].sort();
7871
+ if (leaves.length === 0 && attributeNames.length === 0) continue;
7872
+ const stored = [];
7873
+ const needleCoordinates = new Set((needleLeavesOf.get(logicalId) ?? []).map((coordinate) => JSON.stringify(coordinate)));
7874
+ for (const coordinate of leaves) {
7875
+ const value = valueAtCoordinate(record.properties, coordinate);
7876
+ if (value === void 0 || value === null || persisted(value)) continue;
7877
+ stored.push({
7878
+ coordinate,
7879
+ value,
7880
+ needle: needleCoordinates.has(JSON.stringify(coordinate))
7881
+ });
7882
+ }
7883
+ byLogicalId.set(logicalId, {
7884
+ leaves,
7885
+ stored,
7886
+ attributeNames
7887
+ });
7888
+ const unmaskedAttribute = attributeNames.some((name) => Object.hasOwn(record.attributes ?? {}, name) && !persisted(record.attributes[name]));
7889
+ if (stored.length > 0 || unmaskedAttribute || leaves.length > 0 && JSON.stringify(record.noEchoLeaves) !== JSON.stringify(leaves)) changesAny = true;
7890
+ }
7891
+ const outputSources = {
7892
+ parameters,
7893
+ attributeIsNoEcho: sources.attributeIsNoEcho
7894
+ };
7895
+ const outputKeys = [];
7896
+ const stored = state.outputs;
7897
+ if (stored !== null && typeof stored === "object" && !Array.isArray(stored)) for (const [key, output] of Object.entries(template.Outputs ?? {})) {
7898
+ if (!Object.hasOwn(stored, key)) continue;
7899
+ const value = stored[key];
7900
+ if (value === void 0 || value === null || persisted(value)) continue;
7901
+ if (!readsNoEchoSource(output?.Value, outputSources)) continue;
7902
+ outputKeys.push(key);
7903
+ }
7904
+ if (outputKeys.length > 0) changesAny = true;
7905
+ return {
7906
+ byLogicalId,
7907
+ outputKeys,
7908
+ changesAny,
7909
+ parameters,
7910
+ sources: outputSources,
7911
+ needleSources: {
7912
+ parameters: needleParameters,
7913
+ attributeIsNoEcho: (id, attribute) => needleDeclared.get(id)?.has(attribute) === true
7914
+ }
7915
+ };
7916
+ }
7917
+ function scrubMigrationNeedles(plan, publicTokens) {
7918
+ if (plan === void 0 || plan.stored.length === 0) return void 0;
7919
+ const needles = /* @__PURE__ */ new Map();
7920
+ for (const { value, needle } of plan.stored) if (needle) recordNoEchoParameterFreshValue(value, needles, publicTokens);
7921
+ return needles.size > 0 ? needles : void 0;
7922
+ }
7923
+ function maskScrubNoEchoOutputs(outputs, keys, declared, aliasOf) {
7924
+ if (outputs === void 0 || keys.length === 0) return outputs;
7925
+ const ownAliases = new Set(keys.flatMap((key) => aliasOf.has(key) ? [aliasOf.get(key)] : []));
7926
+ const otherAliases = new Set([...aliasOf].filter(([key]) => !keys.includes(key)).map(([, alias]) => alias));
7927
+ const spelled = new Set(keys.filter((key) => Object.hasOwn(outputs, key)).map((key) => JSON.stringify(outputs[key])));
7928
+ const masked = nullPrototypeRecord();
7929
+ for (const [key, value] of Object.entries(outputs)) {
7930
+ const byValue = !declared.has(key) && !otherAliases.has(key) && spelled.has(JSON.stringify(value));
7931
+ masked[key] = keys.includes(key) || ownAliases.has(key) || byValue ? maskWholeValue(value) : value;
7932
+ }
7933
+ return masked;
7934
+ }
7935
+ function applyScrubNoEcho(scrubbed, record, plan) {
7936
+ if (plan === void 0) return scrubbed;
7937
+ const { leaves, attributeNames } = plan;
7938
+ const next = {
7939
+ ...scrubbed,
7940
+ properties: maskAtCoordinates(scrubbed.properties, leaves),
7941
+ ...leaves.length > 0 && { noEchoLeaves: leaves.map((coordinate) => [...coordinate]) },
7942
+ ...scrubbed.observedProperties !== void 0 && { observedProperties: maskReadbackAtCoordinates(scrubbed.observedProperties, record.properties, leaves) }
7943
+ };
7944
+ const marked = new Set(leaves.map((coordinate) => JSON.stringify(coordinate)));
7945
+ const exact = noEchoExactEchoLeavesOf(scrubbed);
7946
+ if (exact !== void 0) {
7947
+ const kept = exact.filter((coordinate) => marked.has(JSON.stringify(coordinate)));
7948
+ if (kept.length > 0) next.noEchoExactEchoLeaves = kept;
7949
+ else delete next.noEchoExactEchoLeaves;
7950
+ }
7951
+ const attributes = next.attributes;
7952
+ if (attributes !== void 0 && attributes !== null && attributeNames.length > 0) {
7953
+ const masked = { ...attributes };
7954
+ for (const name of attributeNames) if (Object.hasOwn(masked, name)) masked[name] = maskWholeValue(masked[name]);
7955
+ next.attributes = masked;
7956
+ next.noEchoAttributeNames = [...attributeNames];
7957
+ }
7958
+ return next;
7959
+ }
7960
+ function withoutFnIf(value) {
7961
+ if (Array.isArray(value)) return value.map(withoutFnIf);
7962
+ if (value === null || typeof value !== "object") return value;
7963
+ if (Object.hasOwn(value, "Fn::If")) return null;
7964
+ const out = nullPrototypeRecord();
7965
+ for (const [key, inner] of Object.entries(value)) out[key] = withoutFnIf(inner);
7966
+ return out;
7967
+ }
7968
+ function noEchoFilledRowParameters(rowProperties, sources, needleSources) {
7969
+ const names = [];
7970
+ const conditional = [];
7971
+ if (rowProperties === null || typeof rowProperties !== "object") return {
7972
+ names,
7973
+ conditional
7974
+ };
7975
+ const passed = rowProperties["Parameters"];
7976
+ if (passed === null || typeof passed !== "object" || Array.isArray(passed)) return {
7977
+ names,
7978
+ conditional
7979
+ };
7980
+ const unconditioned = {
7981
+ parameters: sources.parameters,
7982
+ ...sources.attributeIsNoEcho !== void 0 && { attributeIsNoEcho: sources.attributeIsNoEcho }
7983
+ };
7984
+ for (const [name, value] of Object.entries(passed)) {
7985
+ if (!readsNoEchoSource(value, unconditioned)) continue;
7986
+ names.push(name);
7987
+ if (!readsNoEchoSource(withoutFnIf(value), needleSources)) conditional.push(name);
7988
+ }
7989
+ return {
7990
+ names,
7991
+ conditional
7992
+ };
7993
+ }
7801
7994
 
7802
7995
  //#endregion
7803
7996
  //#region src/analyzer/drift-normalize.ts
@@ -14349,15 +14542,16 @@ async function buildImportPlan(state, template, cfnClient, parentStackName, opti
14349
14542
  continue;
14350
14543
  }
14351
14544
  const noEchoLeaves = noEchoLeavesOf(stateEntry);
14352
- if (noEchoLeaves !== void 0 && noEchoLeaves.length > 0 && carriesSecretMask(stateEntry.properties) && !carriesSecretMask(withoutCoordinates(stateEntry.properties, noEchoLeaves))) {
14545
+ const masksOnlyAtNoEchoLeaves = noEchoLeaves !== void 0 && noEchoLeaves.length > 0 && carriesSecretMask(stateEntry.properties) && !carriesSecretMask(withoutCoordinates(stateEntry.properties, noEchoLeaves));
14546
+ if (masksOnlyAtNoEchoLeaves && IMPORT_UNSUPPORTED_RECREATABLE_TYPES.has(resourceType) && noEchoLeaves.some((coordinate) => typeof coordinate[0] === "string" && NOECHO_PRE_DELETE_KEYS.has(coordinate[0]))) {
14353
14547
  blocked.push({
14354
14548
  logicalId,
14355
14549
  resourceType,
14356
- reason: "a NoEcho template parameter feeds at least one property, and cdkd state holds only the redaction mask ('***') there, so the export has no value to declare for it. Export this stack without that resource and adopt it into CloudFormation by hand, passing the parameter value yourself."
14550
+ reason: "a NoEcho template parameter feeds a property this resource's pre-delete reads (its principals or its name), and cdkd state holds only the redaction mask ('***') there, so the export cannot tell what to remove. Export this stack without that resource and adopt it into CloudFormation by hand, passing the parameter value yourself."
14357
14551
  });
14358
14552
  continue;
14359
14553
  }
14360
- if (carriesSecretMask(stateEntry.properties)) {
14554
+ if (!masksOnlyAtNoEchoLeaves && carriesSecretMask(stateEntry.properties)) {
14361
14555
  blocked.push({
14362
14556
  logicalId,
14363
14557
  resourceType,
@@ -14448,6 +14642,14 @@ async function buildImportPlan(state, template, cfnClient, parentStackName, opti
14448
14642
  continue;
14449
14643
  }
14450
14644
  const propertiesOverlay = resolved.propertiesOverlay ?? resolved.resourceIdentifier;
14645
+ if ((JSON.stringify(resolved.resourceIdentifier).includes("***") || JSON.stringify(propertiesOverlay).includes("***")) && !(carriesSecretMask(resolved.resourceIdentifier) || carriesSecretMask(propertiesOverlay))) {
14646
+ blocked.push({
14647
+ logicalId,
14648
+ resourceType,
14649
+ reason: "the CloudFormation import identifier of this resource embeds the redaction mask ('***'): it is built from a value cdkd stores only as the mask (a NoEcho value). Export this stack without that resource and adopt it into CloudFormation by hand, passing the parameter value yourself."
14650
+ });
14651
+ continue;
14652
+ }
14451
14653
  if (carriesSecretMask(resolved.resourceIdentifier) || carriesSecretMask(propertiesOverlay)) {
14452
14654
  blocked.push({
14453
14655
  logicalId,
@@ -15262,28 +15464,31 @@ async function resolveChildImportParameters(parentTemplate, parentResolverContex
15262
15464
  const stillSkipped = [];
15263
15465
  for (const key of base.intrinsicSkipped) {
15264
15466
  const intrinsicValue = rawParams[key];
15467
+ let result;
15265
15468
  try {
15266
- const result = await resolver.resolve(intrinsicValue, parentResolverContext);
15267
- if (result === void 0 || result === null) {
15268
- stillSkipped.push(key);
15269
- continue;
15270
- }
15271
- if (typeof result === "string") resolvedParams.push({
15272
- ParameterKey: key,
15273
- ParameterValue: result
15274
- });
15275
- else if (typeof result === "number" || typeof result === "boolean") resolvedParams.push({
15276
- ParameterKey: key,
15277
- ParameterValue: String(result)
15278
- });
15279
- else if (Array.isArray(result)) resolvedParams.push({
15280
- ParameterKey: key,
15281
- ParameterValue: result.map((e) => String(e)).join(",")
15282
- });
15283
- else stillSkipped.push(key);
15469
+ result = await resolver.resolve(intrinsicValue, parentResolverContext);
15284
15470
  } catch {
15285
15471
  stillSkipped.push(key);
15472
+ continue;
15473
+ }
15474
+ if (JSON.stringify(result ?? null).includes("***")) throw new CdkdError(`Cannot export the nested stack row ${quotedOrNotShown(childLogicalId)}: its parameter ${quotedOrNotShown(key)} resolves from a value cdkd stores only as the redaction mask (***), a NoEcho value, so the export has no value to pass to the child. Export the stack without that nested stack and adopt it into CloudFormation by hand, passing the parameter value yourself.`, "EXPORT_MASKED_CHILD_PARAMETER");
15475
+ if (result === void 0 || result === null) {
15476
+ stillSkipped.push(key);
15477
+ continue;
15286
15478
  }
15479
+ if (typeof result === "string") resolvedParams.push({
15480
+ ParameterKey: key,
15481
+ ParameterValue: result
15482
+ });
15483
+ else if (typeof result === "number" || typeof result === "boolean") resolvedParams.push({
15484
+ ParameterKey: key,
15485
+ ParameterValue: String(result)
15486
+ });
15487
+ else if (Array.isArray(result)) resolvedParams.push({
15488
+ ParameterKey: key,
15489
+ ParameterValue: result.map((e) => String(e)).join(",")
15490
+ });
15491
+ else stillSkipped.push(key);
15287
15492
  }
15288
15493
  return {
15289
15494
  params: resolvedParams,
@@ -15863,6 +16068,12 @@ function createExportCommand() {
15863
16068
  cmd.addOption(deprecatedRegionOption);
15864
16069
  return cmd;
15865
16070
  }
16071
+ const NOECHO_PRE_DELETE_KEYS = /* @__PURE__ */ new Set([
16072
+ "Roles",
16073
+ "Users",
16074
+ "Groups",
16075
+ "PolicyName"
16076
+ ]);
15866
16077
  function withoutCoordinates(bag, coordinates) {
15867
16078
  const placeholder = Symbol("noecho-leaf");
15868
16079
  const marked = coordinates.reduce((current, coordinate) => replaceAtCoordinate(current, coordinate, placeholder), bag);
@@ -19694,6 +19905,7 @@ async function resolveImportedProperties(stackState, template, region, stateBack
19694
19905
  stateBackend,
19695
19906
  stackName: stackState.stackName
19696
19907
  };
19908
+ const noEchoInputs = /* @__PURE__ */ new Map();
19697
19909
  for (const [logicalId, resource] of entries) {
19698
19910
  const recordedSecretValues = /* @__PURE__ */ new Map();
19699
19911
  const unresolvedProperties = resource.properties ?? {};
@@ -19704,6 +19916,11 @@ async function resolveImportedProperties(stackState, template, region, stateBack
19704
19916
  recordedSecretValues
19705
19917
  });
19706
19918
  resource.properties = recordedSecretValues.size > 0 ? redactSecretsForState(markSameGenerationBag(resolved), recordedSecretValues, unresolvedProperties) : resolved;
19919
+ noEchoInputs.set(logicalId, {
19920
+ template: unresolvedProperties,
19921
+ resolved,
19922
+ attributes: resource.attributes
19923
+ });
19707
19924
  } catch (err) {
19708
19925
  logger.warn(`Failed to resolve intrinsics in Properties for imported resource ${logicalIdShown(logicalId)} (${resourceTypeShown(resource.resourceType)}): ${maskSecretsInText(describeAwsFailure(err).detail, recordedSecretValues)}.\nState will be written with the raw intrinsic shape, which may cause 'cdkd destroy' to fail on this resource — re-import once every referenced sibling is in state, or remove this resource from state with 'cdkd orphan <StackPath>/<Path/To/Resource>'.` + (unboundParameterNames.length > 0 ? ` This template also declares parameter(s) with no 'Default' that an import cannot bind (${unboundParameterNames.map((name) => plainOrDescribed(name, "parameter name")).join(", ")}), and 'cdkd import' accepts no parameter values — if this property was built from one of those, re-importing a sibling will not change it: give the parameter a 'Default' in the template and re-import, or correct the recorded properties before the next 'cdkd deploy'.` : ""));
19709
19926
  threw = true;
@@ -19735,8 +19952,94 @@ async function resolveImportedProperties(stackState, template, region, stateBack
19735
19952
  logger.warn(`${refusedHere.length} resource(s) in ${displayStackName(stackState.stackName)} depend, directly or through another resource's attributes, on template parameter(s) whose deployed CloudFormation value could not be proven equal to the template 'Default' 'cdkd import' binds` + (named.length > 0 ? ` (${named.join(", ")})` : "") + (unreadable.length > 0 ? ` — ${unreadable.length} of them because their properties could not be checked for such a dependence` : "") + ". Their recorded properties hold the 'Default', NOT the deployed value, and no observed drift baseline was captured for them by this import (the live value may be a secret this import cannot position a redaction for). Review 'cdkd diff' before the next 'cdkd deploy'.");
19736
19953
  }
19737
19954
  }
19955
+ positionImportedNoEcho(stackState, noEchoInputs, template, conditions, unsafeObservedBaselineLogicalIds, logger);
19738
19956
  return unsafeObservedBaselineLogicalIds;
19739
19957
  }
19958
+ function positionImportedNoEcho(stackState, inputs, template, conditions, refusals, logger) {
19959
+ if (inputs.size === 0) return;
19960
+ const resources = stackState.resources ?? {};
19961
+ const declared = /* @__PURE__ */ new Map();
19962
+ for (const [id, record] of Object.entries(resources)) {
19963
+ const names = noEchoAttributeNamesOf(record);
19964
+ if (names !== void 0) declared.set(id, new Set(names));
19965
+ }
19966
+ const sources = {
19967
+ parameters: noEchoParametersOrAll(template),
19968
+ attributeIsNoEcho: (id, attribute) => declared.get(id)?.has(attribute) === true,
19969
+ ...Object.keys(conditions).length > 0 && { conditions }
19970
+ };
19971
+ const leavesOf = /* @__PURE__ */ new Map();
19972
+ const failed = /* @__PURE__ */ new Map();
19973
+ for (let round = 0; round <= inputs.size; round++) {
19974
+ let grew = false;
19975
+ for (const [id, input] of inputs) {
19976
+ let leaves = failed.get(id);
19977
+ if (leaves === void 0) try {
19978
+ leaves = canonicalCoordinates(noEchoCoordinatesOf(input.template, input.resolved, sources));
19979
+ } catch (err) {
19980
+ logger.debug(safeMsg`NoEcho position walk failed for imported ${id}: ${err instanceof Error ? err.name : typeof err} — masking each property that reads a NoEcho source whole and refusing its baseline, fail-closed.`);
19981
+ leaves = topLevelNoEchoProperties(input.template, sources);
19982
+ failed.set(id, leaves);
19983
+ refusals.add(id);
19984
+ }
19985
+ leavesOf.set(id, leaves);
19986
+ const physicalId = Object.hasOwn(resources, id) ? resources[id].physicalId : void 0;
19987
+ for (const [name, attribute] of Object.entries(input.attributes ?? {})) {
19988
+ if (attribute === physicalId) continue;
19989
+ if (!leaves.some((coordinate) => coordinate[0] === name && JSON.stringify(valueAtCoordinate(input.resolved, coordinate)) === JSON.stringify(attribute))) continue;
19990
+ let names = declared.get(id);
19991
+ if (names === void 0) {
19992
+ names = /* @__PURE__ */ new Set();
19993
+ declared.set(id, names);
19994
+ }
19995
+ if (!names.has(name)) {
19996
+ names.add(name);
19997
+ grew = true;
19998
+ }
19999
+ }
20000
+ }
20001
+ if (!grew) break;
20002
+ }
20003
+ for (const [id, leaves] of leavesOf) {
20004
+ if (!Object.hasOwn(resources, id)) continue;
20005
+ const resource = resources[id];
20006
+ if (leaves.length > 0) {
20007
+ resource.properties = maskAtCoordinates(resource.properties, leaves);
20008
+ resource.noEchoLeaves = leaves.map((coordinate) => [...coordinate]);
20009
+ }
20010
+ const echoed = [...declared.get(id) ?? []].filter((name) => resource.attributes !== void 0 && Object.hasOwn(resource.attributes, name));
20011
+ if (echoed.length > 0 && resource.attributes !== void 0) {
20012
+ const attributes = { ...resource.attributes };
20013
+ for (const name of echoed) attributes[name] = maskWholeValue(attributes[name]);
20014
+ resource.attributes = attributes;
20015
+ resource.noEchoAttributeNames = [.../* @__PURE__ */ new Set([...noEchoAttributeNamesOf(resource) ?? [], ...echoed])].sort();
20016
+ }
20017
+ }
20018
+ }
20019
+ function topLevelNoEchoProperties(template, sources) {
20020
+ const leaves = [];
20021
+ for (const [key, value] of Object.entries(template)) {
20022
+ let reads;
20023
+ try {
20024
+ reads = readsNoEchoSource(value, sources);
20025
+ } catch {
20026
+ reads = true;
20027
+ }
20028
+ if (reads) leaves.push([key]);
20029
+ }
20030
+ return canonicalCoordinates(leaves);
20031
+ }
20032
+ function noEchoParametersOrAll(template) {
20033
+ try {
20034
+ return noEchoParameterNamesOf(template);
20035
+ } catch {
20036
+ try {
20037
+ return new Set(Object.keys(template.Parameters ?? {}));
20038
+ } catch {
20039
+ return /* @__PURE__ */ new Set();
20040
+ }
20041
+ }
20042
+ }
19740
20043
  const DYNAMIC_REFERENCE_OPENER = "{{resolve:";
19741
20044
  function countDynamicReferenceOpeners(bag) {
19742
20045
  let text;
@@ -19883,7 +20186,10 @@ async function captureObservedForImportedResources(stackState, providerRegistry,
19883
20186
  }).provider;
19884
20187
  if (!provider.readCurrentState) return;
19885
20188
  const observed = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {}, buildReadCurrentStateContext(stackState, logicalId));
19886
- if (observed !== void 0 && observed !== RESOURCE_NOT_FOUND) resource.observedProperties = redactSecretsForState(observed, NO_RECORDED_SECRETS, resource.properties ?? {}, STATE_SOURCED_BASELINE_RULES);
20189
+ if (observed !== void 0 && observed !== RESOURCE_NOT_FOUND) {
20190
+ const marked = noEchoLeavesOf(resource) ?? [];
20191
+ resource.observedProperties = redactSecretsForState(marked.length > 0 ? maskReadbackAtCoordinates(observed, resource.properties ?? {}, marked) : observed, NO_RECORDED_SECRETS, resource.properties ?? {}, STATE_SOURCED_BASELINE_RULES);
20192
+ }
19887
20193
  } catch (err) {
19888
20194
  logger.debug(`observedProperties capture for imported ${logicalId} (${resource.resourceType}) failed: ${err instanceof Error ? err.name : typeof err} — drift will fall back to template properties for this resource until the next successful deploy.`);
19889
20195
  }
@@ -23431,7 +23737,7 @@ function warnVpcConfigLambdas(routesWithAuth, stacks) {
23431
23737
  const resource = stack.template.Resources?.[logicalId];
23432
23738
  if (!resource || resource.Type !== "AWS::Lambda::Function") continue;
23433
23739
  const vpcConfig = (resource.Properties ?? {})["VpcConfig"];
23434
- if (vpcConfig && typeof vpcConfig === "object" && Object.keys(vpcConfig).length > 0) logger.warn(`Lambda ${logicalId} has VpcConfig — local container will reach external services via the host's network, NOT through the deployed VPC's NAT/private subnets. Calls to private RDS/ElastiCache will fail. See https://github.com/go-to-k/cdkd/blob/main/docs/cli-reference.md (cdkd local start-api — Limitations) for details.`);
23740
+ if (vpcConfig && typeof vpcConfig === "object" && Object.keys(vpcConfig).length > 0) logger.warn(`Lambda ${logicalId} has VpcConfig — local container will reach external services via the host's network, NOT through the deployed VPC's NAT/private subnets. Calls to private RDS/ElastiCache will fail. See https://cdkd.dev/local-start-api/#vpc-config-lambdas for details.`);
23435
23741
  break;
23436
23742
  }
23437
23743
  }
@@ -23440,7 +23746,7 @@ function warnIamRoutes(routesWithAuth) {
23440
23746
  const iamRoutes = [];
23441
23747
  for (const entry of routesWithAuth) if (entry.authorizer?.kind === "iam") iamRoutes.push(entry.route.declaredAt);
23442
23748
  if (iamRoutes.length === 0) return false;
23443
- logger.warn(`${iamRoutes.length} route(s) declare AuthorizationType: AWS_IAM — cdkd local start-api verifies SigV4 signatures against your local AWS credentials, but does NOT emulate IAM policy evaluation (resource / action / condition rules). Signature-verified callers reach the handler under their own identity; downstream authorization is the dev's responsibility. See https://github.com/go-to-k/cdkd/blob/main/docs/cli-reference.md (cdkd local start-api — AWS_IAM authorizer) for details.`);
23749
+ logger.warn(`${iamRoutes.length} route(s) declare AuthorizationType: AWS_IAM — cdkd local start-api verifies SigV4 signatures against your local AWS credentials, but does NOT emulate IAM policy evaluation (resource / action / condition rules). Signature-verified callers reach the handler under their own identity; downstream authorization is the dev's responsibility. See https://cdkd.dev/local-start-api/#aws-iam-authorization for details.`);
23444
23750
  for (const declaredAt of iamRoutes) logger.warn(` - ${declaredAt}`);
23445
23751
  return true;
23446
23752
  }
@@ -24106,7 +24412,7 @@ function resolveMtlsConfig(options) {
24106
24412
  });
24107
24413
  }
24108
24414
  function createLocalStartApiCommand() {
24109
- const startApi = new Command("start-api").description("Run a long-running local HTTP server that maps API Gateway routes (REST v1, HTTP API, Function URL) to Lambda invocations against the AWS Lambda Runtime Interface Emulator (Docker required). Supports Lambda TOKEN/REQUEST authorizers, Cognito User Pool / HTTP v2 JWT authorizers, and AWS_IAM auth (REST v1 `AuthorizationType: AWS_IAM` and Function URL `AuthType: AWS_IAM` — SigV4 signature verification only; IAM policy evaluation is NOT emulated; see https://github.com/go-to-k/cdkd/blob/main/docs/local-emulation.md). When JWKS is unreachable, JWT authorizers fall back to pass-through (every token accepted) with a warn line — local dev fallback. VPC-config Lambdas run locally and surface a warn line at startup; their containers do NOT get attached to the deployed VPC subnets, so calls to private RDS / ElastiCache will fail.").argument("[target]", "Optional API filter. Accepts the bare CDK logical id ('MyHttpApi'; single-stack apps only), stack-qualified logical id ('MyStack:MyHttpApi'), full CDK Construct path ('MyStack/MyHttpApi/Resource'), or an ancestor Construct path that prefix-matches ('MyStack/MyHttpApi'). When omitted, every discovered API gets its own server. Mirrors `cdkd local invoke` / `cdkd local run-task` target syntax.").addOption(new Option("--port <port>", "HTTP server port (default: auto-allocate)").default("0")).addOption(new Option("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option("--stack <name>", "Stack to start (single-stack apps auto-detect)")).addOption(new Option("--warm", "Pre-start one container per Lambda at server boot").default(false)).addOption(new Option("--per-lambda-concurrency <n>", "Pool size cap per Lambda (default 2, max 4)").default("2")).addOption(new Option("--no-pull", "Skip docker pull (cached image)")).addOption(new Option("--container-host <host>", "IP the host uses to bind/probe the RIE port (must be a numeric IP — `docker run -p <ip>:<port>:8080` rejects hostnames). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--debug-port-base <port>", "Reserve a contiguous --debug-port range (one per Lambda)")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--assume-role <arn-or-pair>", "Assume the Lambda's execution role and forward STS-issued temp creds. Two forms: (1) `--assume-role <arn>` sets a single global default ARN used for every routed Lambda; (2) `--assume-role <LogicalId>=<arn>` (repeatable) is a per-Lambda override (wins over the global default and over --assume-role-auto for the named Lambda). Pair with --assume-role-auto to auto-resolve every other Lambda. Precedence: per-Lambda > (--assume-role-auto OR global default) > unset (developer creds passed through).").argParser((raw, prev) => parseAssumeRoleToken(raw, prev))).addOption(new Option("--assume-role-auto", "Auto-resolve EACH routed Lambda's own execution role per-Lambda (literal ARN / Fn::GetAtt against template / --from-cfn-stack state). Slower boot — one STS call per Lambda — but the right shape when each Lambda's deployed role differs. Mutually exclusive with `--assume-role <arn>` (global default); errors at boot. Compatible with `--assume-role <LogicalId>=<arn>` per-Lambda overrides — the map wins for named Lambdas, auto-resolve handles the rest.").default(false)).addOption(new Option("--watch", "Hot-reload: watch the CDK app source tree and re-synth + re-discover routes on a source edit (cdk.out / node_modules / .git excluded; honors cdk.json watch.include / watch.exclude). Off by default; the server keeps the previous version serving when synth fails mid-reload.").default(false)).addOption(new Option("--stage <name>", "Select an API Gateway Stage by its 'StageName'. Default: the first Stage attached to each API. Drives BOTH event.stageVariables and requestContext.stage, for REST v1 and HTTP API v2 alike: when a route's API has a matching templated Stage, the selected StageName is threaded into requestContext.stage. An HTTP API v2 route reports '$default' only when its API carries no AWS::ApiGatewayV2::Stage in the template — that is v2's auto-deployed stage, not a limit on what this flag can select (AWS's CreateStage accepts named stages on v2 too). An API with no Stage matching the selected name is warned about at start-up and its routes get stageVariables: null.")).addOption(new Option("--api <id>", "DEPRECATED — use the positional <target> argument instead. Same accepted forms (bare logical id, stack-qualified, Construct path, ancestor prefix). Will be removed in a future major release.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers (issue #448). Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--from-state", "Read cdkd S3 state for every routed stack and substitute Ref / Fn::GetAtt / Fn::Sub / Fn::Join (and AWS pseudo parameters) in Lambda env vars with the deployed physical IDs / attributes. Off by default — pre-PR warn-and-drop semantics are preserved. Turn on for stacks already deployed via cdkd deploy. Mirrors `cdkd local invoke --from-state` / `cdkd local run-task --from-state`. Re-runs against fresh state on every hot-reload firing (--watch).").default(false)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in Lambda env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the cdkd stack name per routed stack; pass an explicit value when a single CFn stack should serve every routed stack. Mutually exclusive with --from-state. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-state when the same stack name has state in multiple regions, and with --from-cfn-stack as the CFn client region (cdkd does not have a separate --cfn-stack-region flag).").argParser(parseStackRegion)).addOption(new Option("--mtls-truststore <path>", "PEM-encoded CA bundle for client-certificate verification (mutual TLS). When set, the local server switches from HTTP to HTTPS and the TLS handshake rejects clients whose certificate doesn't chain to one of these CAs. Verified certs are surfaced on the Lambda event under requestContext.identity.clientCert (REST v1) / requestContext.authentication.clientCert (HTTP API v2). Must be set together with --mtls-cert + --mtls-key; partial flag sets are rejected. Generate a CA + server + client cert for local dev: openssl req -x509 -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.pem -subj \"/CN=cdkd-local-ca\" -days 365; openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-csr.pem -subj \"/CN=localhost\"; openssl x509 -req -in server-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365; openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-csr.pem -subj \"/CN=client\"; openssl x509 -req -in client-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365; curl --cacert ca.pem --cert client-cert.pem --key client-key.pem https://localhost:<port>/...")).addOption(new Option("--mtls-cert <path>", "PEM-encoded server certificate for mutual TLS. Self-signed is fine for local dev. Must be set together with --mtls-truststore + --mtls-key.")).addOption(new Option("--mtls-key <path>", "PEM-encoded server private key matching --mtls-cert. Must be set together with --mtls-truststore + --mtls-cert.")).addOption(new Option("--strict-sigv4", "Opt-in: enforce strict AWS_IAM SigV4 verification. When set, requests whose signature cannot be cryptographically verified (foreign access-key-id, OR no local AWS credentials configured) are denied. DEFAULT off — warn-and-pass with a placeholder principalId, matching cdk-local's `cdkl start-api`. Enable this when you want local parity with the deployed API Gateway's signature enforcement.").default(false)).action(withErrorHandling(localStartApiCommand));
24415
+ const startApi = new Command("start-api").description("Run a long-running local HTTP server that maps API Gateway routes (REST v1, HTTP API, Function URL) to Lambda invocations against the AWS Lambda Runtime Interface Emulator (Docker required). Supports Lambda TOKEN/REQUEST authorizers, Cognito User Pool / HTTP v2 JWT authorizers, and AWS_IAM auth (REST v1 `AuthorizationType: AWS_IAM` and Function URL `AuthType: AWS_IAM` — SigV4 signature verification only; IAM policy evaluation is NOT emulated; see https://cdkd.dev/local-start-api/#aws-iam-authorization). When JWKS is unreachable, JWT authorizers fall back to pass-through (every token accepted) with a warn line — local dev fallback. VPC-config Lambdas run locally and surface a warn line at startup; their containers do NOT get attached to the deployed VPC subnets, so calls to private RDS / ElastiCache will fail.").argument("[target]", "Optional API filter. Accepts the bare CDK logical id ('MyHttpApi'; single-stack apps only), stack-qualified logical id ('MyStack:MyHttpApi'), full CDK Construct path ('MyStack/MyHttpApi/Resource'), or an ancestor Construct path that prefix-matches ('MyStack/MyHttpApi'). When omitted, every discovered API gets its own server. Mirrors `cdkd local invoke` / `cdkd local run-task` target syntax.").addOption(new Option("--port <port>", "HTTP server port (default: auto-allocate)").default("0")).addOption(new Option("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option("--stack <name>", "Stack to start (single-stack apps auto-detect)")).addOption(new Option("--warm", "Pre-start one container per Lambda at server boot").default(false)).addOption(new Option("--per-lambda-concurrency <n>", "Pool size cap per Lambda (default 2, max 4)").default("2")).addOption(new Option("--no-pull", "Skip docker pull (cached image)")).addOption(new Option("--container-host <host>", "IP the host uses to bind/probe the RIE port (must be a numeric IP — `docker run -p <ip>:<port>:8080` rejects hostnames). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--debug-port-base <port>", "Reserve a contiguous --debug-port range (one per Lambda)")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--assume-role <arn-or-pair>", "Assume the Lambda's execution role and forward STS-issued temp creds. Two forms: (1) `--assume-role <arn>` sets a single global default ARN used for every routed Lambda; (2) `--assume-role <LogicalId>=<arn>` (repeatable) is a per-Lambda override (wins over the global default and over --assume-role-auto for the named Lambda). Pair with --assume-role-auto to auto-resolve every other Lambda. Precedence: per-Lambda > (--assume-role-auto OR global default) > unset (developer creds passed through).").argParser((raw, prev) => parseAssumeRoleToken(raw, prev))).addOption(new Option("--assume-role-auto", "Auto-resolve EACH routed Lambda's own execution role per-Lambda (literal ARN / Fn::GetAtt against template / --from-cfn-stack state). Slower boot — one STS call per Lambda — but the right shape when each Lambda's deployed role differs. Mutually exclusive with `--assume-role <arn>` (global default); errors at boot. Compatible with `--assume-role <LogicalId>=<arn>` per-Lambda overrides — the map wins for named Lambdas, auto-resolve handles the rest.").default(false)).addOption(new Option("--watch", "Hot-reload: watch the CDK app source tree and re-synth + re-discover routes on a source edit (cdk.out / node_modules / .git excluded; honors cdk.json watch.include / watch.exclude). Off by default; the server keeps the previous version serving when synth fails mid-reload.").default(false)).addOption(new Option("--stage <name>", "Select an API Gateway Stage by its 'StageName'. Default: the first Stage attached to each API. Drives BOTH event.stageVariables and requestContext.stage, for REST v1 and HTTP API v2 alike: when a route's API has a matching templated Stage, the selected StageName is threaded into requestContext.stage. An HTTP API v2 route reports '$default' only when its API carries no AWS::ApiGatewayV2::Stage in the template — that is v2's auto-deployed stage, not a limit on what this flag can select (AWS's CreateStage accepts named stages on v2 too). An API with no Stage matching the selected name is warned about at start-up and its routes get stageVariables: null.")).addOption(new Option("--api <id>", "DEPRECATED — use the positional <target> argument instead. Same accepted forms (bare logical id, stack-qualified, Construct path, ancestor prefix). Will be removed in a future major release.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers (issue #448). Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--from-state", "Read cdkd S3 state for every routed stack and substitute Ref / Fn::GetAtt / Fn::Sub / Fn::Join (and AWS pseudo parameters) in Lambda env vars with the deployed physical IDs / attributes. Off by default — pre-PR warn-and-drop semantics are preserved. Turn on for stacks already deployed via cdkd deploy. Mirrors `cdkd local invoke --from-state` / `cdkd local run-task --from-state`. Re-runs against fresh state on every hot-reload firing (--watch).").default(false)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in Lambda env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the cdkd stack name per routed stack; pass an explicit value when a single CFn stack should serve every routed stack. Mutually exclusive with --from-state. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-state when the same stack name has state in multiple regions, and with --from-cfn-stack as the CFn client region (cdkd does not have a separate --cfn-stack-region flag).").argParser(parseStackRegion)).addOption(new Option("--mtls-truststore <path>", "PEM-encoded CA bundle for client-certificate verification (mutual TLS). When set, the local server switches from HTTP to HTTPS and the TLS handshake rejects clients whose certificate doesn't chain to one of these CAs. Verified certs are surfaced on the Lambda event under requestContext.identity.clientCert (REST v1) / requestContext.authentication.clientCert (HTTP API v2). Must be set together with --mtls-cert + --mtls-key; partial flag sets are rejected. Generate a CA + server + client cert for local dev: openssl req -x509 -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.pem -subj \"/CN=cdkd-local-ca\" -days 365; openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-csr.pem -subj \"/CN=localhost\"; openssl x509 -req -in server-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365; openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-csr.pem -subj \"/CN=client\"; openssl x509 -req -in client-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365; curl --cacert ca.pem --cert client-cert.pem --key client-key.pem https://localhost:<port>/...")).addOption(new Option("--mtls-cert <path>", "PEM-encoded server certificate for mutual TLS. Self-signed is fine for local dev. Must be set together with --mtls-truststore + --mtls-key.")).addOption(new Option("--mtls-key <path>", "PEM-encoded server private key matching --mtls-cert. Must be set together with --mtls-truststore + --mtls-cert.")).addOption(new Option("--strict-sigv4", "Opt-in: enforce strict AWS_IAM SigV4 verification. When set, requests whose signature cannot be cryptographically verified (foreign access-key-id, OR no local AWS credentials configured) are denied. DEFAULT off — warn-and-pass with a placeholder principalId, matching cdk-local's `cdkl start-api`. Enable this when you want local parity with the deployed API Gateway's signature enforcement.").default(false)).action(withErrorHandling(localStartApiCommand));
24110
24416
  [
24111
24417
  ...commonOptions,
24112
24418
  ...appOptions,
@@ -27439,4 +27745,4 @@ function collectVerbFlags(program) {
27439
27745
 
27440
27746
  //#endregion
27441
27747
  export { canonicalizeIpProtocolValue as a, buildProgram, resolveSecretDerivedPrincipals as i, runDestroyForStack as n, resolvedResourceTimeoutMs as o, isResolvableSecretPrincipalList as r, canonicalizeIpv4Cidr as t };
27442
- //# sourceMappingURL=program-GmKPVK8p.js.map
27748
+ //# sourceMappingURL=program-BwNb3_Ot.js.map