@go-to-k/cdkd 0.290.6 → 0.290.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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $r as CdkdError, En as S3StateBackend, Jr as AwsClients, Kr as clearBucketRegionCache, Qr as AssetError, Tn as LockManager, Vn as AssetPublisher, Wr as AssemblyReader, Xr as resetAwsClients, Yr as getAwsClients, Zr as setAwsClients, _i as SynthesisError, bi as normalizeAwsError, ci as LockError, di as ProvisioningError, ei as ConfigError, en as DiffCalculator, gi as StateError, it as ProviderRegistry, mt as CloudControlProvider, ni as DependencyError, on as DagBuilder, qr as resolveBucketRegion, r as DeployEngine, sn as TemplateParser, tt as IAMRoleProvider, vi as formatError, xr as Synthesizer, yi as isCdkdError } from "./deploy-engine-BU7n9_qY.js";
1
+ import { $r as CdkdError, En as S3StateBackend, Jr as AwsClients, Kr as clearBucketRegionCache, Qr as AssetError, Tn as LockManager, Vn as AssetPublisher, Wr as AssemblyReader, Xr as resetAwsClients, Yr as getAwsClients, Zr as setAwsClients, _i as SynthesisError, bi as normalizeAwsError, ci as LockError, di as ProvisioningError, ei as ConfigError, en as DiffCalculator, gi as StateError, it as ProviderRegistry, mt as CloudControlProvider, ni as DependencyError, on as DagBuilder, qr as resolveBucketRegion, r as DeployEngine, sn as TemplateParser, tt as IAMRoleProvider, vi as formatError, xr as Synthesizer, yi as isCdkdError } from "./deploy-engine-BMp4b4Vl.js";
2
2
  import { a as setLogger, n as getLogger, t as ConsoleLogger } from "./logger-th1myfgh.js";
3
3
 
4
4
  export { AssemblyReader, AssetError, AssetPublisher, AwsClients, CdkdError, CloudControlProvider, ConfigError, ConsoleLogger, DagBuilder, DependencyError, DeployEngine, DiffCalculator, IAMRoleProvider, LockError, LockManager, ProviderRegistry, ProvisioningError, S3StateBackend, StateError, SynthesisError, Synthesizer, TemplateParser, clearBucketRegionCache, formatError, getAwsClients, getLogger, isCdkdError, normalizeAwsError, resetAwsClients, resolveBucketRegion, setAwsClients, setLogger };
