@go-to-k/cdkd 0.289.5 → 0.289.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
- import { $ as collectInlinePolicyNamesManagedBySiblings, $n as buildDenyExternalAccessPolicy, $r as DynamicReferenceRegionAmbiguousError, $t as describeTypeWithThrottleRetry, A as isStatefulRecreateTargetForReplace, An as exportNamesCarriedFrom, Ar as CFN_TEMPLATE_URL_LIMIT, At as coerceCfnBoolean, B as gray, Bn as createAssetRedirectResolver, Br as processStackMessages, Bt as classifyReplaySecretRegion, C as refusesFinalSnapshot, Ci as retryClassificationText, Cn as UNRENDERABLE, Cr as resolveSkipPrefix, Ct as isUnboundTemplateParameter, D as makeSiblingClaimReader, Dn as shellQuote, Dr as stateBucketExistenceConfirmed, Dt as normalizeAwsTagsToCfn, E as extractDeploymentEventError, En as forceQuitRecoveryClause, Er as resolveUseCdkBootstrapAssets, Et as WAFv2WebACLProvider, F as isWarmThroughputDecrease, Fn as shouldRetainResource, Fr as expectedOwnerParam, Ft as readConfigString, G as collectPublishedOutputNames, Gn as assertAssetBucketRegion, Gr as resetAwsClients, Gt as s3BucketDualStackDomainName, H as red, Hn as rewriteTemplateAssetReferences, Hr as resolveBucketRegion, Ht as withSharedDrainBudget, I as toFiniteNumber, In as AssetPublisher, Ir as PARTITION_TABLE, It as replayWarn, J as secretBearing, Jn as isCrossRegionRedirect, Jr as CdkdError, Jt as applyRoleArnIfSet, K as exportAliasCollisionScrubWarning, Kn as ensureAssetStorage, Kr as setAwsClients, Kt as s3BucketRegionalDomainName, L as formatResourceLine, Ln as stringifyValue, Lr as canonicalizeRegion, Lt as requireConfigArray, M as renderStatefulReason, Mn as importableOutputs, Mr as findLargeInlineResources, Mt as configBooleanRefusal, N as WARM_THROUGHPUT_MEMBERS, Nn as orphansAfterRollback, Nr as uploadCfnTemplate, Nt as configIntegerRefusal, O as planOrphanAdoption, On as CUSTOM_RESOURCE_RESPONSE_PREFIX, Or as warnDeprecatedNoPrefixCliFlag, Ot as resolveExplicitPhysicalId, P as coerceWarmThroughput$1, Pn as orphansCarriedFrom, Pr as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Pt as configStringRefusal, Q as IAMRoleProvider, Qn as validateContainerRepoName, Qr as DeployCancelledError, Qt as findSilentDropProperties, R as bold, Rn as WorkGraph, Rr as derivePartitionAndUrlSuffix, Rt as requireConfigObject, S as isFinalSnapshotError, Si as markRedactedCause, Sn as rebuildClientForBucketRegion, Sr as resolveCaptureObservedState, St as getAccountInfo, T as makeCanonicalizePropertiesFn, Tn as buildLockContentionMessage, Tr as resolveStateBucketWithDefaultAndSource, Tt as refStateLookupFromResource, U as yellow, Un as AssetModeResolver, Ur as AwsClients, Ut as s3BucketArn, V as green, Vn as loadPublishableAssetManifest, Vt as producerRegionsFromState, W as collectDeclaredOutputNames, Wn as BOOTSTRAP_MARKER_PREFIX, Wr as getAwsClients, Wt as s3BucketDomainName, X as secretSafeKeyDisplay, Xn as readBootstrapMarkerBody, Xr as CrossAccountSecretRefusalError, Xt as INTRINSIC_KEYS, Y as secretBearingStateKeyWarning, Yn as parseBootstrapMarker, Yt as DiffCalculator, Z as getCurrentResourceSecrets, Zn as validateAssetBucketName, Zt as findActionableSilentDrops, _ as ATOMIC_FINAL_SNAPSHOT_TYPES, _i as isMarkedNonRetryable, _n as recoverMaskedOutput, _r as synthesisStatusMessage, _t as isTerminationProtectionPropagationError, a as DeploymentEventsStore, ai as PartialFailureError, an as STATE_SOURCED_READBACK_RULES, ar as dockerSpawnEnvWithSensitive, at as maskerOrIdentity, b as ccRoutedFinalSnapshotError, bi as isTransientServerError, bn as LockManager, br as resolveApp, bt as cfnRefValueFromPhysicalId, c as replayFailedOperations, ci as ResourceUpdateNotSupportedError, cn as createSecretMasker, cr as partitionSensitiveEnv, ct as interruptWatchListenerCount, d as updatePartialReason, dn as identityKeyFor, dr as runDockerStreaming, dt as CloudControlProvider, ei as IntrinsicResolutionRefusalError, en as withRetry, er as describeAwsFailure, et as clearOnUpdateRemoval, f as withResourceDeadline, fn as isSingleDynamicReferenceToken, fr as escapeRegExp, ft as slowCcOperationTimeoutMs, g as bindingSkippedOutputs, gi as withErrorHandling, gn as recordMaskOnlyValue, gr as Synthesizer, gt as disableInstanceApiTermination, h as computeImplicitDeleteEdges, hi as normalizeAwsError, hn as maskSecretsInText, hr as getDockerImageBySourceHash, ht as deleteSkipReason, i as DeploymentEventsReader, ii as NestedStackChildDirectDestroyError, in as STATE_SOURCED_CROSS_GENERATION_RULES, ir as describeDockerFailure, it as maskDeep, j as isStatefulRecreateTargetSync, jn as importableOutputKeys, jr as MIGRATE_TMP_PREFIX, jt as coerceCfnInteger, k as MULTI_REGION_RECREATE_BLOCKED_TYPES, kn as DEFAULT_STATE_PREFIX, kr as CFN_TEMPLATE_BODY_LIMIT, kt as assertRegionMatch, l as replayRollback, li as StackHasActiveImportsError, ln as dynamicReferenceTokens, lr as redactDockerArgvValues, lt as isInterruptedWaitError, m as IMPLICIT_DELETE_DEPENDENCIES, mn as maskSecretsInError, mr as AssetManifestLoader, mt as deleteIndeterminateGuards, n as DEFAULT_RESOURCE_WARN_AFTER_MS, ni as LocalStartServiceError, nn as TemplateParser, nr as describeDockerCapturedOutput, nt as wouldReturnToSdkProvider, o as planFailedOps, oi as ProvisioningError, on as TEMPLATE_SOURCED_RULES, or as formatDockerLoginError, ot as beginCommandInterruptScope, p as maskingRetryLogger, pn as markSameGenerationBag, pr as stripControlChars, pt as UNSPECIFIED_SKIP_REASON, q as isExportAliasCollision, qn as getBootstrapMarkerKey, qt as s3BucketWebsiteUrl, r as DeployEngine, rn as STATE_SOURCED_BASELINE_RULES, rr as describeDockerExecFailure, rt as createMaskedRetryLogger, s as planRollback, si as ResourceTimeoutError, sn as carriesSecretMask, sr as getDockerCmd, st as endCommandInterruptScope, t as DEFAULT_RESOURCE_TIMEOUT_MS, ti as LocalInvokeBuildError$1, tn as DagBuilder, tr as buildDockerImage, tt as ProviderRegistry, u as updatePartialMessage, ui as StackTerminationProtectionError, un as errorCauseChain, ur as runDockerForeground, ut as startInterruptWatch, v as PRE_DELETE_SNAPSHOT_TYPES, vi as isRetryableTransientError, vn as redactSecretsForState, vr as getDefaultStateBucketName, vt as IntrinsicFunctionResolver, w as unsupportedFinalSnapshotError, wn as buildForceUnlockCommand, wr as resolveStateBucketWithDefault, wt as parameterTypeMayLoseSecretIdentity, x as createPreDeleteFinalSnapshot, xi as markNonRetryable, xn as S3StateBackend, xr as resolveAutoAssetStorage, xt as coerceParameterTypedValue, y as buildFinalSnapshotIdentifier, yi as isThrottlingError, yn as scrubResourceRecord, yr as getLegacyStateBucketName, yt as carriesDynamicReference, z as cyan, zn as buildAssetRedirectMap, zr as AssemblyReader, zt as requireConfigString } from "./deploy-engine-Dhgm0r8o.js";
2
- import { _ as withSkipPrefix, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, y as displaySafe } from "./logger-CecsQ1UT.js";
1
+ import { $ as collectInlinePolicyNamesManagedBySiblings, $n as describeAwsFailure, $r as IntrinsicResolutionRefusalError, $t as describeTypeWithThrottleRetry, A as isStatefulRecreateTargetForReplace, An as importableOutputKeys, Ar as MIGRATE_TMP_PREFIX, At as coerceCfnBoolean, B as gray, Bn as loadPublishableAssetManifest, Bt as classifyReplaySecretRegion, C as refusesFinalSnapshot, Cn as buildForceUnlockCommand, Cr as resolveStateBucketWithDefault, Ct as isUnboundTemplateParameter, D as makeSiblingClaimReader, Dn as CUSTOM_RESOURCE_RESPONSE_PREFIX, Dr as warnDeprecatedNoPrefixCliFlag, Dt as normalizeAwsTagsToCfn, E as extractDeploymentEventError, En as shellQuote, Er as stateBucketExistenceConfirmed, Et as WAFv2WebACLProvider, F as isWarmThroughputDecrease, Fn as AssetPublisher, Fr as PARTITION_TABLE, Ft as readConfigString, G as collectPublishedOutputNames, Gn as ensureAssetStorage, Gr as setAwsClients, Gt as s3BucketDualStackDomainName, H as red, Hn as AssetModeResolver, Hr as AwsClients, Ht as withSharedDrainBudget, I as toFiniteNumber, In as stringifyValue, Ir as canonicalizeRegion, It as replayWarn, J as secretBearing, Jn as parseBootstrapMarker, Jt as applyRoleArnIfSet, K as exportAliasCollisionScrubWarning, Kn as getBootstrapMarkerKey, Kt as s3BucketRegionalDomainName, L as formatResourceLine, Ln as WorkGraph, Lr as derivePartitionAndUrlSuffix, Lt as requireConfigArray, M as renderStatefulReason, Mn as orphansAfterRollback, Mr as uploadCfnTemplate, Mt as configBooleanRefusal, N as WARM_THROUGHPUT_MEMBERS, Nn as orphansCarriedFrom, Nr as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Nt as configIntegerRefusal, O as planOrphanAdoption, On as DEFAULT_STATE_PREFIX, Or as CFN_TEMPLATE_BODY_LIMIT, Ot as resolveExplicitPhysicalId, P as coerceWarmThroughput$1, Pn as shouldRetainResource, Pr as expectedOwnerParam, Pt as configStringRefusal, Q as IAMRoleProvider, Qn as buildDenyExternalAccessPolicy, Qr as DynamicReferenceRegionAmbiguousError, Qt as findSilentDropProperties, R as bold, Rn as buildAssetRedirectMap, Rr as AssemblyReader, Rt as requireConfigObject, S as isFinalSnapshotError, Si as retryClassificationText, Sn as rebuildClientForBucketRegion, Sr as resolveSkipPrefix, St as getAccountInfo, T as makeCanonicalizePropertiesFn, Tn as forceQuitRecoveryClause, Tr as resolveUseCdkBootstrapAssets, Tt as refStateLookupFromResource, U as yellow, Un as BOOTSTRAP_MARKER_PREFIX, Ur as getAwsClients, Ut as s3BucketArn, V as green, Vn as rewriteTemplateAssetReferences, Vr as resolveBucketRegion, Vt as producerRegionsFromState, W as collectDeclaredOutputNames, Wn as assertAssetBucketRegion, Wr as resetAwsClients, Wt as s3BucketDomainName, X as secretSafeKeyDisplay, Xn as validateAssetBucketName, Xt as INTRINSIC_KEYS, Y as secretBearingStateKeyWarning, Yn as readBootstrapMarkerBody, Yr as CrossAccountSecretRefusalError, Yt as DiffCalculator, Z as getCurrentResourceSecrets, Zn as validateContainerRepoName, Zr as DeployCancelledError, Zt as findActionableSilentDrops, _ as ATOMIC_FINAL_SNAPSHOT_TYPES, _i as isRetryableTransientError, _n as recoverMaskedOutput, _r as getDefaultStateBucketName, _t as isTerminationProtectionPropagationError, a as DeploymentEventsStore, ai as ProvisioningError, an as STATE_SOURCED_READBACK_RULES, ar as formatDockerLoginError, at as maskerOrIdentity, b as ccRoutedFinalSnapshotError, bi as markNonRetryable, bn as LockManager, br as resolveAutoAssetStorage, bt as cfnRefValueFromPhysicalId, c as replayFailedOperations, ci as StackHasActiveImportsError, cn as createSecretMasker, cr as redactDockerArgvValues, ct as interruptWatchListenerCount, d as updatePartialReason, dn as identityKeyFor, dr as escapeRegExp, dt as CloudControlProvider, ei as LocalInvokeBuildError$1, en as withRetry, er as buildDockerImage, et as clearOnUpdateRemoval, f as withResourceDeadline, fn as isSingleDynamicReferenceToken, fr as stripControlChars, ft as slowCcOperationTimeoutMs, g as bindingSkippedOutputs, gi as isMarkedNonRetryable, gn as recordMaskOnlyValue, gr as synthesisStatusMessage, gt as disableInstanceApiTermination, h as computeImplicitDeleteEdges, hi as withErrorHandling, hn as maskSecretsInText, hr as Synthesizer, ht as deleteSkipReason, i as DeploymentEventsReader, ii as PartialFailureError, in as STATE_SOURCED_CROSS_GENERATION_RULES, ir as dockerSpawnEnvWithSensitive, it as maskDeep, j as isStatefulRecreateTargetSync, jn as importableOutputs, jr as findLargeInlineResources, jt as coerceCfnInteger, k as MULTI_REGION_RECREATE_BLOCKED_TYPES, kn as exportNamesCarriedFrom, kr as CFN_TEMPLATE_URL_LIMIT, kt as assertRegionMatch, l as replayRollback, li as StackTerminationProtectionError, ln as dynamicReferenceTokens, lr as runDockerForeground, lt as isInterruptedWaitError, m as IMPLICIT_DELETE_DEPENDENCIES, mi as normalizeAwsError, mn as maskSecretsInError, mr as getDockerImageBySourceHash, mt as deleteIndeterminateGuards, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as TemplateParser, nr as describeDockerExecFailure, nt as wouldReturnToSdkProvider, o as planFailedOps, oi as ResourceTimeoutError, on as TEMPLATE_SOURCED_RULES, or as getDockerCmd, ot as beginCommandInterruptScope, p as maskingRetryLogger, pn as markSameGenerationBag, pr as AssetManifestLoader, pt as UNSPECIFIED_SKIP_REASON, q as isExportAliasCollision, qn as isCrossRegionRedirect, qr as CdkdError, qt as s3BucketWebsiteUrl, r as DeployEngine, ri as NestedStackChildDirectDestroyError, rn as STATE_SOURCED_BASELINE_RULES, rr as describeDockerFailure, rt as createMaskedRetryLogger, s as planRollback, si as ResourceUpdateNotSupportedError, sn as carriesSecretMask, sr as partitionSensitiveEnv, st as endCommandInterruptScope, t as DEFAULT_RESOURCE_TIMEOUT_MS, ti as LocalStartServiceError, tn as DagBuilder, tr as describeDockerCapturedOutput, tt as ProviderRegistry, u as updatePartialMessage, un as errorCauseChain, ur as runDockerStreaming, ut as startInterruptWatch, v as PRE_DELETE_SNAPSHOT_TYPES, vi as isThrottlingError, vn as redactSecretsForState, vr as getLegacyStateBucketName, vt as IntrinsicFunctionResolver, w as unsupportedFinalSnapshotError, wn as buildLockContentionMessage, wr as resolveStateBucketWithDefaultAndSource, wt as parameterTypeMayLoseSecretIdentity, x as createPreDeleteFinalSnapshot, xi as markRedactedCause, xn as S3StateBackend, xr as resolveCaptureObservedState, xt as coerceParameterTypedValue, y as buildFinalSnapshotIdentifier, yi as isTransientServerError, yn as scrubResourceRecord, yr as resolveApp, yt as carriesDynamicReference, z as cyan, zn as createAssetRedirectResolver, zr as processStackMessages, zt as requireConfigString } from "./deploy-engine-DrTOY3f-.js";
2
+ import { _ as withSkipPrefix, b as displaySafe, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, x as truncateCodePoints, y as UNRENDERABLE } from "./logger-DTEUzYP_.js";
3
3
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
4
- import { t as getCdkdVersion } from "./version-DMsY_Ble.js";
5
- import { r as protectedReplacementAdvice, t as ASGProvider } from "./asg-provider-DD_xuWE3.js";
4
+ import { t as getCdkdVersion } from "./version-DJGTB4Rm.js";
5
+ import { r as protectedReplacementAdvice, t as ASGProvider } from "./asg-provider-D6Zyjgrr.js";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { createHash, randomBytes, randomUUID } from "node:crypto";
8
8
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, NotFound, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -24300,6 +24300,109 @@ function requireSecretStringShape(literal) {
24300
24300
  throw new Error(`SecretString must be a string, got ${literal === null ? "null" : Array.isArray(literal) ? "array" : typeof literal}`);
24301
24301
  }
