@go-to-k/cdkd 0.280.4 → 0.280.5

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 DiffCalculator, $t as resolveBucketRegion, A as red, At as getDockerImageBySourceHash, B as isTerminationProtectionPropagationError, Bt as resolveStateBucketWithDefaultAndSource, C as isStatefulRecreateTargetSync, Ct as validateContainerRepoName, D as cyan, Dt as runDockerForeground, E as bold, En as withErrorHandling, Et as getDockerCmd, F as ProviderRegistry, Ft as resolveApp, G as normalizeAwsTagsToCfn, Gt as CFN_TEMPLATE_URL_LIMIT, H as cfnRefValueFromPhysicalId, Ht as stateBucketExistenceConfirmed, I as findActionableSilentDrops, It as resolveAutoAssetStorage, J as readConfigString, Jt as uploadCfnTemplate, K as resolveExplicitPhysicalId, Kt as MIGRATE_TMP_PREFIX, L as CloudControlProvider, Lt as resolveCaptureObservedState, M as IAMRoleProvider, Mt as synthesisStatusMessage, N as collectInlinePolicyNamesManagedBySiblings, Nt as getDefaultStateBucketName, O as gray, Ot as runDockerStreaming, P as clearOnUpdateRemoval, Pt as getLegacyStateBucketName, Q as applyRoleArnIfSet, R as slowCcOperationTimeoutMs, Rt as resolveSkipPrefix, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as validateAssetBucketName, T as formatResourceLine, Tn as normalizeAwsError, Tt as formatDockerLoginError, U as refStateLookupFromResource, Ut as warnDeprecatedNoPrefixCliFlag, V as IntrinsicFunctionResolver, Vt as resolveUseCdkBootstrapAssets, W as WAFv2WebACLProvider, Wt as CFN_TEMPLATE_BODY_LIMIT, X as requireConfigArray, Xt as AssemblyReader, Y as replayWarn, Yt as expectedOwnerParam, Z as requireConfigString, Zt as processStackMessages, _ as createPreDeleteFinalSnapshot, _n as ResourceTimeoutError, _t as AssetModeResolver, a as DeploymentEventsStore, an as CdkdError, at as TemplateParser, b as unsupportedFinalSnapshotError, bn as StackTerminationProtectionError, bt as getBootstrapMarkerKey, c as replayFailedOperations, cn as DeployCancelledError, ct as rebuildClientForBucketRegion, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalStartServiceError, dt as stringifyValue, en as AwsClients, et as describeTypeWithThrottleRetry, f as computeImplicitDeleteEdges, ft as WorkGraph, g as ccRoutedFinalSnapshotError, gn as ProvisioningError, gt as rewriteTemplateAssetReferences, h as buildFinalSnapshotIdentifier, hn as PartialFailureError, ht as loadPublishableAssetManifest, i as DeploymentEventsReader, it as DagBuilder, j as yellow, jt as Synthesizer, k as green, kt as AssetManifestLoader, l as replayRollback, ln as LocalInvokeBuildError$1, lt as shouldRetainResource, m as PRE_DELETE_SNAPSHOT_TYPES, mn as NestedStackChildDirectDestroyError, mt as createAssetRedirectResolver, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resetAwsClients, nt as isRetryableTransientError, o as planFailedOps, ot as LockManager, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as MissingCdkCliError, pt as buildAssetRedirectMap, q as assertRegionMatch, qt as findLargeInlineResources, r as DeployEngine, rn as setAwsClients, rt as isThrottlingError, s as planRollback, st as S3StateBackend, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as getAwsClients, tt as withRetry, u as withResourceDeadline, un as LocalMigrateError, ut as AssetPublisher, v as isFinalSnapshotError, vn as ResourceUpdateNotSupportedError, vt as BOOTSTRAP_MARKER_PREFIX, w as renderStatefulReason, wt as buildDockerImage, x as extractDeploymentEventError, xt as parseBootstrapMarker, y as refusesFinalSnapshot, yn as StackHasActiveImportsError, yt as ensureAssetStorage, z as disableInstanceApiTermination, zt as resolveStateBucketWithDefault } from "./deploy-engine-CttwgBIB.js";
2
+ import { $ as DiffCalculator, $t as resolveBucketRegion, A as red, At as getDockerImageBySourceHash, B as isTerminationProtectionPropagationError, Bt as resolveStateBucketWithDefaultAndSource, C as isStatefulRecreateTargetSync, Ct as validateContainerRepoName, D as cyan, Dt as runDockerForeground, E as bold, En as withErrorHandling, Et as getDockerCmd, F as ProviderRegistry, Ft as resolveApp, G as normalizeAwsTagsToCfn, Gt as CFN_TEMPLATE_URL_LIMIT, H as cfnRefValueFromPhysicalId, Ht as stateBucketExistenceConfirmed, I as findActionableSilentDrops, It as resolveAutoAssetStorage, J as readConfigString, Jt as uploadCfnTemplate, K as resolveExplicitPhysicalId, Kt as MIGRATE_TMP_PREFIX, L as CloudControlProvider, Lt as resolveCaptureObservedState, M as IAMRoleProvider, Mt as synthesisStatusMessage, N as collectInlinePolicyNamesManagedBySiblings, Nt as getDefaultStateBucketName, O as gray, Ot as runDockerStreaming, P as clearOnUpdateRemoval, Pt as getLegacyStateBucketName, Q as applyRoleArnIfSet, R as slowCcOperationTimeoutMs, Rt as resolveSkipPrefix, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as validateAssetBucketName, T as formatResourceLine, Tn as normalizeAwsError, Tt as formatDockerLoginError, U as refStateLookupFromResource, Ut as warnDeprecatedNoPrefixCliFlag, V as IntrinsicFunctionResolver, Vt as resolveUseCdkBootstrapAssets, W as WAFv2WebACLProvider, Wt as CFN_TEMPLATE_BODY_LIMIT, X as requireConfigArray, Xt as AssemblyReader, Y as replayWarn, Yt as expectedOwnerParam, Z as requireConfigString, Zt as processStackMessages, _ as createPreDeleteFinalSnapshot, _n as ResourceTimeoutError, _t as AssetModeResolver, a as DeploymentEventsStore, an as CdkdError, at as TemplateParser, b as unsupportedFinalSnapshotError, bn as StackTerminationProtectionError, bt as getBootstrapMarkerKey, c as replayFailedOperations, cn as DeployCancelledError, ct as rebuildClientForBucketRegion, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalStartServiceError, dt as stringifyValue, en as AwsClients, et as describeTypeWithThrottleRetry, f as computeImplicitDeleteEdges, ft as WorkGraph, g as ccRoutedFinalSnapshotError, gn as ProvisioningError, gt as rewriteTemplateAssetReferences, h as buildFinalSnapshotIdentifier, hn as PartialFailureError, ht as loadPublishableAssetManifest, i as DeploymentEventsReader, it as DagBuilder, j as yellow, jt as Synthesizer, k as green, kt as AssetManifestLoader, l as replayRollback, ln as LocalInvokeBuildError$1, lt as shouldRetainResource, m as PRE_DELETE_SNAPSHOT_TYPES, mn as NestedStackChildDirectDestroyError, mt as createAssetRedirectResolver, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resetAwsClients, nt as isRetryableTransientError, o as planFailedOps, ot as LockManager, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as MissingCdkCliError, pt as buildAssetRedirectMap, q as assertRegionMatch, qt as findLargeInlineResources, r as DeployEngine, rn as setAwsClients, rt as isThrottlingError, s as planRollback, st as S3StateBackend, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as getAwsClients, tt as withRetry, u as withResourceDeadline, un as LocalMigrateError, ut as AssetPublisher, v as isFinalSnapshotError, vn as ResourceUpdateNotSupportedError, vt as BOOTSTRAP_MARKER_PREFIX, w as renderStatefulReason, wt as buildDockerImage, x as extractDeploymentEventError, xt as parseBootstrapMarker, y as refusesFinalSnapshot, yn as StackHasActiveImportsError, yt as ensureAssetStorage, z as disableInstanceApiTermination, zt as resolveStateBucketWithDefault } from "./deploy-engine-C5xOvZbg.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BYMEE-BS.js";
4
- import { t as ASGProvider } from "./asg-provider-Cyuov8l5.js";
4
+ import { t as ASGProvider } from "./asg-provider-DINOy61N.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";
@@ -12954,7 +12954,8 @@ var DynamoDBGlobalTableProvider = class {
12954
12954
  if (tableArn) await this.applyTagDiff(tableArn, extractLocalTags(previousProperties), extractLocalTags(properties));
12955
12955
  const recordedOldBilling = previousProperties["BillingMode"];
12956
12956
  const recordedOldBillingUsable = recordedOldBilling === void 0 || typeof recordedOldBilling === "string" && recordedOldBilling.trim() !== "";
12957
- const oldBilling = recordedOldBillingUsable ? recordedOldBilling ?? "PAY_PER_REQUEST" : describeResp.Table?.BillingModeSummary?.BillingMode ?? "PROVISIONED";
12957
+ const liveBillingMode = describeResp.Table?.BillingModeSummary?.BillingMode ?? "PROVISIONED";
12958
+ const oldBilling = recordedOldBillingUsable ? recordedOldBilling ?? "PAY_PER_REQUEST" : liveBillingMode;
12958
12959
  if (!recordedOldBillingUsable) this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: the recorded previous BillingMode is unusable (${JSON.stringify(recordedOldBilling)}) — using the table's actual billing mode (${oldBilling}) as the comparison baseline for this update so a corrected template does not issue a same-mode UpdateTable.`);
12959
12960
  let billingUnusable = false;
12960
12961
  const requestedBilling = requireConfigString(properties["BillingMode"], "PAY_PER_REQUEST", "AWS::DynamoDB::GlobalTable BillingMode", { onUnusable: (message) => {
@@ -12970,12 +12971,12 @@ var DynamoDBGlobalTableProvider = class {
12970
12971
  let desiredGsiUnusable = false;
12971
12972
  const onUnusableGsiBlock = (message) => {
12972
12973
  desiredGsiUnusable = true;
12973
- this.logger.warn(`${message} No GlobalSecondaryIndexes change is applied by this update; the table's existing indexes are left untouched.`);
12974
+ this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: ${message} No GlobalSecondaryIndexes change is applied by this update; the table's existing indexes are left untouched.`);
12974
12975
  };
12975
12976
  let previousGsiUnusable = false;
12976
12977
  const onUnusablePreviousGsiBlock = (message) => {
12977
12978
  previousGsiUnusable = true;
12978
- this.logger.warn(`${message} (recorded in cdkd state, not in the template) — using the table's LIVE indexes as the comparison baseline for this update, so a corrected template still applies.`);
12979
+ this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: ${message} (recorded in cdkd state, not in the template) — using the table's LIVE indexes as the comparison baseline for this update, so a corrected template still applies.`);
12979
12980
  };
12980
12981
  const liveIndexNames = new Set((describeResp.Table?.GlobalSecondaryIndexes ?? []).map((live) => live.IndexName).filter((name) => typeof name === "string"));
12981
12982
  const desiredSdkIndexes = toSdkGlobalSecondaryIndexes(properties, currentRegion, newBilling, "min", flippingToProvisioned ? void 0 : diagnostics, onUnusableGsiBlock);
@@ -13182,11 +13183,15 @@ var DynamoDBGlobalTableProvider = class {
13182
13183
  await this.waitForReplicaActive(physicalId, region, logicalId);
13183
13184
  }
13184
13185
  const previousTranslatedIndexes = toSdkGlobalSecondaryIndexes(previousProperties, currentRegion, oldBilling, "min", void 0, onUnusablePreviousGsiBlock);
13185
- const previousSdkIndexes = previousGsiUnusable ? desiredSdkIndexes.filter((gsi) => typeof gsi.IndexName === "string" && liveIndexNames.has(gsi.IndexName)) : previousTranslatedIndexes;
13186
+ const previousSdkIndexes = previousGsiUnusable ? buildLiveRecoveryGsiBaseline(desiredSdkIndexes, describeResp.Table?.GlobalSecondaryIndexes, {
13187
+ carryLiveValues: oldBilling === newBilling && liveBillingMode === newBilling,
13188
+ liveBillingMode,
13189
+ uncomparableCapacityIndexNames: collectUncomparableCapacityGsiNames(properties, currentRegion)
13190
+ }) : previousTranslatedIndexes;
13186
13191
  if (previousGsiUnusable) {
13187
13192
  const desiredNames = new Set(desiredSdkIndexes.map((gsi) => gsi.IndexName).filter((name) => typeof name === "string"));
13188
13193
  const liveOnly = [...liveIndexNames].filter((name) => !desiredNames.has(name));
13189
- if (liveOnly.length > 0) this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: ${liveOnly.join(", ")} exist(s) on the table but not in the template. No Delete is issued while the recorded GlobalSecondaryIndexes are unusable — a junk state record cannot prove cdkd created them. Re-deploy once state carries a valid block to remove them.`);
13194
+ if (liveOnly.length > 0) this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: ${liveOnly.join(", ")} exist(s) on the table but not in the template. No Delete is issued while the recorded GlobalSecondaryIndexes are unusable — a junk state record cannot prove cdkd created them, and an index delete is irreversible. This does NOT self-heal, and no later cdkd deploy will remove them: delete the index directly, e.g. aws dynamodb update-table --table-name ${physicalId} --global-secondary-index-updates '[{"Delete":{"IndexName":"<name>"}}]'.`);
13190
13195
  }
13191
13196
  const gsiDiff = desiredGsiUnusable ? {
13192
13197
  added: [],
@@ -14941,6 +14946,159 @@ function collectRawOnDemandDeclarations(properties, region) {
14941
14946
  return out;
14942
14947
  }
14943
14948
  /**
14949
+ * Names of the GSIs whose PROVISIONED capacity must NOT be compared against
14950
+ * the live table (issue #1571). Two disjoint reasons, and both are about the
14951
+ * DESIRED side being a number the template did not actually choose:
14952
+ *
14953
+ * - **auto-scaled** — the live number is owned by Application Auto Scaling
14954
+ * while the translation takes `MinCapacity` (see {@link CapacitySource}), so
14955
+ * a live 10 against a template min of 1 reads as a scale-down NOBODY ASKED
14956
+ * FOR. This was one of the three measured failure modes of the first
14957
+ * value-carrying baseline (#1551), and the only one that cannot be resolved
14958
+ * by reading the live side more carefully — both numbers are correct, they
14959
+ * answer different questions.
14960
+ * - **not template-determined** — no capacity resolves to a finite number, so
14961
+ * `toSdkGlobalSecondaryIndexes` substitutes `DEFAULT_CAPACITY_UNITS` (5/5,
14962
+ * the issue #1511 class). Comparing that invented default against the live
14963
+ * value turns it into a WRITE. Found by review, not by the first cut.
14964
+ *
14965
+ * Walks the same two sources as {@link toSdkGlobalSecondaryIndexes} and
14966
+ * {@link collectRawOnDemandDeclarations} — the LOCAL replica's index entry
14967
+ * first (the canonical CDK spelling), the GSI-level block as the
14968
+ * hand-authored fallback for read, the top-level GSI for write. A divergence
14969
+ * between the three is what would re-open the bug, so they are kept adjacent.
14970
+ *
14971
+ * The auto-scaling arm tests PRESENCE of the `*CapacityAutoScalingSettings`
14972
+ * key, not whether its members coerce: a block that is itself an unresolved
14973
+ * intrinsic still means "this index is autoscaled", and "might be" must read
14974
+ * as "is" — a false negative issues an unrequested scale-down.
14975
+ *
14976
+ * KNOWN BOUND: detection is TEMPLATE-side only. An index autoscaled OUT OF
14977
+ * BAND (no `*CapacityAutoScalingSettings` in the template) has a
14978
+ * template-determined capacity, so its live value IS compared and the recovery
14979
+ * deploy re-asserts the template's number — which is what a clean previous
14980
+ * side would also have done, so this matches ordinary cdkd semantics rather
14981
+ * than being a recovery-path defect.
14982
+ *
14983
+ * And the cost of a false positive is a PERMANENT divergence, not "one deploy
14984
+ * of lag": the deploy records the template value as state, so the next diff
14985
+ * sees previous == desired and never revisits it. That is the same self-heal
14986
+ * fallacy this PR corrects in the live-only warning; it is accepted here
14987
+ * because the alternative is writing a number the user never asked for.
14988
+ */
14989
+ function collectUncomparableCapacityGsiNames(properties, region) {
14990
+ const out = /* @__PURE__ */ new Set();
14991
+ const rawIndexes = properties["GlobalSecondaryIndexes"];
14992
+ if (!Array.isArray(rawIndexes)) return out;
14993
+ const replicas = properties["Replicas"];
14994
+ const localReplicaIndexes = asRecord$1(Array.isArray(replicas) ? replicas.find((r) => asRecord$1(r)?.["Region"] === region) : void 0)?.["GlobalSecondaryIndexes"];
14995
+ const localByName = /* @__PURE__ */ new Map();
14996
+ if (Array.isArray(localReplicaIndexes)) for (const entry of localReplicaIndexes) {
14997
+ const record = asRecord$1(entry);
14998
+ const name = record?.["IndexName"];
14999
+ if (record && typeof name === "string") localByName.set(name, record);
15000
+ }
15001
+ for (const entry of rawIndexes) {
15002
+ const gsi = asRecord$1(entry);
15003
+ const name = gsi?.["IndexName"];
15004
+ if (!gsi || typeof name !== "string") continue;
15005
+ const readBlocks = [localByName.get(name)?.["ReadProvisionedThroughputSettings"], gsi["ReadProvisionedThroughputSettings"]];
15006
+ const writeBlock = gsi["WriteProvisionedThroughputSettings"];
15007
+ if (readBlocks.some((block) => asRecord$1(block)?.["ReadCapacityAutoScalingSettings"] !== void 0 || isUnresolvedIntrinsicBlock(block)) || asRecord$1(writeBlock)?.["WriteCapacityAutoScalingSettings"] !== void 0 || isUnresolvedIntrinsicBlock(writeBlock)) {
15008
+ out.add(name);
15009
+ continue;
15010
+ }
15011
+ const explicitProvisioned = asRecord$1(gsi["ProvisionedThroughput"]);
15012
+ const derivedRead = toFiniteNumber(explicitProvisioned?.["ReadCapacityUnits"]) ?? deriveReadCapacityUnits(asRecord$1(readBlocks[0])) ?? deriveReadCapacityUnits(asRecord$1(readBlocks[1]));
15013
+ const derivedWrite = toFiniteNumber(explicitProvisioned?.["WriteCapacityUnits"]) ?? deriveWriteCapacityUnits(asRecord$1(writeBlock));
15014
+ if (derivedRead === void 0 || derivedWrite === void 0) out.add(name);
15015
+ }
15016
+ return out;
15017
+ }
15018
+ /**
15019
+ * Build the GSI diff baseline used when the cdkd STATE record's
15020
+ * `GlobalSecondaryIndexes` is present-but-unusable (issue #1571, closing the
15021
+ * residual #1551 / PR #1562 measured and deliberately left open).
15022
+ *
15023
+ * The entries are the DESIRED indexes filtered to the names that EXIST live —
15024
+ * the live table is the only side that can answer "does this index exist",
15025
+ * which is what stops the permanent index loss #1562 was about. What #1562
15026
+ * could not settle was the VALUES: it copied the desired entry verbatim, so
15027
+ * the diff could only ever produce ADDs and every capacity / ceiling edit
15028
+ * silently lagged one deploy.
15029
+ *
15030
+ * This carries live VALUES, but only the ones that are safe to compare, and
15031
+ * the exclusions are the three measured failure modes of the first attempt
15032
+ * (recorded at the `liveIndexNames` call site) rather than a guess:
15033
+ *
15034
+ * - **`ProvisionedThroughput` is gated on the LIVE billing mode.**
15035
+ * `DescribeTable` reports `{ReadCapacityUnits: 0, WriteCapacityUnits: 0}`
15036
+ * for every index of a PAY_PER_REQUEST table, so an ungated read produced a
15037
+ * "modified" on every index and re-sent `{0, 0}`, which AWS rejects.
15038
+ * - **An AUTOSCALED index keeps identity-only capacity.** The live number
15039
+ * belongs to Application Auto Scaling; the desired side is `MinCapacity`.
15040
+ * Comparing them reads as a scale-down the user never asked for.
15041
+ * - **`KeySchema` / `Projection` / `WarmThroughput` are always the desired
15042
+ * side.** All three are copied from `desired`, so they can never DIFFER —
15043
+ * deliberately. `KeySchema` and `Projection` are immutable on an existing
15044
+ * index (a difference produces only a "recreate the index" warning, and
15045
+ * AWS's `Projection.NonKeyAttributes` READBACK ORDER is not guaranteed, so
15046
+ * the comparison would be a coin flip); `WarmThroughput` reads back with a
15047
+ * `Status` member the translated shape does not carry, and DynamoDB warm
15048
+ * throughput is increase-only, so a manufactured difference is a real
15049
+ * AWS-side risk.
15050
+ *
15051
+ * `OnDemandThroughput` IS carried from live on an on-demand table, and that is
15052
+ * the second thing this fixes: the `modified` loop derives the `-1` ceiling
15053
+ * RESET (the #1160 absent-field-removal class) from the PREVIOUS side, so with
15054
+ * a desired-copy baseline a template that dropped `MaxReadRequestUnits` left
15055
+ * the old ceiling live in AWS forever while cdkd reported success.
15056
+ *
15057
+ * REMOVES are still not derivable here and are deliberately absent: an index
15058
+ * live but not in the template is in NEITHER side, so no `Delete` is issued.
15059
+ * A junk state record cannot distinguish "cdkd created this and the template
15060
+ * dropped it" from "somebody added it out of band", the delete is irreversible
15061
+ * and a re-create costs a full backfill. The caller names the live-only
15062
+ * indexes and points at the remedy.
15063
+ */
15064
+ function buildLiveRecoveryGsiBaseline(desiredSdkIndexes, liveIndexes, options) {
15065
+ const liveByName = /* @__PURE__ */ new Map();
15066
+ for (const live of liveIndexes ?? []) if (typeof live.IndexName === "string") liveByName.set(live.IndexName, live);
15067
+ const baseline = [];
15068
+ for (const desired of desiredSdkIndexes) {
15069
+ if (typeof desired.IndexName !== "string") continue;
15070
+ const live = liveByName.get(desired.IndexName);
15071
+ if (!live) continue;
15072
+ const entry = { ...desired };
15073
+ if (!options.carryLiveValues) {
15074
+ baseline.push(entry);
15075
+ continue;
15076
+ }
15077
+ if (options.liveBillingMode === "PROVISIONED") {
15078
+ if (options.uncomparableCapacityIndexNames.has(desired.IndexName)) {
15079
+ baseline.push(entry);
15080
+ continue;
15081
+ }
15082
+ const liveRead = toFiniteNumber(live.ProvisionedThroughput?.ReadCapacityUnits);
15083
+ const liveWrite = toFiniteNumber(live.ProvisionedThroughput?.WriteCapacityUnits);
15084
+ if (desired.ProvisionedThroughput && liveRead !== void 0 && liveWrite !== void 0) entry.ProvisionedThroughput = {
15085
+ ReadCapacityUnits: liveRead,
15086
+ WriteCapacityUnits: liveWrite
15087
+ };
15088
+ } else {
15089
+ const liveRead = toFiniteNumber(live.OnDemandThroughput?.MaxReadRequestUnits);
15090
+ const liveWrite = toFiniteNumber(live.OnDemandThroughput?.MaxWriteRequestUnits);
15091
+ if (liveRead === void 0 && liveWrite === void 0) delete entry.OnDemandThroughput;
15092
+ else entry.OnDemandThroughput = {
15093
+ ...liveRead !== void 0 && { MaxReadRequestUnits: liveRead },
15094
+ ...liveWrite !== void 0 && { MaxWriteRequestUnits: liveWrite }
15095
+ };
15096
+ }
15097
+ baseline.push(entry);
15098
+ }
15099
+ return baseline;
15100
+ }
15101
+ /**
14944
15102
  * Translate a CFn `Replicas[].GlobalSecondaryIndexes[]` blob (the
14945
15103
  * `ReplicaGlobalSecondaryIndexSpecification` shape) into the SDK's
14946
15104
  * `ReplicaGlobalSecondaryIndex[]` used by `CreateReplicationGroupMemberAction`
@@ -68549,7 +68707,7 @@ function createMigrateCommand() {
68549
68707
  */
68550
68708
  function buildProgram() {
68551
68709
  const program = new Command();
68552
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.4");
68710
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.5");
68553
68711
  program.hook("preAction", (_thisCommand, actionCommand) => {
68554
68712
  const { profile } = actionCommand.optsWithGlobals();
68555
68713
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;