@@ -1,8 +1,8 @@
1
- import { $ as secretSafeKeyDisplay, $n as isCrossRegionRedirect, $r as CdkdError, $t as applyRoleArnIfSet, A as planOrphanAdoption, An as forceQuitRecoveryClause, Ar as resolveStateBucketWithDefaultAndSource, At as isSettledInstanceState, B as formatResourceLine, Bn as shouldRetainResource, Br as expectedOwnerParam, Bt as readConfigString, C as createPreDeleteFinalSnapshot, Ci as isRetryableTransientError, Cn as redactSecretsForState, Cr as getDefaultStateBucketName, Ct as cfnRefValueFromPhysicalId, D as makeCanonicalizePropertiesFn, Di as markRedactedCause, Dn as rebuildClientForBucketRegion, Dr as resolveCaptureObservedState, Dt as isUnboundTemplateParameter, E as unsupportedFinalSnapshotError, Ei as markNonRetryable, En as S3StateBackend, Er as resolveAutoAssetStorage, Et as isImpossibleEmptyStoredAttribute, F as WARM_THROUGHPUT_MEMBERS, Fn as exportNamesCarriedFrom, Fr as CFN_TEMPLATE_URL_LIMIT, Ft as coerceCfnBoolean, G as red, Gn as createAssetRedirectResolver, Gr as processStackMessages, Gt as classifyReplaySecretRegion, H as cyan, Hn as stringifyValue, Hr as canonicalizeRegion, Ht as requireConfigArray, I as coerceWarmThroughput$1, In as importableOutputKeys, Ir as MIGRATE_TMP_PREFIX, It as coerceCfnInteger, J as collectPublishedOutputNames, Jn as AssetModeResolver, Jr as AwsClients, Jt as s3BucketArn, K as yellow, Kn as loadPublishableAssetManifest, Kt as producerRegionsFromState, L as isWarmThroughputDecrease, Ln as importableOutputs, Lr as findLargeInlineResources, Lt as configBooleanRefusal, M as isStatefulRecreateTargetForReplace, Mn as shellQuote, Mr as stateBucketExistenceConfirmed, Mt as normalizeAwsTagsToCfn, N as isStatefulRecreateTargetSync, Nn as CUSTOM_RESOURCE_RESPONSE_PREFIX, Nr as warnDeprecatedNoPrefixCliFlag, Nt as resolveExplicitPhysicalId, O as extractDeploymentEventError, Oi as retryClassificationText, On as buildForceUnlockCommand, Or as resolveSkipPrefix, Ot as parameterTypeMayLoseSecretIdentity, P as renderStatefulReason, Pn as DEFAULT_STATE_PREFIX, Pr as CFN_TEMPLATE_BODY_LIMIT, Pt as assertRegionMatch, Q as secretBearingStateKeyWarning, Qn as getBootstrapMarkerKey, Qt as s3BucketWebsiteUrl, R as toCfnInteger, Rn as orphansAfterRollback, Rr as uploadCfnTemplate, Rt as configIntegerRefusal, S as ccRoutedFinalSnapshotError, Si as isMarkedNonRetryable, Sn as recoverMaskedOutput, Sr as synthesisStatusMessage, St as carriesDynamicReference, T as refusesFinalSnapshot, Ti as isTransientServerError, Tn as LockManager, Tr as resolveApp, Tt as getAccountInfo, U as gray, Un as WorkGraph, Ur as derivePartitionAndUrlSuffix, Ut as requireConfigObject, V as bold, Vn as AssetPublisher, Vr as PARTITION_TABLE, Vt as replayWarn, W as green, Wn as buildAssetRedirectMap, Wr as AssemblyReader, Wt as requireConfigString, X as isExportAliasCollision, Xn as assertAssetBucketRegion, Xr as resetAwsClients, Xt as s3BucketDualStackDomainName, Y as exportAliasCollisionScrubWarning, Yn as BOOTSTRAP_MARKER_PREFIX, Yr as getAwsClients, Yt as s3BucketDomainName, Z as secretBearing, Zn as ensureAssetStorage, Zr as setAwsClients, Zt as s3BucketRegionalDomainName, _ as isSecretBearingReferenceString, _n as isSingleDynamicReferenceToken, _r as escapeRegExp, _t as deleteIndeterminateGuards, a as DeploymentEventsStore, ai as IntrinsicResolutionRefusalError, an as withRetry, ar as describeAwsFailure, at as wouldReturnToSdkProvider, b as PRE_DELETE_SNAPSHOT_TYPES, bi as normalizeAwsError, bn as maskSecretsInText, br as getDockerImageBySourceHash, bt as isTerminationProtectionPropagationError, c as replayFailedOperations, cn as STATE_SOURCED_BASELINE_RULES, cr as describeDockerExecFailure, ct as maskerOrIdentity, d as updatePartialReason, di as ProvisioningError, dn as TEMPLATE_SOURCED_RULES, dr as formatDockerLoginError, dt as interruptWatchListenerCount, en as DiffCalculator, er as parseBootstrapMarker, et as getCurrentResourceSecrets, f as withResourceDeadline, fi as ResourceTimeoutError, fn as carriesSecretMask, fr as getDockerCmd, ft as isInterruptedWaitError, g as bagHoldsSecretExpression, gn as identityKeyFor, gr as runDockerStreaming, gt as UNSPECIFIED_SKIP_REASON, h as computeImplicitDeleteEdges, hi as StackTerminationProtectionError, hn as errorCauseChain, hr as runDockerForeground, ht as slowCcOperationTimeoutMs, i as DeploymentEventsReader, ii as DynamicReferenceRegionAmbiguousError, in as describeTypeWithThrottleRetry, ir as buildDenyExternalAccessPolicy, it as ProviderRegistry, j as MULTI_REGION_RECREATE_BLOCKED_TYPES, jn as formatLockExpiry, jr as resolveUseCdkBootstrapAssets, jt as WAFv2WebACLProvider, k as makeSiblingClaimReader, kn as buildLockContentionMessage, kr as resolveStateBucketWithDefault, kt as refStateLookupFromResource, l as replayRollback, li as NestedStackChildDirectDestroyError, ln as STATE_SOURCED_CROSS_GENERATION_RULES, lr as describeDockerFailure, lt as beginCommandInterruptScope, m as IMPLICIT_DELETE_DEPENDENCIES, mi as StackHasActiveImportsError, mn as dynamicReferenceTokens, mr as redactDockerArgvValues, mt as CloudControlProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as findActionableSilentDrops, nr as validateAssetBucketName, nt as collectInlinePolicyNamesManagedBySiblings, o as planFailedOps, oi as LocalInvokeBuildError$1, on as DagBuilder, or as buildDockerImage, ot as createMaskedRetryLogger, p as maskingRetryLogger, pi as ResourceUpdateNotSupportedError, pn as createSecretMasker, pr as partitionSensitiveEnv, pt as startInterruptWatch, q as collectDeclaredOutputNames, qn as rewriteTemplateAssetReferences, qr as resolveBucketRegion, qt as withSharedDrainBudget, r as DeployEngine, ri as DeployCancelledError, rn as findSilentDropProperties, rr as validateContainerRepoName, rt as clearOnUpdateRemoval, s as planRollback, si as LocalStartServiceError, sn as TemplateParser, sr as describeDockerCapturedOutput, st as maskDeep, t as DEFAULT_RESOURCE_TIMEOUT_MS, ti as CrossAccountSecretRefusalError, tn as INTRINSIC_KEYS, tr as readBootstrapMarkerBody, tt as IAMRoleProvider, u as updatePartialMessage, ui as PartialFailureError, un as STATE_SOURCED_READBACK_RULES, ur as dockerSpawnEnvWithSensitive, ut as endCommandInterruptScope, v as bindingSkippedOutputs, vn as markSameGenerationBag, vr as stripControlChars, vt as deleteSkipReason, w as isFinalSnapshotError, wi as isThrottlingError, wn as scrubResourceRecord, wr as getLegacyStateBucketName, wt as coerceParameterTypedValue, x as buildFinalSnapshotIdentifier, xi as withErrorHandling, xn as recordMaskOnlyValue, xr as Synthesizer, xt as IntrinsicFunctionResolver, y as ATOMIC_FINAL_SNAPSHOT_TYPES, yn as maskSecretsInError, yr as AssetManifestLoader, yt as disableInstanceApiTermination, z as toFiniteNumber, zn as orphansCarriedFrom, zr as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, zt as configStringRefusal } from "./deploy-engine-BU7n9_qY.js";
1
+ import { $ as secretSafeKeyDisplay, $n as isCrossRegionRedirect, $r as CdkdError, $t as applyRoleArnIfSet, A as planOrphanAdoption, An as forceQuitRecoveryClause, Ar as resolveStateBucketWithDefaultAndSource, At as isSettledInstanceState, B as formatResourceLine, Bn as shouldRetainResource, Br as expectedOwnerParam, Bt as readConfigString, C as createPreDeleteFinalSnapshot, Ci as isRetryableTransientError, Cn as redactSecretsForState, Cr as getDefaultStateBucketName, Ct as cfnRefValueFromPhysicalId, D as makeCanonicalizePropertiesFn, Di as markRedactedCause, Dn as rebuildClientForBucketRegion, Dr as resolveCaptureObservedState, Dt as isUnboundTemplateParameter, E as unsupportedFinalSnapshotError, Ei as markNonRetryable, En as S3StateBackend, Er as resolveAutoAssetStorage, Et as isImpossibleEmptyStoredAttribute, F as WARM_THROUGHPUT_MEMBERS, Fn as exportNamesCarriedFrom, Fr as CFN_TEMPLATE_URL_LIMIT, Ft as coerceCfnBoolean, G as red, Gn as createAssetRedirectResolver, Gr as processStackMessages, Gt as classifyReplaySecretRegion, H as cyan, Hn as stringifyValue, Hr as canonicalizeRegion, Ht as requireConfigArray, I as coerceWarmThroughput$1, In as importableOutputKeys, Ir as MIGRATE_TMP_PREFIX, It as coerceCfnInteger, J as collectPublishedOutputNames, Jn as AssetModeResolver, Jr as AwsClients, Jt as s3BucketArn, K as yellow, Kn as loadPublishableAssetManifest, Kt as producerRegionsFromState, L as isWarmThroughputDecrease, Ln as importableOutputs, Lr as findLargeInlineResources, Lt as configBooleanRefusal, M as isStatefulRecreateTargetForReplace, Mn as shellQuote, Mr as stateBucketExistenceConfirmed, Mt as normalizeAwsTagsToCfn, N as isStatefulRecreateTargetSync, Nn as CUSTOM_RESOURCE_RESPONSE_PREFIX, Nr as warnDeprecatedNoPrefixCliFlag, Nt as resolveExplicitPhysicalId, O as extractDeploymentEventError, Oi as retryClassificationText, On as buildForceUnlockCommand, Or as resolveSkipPrefix, Ot as parameterTypeMayLoseSecretIdentity, P as renderStatefulReason, Pn as DEFAULT_STATE_PREFIX, Pr as CFN_TEMPLATE_BODY_LIMIT, Pt as assertRegionMatch, Q as secretBearingStateKeyWarning, Qn as getBootstrapMarkerKey, Qt as s3BucketWebsiteUrl, R as toCfnInteger, Rn as orphansAfterRollback, Rr as uploadCfnTemplate, Rt as configIntegerRefusal, S as ccRoutedFinalSnapshotError, Si as isMarkedNonRetryable, Sn as recoverMaskedOutput, Sr as synthesisStatusMessage, St as carriesDynamicReference, T as refusesFinalSnapshot, Ti as isTransientServerError, Tn as LockManager, Tr as resolveApp, Tt as getAccountInfo, U as gray, Un as WorkGraph, Ur as derivePartitionAndUrlSuffix, Ut as requireConfigObject, V as bold, Vn as AssetPublisher, Vr as PARTITION_TABLE, Vt as replayWarn, W as green, Wn as buildAssetRedirectMap, Wr as AssemblyReader, Wt as requireConfigString, X as isExportAliasCollision, Xn as assertAssetBucketRegion, Xr as resetAwsClients, Xt as s3BucketDualStackDomainName, Y as exportAliasCollisionScrubWarning, Yn as BOOTSTRAP_MARKER_PREFIX, Yr as getAwsClients, Yt as s3BucketDomainName, Z as secretBearing, Zn as ensureAssetStorage, Zr as setAwsClients, Zt as s3BucketRegionalDomainName, _ as isSecretBearingReferenceString, _n as isSingleDynamicReferenceToken, _r as escapeRegExp, _t as deleteIndeterminateGuards, a as DeploymentEventsStore, ai as IntrinsicResolutionRefusalError, an as withRetry, ar as describeAwsFailure, at as wouldReturnToSdkProvider, b as PRE_DELETE_SNAPSHOT_TYPES, bi as normalizeAwsError, bn as maskSecretsInText, br as getDockerImageBySourceHash, bt as isTerminationProtectionPropagationError, c as replayFailedOperations, cn as STATE_SOURCED_BASELINE_RULES, cr as describeDockerExecFailure, ct as maskerOrIdentity, d as updatePartialReason, di as ProvisioningError, dn as TEMPLATE_SOURCED_RULES, dr as formatDockerLoginError, dt as interruptWatchListenerCount, en as DiffCalculator, er as parseBootstrapMarker, et as getCurrentResourceSecrets, f as withResourceDeadline, fi as ResourceTimeoutError, fn as carriesSecretMask, fr as getDockerCmd, ft as isInterruptedWaitError, g as bagHoldsSecretExpression, gn as identityKeyFor, gr as runDockerStreaming, gt as UNSPECIFIED_SKIP_REASON, h as computeImplicitDeleteEdges, hi as StackTerminationProtectionError, hn as errorCauseChain, hr as runDockerForeground, ht as slowCcOperationTimeoutMs, i as DeploymentEventsReader, ii as DynamicReferenceRegionAmbiguousError, in as describeTypeWithThrottleRetry, ir as buildDenyExternalAccessPolicy, it as ProviderRegistry, j as MULTI_REGION_RECREATE_BLOCKED_TYPES, jn as formatLockExpiry, jr as resolveUseCdkBootstrapAssets, jt as WAFv2WebACLProvider, k as makeSiblingClaimReader, kn as buildLockContentionMessage, kr as resolveStateBucketWithDefault, kt as refStateLookupFromResource, l as replayRollback, li as NestedStackChildDirectDestroyError, ln as STATE_SOURCED_CROSS_GENERATION_RULES, lr as describeDockerFailure, lt as beginCommandInterruptScope, m as IMPLICIT_DELETE_DEPENDENCIES, mi as StackHasActiveImportsError, mn as dynamicReferenceTokens, mr as redactDockerArgvValues, mt as CloudControlProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as findActionableSilentDrops, nr as validateAssetBucketName, nt as collectInlinePolicyNamesManagedBySiblings, o as planFailedOps, oi as LocalInvokeBuildError$1, on as DagBuilder, or as buildDockerImage, ot as createMaskedRetryLogger, p as maskingRetryLogger, pi as ResourceUpdateNotSupportedError, pn as createSecretMasker, pr as partitionSensitiveEnv, pt as startInterruptWatch, q as collectDeclaredOutputNames, qn as rewriteTemplateAssetReferences, qr as resolveBucketRegion, qt as withSharedDrainBudget, r as DeployEngine, ri as DeployCancelledError, rn as findSilentDropProperties, rr as validateContainerRepoName, rt as clearOnUpdateRemoval, s as planRollback, si as LocalStartServiceError, sn as TemplateParser, sr as describeDockerCapturedOutput, st as maskDeep, t as DEFAULT_RESOURCE_TIMEOUT_MS, ti as CrossAccountSecretRefusalError, tn as INTRINSIC_KEYS, tr as readBootstrapMarkerBody, tt as IAMRoleProvider, u as updatePartialMessage, ui as PartialFailureError, un as STATE_SOURCED_READBACK_RULES, ur as dockerSpawnEnvWithSensitive, ut as endCommandInterruptScope, v as bindingSkippedOutputs, vn as markSameGenerationBag, vr as stripControlChars, vt as deleteSkipReason, w as isFinalSnapshotError, wi as isThrottlingError, wn as scrubResourceRecord, wr as getLegacyStateBucketName, wt as coerceParameterTypedValue, x as buildFinalSnapshotIdentifier, xi as withErrorHandling, xn as recordMaskOnlyValue, xr as Synthesizer, xt as IntrinsicFunctionResolver, y as ATOMIC_FINAL_SNAPSHOT_TYPES, yn as maskSecretsInError, yr as AssetManifestLoader, yt as disableInstanceApiTermination, z as toFiniteNumber, zn as orphansCarriedFrom, zr as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, zt as configStringRefusal } from "./deploy-engine-BMp4b4Vl.js";
2
2
  import { S as truncateCodePoints, _ as withSkipPrefix, b as displayIdent, 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 displaySafe, y as UNRENDERABLE } from "./logger-th1myfgh.js";