24302
24302
  /**
24303
+ * The character classes a `GenerateSecretString` block leaves available,
24304
+ * after the `Exclude*` switches and `ExcludeCharacters` (issue #3068), or the
24305
+ * refusal that says why no password can be minted from it. ONE function for
24306
+ * the predicate and the generator, so the shapes the predicate refuses are
24307
+ * exactly the shapes the generator cannot serve.
24308
+ *
24309
+ * The caller has already run the member SHAPE predicates (`ExcludeCharacters`
24310
+ * is a string or absent, the booleans coerce, `PasswordLength` is an integer
24311
+ * in range) — this function reads the block by cast on that precondition.
24312
+ *
24313
+ * Three refusals, each MEASURED on CloudFormation (us-east-1, 2026-09-14): the
24314
+ * docs give the default (`RequireEachIncludedType` on) and the four-type
24315
+ * wording, but none of the refusal shapes or their messages:
24316
+ *
24317
+ * - `RequireEachIncludedType` defaults to TRUE and covers the four classes
24318
+ * (upper, lower, number, punctuation) that are not switched off; a space is
24319
+ * never required, only admitted. With it on, a class the `Exclude*` switch
24320
+ * keeps but `ExcludeCharacters` empties is refused: `All characters of the
24321
+ * desired type have been excluded`. With it OFF the same template CREATES
24322
+ * (measured), so the refusal is scoped to REQUIRED classes.
24323
+ * - With it on, `PasswordLength` below the number of required classes is
24324
+ * refused: `Password length is too short based on the required types`.
24325
+ * - A pool with no character at all is refused: `All characters have been
24326
+ * excluded from selection`. The old local fallback to lowercase invented a
24327
+ * charset the template had excluded.
24328
+ */
24329
+ function generateCharset(config) {
24330
+ const PUNCTUATION = "!\"#$%&'()*+,-./:;<=>?@[\\]^_" + String.fromCharCode(96) + "{|}~";
24331
+ const off = (key) => coerceCfnBoolean(config[key]) ?? false;
24332
+ const excluded = new Set(config["ExcludeCharacters"] ?? "");
24333
+ const strip = (chars) => [...chars].filter((c) => !excluded.has(c)).join("");
24334
+ const classes = [
24335
+ [
24336
+ "uppercase",
24337
+ strip("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
24338
+ "ExcludeUppercase"
24339
+ ],
24340
+ [
24341
+ "lowercase",
24342
+ strip("abcdefghijklmnopqrstuvwxyz"),
24343
+ "ExcludeLowercase"
24344
+ ],
24345
+ [
24346
+ "number",
24347
+ strip("0123456789"),
24348
+ "ExcludeNumbers"
24349
+ ],
24350
+ [
24351
+ "punctuation",
24352
+ strip(PUNCTUATION),
24353
+ "ExcludePunctuation"
24354
+ ]
24355
+ ];
24356
+ const requireEach = coerceCfnBoolean(config["RequireEachIncludedType"]) ?? true;
24357
+ const included = classes.filter(([, , switchKey]) => !off(switchKey));
24358
+ const required = [];
24359
+ if (requireEach) for (const [name, chars, switchKey] of included) {
24360
+ if (chars.length === 0) return {
24361
+ required: [],
24362
+ pool: "",
24363
+ refusal: `all characters of the ${name} type have been excluded while RequireEachIncludedType requires one (exclude the type with ${switchKey} instead)`
24364
+ };
24365
+ required.push(chars);
24366
+ }
24367
+ const space = (coerceCfnBoolean(config["IncludeSpace"]) ?? false) && !excluded.has(" ") ? " " : "";
24368
+ const pool = included.map(([, chars]) => chars).join("") + space;
24369
+ if (pool.length === 0) return {
24370
+ required: [],
24371
+ pool: "",
24372
+ refusal: "all characters have been excluded from selection, so no password can be generated"
24373
+ };
24374
+ const length = coerceCfnInteger(config["PasswordLength"]) ?? 32;
24375
+ if (required.length > length) return {
24376
+ required: [],
24377
+ pool: "",
24378
+ refusal: `PasswordLength ${length} is too short for the ${required.length} character types RequireEachIncludedType requires`
24379
+ };
24380
+ return {
24381
+ required,
24382
+ pool
24383
+ };
24384
+ }
24385
+ /**
24386
+ * A uniformly distributed index below `n`, by rejection: a raw draw taken
24387
+ * modulo `n` biases toward the low indexes whenever the draw's range is not
24388
+ * a multiple of `n` (2^32 never is for a 26- or 32-character class), and a
24389
+ * password generator should not.
24390
+ * The rejection IS fenced, deterministically: the unit suite stubs
24391
+ * `crypto.getRandomValues` to hand back a draw at or above `limit` and then
24392
+ * one below it, and asserts the first is thrown away (a `% n` shortcut would
24393
+ * mint from it). The bias itself is about 1 part in 2^32 / n per index at
24394
+ * this width — negligible either way; the rejection makes it zero.
24395
+ */
24396
+ function randomIndex(n) {
24397
+ if (!Number.isInteger(n) || n <= 0) throw new Error(`randomIndex: range must be a positive integer (got ${n})`);
24398
+ const limit = Math.floor(4294967296 / n) * n;
24399
+ const draw = /* @__PURE__ */ new Uint32Array(1);
24400
+ for (;;) {
24401
+ crypto.getRandomValues(draw);
24402
+ if (draw[0] < limit) return draw[0] % n;
24403
+ }
24404
+ }
24405
+ /**
24303
24406
  * The refusal for the MEMBERS of a `GenerateSecretString` block whose container
24304
24407
  * has already passed `requireConfigObject` (issue #3056), or `undefined` when
24305
24408
  * every member is usable. ONE predicate for two readers — the generator, which
@@ -24328,8 +24431,10 @@ function requireSecretStringShape(literal) {
24328
24431
  */
24329
24432
  function generateMemberRefusal(config) {
24330
24433
  const P = "AWS::SecretsManager::Secret GenerateSecretString";
24331
- const shape = configIntegerRefusal(config, "PasswordLength", P, 1, 4096) ?? configBooleanRefusal(config, "ExcludeUppercase", P) ?? configBooleanRefusal(config, "ExcludeLowercase", P) ?? configBooleanRefusal(config, "ExcludeNumbers", P) ?? configBooleanRefusal(config, "ExcludePunctuation", P) ?? configStringRefusal(config, "ExcludeCharacters", "", P) ?? configStringRefusal(config, "GenerateStringKey", "required", P) ?? configStringRefusal(config, "SecretStringTemplate", "required", P);
24434
+ const shape = configIntegerRefusal(config, "PasswordLength", P, 1, 4096) ?? configBooleanRefusal(config, "ExcludeUppercase", P) ?? configBooleanRefusal(config, "ExcludeLowercase", P) ?? configBooleanRefusal(config, "ExcludeNumbers", P) ?? configBooleanRefusal(config, "ExcludePunctuation", P) ?? configBooleanRefusal(config, "IncludeSpace", P) ?? configBooleanRefusal(config, "RequireEachIncludedType", P) ?? configStringRefusal(config, "ExcludeCharacters", "", P) ?? configStringRefusal(config, "GenerateStringKey", "required", P) ?? configStringRefusal(config, "SecretStringTemplate", "required", P);
24332
24435
  if (shape !== void 0) return shape;
24436
+ const charset = generateCharset(config);
24437
+ if (charset.refusal !== void 0) return `${P}: ${charset.refusal}`;
24333
24438
  const key = config["GenerateStringKey"];
24334
24439
  const template = config["SecretStringTemplate"];
24335
24440
  if (key === void 0 && template === void 0) return void 0;
@@ -24685,10 +24790,11 @@ var SecretsManagerSecretProvider = class {
24685
24790
  * With no `onUnusable` a refusal THROWS (the create path, where the block
24686
24791
  * is template-borne). With one, the message is handed over and `undefined`
24687
24792
  * is returned — the update path's SKIP, decided by the caller, so that this
24688
- * function never mints from a block it could not read. The two members the
24689
- * schema declares that this recipe does not implement, `IncludeSpace` and
24690
- * `RequireEachIncludedType`, are a separate fidelity gap (issue #3068), not
24691
- * a shape question.
24793
+ * function never mints from a block it could not read. The recipe itself —
24794
+ * the four classes, the service's punctuation set, `IncludeSpace`, and the
24795
+ * `RequireEachIncludedType` guarantee — lives in `generateCharset` (issue
24796
+ * #3068), shared with the predicate so the block it refuses and the block
24797
+ * it mints from cannot disagree.
24692
24798
  */
24693
24799
  generateSecretString(config, options) {
24694
24800
  const refusal = generateMemberRefusal(config);
@@ -24700,22 +24806,15 @@ var SecretsManagerSecretProvider = class {
24700
24806
  throw new Error(refusal);
24701
24807
  }
24702
24808
  const length = coerceCfnInteger(config["PasswordLength"]) ?? 32;
24703
- const excludeUppercase = coerceCfnBoolean(config["ExcludeUppercase"]) ?? false;
24704
- const excludeLowercase = coerceCfnBoolean(config["ExcludeLowercase"]) ?? false;
24705
- const excludeNumbers = coerceCfnBoolean(config["ExcludeNumbers"]) ?? false;
24706
- const excludePunctuation = coerceCfnBoolean(config["ExcludePunctuation"]) ?? false;
24707
- const excludeCharacters = config["ExcludeCharacters"] ?? "";
24708
- let chars = "";
24709
- if (!excludeUppercase) chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
24710
- if (!excludeLowercase) chars += "abcdefghijklmnopqrstuvwxyz";
24711
- if (!excludeNumbers) chars += "0123456789";
24712
- if (!excludePunctuation) chars += "!@#$%^&*()_+-=[]{}|;:,.<>?";
24713
- if (excludeCharacters) for (const c of excludeCharacters) chars = chars.replaceAll(c, "");
24714
- if (chars.length === 0) chars = "abcdefghijklmnopqrstuvwxyz";
24715
- const bytes = new Uint8Array(length);
24716
- crypto.getRandomValues(bytes);
24717
- let password = "";
24718
- for (let i = 0; i < length; i++) password += chars[bytes[i] % chars.length];
24809
+ const { required, pool } = generateCharset(config);
24810
+ const out = [];
24811
+ for (let i = 0; i < length; i++) out.push(pool[randomIndex(pool.length)]);
24812
+ const positions = Array.from({ length }, (_, i) => i);
24813
+ for (const classChars of required) {
24814
+ const slot = positions.splice(randomIndex(positions.length), 1)[0];
24815
+ out[slot] = classChars[randomIndex(classChars.length)];
24816
+ }
24817
+ const password = out.join("");
24719
24818
  const generateStringKey = config["GenerateStringKey"];
24720
24819
  const secretStringTemplate = config["SecretStringTemplate"];
24721
24820
  if (generateStringKey === void 0 || secretStringTemplate === void 0) return password;
@@ -74601,8 +74700,8 @@ async function buildCdkdStateStackTree(rootStackName, region, stateBackend, pref
74601
74700
  }
74602
74701
  async function walkCdkdStateStackTree(stackName, region, state, stateBackend) {
74603
74702
  const nestedChildren = /* @__PURE__ */ new Map();
74604
- for (const [logicalId, resource] of Object.entries(state.resources)) {
74605
- if (resource.resourceType !== "AWS::CloudFormation::Stack") continue;
74703
+ for (const [logicalId, entry] of Object.entries(state.resources ?? {})) {
74704
+ if (entry?.resourceType !== "AWS::CloudFormation::Stack") continue;
74606
74705
  const childStackName = `${stackName}~${logicalId}`;
74607
74706
  const childResult = await stateBackend.getState(childStackName, region);
74608
74707
  if (!childResult) throw new Error(`cdkd state is missing nested-child '${safeSegment(childStackName)}' (${safeSegment(region)}). Parent stack '${safeSegment(stackName)}' lists '${safeSegment(logicalId)}' as an ${NESTED_STACK_RESOURCE_TYPE} row but no child state file exists at 'cdkd/${safeSegment(childStackName)}/${safeSegment(region)}/state.json'. The cdkd state tree is inconsistent — re-deploy the parent stack to refresh, or run 'cdkd state orphan ${safeSegment(stackName)}' and re-import.`);
@@ -76659,7 +76758,7 @@ function formatStackRef(ref) {
76659
76758
  * `()` would read as "no region" rather than "a region cdkd will not print".
76660
76759
  */
76661
76760
  function formatStackRefSafe(ref) {
76662
- return ref.region ? `${safe(ref.stackName)} (${safe(ref.region)})` : safe(ref.stackName);
76761
+ return ref.region ? `${safe$1(ref.stackName)} (${safe$1(ref.region)})` : safe$1(ref.stackName);
76663
76762
  }
76664
76763
  /**
76665
76764
  * One spelling of "this value came from an S3 key or a state record, and is
@@ -76685,7 +76784,7 @@ function formatStackRefSafe(ref) {
76685
76784
  * text (a parser's own message, an AWS error) takes the denylist class
76686
76785
  * instead; `display-safe.ts`'s header draws that line.
76687
76786
  */
76688
- function safe(value) {
76787
+ function safe$1(value) {
76689
76788
  return displaySafe(value, { asciiOnly: true }) || "<unrenderable>";
76690
76789
  }
76691
76790
  /**
@@ -76696,18 +76795,18 @@ function safe(value) {
76696
76795
  */
76697
76796
  function resolveSingleRegion(stackName, refs, requestedRegion) {
76698
76797
  const matches = refs.filter((r) => r.stackName === stackName);
76699
- if (matches.length === 0) throw new Error(`No state found for stack '${safe(stackName)}'. Run 'cdkd state list' to see available stacks.`);
76798
+ if (matches.length === 0) throw new Error(`No state found for stack '${safe$1(stackName)}'. Run 'cdkd state list' to see available stacks.`);
76700
76799
  if (requestedRegion) {
76701
76800
  const ref = matches.find((r) => r.region === requestedRegion);
76702
76801
  if (!ref) {
76703
- const seen = matches.map((r) => r.region === void 0 ? "(legacy)" : safe(r.region));
76704
- throw new Error(`No state found for stack '${safe(stackName)}' in region '${safe(requestedRegion)}'. Available regions: ${seen.join(", ")}.`);
76802
+ const seen = matches.map((r) => r.region === void 0 ? "(legacy)" : safe$1(r.region));
76803
+ throw new Error(`No state found for stack '${safe$1(stackName)}' in region '${safe$1(requestedRegion)}'. Available regions: ${seen.join(", ")}.`);
76705
76804
  }
76706
76805
  return ref;
76707
76806
  }
76708
76807
  if (matches.length === 1) return matches[0];
76709
- const regions = matches.map((r) => r.region === void 0 ? "(legacy)" : safe(r.region));
76710
- throw new Error(`Stack '${safe(stackName)}' has state in multiple regions: ${regions.join(", ")}. Re-run with --stack-region <region> to disambiguate.`);
76808
+ const regions = matches.map((r) => r.region === void 0 ? "(legacy)" : safe$1(r.region));
76809
+ throw new Error(`Stack '${safe$1(stackName)}' has state in multiple regions: ${regions.join(", ")}. Re-run with --stack-region <region> to disambiguate.`);
76711
76810
  }
76712
76811
  /**
76713
76812
  * Shared bootstrap for every `state` subcommand: build the AWS clients,
@@ -76819,7 +76918,7 @@ async function stateListCommand(options) {
76819
76918
  return {
76820
76919
  stackName: ref.stackName,
76821
76920
  region: ref.region ?? null,
76822
- resourceCount: state ? Object.keys(state.resources).length : 0,
76921
+ resourceCount: state ? Object.keys(state.resources ?? {}).length : 0,
76823
76922
  lastModified: state && typeof state.lastModified === "number" ? new Date(state.lastModified).toISOString() : null,
76824
76923
  locked
76825
76924
  };
@@ -76928,17 +77027,20 @@ async function stateResourcesCommand(stackName, options) {
76928
77027
  const setup = await setupStateBackend(options);
76929
77028
  try {
76930
77029
  const ref = resolveSingleRegion(stackName, await setup.stateBackend.listStacks(), options.stackRegion);
76931
- if (!ref.region) throw new Error(`Stack '${safe(stackName)}' has only a legacy state record without a region. Run 'cdkd deploy ${safe(stackName)}' (or any cdkd write) to migrate it to the region-scoped layout, then re-run this command.`);
77030
+ if (!ref.region) throw new Error(`Stack '${safe$1(stackName)}' has only a legacy state record without a region. Run 'cdkd deploy ${safe$1(stackName)}' (or any cdkd write) to migrate it to the region-scoped layout, then re-run this command.`);
76932
77031
  const stateResult = await setup.stateBackend.getState(stackName, ref.region);
76933
- if (!stateResult) throw new Error(`No state found for stack '${safe(stackName)}' (${safe(ref.region)}) in s3://${setup.bucket}/${setup.prefix}/. Run 'cdkd state list' to see available stacks.`);
77032
+ if (!stateResult) throw new Error(`No state found for stack '${safe$1(stackName)}' (${safe$1(ref.region)}) in s3://${setup.bucket}/${setup.prefix}/. Run 'cdkd state list' to see available stacks.`);
76934
77033
  const resources = stateResult.state.resources ?? {};
76935
- const details = Object.entries(resources).map(([logicalId, resource]) => ({
76936
- logicalId,
76937
- resourceType: resource.resourceType,
76938
- physicalId: resource.physicalId,
76939
- dependencies: resource.dependencies ?? [],
76940
- attributes: resource.attributes ?? {}
76941
- })).sort((a, b) => a.logicalId.localeCompare(b.logicalId));
77034
+ const details = Object.entries(resources).map(([logicalId, entry]) => {
77035
+ const resource = entry ?? {};
77036
+ return {
77037
+ logicalId,
77038
+ resourceType: resource.resourceType,
77039
+ physicalId: resource.physicalId,
77040
+ dependencies: resource.dependencies ?? [],
77041
+ attributes: resource.attributes ?? {}
77042
+ };
77043
+ }).sort((a, b) => a.logicalId.localeCompare(b.logicalId));
76942
77044
  if (options.json) {
76943
77045
  process.stdout.write(`${JSON.stringify(details, null, 2)}\n`);
76944
77046
  return;
@@ -77082,20 +77184,35 @@ function formatLastModified(value) {
77082
77184
  * whole control class with spaces. They arrive here as control-free strings, so
77083
77185
  * a guard would be redundant — and a test for one could only be written by
77084
77186
  * mocking the read that sanitises them, which would pin nothing about the real
77085
- * path. `displaySafe`'s own `String(value)` is unguarded, so a value that throws
77086
- * on coercion fails THERE, before this function; that is go-to-k/cdkd#2947 and
77087
- * not something a guard here could catch either.
77187
+ * path. A value whose coercion THROWS is absorbed there too: `displaySafe`
77188
+ * falls back to `Object.prototype.toString` (go-to-k/cdkd#2947).
77088
77189
  *
77089
77190
  * `expiresAt` is declared a number and is not guaranteed to be one, but it
77090
77191
  * reaches the row only through subtraction and `formatDuration`, so no character
77091
- * the record carries can survive into the output either.
77192
+ * the record carries can survive into the output either. One that is not a
77193
+ * finite number — absent, `{}`, `"soon"`, or the `NaN` that `getLockRecord`
77194
+ * substitutes for a coercion that throws (go-to-k/cdkd#2947) — is reported as
77195
+ * an UNKNOWN deadline rather than pushed through the arithmetic, which printed
77196
+ * `expired NaNmNaNs ago` (issue #3083). The wording is the one
77197
+ * `lock-contention-message.ts`'s `formatRemaining` already uses for the same
77198
+ * input, so the two lock renderers agree. What the expiry CHECK does with such
77199
+ * a value (`isLockExpired` treats it as expired) is a separate decision that
77200
+ * this row does not restate.
77092
77201
  */
77093
77202
  function formatLockSummary(lockInfo) {
77094
77203
  if (!lockInfo) return "unlocked";
77095
77204
  const opStr = lockInfo.operation ? ` (operation: ${lockInfo.operation})` : "";
77096
- const expiresInMs = lockInfo.expiresAt - Date.now();
77097
- const expiresStr = expiresInMs > 0 ? `expires in ${formatDuration(expiresInMs)}` : `expired ${formatDuration(-expiresInMs)} ago`;
77098
- return `locked by ${lockInfo.owner}${opStr}, ${expiresStr}`;
77205
+ return `locked by ${lockInfo.owner}${opStr}, ${formatExpiry(lockInfo.expiresAt)}`;
77206
+ }
77207
+ /**
77208
+ * `expires in 1m23s` / `expired 45s ago` for a finite deadline, `expires at an
77209
+ * unknown time` for anything else. The non-finite arm exists because
77210
+ * `expiresAt` is an unchecked cast (see `formatLockSummary`).
77211
+ */
77212
+ function formatExpiry(expiresAt) {
77213
+ if (!Number.isFinite(expiresAt)) return "expires at an unknown time";
77214
+ const expiresInMs = expiresAt - Date.now();
77215
+ return expiresInMs > 0 ? `expires in ${formatDuration(expiresInMs)}` : `expired ${formatDuration(-expiresInMs)} ago`;
77099
77216
  }
77100
77217
  /**
77101
77218
  * Create the `state resources` subcommand.
@@ -77135,9 +77252,9 @@ async function stateShowCommand(stackName, options) {
77135
77252
  const setup = await setupStateBackend(options);
77136
77253
  try {
77137
77254
  const ref = resolveSingleRegion(stackName, await setup.stateBackend.listStacks(), options.stackRegion);
77138
- if (!ref.region) throw new Error(`Stack '${safe(stackName)}' has only a legacy state record without a region. Run 'cdkd deploy ${safe(stackName)}' (or any cdkd write) to migrate it to the region-scoped layout, then re-run this command.`);
77255
+ if (!ref.region) throw new Error(`Stack '${safe$1(stackName)}' has only a legacy state record without a region. Run 'cdkd deploy ${safe$1(stackName)}' (or any cdkd write) to migrate it to the region-scoped layout, then re-run this command.`);
77139
77256
  const [stateResult, lockInfo] = await Promise.all([setup.stateBackend.getState(stackName, ref.region), setup.lockManager.getLockInfo(stackName, ref.region)]);
77140
- if (!stateResult) throw new Error(`No state found for stack '${safe(stackName)}' (${safe(ref.region)}) in s3://${setup.bucket}/${setup.prefix}/. Run 'cdkd state list' to see available stacks.`);
77257
+ if (!stateResult) throw new Error(`No state found for stack '${safe$1(stackName)}' (${safe$1(ref.region)}) in s3://${setup.bucket}/${setup.prefix}/. Run 'cdkd state list' to see available stacks.`);
77141
77258
  if (options.showNested) {
77142
77259
  const treeWithLocks = await loadLocksForTree(await buildCdkdStateStackTree(stackName, ref.region, setup.stateBackend, stateResult.state), setup.lockManager, lockInfo);
77143
77260
  if (options.json) {
@@ -77243,12 +77360,13 @@ function renderStateBlock(state, lockInfo, withLegend) {
77243
77360
  lines.push("Skipped outputs:");
77244
77361
  for (const [k, digest] of sortedSkippedOutputs(state)) {
77245
77362
  const fullDigest = formatAttributeValue(digest);
77246
- const shownDigest = fullDigest.length > SKIPPED_DIGEST_PREVIEW_LEN && fullDigest !== UNSERIALIZABLE ? `${fullDigest.slice(0, SKIPPED_DIGEST_PREVIEW_LEN)}…` : fullDigest;
77363
+ const cut = truncateCodePoints(fullDigest, SKIPPED_DIGEST_PREVIEW_LEN);
77364
+ const shownDigest = cut.truncated && fullDigest !== UNSERIALIZABLE ? `${cut.text}…` : fullDigest;
77247
77365
  lines.push(` ${stripControlChars(k)}: ${shownDigest}`);
77248
77366
  }
77249
77367
  if (withLegend) lines.push(...skippedOutputsLegend());
77250
77368
  }
77251
- const resourceEntries = Object.entries(state.resources ?? {}).sort(([a], [b]) => a.localeCompare(b));
77369
+ const resourceEntries = Object.entries(state.resources ?? {}).map(([logicalId, entry]) => [logicalId, entry ?? {}]).sort(([a], [b]) => a.localeCompare(b));
77252
77370
  lines.push("");
77253
77371
  lines.push(`Resources (${resourceEntries.length}):`);
77254
77372
  for (const [logicalId, resource] of resourceEntries) {
@@ -78301,6 +78419,35 @@ function snapshotNote(resourceType, effectiveProvisionedBy, skipFinalSnapshot) {
78301
78419
  return "DeletionPolicy Snapshot — final snapshot, then delete";
78302
78420
  }
78303
78421
  /**
78422
+ * One spelling of "this value came from an S3 key or a rollback-journal record,
78423
+ * and is about to be interpolated into a message a terminal will render"
78424
+ * (issue #3064).
78425
+ *
78426
+ * `rollback-journal.json` is a sibling of `state.json` in the same bucket, so
78427
+ * anyone with `s3:PutObject` writes it, and cdkd's output is line-oriented --
78428
+ * an injected newline invents a line that reads like a real one. Here that is
78429
+ * worse than a forged diagnostic: the plan preview below is what the user
78430
+ * CONFIRMS against, so a planted journal could forge the plan rows themselves.
78431
+ *
78432
+ * The ASCII allowlist, because every value it guards has a known charset: a
78433
+ * logical id, a CFn resource type, a change type, a run id, a segment reason,
78434
+ * a stack name, an AWS region. Call it for those; `grep safe(` answers the
78435
+ * scope and this comment does not.
78436
+ *
78437
+ * NOT for a value that is about to be USED rather than shown -- the preview
78438
+ * indexes `previewState` by the RAW `op.logicalId`, and sanitising a lookup
78439
+ * key silently mismatches the record it is meant to find.
78440
+ *
78441
+ * NOT for free-form error text either. An SDK or provider message legitimately
78442
+ * carries non-ASCII (a resource name, AWS's own wording), so a site that renders
78443
+ * one calls `displaySafe()` directly and takes the DENYLIST -- the same class
78444
+ * `formatError` picks for a `cause`, and for the same reason. `grep displaySafe(`
78445
+ * answers how many; a count written here was wrong on its first revision.
78446
+ */
78447
+ function safe(value) {
78448
+ return displaySafe(value, { asciiOnly: true }) || "<unrenderable>";
78449
+ }
78450
+ /**
78304
78451
  * Human label for a planned rollback action (plan preview). `skipFinalSnapshot`
78305
78452
  * is threaded in because the classifier is pure (it cannot see CLI flags) and
78306
78453
  * the Snapshot label would otherwise promise a final snapshot the run is about
@@ -78310,17 +78457,17 @@ function actionLabel(item, skipFinalSnapshot) {
78310
78457
  const { op, action, replacement } = item;
78311
78458
  const rep = replacement ? " [replacement occurred, best-effort revert]" : "";
78312
78459
  switch (action) {
78313
- case "delete": return ` - delete ${op.logicalId} (${op.resourceType})${rep}`;
78314
- case "delete-with-final-snapshot": return ` - delete ${op.logicalId} (${op.resourceType}) [${snapshotNote(op.resourceType, item.effectiveProvisionedBy, skipFinalSnapshot)}]`;
78315
- case "orphan-retain": return ` - orphan ${op.logicalId} (${op.resourceType}) [DeletionPolicy Retain — left in AWS]`;
78316
- case "orphan-flag": return ` - orphan ${op.logicalId} (${op.resourceType}) [--orphan]`;
78317
- case "revert": return ` - revert ${op.logicalId} (${op.resourceType})${rep}`;
78318
- case "reverse-replacement": return item.retainsNewResource ? ` - reverse-replace ${op.logicalId} (${op.resourceType}) [re-create old resource; new one RETAINED (UpdateReplacePolicy: Retain) and left untracked — REFUSED instead if the re-create collides with the name the retained resource still holds]` : ` - reverse-replace ${op.logicalId} (${op.resourceType}) [re-create old resource, delete new]`;
78319
- case "reverse-replacement-readopt": return item.retainsNewResource ? ` - reverse-replace ${op.logicalId} (${op.resourceType}) [re-adopt retained old resource; new one RETAINED (UpdateReplacePolicy: Retain) and left untracked]` : ` - reverse-replace ${op.logicalId} (${op.resourceType}) [delete new, re-adopt retained old resource]`;
78320
- case "unrecoverable-delete": return ` - (cannot restore) ${op.logicalId} (${op.resourceType}) — was DELETED, unrecoverable`;
78321
- case "skip-mismatch": return ` - skip ${op.logicalId} (${op.resourceType}) — physical id changed, needs manual attention`;
78322
- case "skip-absent": return ` - skip ${op.logicalId} (${op.resourceType}) — no longer in state`;
78323
- case "skip-already-done": return ` - skip ${op.logicalId} (${op.resourceType}) — already reverted`;
78460
+ case "delete": return ` - delete ${safe(op.logicalId)} (${safe(op.resourceType)})${rep}`;
78461
+ case "delete-with-final-snapshot": return ` - delete ${safe(op.logicalId)} (${safe(op.resourceType)}) [${snapshotNote(op.resourceType, item.effectiveProvisionedBy, skipFinalSnapshot)}]`;
78462
+ case "orphan-retain": return ` - orphan ${safe(op.logicalId)} (${safe(op.resourceType)}) [DeletionPolicy Retain — left in AWS]`;
78463
+ case "orphan-flag": return ` - orphan ${safe(op.logicalId)} (${safe(op.resourceType)}) [--orphan]`;
78464
+ case "revert": return ` - revert ${safe(op.logicalId)} (${safe(op.resourceType)})${rep}`;
78465
+ case "reverse-replacement": return item.retainsNewResource ? ` - reverse-replace ${safe(op.logicalId)} (${safe(op.resourceType)}) [re-create old resource; new one RETAINED (UpdateReplacePolicy: Retain) and left untracked — REFUSED instead if the re-create collides with the name the retained resource still holds]` : ` - reverse-replace ${safe(op.logicalId)} (${safe(op.resourceType)}) [re-create old resource, delete new]`;
78466
+ case "reverse-replacement-readopt": return item.retainsNewResource ? ` - reverse-replace ${safe(op.logicalId)} (${safe(op.resourceType)}) [re-adopt retained old resource; new one RETAINED (UpdateReplacePolicy: Retain) and left untracked]` : ` - reverse-replace ${safe(op.logicalId)} (${safe(op.resourceType)}) [delete new, re-adopt retained old resource]`;
78467
+ case "unrecoverable-delete": return ` - (cannot restore) ${safe(op.logicalId)} (${safe(op.resourceType)}) — was DELETED, unrecoverable`;
78468
+ case "skip-mismatch": return ` - skip ${safe(op.logicalId)} (${safe(op.resourceType)}) — physical id changed, needs manual attention`;
78469
+ case "skip-absent": return ` - skip ${safe(op.logicalId)} (${safe(op.resourceType)}) — no longer in state`;
78470
+ case "skip-already-done": return ` - skip ${safe(op.logicalId)} (${safe(op.resourceType)}) — already reverted`;
78324
78471
  }
78325
78472
  }
78326
78473
  /**
@@ -78332,13 +78479,13 @@ function actionLabel(item, skipFinalSnapshot) {
78332
78479
  function failedActionLabel(item, skipFinalSnapshot) {
78333
78480
  const { op, action } = item;
78334
78481
  switch (action) {
78335
- case "revert-failed-update": return ` - revert ${op.logicalId} (${op.resourceType}) [FAILED update — remote state unknown, force-applying previous properties]`;
78336
- case "delete-failed-create": return ` - delete ${op.logicalId} (${op.resourceType}) [FAILED create]`;
78337
- case "delete-failed-create-with-final-snapshot": return ` - delete ${op.logicalId} (${op.resourceType}) [FAILED create, ${snapshotNote(op.resourceType, item.effectiveProvisionedBy, skipFinalSnapshot)}]`;
78338
- case "orphan-failed-create-retain": return ` - orphan ${op.logicalId} (${op.resourceType}) [FAILED create, DeletionPolicy Retain — left in AWS]`;
78339
- case "skip-failed-unknown": return ` - skip ${op.logicalId} (${op.resourceType}) — failed CREATE recorded no physical id`;
78340
- case "skip-failed-noop": return ` - skip ${op.logicalId} (${op.resourceType}) — failed ${op.changeType} left nothing to revert`;
78341
- case "skip-failed-absent": return ` - skip ${op.logicalId} (${op.resourceType}) — no previous state available`;
78482
+ case "revert-failed-update": return ` - revert ${safe(op.logicalId)} (${safe(op.resourceType)}) [FAILED update — remote state unknown, force-applying previous properties]`;
78483
+ case "delete-failed-create": return ` - delete ${safe(op.logicalId)} (${safe(op.resourceType)}) [FAILED create]`;
78484
+ case "delete-failed-create-with-final-snapshot": return ` - delete ${safe(op.logicalId)} (${safe(op.resourceType)}) [FAILED create, ${snapshotNote(op.resourceType, item.effectiveProvisionedBy, skipFinalSnapshot)}]`;
78485
+ case "orphan-failed-create-retain": return ` - orphan ${safe(op.logicalId)} (${safe(op.resourceType)}) [FAILED create, DeletionPolicy Retain — left in AWS]`;
78486
+ case "skip-failed-unknown": return ` - skip ${safe(op.logicalId)} (${safe(op.resourceType)}) — failed CREATE recorded no physical id`;
78487
+ case "skip-failed-noop": return ` - skip ${safe(op.logicalId)} (${safe(op.resourceType)}) — failed ${safe(op.changeType)} left nothing to revert`;
78488
+ case "skip-failed-absent": return ` - skip ${safe(op.logicalId)} (${safe(op.resourceType)}) — no previous state available`;
78342
78489
  }
78343
78490
  }
78344
78491
  /**
@@ -78379,7 +78526,7 @@ async function rollbackCommand(stackArg, options) {
78379
78526
  return;
78380
78527
  }
78381
78528
  if (scoped.length > 1) {
78382
- const list = scoped.map((c) => ` - ${c.stackName} (${c.region})`).join("\n");
78529
+ const list = scoped.map((c) => ` - ${safe(c.stackName)} (${safe(c.region)})`).join("\n");
78383
78530
  throw new Error(`Multiple stacks have a rollback journal. Pick one:\n${list}\nRe-run 'cdkd rollback <stack>' (add --stack-region if the same name spans regions).`);
78384
78531
  }
78385
78532
  ref = scoped[0];
@@ -78412,25 +78559,25 @@ async function rollbackCommand(stackArg, options) {
78412
78559
  try {
78413
78560
  const stateData = await setup.stateBackend.getState(stackName, region);
78414
78561
  const journal = await setup.stateBackend.loadRollbackJournal(stackName, region);
78415
- if (!journal || journal.segments.length === 0) throw new Error(`Nothing to roll back for '${stackName}' (${region}). Run 'cdkd deploy' to (re)deploy, or 'cdkd destroy' to clean up.`);
78416
- if (!stateData) throw new Error(`Rollback journal exists for '${stackName}' (${region}) but its state.json is missing (keys: ${setup.prefix}/${stackName}/${region}/state.json and .../rollback-journal.json). State appears corrupted — inspect the bucket manually.`);
78562
+ if (!journal || journal.segments.length === 0) throw new Error(`Nothing to roll back for '${safe(stackName)}' (${safe(region)}). Run 'cdkd deploy' to (re)deploy, or 'cdkd destroy' to clean up.`);
78563
+ if (!stateData) throw new Error(`Rollback journal exists for '${safe(stackName)}' (${safe(region)}) but its state.json is missing (keys: ${safe(`${setup.prefix}/${stackName}/${region}`)}/state.json and .../rollback-journal.json). State appears corrupted — inspect the bucket manually.`);
78417
78564
  const baseState = stateData.state;
78418
78565
  const stateResources = { ...baseState.resources };
78419
78566
  const mintedOrphans = [];
78420
78567
  const orphanLogicalIds = new Set(options.orphan ?? []);
78421
78568
  const newestSegment = journal.segments[journal.segments.length - 1];
78422
- if (newestSegment.roleArn && !options.roleArn) logger.info(`Note: the failed deploy ran with --role-arn ${newestSegment.roleArn}; this rollback is running with ambient credentials (pass --role-arn to match).`);
78423
- logger.info(`\nRollback plan for '${stackName}' (${region}):`);
78569
+ if (newestSegment.roleArn && !options.roleArn) logger.info(`Note: the failed deploy ran with --role-arn ${safe(newestSegment.roleArn)}; this rollback is running with ambient credentials (pass --role-arn to match).`);
78570
+ logger.info(`\nRollback plan for '${safe(stackName)}' (${safe(region)}):`);
78424
78571
  const planStateView = { ...stateResources };
78425
78572
  for (let s = journal.segments.length - 1; s >= 0; s--) {
78426
78573
  const segment = journal.segments[s];
78427
- logger.info(`\n Segment ${s + 1}/${journal.segments.length} (${segment.reason}${segment.runId ? `, run ${segment.runId}` : ""}):`);
78574
+ logger.info(`\n Segment ${s + 1}/${journal.segments.length} (${safe(segment.reason)}${segment.runId ? `, run ${safe(segment.runId)}` : ""}):`);
78428
78575
  if (segment.failedOperations && segment.failedOperations.length > 0) {
78429
78576
  if (options.revertFailed) {
78430
78577
  const failedPlan = planFailedOps(segment.failedOperations, planStateView);
78431
78578
  for (const item of failedPlan) logger.info(failedActionLabel(item, options.skipFinalSnapshot === true));
78432
78579
  applyFailedPlanToPreview(failedPlan, planStateView, options.skipFinalSnapshot === true);
78433
- } else for (const fop of segment.failedOperations) logger.info(` - (left as-is) ${fop.logicalId} (${fop.resourceType}) — its ${fop.changeType} FAILED mid-deploy; pass --revert-failed to attempt reverting it`);
78580
+ } else for (const fop of segment.failedOperations) logger.info(` - (left as-is) ${safe(fop.logicalId)} (${safe(fop.resourceType)}) — its ${safe(fop.changeType)} FAILED mid-deploy; pass --revert-failed to attempt reverting it`);
78434
78581
  }
78435
78582
  const plan = planRollback(segment.operations, planStateView, orphanLogicalIds);
78436
78583
  for (const item of plan) logger.info(actionLabel(item, options.skipFinalSnapshot === true));
@@ -78438,7 +78585,7 @@ async function rollbackCommand(stackArg, options) {
78438
78585
  }
78439
78586
  logger.info("");
78440
78587
  if (!skipConfirmation) {
78441
- if (!await confirm(`Roll back '${stackName}' (${region})?`)) {
78588
+ if (!await confirm(`Roll back '${safe(stackName)}' (${safe(region)})?`)) {
78442
78589
  logger.info("Rollback cancelled");
78443
78590
  return;
78444
78591
  }
@@ -78476,7 +78623,7 @@ async function rollbackCommand(stackArg, options) {
78476
78623
  const fresh = await setup.stateBackend.getState(stackName, region);
78477
78624
  currentEtag = await setup.stateBackend.saveState(stackName, region, next(), { ...fresh?.etag !== void 0 && { expectedEtag: fresh.etag } });
78478
78625
  } catch (retryError) {
78479
- logger.warn(`Failed to persist state after a rollback operation: ${retryError instanceof Error ? retryError.message : String(retryError)}. The resource was reverted in AWS; re-run 'cdkd rollback ${stackName}' to reconcile state.`);
78626
+ logger.warn(`Failed to persist state after a rollback operation: ${displaySafe(retryError instanceof Error ? retryError.message : String(retryError))}. The resource was reverted in AWS; re-run 'cdkd rollback ${safe(stackName)}' to reconcile state.`);
78480
78627
  }
78481
78628
  }
78482
78629
  };
@@ -78519,7 +78666,7 @@ async function rollbackCommand(stackArg, options) {
78519
78666
  if (remaining.length === 0) delete segment.failedOperations;
78520
78667
  else segment.failedOperations = remaining;
78521
78668
  } catch (stripError) {
78522
- logger.warn(`Failed to strip replayed failed-ops from the journal: ${stripError instanceof Error ? stripError.message : String(stripError)}`);
78669
+ logger.warn(`Failed to strip replayed failed-ops from the journal: ${displaySafe(stripError instanceof Error ? stripError.message : String(stripError))}`);
78523
78670
  }
78524
78671
  if (failedResult.interrupted) return {
78525
78672
  failures: failedOpFailures,
@@ -78555,16 +78702,16 @@ async function rollbackCommand(stackArg, options) {
78555
78702
  const survivingOrphans = orphansAfterRollback(baseState, mintedOrphans).orphans ?? [];
78556
78703
  if (journal.segments.length === 0 && oldestInitialDeploy && Object.keys(stateResources).length === 0 && survivingOrphans.length === 0) {
78557
78704
  await setup.stateBackend.deleteState(stackName, region);
78558
- logger.info(`State for '${stackName}' (${region}) removed (stack fully rolled back).`);
78705
+ logger.info(`State for '${safe(stackName)}' (${safe(region)}) removed (stack fully rolled back).`);
78559
78706
  }
78560
- if (interrupted) throw new PartialFailureError(`Rollback interrupted. Journal preserved — re-run 'cdkd rollback ${stackName}' to finish.`);
78561
- if (totalFailures > 0) throw new PartialFailureError(`Rollback completed with ${totalFailures} failed operation(s). Journal preserved — re-run 'cdkd rollback ${stackName}' to retry.`);
78707
+ if (interrupted) throw new PartialFailureError(`Rollback interrupted. Journal preserved — re-run 'cdkd rollback ${safe(stackName)}' to finish.`);
78708
+ if (totalFailures > 0) throw new PartialFailureError(`Rollback completed with ${totalFailures} failed operation(s). Journal preserved — re-run 'cdkd rollback ${safe(stackName)}' to retry.`);
78562
78709
  if (totalWarnings > 0) throw new PartialFailureError(`Rollback completed with ${totalWarnings} skipped/unrecoverable operation(s) (see warnings above).`);
78563
- logger.info(`\nRollback of '${stackName}' (${region}) complete.`);
78710
+ logger.info(`\nRollback of '${safe(stackName)}' (${safe(region)}) complete.`);
78564
78711
  } finally {
78565
78712
  try {
78566
78713
  await setup.lockManager.releaseLock(stackName, region).catch((err) => {
78567
- logger.warn(`Failed to release lock for '${stackName}' (${region}): ${err instanceof Error ? err.message : String(err)}`);
78714
+ logger.warn(`Failed to release lock for '${safe(stackName)}' (${safe(region)}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
78568
78715
  });
78569
78716
  } finally {
78570
78717
  process.removeListener("SIGINT", sigintHandler);
@@ -91937,4 +92084,4 @@ function buildProgram() {
91937
92084
 
91938
92085
  //#endregion
91939
92086
  export { buildProgram };
91940
- //# sourceMappingURL=program-CgSZ7WgF.js.map
92087
+ //# sourceMappingURL=program-Ca0PiFL-.js.map