@go-to-k/cdkd 0.284.29 → 0.284.30

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/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { $ as endCommandInterruptScope, $t as createAssetRedirectResolver, A as MULTI_REGION_RECREATE_BLOCKED_TYPES, An as resolveUseCdkBootstrapAssets, At as maskSecretsInText, B as collectDeclaredOutputNames, Bn as canonicalizeRegion, Bt as INTRINSIC_KEYS, C as ccRoutedFinalSnapshotError, Cn as getLegacyStateBucketName, Ct as STATE_SOURCED_READBACK_RULES, D as unsupportedFinalSnapshotError, Dn as resolveSkipPrefix, Dt as errorCauseChain, E as refusesFinalSnapshot, En as resolveCaptureObservedState, Et as dynamicReferenceTokens, F as cyan, Fn as MIGRATE_TMP_PREFIX, Ft as s3BucketDualStackDomainName, G as stateKeySecretExposure, Gn as resolveBucketRegion, Gt as LockManager, H as exportAliasCollisionScrubWarning, Hn as AssemblyReader, Ht as withRetry, I as gray, In as findLargeInlineResources, It as s3BucketRegionalDomainName, J as clearOnUpdateRemoval, Jn as resetAwsClients, Jt as shouldRetainResource, K as IAMRoleProvider, Kn as AwsClients, Kt as S3StateBackend, L as green, Ln as uploadCfnTemplate, Lt as s3BucketWebsiteUrl, M as renderStatefulReason, Mn as warnDeprecatedNoPrefixCliFlag, Mt as scrubResourceRecord, N as formatResourceLine, Nn as CFN_TEMPLATE_BODY_LIMIT, Nt as s3BucketArn, O as makeCanonicalizePropertiesFn, On as resolveStateBucketWithDefault, Ot as isSingleDynamicReferenceToken, P as bold, Pn as CFN_TEMPLATE_URL_LIMIT, Pt as s3BucketDomainName, Q as beginCommandInterruptScope, Qt as buildAssetRedirectMap, R as red, Rn as expectedOwnerParam, Rt as applyRoleArnIfSet, S as buildFinalSnapshotIdentifier, Sn as getDefaultStateBucketName, Sr as markNonRetryable, St as STATE_SOURCED_CROSS_GENERATION_RULES, T as isFinalSnapshotError, Tn as resolveAutoAssetStorage, Tt as createSecretMasker, U as isExportAliasCollision, Un as processStackMessages, Ut as DagBuilder, V as collectPublishedOutputNames, Vn as derivePartitionAndUrlSuffix, Vt as describeTypeWithThrottleRetry, W as secretBearingStateKeyWarning, Wt as TemplateParser, X as findActionableSilentDrops, Xt as stringifyValue, Y as ProviderRegistry, Yn as setAwsClients, Yt as AssetPublisher, Z as findSilentDropProperties, Zn as CdkdError, Zt as WorkGraph, _ as maskingRetryLogger, _n as runDockerStreaming, _r as normalizeAwsError, _t as readConfigString, a as DeploymentEventsStore, an as BOOTSTRAP_MARKER_PREFIX, ar as MissingCdkCliError, at as isTerminationProtectionPropagationError, b as ATOMIC_FINAL_SNAPSHOT_TYPES, bn as Synthesizer, br as isRetryableTransientError, bt as requireConfigObject, c as planRollback, cn as parseBootstrapMarker, cr as ProvisioningError, ct as getAccountInfo, d as replayRollback, dn as validateContainerRepoName, dr as StackHasActiveImportsError, dt as normalizeAwsTagsToCfn, en as loadPublishableAssetManifest, er as DeployCancelledError, et as isInterruptedWaitError, f as updatePartialMessage, fn as buildDenyExternalAccessPolicy, fr as StackTerminationProtectionError, ft as resolveExplicitPhysicalId, g as withResourceDeadline, gn as runDockerForeground, gt as configStringRefusal, h as deleteSkipReason, hn as getDockerCmd, ht as configBooleanRefusal, i as DeploymentEventsReader, in as AssetModeResolver, it as disableInstanceApiTermination, j as isStatefulRecreateTargetSync, jn as stateBucketExistenceConfirmed, jt as redactSecretsForState, k as extractDeploymentEventError, kn as resolveStateBucketWithDefaultAndSource, kt as maskSecretsInError, l as producerRegionsFromState, ln as readBootstrapMarkerBody, lr as ResourceTimeoutError, lt as refStateLookupFromResource, m as UNSPECIFIED_SKIP_REASON, mn as formatDockerLoginError, mt as coerceCfnBoolean, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as escapeRegExp, nr as LocalMigrateError, nt as CloudControlProvider, o as classifyReplaySecretRegion, on as ensureAssetStorage, or as NestedStackChildDirectDestroyError, ot as IntrinsicFunctionResolver, p as updatePartialReason, pn as buildDockerImage, pt as assertRegionMatch, q as collectInlinePolicyNamesManagedBySiblings, qn as getAwsClients, qt as rebuildClientForBucketRegion, r as DeployEngine, rn as stripControlChars, rr as LocalStartServiceError, rt as slowCcOperationTimeoutMs, s as planFailedOps, sn as getBootstrapMarkerKey, sr as PartialFailureError, st as cfnRefValueFromPhysicalId, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as rewriteTemplateAssetReferences, tr as LocalInvokeBuildError$1, tt as startInterruptWatch, u as replayFailedOperations, un as validateAssetBucketName, ur as ResourceUpdateNotSupportedError, ut as WAFv2WebACLProvider, v as IMPLICIT_DELETE_DEPENDENCIES, vn as AssetManifestLoader, vr as withErrorHandling, vt as replayWarn, w as createPreDeleteFinalSnapshot, wn as resolveApp, wt as TEMPLATE_SOURCED_RULES, x as PRE_DELETE_SNAPSHOT_TYPES, xn as synthesisStatusMessage, xr as isThrottlingError, xt as requireConfigString, y as computeImplicitDeleteEdges, yn as getDockerImageBySourceHash, yr as isMarkedNonRetryable, yt as requireConfigArray, z as yellow, zn as PARTITION_TABLE, zt as DiffCalculator } from "./deploy-engine-CE-tOz2d.js";
2
+ import { $ as endCommandInterruptScope, $t as createAssetRedirectResolver, A as MULTI_REGION_RECREATE_BLOCKED_TYPES, An as resolveUseCdkBootstrapAssets, At as maskSecretsInText, B as collectDeclaredOutputNames, Bn as canonicalizeRegion, Bt as INTRINSIC_KEYS, C as ccRoutedFinalSnapshotError, Cn as getLegacyStateBucketName, Ct as STATE_SOURCED_READBACK_RULES, D as unsupportedFinalSnapshotError, Dn as resolveSkipPrefix, Dt as errorCauseChain, E as refusesFinalSnapshot, En as resolveCaptureObservedState, Et as dynamicReferenceTokens, F as cyan, Fn as MIGRATE_TMP_PREFIX, Ft as s3BucketDualStackDomainName, G as stateKeySecretExposure, Gn as resolveBucketRegion, Gt as LockManager, H as exportAliasCollisionScrubWarning, Hn as AssemblyReader, Ht as withRetry, I as gray, In as findLargeInlineResources, It as s3BucketRegionalDomainName, J as clearOnUpdateRemoval, Jn as resetAwsClients, Jt as shouldRetainResource, K as IAMRoleProvider, Kn as AwsClients, Kt as S3StateBackend, L as green, Ln as uploadCfnTemplate, Lt as s3BucketWebsiteUrl, M as renderStatefulReason, Mn as warnDeprecatedNoPrefixCliFlag, Mt as scrubResourceRecord, N as formatResourceLine, Nn as CFN_TEMPLATE_BODY_LIMIT, Nt as s3BucketArn, O as makeCanonicalizePropertiesFn, On as resolveStateBucketWithDefault, Ot as isSingleDynamicReferenceToken, P as bold, Pn as CFN_TEMPLATE_URL_LIMIT, Pt as s3BucketDomainName, Q as beginCommandInterruptScope, Qt as buildAssetRedirectMap, R as red, Rn as expectedOwnerParam, Rt as applyRoleArnIfSet, S as buildFinalSnapshotIdentifier, Sn as getDefaultStateBucketName, Sr as markNonRetryable, St as STATE_SOURCED_CROSS_GENERATION_RULES, T as isFinalSnapshotError, Tn as resolveAutoAssetStorage, Tt as createSecretMasker, U as isExportAliasCollision, Un as processStackMessages, Ut as DagBuilder, V as collectPublishedOutputNames, Vn as derivePartitionAndUrlSuffix, Vt as describeTypeWithThrottleRetry, W as secretBearingStateKeyWarning, Wt as TemplateParser, X as findActionableSilentDrops, Xt as stringifyValue, Y as ProviderRegistry, Yn as setAwsClients, Yt as AssetPublisher, Z as findSilentDropProperties, Zn as CdkdError, Zt as WorkGraph, _ as maskingRetryLogger, _n as runDockerStreaming, _r as normalizeAwsError, _t as readConfigString, a as DeploymentEventsStore, an as BOOTSTRAP_MARKER_PREFIX, ar as MissingCdkCliError, at as isTerminationProtectionPropagationError, b as ATOMIC_FINAL_SNAPSHOT_TYPES, bn as Synthesizer, br as isRetryableTransientError, bt as requireConfigObject, c as planRollback, cn as parseBootstrapMarker, cr as ProvisioningError, ct as getAccountInfo, d as replayRollback, dn as validateContainerRepoName, dr as StackHasActiveImportsError, dt as normalizeAwsTagsToCfn, en as loadPublishableAssetManifest, er as DeployCancelledError, et as isInterruptedWaitError, f as updatePartialMessage, fn as buildDenyExternalAccessPolicy, fr as StackTerminationProtectionError, ft as resolveExplicitPhysicalId, g as withResourceDeadline, gn as runDockerForeground, gt as configStringRefusal, h as deleteSkipReason, hn as getDockerCmd, ht as configBooleanRefusal, i as DeploymentEventsReader, in as AssetModeResolver, it as disableInstanceApiTermination, j as isStatefulRecreateTargetSync, jn as stateBucketExistenceConfirmed, jt as redactSecretsForState, k as extractDeploymentEventError, kn as resolveStateBucketWithDefaultAndSource, kt as maskSecretsInError, l as producerRegionsFromState, ln as readBootstrapMarkerBody, lr as ResourceTimeoutError, lt as refStateLookupFromResource, m as UNSPECIFIED_SKIP_REASON, mn as formatDockerLoginError, mt as coerceCfnBoolean, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as escapeRegExp, nr as LocalMigrateError, nt as CloudControlProvider, o as classifyReplaySecretRegion, on as ensureAssetStorage, or as NestedStackChildDirectDestroyError, ot as IntrinsicFunctionResolver, p as updatePartialReason, pn as buildDockerImage, pt as assertRegionMatch, q as collectInlinePolicyNamesManagedBySiblings, qn as getAwsClients, qt as rebuildClientForBucketRegion, r as DeployEngine, rn as stripControlChars, rr as LocalStartServiceError, rt as slowCcOperationTimeoutMs, s as planFailedOps, sn as getBootstrapMarkerKey, sr as PartialFailureError, st as cfnRefValueFromPhysicalId, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as rewriteTemplateAssetReferences, tr as LocalInvokeBuildError$1, tt as startInterruptWatch, u as replayFailedOperations, un as validateAssetBucketName, ur as ResourceUpdateNotSupportedError, ut as WAFv2WebACLProvider, v as IMPLICIT_DELETE_DEPENDENCIES, vn as AssetManifestLoader, vr as withErrorHandling, vt as replayWarn, w as createPreDeleteFinalSnapshot, wn as resolveApp, wt as TEMPLATE_SOURCED_RULES, x as PRE_DELETE_SNAPSHOT_TYPES, xn as synthesisStatusMessage, xr as isThrottlingError, xt as requireConfigString, y as computeImplicitDeleteEdges, yn as getDockerImageBySourceHash, yr as isMarkedNonRetryable, yt as requireConfigArray, z as yellow, zn as PARTITION_TABLE, zt as DiffCalculator } from "./deploy-engine-BFgi0RJr.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as getCurrentStackName, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
4
- import { t as ASGProvider } from "./asg-provider-DzbiUvJi.js";
4
+ import { t as ASGProvider } from "./asg-provider-qMgJEhCM.js";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { createHash, randomBytes, randomUUID } from "node:crypto";
7
7
  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, 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";