3
3
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
4
- import { t as getCdkdVersion } from "./version-BvSdNpMz.js";
5
- import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-CsdVn4cg.js";
4
+ import { t as getCdkdVersion } from "./version-XcHj8rQZ.js";
5
+ import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-JRuQeFtl.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";
@@ -73789,8 +73789,12 @@ function createStateMigrateCommand() {
73789
73789
  * or destroyed out-of-band) are reported at the root level so they stay
73790
73790
  * visible to `cdkd state list` rather than vanishing silently.
73791
73791
  *
73792
- * A self-link (parent equals self) is treated as a missing parent — the
73793
- * node lands at the root rather than building an infinite tree.
73792
+ * Every node on a parent LOOP lands at the root rather than building an
73793
+ * infinite tree. A self-link (parent equals self) is the one-node loop. A
73794
+ * longer one (A names B, B names A) used to be linked as given, so each member
73795
+ * was filed as the other's child, none was a root, and the whole loop vanished
73796
+ * from both the text and the JSON view. A node hanging off a loop still sits
73797
+ * under its parent, which is now visible (issue #3069).
73794
73798
  *
73795
73799
  * The roots and every child list are sorted alphabetically by `stackName`,
73796
73800
  * then by `region` (legacy `undefined` last), so output is stable across
@@ -73803,14 +73807,27 @@ function buildStackTree(entries) {
73803
73807
  ...entry,
73804
73808
  children: []
73805
73809
  });
73810
+ const parentOf = (node) => node.parentStack === void 0 ? void 0 : byKey.get(refKey(node.parentStack, node.parentRegion));
73811
+ const loopMembers = /* @__PURE__ */ new Set();
73812
+ const settled = /* @__PURE__ */ new Set();
73813
+ for (const start of byKey.values()) {
73814
+ const path = [];
73815
+ const onPath = /* @__PURE__ */ new Map();
73816
+ let current = start;
73817
+ while (current !== void 0 && !settled.has(current) && !onPath.has(current)) {
73818
+ onPath.set(current, path.length);
73819
+ path.push(current);
73820
+ current = parentOf(current);
73821
+ }
73822
+ if (current !== void 0 && onPath.has(current)) for (const member of path.slice(onPath.get(current))) loopMembers.add(member);
73823
+ for (const node of path) settled.add(node);
73824
+ }
73806
73825
  const roots = [];
73807
73826
  for (const node of byKey.values()) {
73808
- if (node.parentStack !== void 0) {
73809
- const parent = byKey.get(refKey(node.parentStack, node.parentRegion));
73810
- if (parent && parent !== node) {
73811
- parent.children.push(node);
73812
- continue;
73813
- }
73827
+ const parent = parentOf(node);
73828
+ if (parent && !loopMembers.has(node)) {
73829
+ parent.children.push(node);
73830
+ continue;
73814
73831
  }
73815
73832
  roots.push(node);
73816
73833
  }
@@ -77456,14 +77473,81 @@ function createExportCommand() {
77456
77473
  //#endregion
77457
77474
  //#region src/cli/commands/state.ts
77458
77475
  /**
77459
- * Render `Stack` or `Stack (region)` — used by every state subcommand's
77460
- * default output mode and ambiguity error messages.
77476
+ * The reasons a `--long` row carries for a failed read. FIXED text, never the
77477
+ * caught error's message: `getState`'s invalid-JSON refusal interpolates V8's
77478
+ * `SyntaxError`, which quotes bytes of the state body, and anyone with
77479
+ * `s3:PutObject` on the bucket chooses those bytes. Sanitizing or truncating
77480
+ * that message does not redact it, so a planted plaintext would reach both
77481
+ * `--long` and `--long --json` (issue #3069). `cdkd state show` for the one
77482
+ * stack is where the specific error is reported.
77483
+ *
77484
+ * The failure is deliberately not classified further: `getState` wraps a parse
77485
+ * refusal, the unsupported-version refusal and an AWS read failure in the same
77486
+ * `StateError`, so any finer reason would be a guess about the class.
77487
+ */
77488
+ const STATE_READ_FAILED_REASON = "state record could not be read; run `cdkd state show` for the error";
77489
+ const LOCK_READ_FAILED_REASON = "lock could not be read; run `cdkd state show` for the error";
77490
+ /**
77491
+ * The lock reason for a LEGACY row (no region). `cdkd state show` refuses such
77492
+ * a record before it reads the lock, so pointing there would send the user to
77493
+ * a command that never shows the error.
77494
+ */
77495
+ const LEGACY_LOCK_READ_FAILED_REASON = "lock could not be read";
77496
+ /**
77497
+ * The record-side reason for a record that WAS read but whose `resources` is
77498
+ * present and not a JSON object. `parseStateBody` validates nothing inside the
77499
+ * root, so `Object.keys` would count a planted string per character or a list
77500
+ * per element -- a made-up number, and for a string of millions of characters
77501
+ * an array of that many keys, built outside {@link readOrFailure}'s `try`. It
77502
+ * reuses `stateReadError` so `resourceCount` stays `null` exactly when a reason
77503
+ * is set: the text row never prints `Resources: null`, and the warning counts
77504
+ * the row (issue #3069).
77505
+ */
77506
+ const RESOURCES_MALFORMED_REASON = "resources is not a JSON object; run `cdkd state show --json` to see the record";
77507
+ /**
77508
+ * A record's resource count, or `null` when its `resources` is not a JSON
77509
+ * object ({@link RESOURCES_MALFORMED_REASON}). An absent or `null` bag counts
77510
+ * as zero, the tolerance `docs/cli-state.md` documents for it.
77511
+ */
77512
+ function resourceCountOrNull(resources) {
77513
+ if (resources === void 0 || resources === null) return 0;
77514
+ if (typeof resources !== "object" || Array.isArray(resources)) return null;
77515
+ return Object.keys(resources).length;
77516
+ }
77517
+ /**
77518
+ * Run one read and report whether it threw, WITHOUT keeping the error. The
77519
+ * error is dropped on purpose ({@link STATE_READ_FAILED_REASON} says why): a
77520
+ * caller that never holds it cannot copy it into a row.
77521
+ */
77522
+ async function readOrFailure(read) {
77523
+ try {
77524
+ return {
77525
+ ok: true,
77526
+ value: await read()
77527
+ };
77528
+ } catch {
77529
+ return { ok: false };
77530
+ }
77531
+ }
77532
+ /**
77533
+ * A record's `lastModified` as an ISO string, or `null` when it is not a
77534
+ * timestamp `Date` can represent. `parseStateBody` does not validate the
77535
+ * field, and `toISOString()` THROWS a `RangeError` for any number outside
77536
+ * JavaScript's date range (`1e300`, `NaN`-producing values, `-1e20`). That
77537
+ * throw sits AFTER {@link readOrFailure} reported success, so without this
77538
+ * check one planted record would still reject the whole `--long` listing
77539
+ * (issue #3069, security review).
77461
77540
  */
77462
- function formatStackRef(ref) {
77463
- return ref.region ? `${ref.stackName} (${ref.region})` : ref.stackName;
77541
+ function isoTimestampOrNull(value) {
77542
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
77543
+ const date = new Date(value);
77544
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
77464
77545
  }
77465
77546
  /**
77466
- * {@link formatStackRef} for a sentence a CONFIRMATION PROMPT renders.
77547
+ * Render `Stack` or `Stack (region)` for a line a terminal renders: a
77548
+ * CONFIRMATION PROMPT's sentence, and every `state list` text view -- the
77549
+ * default one-reference-per-line listing and the `--long` / `--tree` rows
77550
+ * (issue #3069). The unsanitized twin it replaced lost its last caller there.
77467
77551
  *
77468
77552
  * Both halves come from an S3 key segment (or, for a legacy record, a state
77469
77553
  * body), so both are attacker-influenced in exactly the way issue #2170 round
@@ -77621,7 +77705,7 @@ async function stateListCommand(options) {
77621
77705
  return;
77622
77706
  }
77623
77707
  if (!options.long && !options.json) {
77624
- for (const ref of refs) process.stdout.write(`${formatStackRef(ref)}\n`);
77708
+ for (const ref of refs) process.stdout.write(`${formatStackRefSafe(ref)}\n`);
77625
77709
  return;
77626
77710
  }
77627
77711
  if (options.json && !options.long) {
@@ -77634,30 +77718,35 @@ async function stateListCommand(options) {
77634
77718
  }
77635
77719
  const details = await Promise.all(refs.map(async (ref) => {
77636
77720
  const lookupRegion = ref.region ?? "";
77637
- const [stateResult, locked] = await Promise.all([lookupRegion ? setup.stateBackend.getState(ref.stackName, lookupRegion) : Promise.resolve(null), setup.lockManager.isLocked(ref.stackName, ref.region)]);
77638
- const state = stateResult?.state;
77721
+ const [stateRead, lockRead] = await Promise.all([readOrFailure(() => lookupRegion ? setup.stateBackend.getState(ref.stackName, lookupRegion) : Promise.resolve(null)), readOrFailure(() => setup.lockManager.isLocked(ref.stackName, ref.region))]);
77722
+ const state = stateRead.ok ? stateRead.value?.state : void 0;
77723
+ const resourceCount = !stateRead.ok ? null : state ? resourceCountOrNull(state.resources) : 0;
77639
77724
  return {
77640
77725
  stackName: ref.stackName,
77641
77726
  region: ref.region ?? null,
77642
- resourceCount: state ? Object.keys(state.resources ?? {}).length : 0,
77643
- lastModified: state && typeof state.lastModified === "number" ? new Date(state.lastModified).toISOString() : null,
77644
- locked
77727
+ resourceCount,
77728
+ lastModified: state ? isoTimestampOrNull(state.lastModified) : null,
77729
+ locked: lockRead.ok ? lockRead.value : null,
77730
+ stateReadError: !stateRead.ok ? STATE_READ_FAILED_REASON : resourceCount === null ? RESOURCES_MALFORMED_REASON : null,
77731
+ lockReadError: lockRead.ok ? null : ref.region ? LOCK_READ_FAILED_REASON : LEGACY_LOCK_READ_FAILED_REASON
77645
77732
  };
77646
77733
  }));
77734
+ const degraded = details.filter((d) => d.stateReadError !== null || d.lockReadError !== null);
77735
+ if (degraded.length > 0) logger.warn(`${degraded.length} of ${details.length} stack(s) could not be fully read or counted; their rows say why.`);
77647
77736
  if (options.json) {
77648
77737
  process.stdout.write(`${JSON.stringify(details, null, 2)}\n`);
77649
77738
  return;
77650
77739
  }
77651
77740
  const lines = [];
77652
77741
  for (const detail of details) {
77653
- lines.push(formatStackRef({
77742
+ lines.push(formatStackRefSafe({
77654
77743
  stackName: detail.stackName,
77655
77744
  ...detail.region ? { region: detail.region } : {}
77656
77745
  }));
77657
- lines.push(` Region: ${detail.region ?? "(legacy)"}`);
77658
- lines.push(` Resources: ${detail.resourceCount}`);
77746
+ lines.push(` Region: ${detail.region === null ? "(legacy)" : safe$1(detail.region)}`);
77747
+ lines.push(` Resources: ${detail.stateReadError !== null ? `unknown (${detail.stateReadError})` : String(detail.resourceCount)}`);
77659
77748
  lines.push(` Last Modified: ${detail.lastModified ?? "unknown"}`);
77660
- lines.push(` Lock: ${detail.locked ? "locked" : "unlocked"}`);
77749
+ lines.push(` Lock: ${detail.lockReadError !== null ? `unknown (${detail.lockReadError})` : detail.locked ? "locked" : "unlocked"}`);
77661
77750
  lines.push("");
77662
77751
  }
77663
77752
  if (lines.length > 0) {
@@ -77694,12 +77783,13 @@ async function renderTreeMode(refs, stateBackend, asJson) {
77694
77783
  region: ref.region
77695
77784
  };
77696
77785
  }
77786
+ const linkIsValid = typeof state?.parentStack === "string" && (state.parentRegion === void 0 || typeof state.parentRegion === "string");
77697
77787
  return {
77698
77788
  stackName: ref.stackName,
77699
77789
  region: ref.region,
77700
- ...state?.parentStack !== void 0 && { parentStack: state.parentStack },
77701
- ...state?.parentLogicalId !== void 0 && { parentLogicalId: state.parentLogicalId },
77702
- ...state?.parentRegion !== void 0 && { parentRegion: state.parentRegion }
77790
+ ...linkIsValid && { parentStack: state.parentStack },
77791
+ ...linkIsValid && typeof state?.parentLogicalId === "string" && { parentLogicalId: state.parentLogicalId },
77792
+ ...linkIsValid && typeof state?.parentRegion === "string" && { parentRegion: state.parentRegion }
77703
77793
  };
77704
77794
  }));
77705
77795
  const roots = buildStackTree(entries);
@@ -77708,7 +77798,7 @@ async function renderTreeMode(refs, stateBackend, asJson) {
77708
77798
  return;
77709
77799
  }
77710
77800
  if (roots.length === 0) return;
77711
- const rendered = renderStackTreeAscii(roots, (node) => formatStackRef({
77801
+ const rendered = renderStackTreeAscii(roots, (node) => formatStackRefSafe({
77712
77802
  stackName: node.stackName,
77713
77803
  ...node.region ? { region: node.region } : {}
77714
77804
  }));
@@ -92908,4 +92998,4 @@ function buildProgram() {
92908
92998
 
92909
92999
  //#endregion
92910
93000
  export { buildProgram };
92911
- //# sourceMappingURL=program-Cl3fCD6-.js.map
93001
+ //# sourceMappingURL=program-Ckl60p0E.js.map