@@ -64081,6 +64081,30 @@ function stripWalk(value) {
64081
64081
  //#endregion
64082
64082
  //#region src/cli/commands/drift.ts
64083
64083
  /**
64084
+ * Route one outcome to the handler for its variant.
64085
+ *
64086
+ * The mechanism issue [#2135](https://github.com/go-to-k/cdkd/issues/2135) asks
64087
+ * for, and the reason every consumer in this file goes through it rather than
64088
+ * filtering on `o.kind === '...'`: `handlers` is a MAPPED TYPE over
64089
+ * `DriftOutcome['kind']`, so it must name EVERY variant. Adding a member to the
64090
+ * union turns every call site that has not been updated into a compile error
64091
+ * ("property '<kind>' is missing"), instead of leaving it to fall through to
64092
+ * whatever it happened to do before. A `.filter()` predicate cannot do that —
64093
+ * it keeps compiling and silently stops matching the new state.
64094
+ *
64095
+ * A handler that deliberately does nothing with a variant still has to be
64096
+ * written out, which is the point: the author of the next variant has to decide,
64097
+ * per consumer, what it means there.
64098
+ *
64099
+ * Exported, with {@link DriftOutcome} and {@link NotComparedCause}, so
64100
+ * `tests/unit/cli/drift-outcome.test-d.ts` can fence the mapped type itself:
64101
+ * relaxing it to a `Partial` record would silently un-fence every consumer in
64102
+ * this file while changing no runtime behaviour, so no runtime test can see it.
64103
+ */
64104
+ function matchOutcome(outcome, handlers) {
64105
+ return handlers[outcome.kind](outcome);
64106
+ }
64107
+ /**
64084
64108
  * Distinguish "drift detected" (exit 1) from "command crashed" (exit 1
64085
64109
  * via the default handler) so the drift command can fail fast and the
64086
64110
  * top-level handler doesn't add a stack trace for the expected case.
@@ -64105,18 +64129,19 @@ var DriftDetectedError = class DriftDetectedError extends CdkdError {
64105
64129
  * `{{resolve:ssm-secure:...}}` token — a pre-existing population cdkd resolves
64106
64130
  * for nobody, which can never clear on a re-run, and which this change did not
64107
64131
  * create. Exiting non-zero for them would break `cdkd drift` in CI forever over
64108
- * an unrelated defect, so the exit reads `comparisonRefused` and the report
64109
- * reads `referencesUnresolved`. See that field's note.
64132
+ * an unrelated defect, so the exit reads the `refused` cause alone while the
64133
+ * report covers both. See `NotComparedCause` and `outcomeExitSignal`.
64110
64134
  *
64111
64135
  * WHY A NON-ZERO EXIT, and why it is a PRESERVATION rather than a new signal.
64112
64136
  * Pre-#2108 that population resolved the reference in the WRONG region, the
64113
64137
  * baseline could never equal what AWS held, and the resource was reported
64114
64138
  * `drifted` -- so `cdkd drift` exited 1 and every CI gate keyed on the exit code
64115
64139
  * fired. #2108 correctly stopped comparing against a foreign region's plaintext,
64116
- * which made the same population report `clean`; without this the command would
64117
- * exit 0 and print `no drift detected` for a stack whose secret-bearing
64118
- * properties were never looked at. Round 1 of that change surfaced the refusal
64119
- * in `--json` (`notCompared`) and in the human report, but the exit code -- the
64140
+ * which made the same population report `notCompared`; without this the
64141
+ * command would exit 0 and print `no drift detected` for a stack whose
64142
+ * secret-bearing properties were never looked at. Round 1 of that change
64143
+ * surfaced the refusal in `--json` (`notCompared`) and in the human report,
64144
+ * but the exit code -- the
64120
64145
  * signal most CI gates actually read -- still said "pass".
64121
64146
  *
64122
64147
  * WHY EXIT 2 RATHER THAN 1. `2` is this repo's established "work completed but
@@ -64153,32 +64178,56 @@ var DriftComparisonRefusedError = class DriftComparisonRefusedError extends Cdkd
64153
64178
  }
64154
64179
  };
64155
64180
  /**
64156
- * Every outcome on one report that was only PARTIALLY compared -- `drifted` or
64157
- * `clean`, carrying `referencesUnresolved` (issue #2108).
64181
+ * Every outcome on one report that was only PARTIALLY compared -- the
64182
+ * `notCompared` variant, plus a `drifted` one whose `notComparedCause` is set
64183
+ * (issues #2108 / #2135).
64184
+ *
64185
+ * ONE spelling, because TWO renderings must agree about the same run: the
64186
+ * `--json` `notCompared` roll-up and the human report's `PARTIALLY compared`
64187
+ * block (whose count is also what the `N of M fully checked` line subtracts).
64188
+ * A roll-up spelled per reader is how the payload and the human summary come to
64189
+ * disagree.
64158
64190
  *
64159
- * ONE spelling, because there are now THREE readers that must agree: the
64160
- * `--json` `notCompared` roll-up, the human report's `PARTIALLY compared` block,
64161
- * and the EXIT CODE. A predicate spelled per reader is how the payload and the
64162
- * exit code come to disagree about the same run.
64191
+ * The EXIT CODE deliberately does NOT read this see {@link outcomeExitSignal}
64192
+ * and {@link NotComparedCause} for why it is scoped to refusals alone.
64163
64193
  */
64164
64194
  function notComparedOutcomes(report) {
64165
- return report.outcomes.filter((o) => (o.kind === "drifted" || o.kind === "clean") && o.referencesUnresolved);
64195
+ return report.outcomes.flatMap((o) => matchOutcome(o, {
64196
+ drifted: (d) => d.notComparedCause === void 0 ? [] : [d],
64197
+ notCompared: (n) => [n],
64198
+ clean: () => [],
64199
+ unsupported: () => [],
64200
+ skipped: () => []
64201
+ }));
64166
64202
  }
64167
64203
  /**
64168
- * Every outcome whose comparison cdkd DELIBERATELY REFUSED (issue #2108) the
64169
- * strict subset of {@link notComparedOutcomes} that drives the EXIT CODE.
64170
- *
64171
- * Deliberately NOT the same predicate, and the asymmetry is the point: the
64172
- * REPORT covers everything that was not compared, because as information both
64173
- * populations matter equally, while the exit code covers only the population
64174
- * this change created. Driving it off `referencesUnresolved` would exit
64175
- * non-zero forever for every stack holding an `{{resolve:ssm-secure:...}}`
64176
- * reference permanent, unclearable, and unrelated to this issue. See the
64177
- * `comparisonRefused` field note, and issue
64178
- * [#2135](https://github.com/go-to-k/cdkd/issues/2135) for the structural fix.
64179
- */
64180
- function refusedComparisonOutcomes(report) {
64181
- return report.outcomes.filter((o) => (o.kind === "drifted" || o.kind === "clean") && o.comparisonRefused);
64204
+ * What one outcome contributes to the run's EXIT CODE (issues #2108 / #2135).
64205
+ *
64206
+ * The exit-code CONSUMER, kept as an exhaustive `matchOutcome` so a new outcome
64207
+ * variant cannot inherit `none` by omission reporting a resource cdkd never
64208
+ * compared as a pass is precisely the round-2 defect #2135 exists to make
64209
+ * impossible.
64210
+ *
64211
+ * `refused` is a STRICT SUBSET of what {@link notComparedOutcomes} rolls up, and
64212
+ * the asymmetry is the point: the REPORT covers everything that was not
64213
+ * compared, because as information both causes matter equally, while the exit
64214
+ * code covers only the population #2108 created. Exiting non-zero on
64215
+ * `unresolvedToken` would break `cdkd drift` in CI forever for every stack
64216
+ * holding an `{{resolve:ssm-secure:...}}` reference — permanent, unclearable,
64217
+ * and unrelated. See {@link NotComparedCause}.
64218
+ *
64219
+ * A `drifted` outcome reports `drifted` even when its own comparison was
64220
+ * refused: drift is the stronger, actionable signal and the caller ranks it
64221
+ * first, so a consumer gating on `1` loses nothing it gets today.
64222
+ */
64223
+ function outcomeExitSignal(outcome) {
64224
+ return matchOutcome(outcome, {
64225
+ drifted: () => "drifted",
64226
+ notCompared: (n) => n.notComparedCause === "refused" ? "refused" : "none",
64227
+ clean: () => "none",
64228
+ unsupported: () => "none",
64229
+ skipped: () => "none"
64230
+ });
64182
64231
  }
64183
64232
  /**
64184
64233
  * `cdkd drift [<stack>...]` command implementation.
@@ -64248,8 +64297,9 @@ async function driftCommand(stacks, options) {
64248
64297
  }
64249
64298
  if (options.json) writeJsonReport(reports);
64250
64299
  else writeHumanReport(reports);
64251
- const drifted = reports.some((r) => r.outcomes.some((o) => o.kind === "drifted"));
64252
- const anyRefused = reports.some((r) => refusedComparisonOutcomes(r).length > 0);
64300
+ const signals = reports.flatMap((r) => r.outcomes.map(outcomeExitSignal));
64301
+ const drifted = signals.includes("drifted");
64302
+ const anyRefused = signals.includes("refused");
64253
64303
  if (!options.accept && !options.revert) {
64254
64304
  if (drifted) throw new DriftDetectedError();
64255
64305
  if (anyRefused) throw new DriftComparisonRefusedError();
@@ -64953,14 +65003,17 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
64953
65003
  unionWalkObjects: useObserved,
64954
65004
  unorderedPaths
64955
65005
  }), secrets, secretResolutionFailed ? seededSecretPaths : secretPaths);
64956
- const referencesUnresolved = secretResolutionFailed || unresolvedTokens.size > 0;
64957
- const comparisonRefused = secretResolutionFailed;
64958
- if (reported.changes.length === 0) outcomes.push({
64959
- kind: "clean",
65006
+ const notComparedCause = secretResolutionFailed ? "refused" : unresolvedTokens.size > 0 ? "unresolvedToken" : void 0;
65007
+ if (reported.changes.length === 0) if (notComparedCause !== void 0) outcomes.push({
65008
+ kind: "notCompared",
64960
65009
  logicalId,
64961
65010
  resourceType: resource.resourceType,
64962
- referencesUnresolved,
64963
- comparisonRefused
65011
+ notComparedCause
65012
+ });
65013
+ else outcomes.push({
65014
+ kind: "clean",
65015
+ logicalId,
65016
+ resourceType: resource.resourceType
64964
65017
  });
64965
65018
  else outcomes.push({
64966
65019
  kind: "drifted",
@@ -64969,8 +65022,7 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
64969
65022
  ...reported,
64970
65023
  awsProperties: aws,
64971
65024
  secrets,
64972
- referencesUnresolved,
64973
- comparisonRefused
65025
+ notComparedCause
64974
65026
  });
64975
65027
  }
64976
65028
  return {
@@ -65067,7 +65119,13 @@ async function runAccept(reports, stateBackend, stateConfig, awsClients, options
65067
65119
  const lockManager = new LockManager(awsClients.s3, stateConfig);
65068
65120
  const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
65069
65121
  for (const report of reports) {
65070
- const driftedOutcomes = report.outcomes.filter((o) => o.kind === "drifted");
65122
+ const driftedOutcomes = report.outcomes.flatMap((o) => matchOutcome(o, {
65123
+ drifted: (d) => [d],
65124
+ clean: () => [],
65125
+ notCompared: () => [],
65126
+ unsupported: () => [],
65127
+ skipped: () => []
65128
+ }));
65071
65129
  if (driftedOutcomes.length === 0) continue;
65072
65130
  await lockManager.acquireLock(report.stackName, report.region, owner, "drift-accept");
65073
65131
  try {
@@ -65685,7 +65743,13 @@ async function runRevert(reports, providerRegistry, stateBackend, stateConfig, a
65685
65743
  let totalSucceeded = 0;
65686
65744
  let totalUnresolvable = 0;
65687
65745
  for (const report of reports) {
65688
- const driftedOutcomes = report.outcomes.filter((o) => o.kind === "drifted");
65746
+ const driftedOutcomes = report.outcomes.flatMap((o) => matchOutcome(o, {
65747
+ drifted: (d) => [d],
65748
+ clean: () => [],
65749
+ notCompared: () => [],
65750
+ unsupported: () => [],
65751
+ skipped: () => []
65752
+ }));
65689
65753
  if (driftedOutcomes.length === 0) continue;
65690
65754
  await lockManager.acquireLock(report.stackName, report.region, owner, "drift-revert");
65691
65755
  const narrowedByLogicalId = /* @__PURE__ */ new Map();
@@ -65836,7 +65900,13 @@ async function runRevert(reports, providerRegistry, stateBackend, stateConfig, a
65836
65900
  */
65837
65901
  function printAcceptPlan(reports) {
65838
65902
  for (const report of reports) {
65839
- const drifted = report.outcomes.filter((o) => o.kind === "drifted");
65903
+ const drifted = report.outcomes.flatMap((o) => matchOutcome(o, {
65904
+ drifted: (d) => [d],
65905
+ clean: () => [],
65906
+ notCompared: () => [],
65907
+ unsupported: () => [],
65908
+ skipped: () => []
65909
+ }));
65840
65910
  if (drifted.length === 0) continue;
65841
65911
  process.stdout.write(`\nPlan (--accept): update cdkd state for ${report.stackName} (${report.region}):\n`);
65842
65912
  for (const o of drifted) {
@@ -65859,7 +65929,13 @@ function printAcceptPlan(reports) {
65859
65929
  */
65860
65930
  function printRevertPlan(reports) {
65861
65931
  for (const report of reports) {
65862
- const drifted = report.outcomes.filter((o) => o.kind === "drifted");
65932
+ const drifted = report.outcomes.flatMap((o) => matchOutcome(o, {
65933
+ drifted: (d) => [d],
65934
+ clean: () => [],
65935
+ notCompared: () => [],
65936
+ unsupported: () => [],
65937
+ skipped: () => []
65938
+ }));
65863
65939
  if (drifted.length === 0) continue;
65864
65940
  process.stdout.write(`\nPlan (--revert): push cdkd state values back into AWS for ${report.stackName} (${report.region}):\n`);
65865
65941
  for (const o of drifted) {
@@ -65869,7 +65945,7 @@ function printRevertPlan(reports) {
65869
65945
  const stateResource = report.state.resources[o.logicalId];
65870
65946
  if (stateResource) {
65871
65947
  const preserved = findRevertPreservedTagKeys(o.changes, stateResource.observedProperties ?? stateResource.properties ?? {}, o.awsProperties);
65872
- const cannotMaskKeys = o.referencesUnresolved;
65948
+ const cannotMaskKeys = o.notComparedCause !== void 0;
65873
65949
  if (cannotMaskKeys && preserved.length > 0) process.stdout.write(` ! ${preserved.length} AWS-authored tag(s) will be preserved, but cdkd could not resolve this resource's dynamic reference(s), so their names are withheld — they come from the live readback and cannot be checked for secrets without them.\n`);
65874
65950
  if (!cannotMaskKeys && preserved.length > 0) {
65875
65951
  const tagWord = preserved.length === 1 ? "tag" : "tags";
@@ -65881,7 +65957,7 @@ function printRevertPlan(reports) {
65881
65957
  }
65882
65958
  if (stateResource && stateResource.observedProperties === void 0) {
65883
65959
  const unbaselined = findRevertUnbaselinedAwsKeys(o.changes, stateResource.properties ?? {}, o.awsProperties);
65884
- if (o.referencesUnresolved && unbaselined.length > 0) process.stdout.write(` ! ${unbaselined.length} AWS-authored value(s) will be left untouched, but cdkd could not resolve this resource's dynamic reference(s), so their paths are withheld — they come from the live readback and cannot be checked for secrets without them.\n`);
65960
+ if (o.notComparedCause !== void 0 && unbaselined.length > 0) process.stdout.write(` ! ${unbaselined.length} AWS-authored value(s) will be left untouched, but cdkd could not resolve this resource's dynamic reference(s), so their paths are withheld — they come from the live readback and cannot be checked for secrets without them.\n`);
65885
65961
  else if (unbaselined.length > 0) {
65886
65962
  const word = unbaselined.length === 1 ? "value" : "values";
65887
65963
  process.stdout.write(` ! this resource has no observed-capture baseline, so the revert pushes the raw TEMPLATE and LEAVES ${unbaselined.length} AWS-authored ${word} untouched:\n`);
@@ -65923,28 +65999,44 @@ async function confirmPrompt$5(prompt) {
65923
65999
  }
65924
66000
  function writeJsonReport(reports) {
65925
66001
  const payload = reports.map((r) => {
65926
- const drifted = r.outcomes.filter((o) => o.kind === "drifted").map((o) => ({
65927
- logicalId: o.logicalId,
65928
- type: o.resourceType,
65929
- changes: o.changes,
65930
- referencesUnresolved: o.referencesUnresolved
65931
- }));
65932
- const clean = r.outcomes.filter((o) => o.kind === "clean").map((o) => ({
65933
- logicalId: o.logicalId,
65934
- type: o.resourceType,
65935
- referencesUnresolved: o.referencesUnresolved
65936
- }));
66002
+ const drifted = [];
66003
+ const clean = [];
66004
+ const notSupported = [];
66005
+ const skipped = [];
66006
+ for (const o of r.outcomes) matchOutcome(o, {
66007
+ drifted: (d) => {
66008
+ drifted.push({
66009
+ logicalId: d.logicalId,
66010
+ type: d.resourceType,
66011
+ changes: d.changes,
66012
+ referencesUnresolved: d.notComparedCause !== void 0
66013
+ });
66014
+ },
66015
+ clean: (c) => {
66016
+ clean.push({
66017
+ logicalId: c.logicalId,
66018
+ type: c.resourceType,
66019
+ referencesUnresolved: false
66020
+ });
66021
+ },
66022
+ notCompared: () => {},
66023
+ unsupported: (u) => {
66024
+ notSupported.push({
66025
+ logicalId: u.logicalId,
66026
+ type: u.resourceType
66027
+ });
66028
+ },
66029
+ skipped: (sk) => {
66030
+ skipped.push({
66031
+ logicalId: sk.logicalId,
66032
+ type: sk.resourceType
66033
+ });
66034
+ }
66035
+ });
65937
66036
  const notCompared = notComparedOutcomes(r).map((o) => ({
65938
66037
  logicalId: o.logicalId,
65939
- type: o.resourceType
65940
- }));
65941
- const notSupported = r.outcomes.filter((o) => o.kind === "unsupported").map((o) => ({
65942
- logicalId: o.logicalId,
65943
- type: o.resourceType
65944
- }));
65945
- const skipped = r.outcomes.filter((o) => o.kind === "skipped").map((o) => ({
65946
- logicalId: o.logicalId,
65947
- type: o.resourceType
66038
+ type: o.resourceType,
66039
+ referencesUnresolved: true
65948
66040
  }));
65949
66041
  return {
65950
66042
  stack: r.stackName,
@@ -65960,10 +66052,27 @@ function writeJsonReport(reports) {
65960
66052
  }
65961
66053
  function writeHumanReport(reports) {
65962
66054
  for (const report of reports) {
65963
- const drifted = report.outcomes.filter((o) => o.kind === "drifted");
65964
- const unsupported = report.outcomes.filter((o) => o.kind === "unsupported");
65965
- const skippedCount = report.outcomes.filter((o) => o.kind === "skipped").length;
65966
- const inspected = report.outcomes.length - skippedCount;
66055
+ const drifted = [];
66056
+ const unsupported = [];
66057
+ let inspectedCount = 0;
66058
+ for (const o of report.outcomes) matchOutcome(o, {
66059
+ drifted: (d) => {
66060
+ drifted.push(d);
66061
+ inspectedCount += 1;
66062
+ },
66063
+ unsupported: (u) => {
66064
+ unsupported.push(u);
66065
+ inspectedCount += 1;
66066
+ },
66067
+ skipped: () => {},
66068
+ clean: () => {
66069
+ inspectedCount += 1;
66070
+ },
66071
+ notCompared: () => {
66072
+ inspectedCount += 1;
66073
+ }
66074
+ });
66075
+ const inspected = inspectedCount;
65967
66076
  const notCompared = notComparedOutcomes(report);
65968
66077
  const checked = inspected - notCompared.length;
65969
66078
  if (drifted.length === 0) if (notCompared.length > 0) process.stdout.write(`⚠ ${report.stackName} (${report.region}): no drift detected, but ${checked} of ${inspected} resource${inspected === 1 ? "" : "s"} fully checked (${notCompared.length} only partially compared, ${unsupported.length} unsupported)\n`);
@@ -71646,8 +71755,8 @@ async function rollbackCommand(stackArg, options) {
71646
71755
  try {
71647
71756
  await setup.lockManager.acquireLockWithRetry(stackName, region, void 0, "rollback");
71648
71757
  } catch (error) {
71649
- unforwardSigterm();
71650
71758
  process.removeListener("SIGINT", sigintHandler);
71759
+ unforwardSigterm();
71651
71760
  throw error;
71652
71761
  }
71653
71762
  try {
@@ -71792,11 +71901,14 @@ async function rollbackCommand(stackArg, options) {
71792
71901
  if (totalWarnings > 0) throw new PartialFailureError(`Rollback completed with ${totalWarnings} skipped/unrecoverable operation(s) (see warnings above).`);
71793
71902
  logger.info(`\nRollback of '${stackName}' (${region}) complete.`);
71794
71903
  } finally {
71795
- unforwardSigterm();
71796
- process.removeListener("SIGINT", sigintHandler);
71797
- await setup.lockManager.releaseLock(stackName, region).catch((err) => {
71798
- logger.warn(`Failed to release lock for '${stackName}' (${region}): ${err instanceof Error ? err.message : String(err)}`);
71799
- });
71904
+ try {
71905
+ await setup.lockManager.releaseLock(stackName, region).catch((err) => {
71906
+ logger.warn(`Failed to release lock for '${stackName}' (${region}): ${err instanceof Error ? err.message : String(err)}`);
71907
+ });
71908
+ } finally {
71909
+ process.removeListener("SIGINT", sigintHandler);
71910
+ unforwardSigterm();
71911
+ }
71800
71912
  }
71801
71913
  } finally {
71802
71914
  if (stackAwsClients) {
@@ -84995,7 +85107,7 @@ function createMigrateCommand() {
84995
85107
  */
84996
85108
  function buildProgram() {
84997
85109
  const program = new Command();
84998
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.284.29");
85110
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.284.30");
84999
85111
  program.hook("preAction", (_thisCommand, actionCommand) => {
85000
85112
  const { profile } = actionCommand.optsWithGlobals();
85001
85113
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;