@go-to-k/cdkd 0.281.0 → 0.281.2

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 requireConfigArray, $t as expectedOwnerParam, A as green, An as withErrorHandling, At as getDockerCmd, B as slowCcOperationTimeoutMs, Bt as resolveAutoAssetStorage, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackHasActiveImportsError, Ct as ensureAssetStorage, D as bold, Dt as validateContainerRepoName, E as formatResourceLine, Et as validateAssetBucketName, F as clearOnUpdateRemoval, Ft as Synthesizer, G as refStateLookupFromResource, Gt as resolveUseCdkBootstrapAssets, H as isTerminationProtectionPropagationError, Ht as resolveSkipPrefix, I as ProviderRegistry, It as synthesisStatusMessage, J as resolveExplicitPhysicalId, Jt as CFN_TEMPLATE_BODY_LIMIT, K as WAFv2WebACLProvider, Kt as stateBucketExistenceConfirmed, L as findActionableSilentDrops, Lt as getDefaultStateBucketName, M as yellow, Mt as runDockerStreaming, N as IAMRoleProvider, Nt as AssetManifestLoader, O as cyan, Ot as buildDockerImage, P as collectInlinePolicyNamesManagedBySiblings, Pt as getDockerImageBySourceHash, Q as replayWarn, Qt as uploadCfnTemplate, R as findSilentDropProperties, Rt as getLegacyStateBucketName, S as extractDeploymentEventError, Sn as ResourceUpdateNotSupportedError, St as BOOTSTRAP_MARKER_PREFIX, T as renderStatefulReason, Tt as parseBootstrapMarker, U as IntrinsicFunctionResolver, Ut as resolveStateBucketWithDefault, V as disableInstanceApiTermination, Vt as resolveCaptureObservedState, W as cfnRefValueFromPhysicalId, Wt as resolveStateBucketWithDefaultAndSource, X as configStringRefusal, Xt as MIGRATE_TMP_PREFIX, Y as assertRegionMatch, Yt as CFN_TEMPLATE_URL_LIMIT, Z as readConfigString, Zt as findLargeInlineResources, _ as createPreDeleteFinalSnapshot, _n as MissingCdkCliError, _t as buildAssetRedirectMap, a as DeploymentEventsStore, an as getAwsClients, at as withRetry, b as unsupportedFinalSnapshotError, bn as ProvisioningError, bt as rewriteTemplateAssetReferences, c as replayFailedOperations, ct as DagBuilder, d as IMPLICIT_DELETE_DEPENDENCIES, dt as S3StateBackend, en as AssemblyReader, et as requireConfigObject, f as computeImplicitDeleteEdges, fn as DeployCancelledError, ft as rebuildClientForBucketRegion, g as ccRoutedFinalSnapshotError, gt as WorkGraph, h as buildFinalSnapshotIdentifier, hn as LocalStartServiceError, ht as stringifyValue, i as DeploymentEventsReader, in as AwsClients, it as describeTypeWithThrottleRetry, j as red, jt as runDockerForeground, k as gray, kn as normalizeAwsError, kt as formatDockerLoginError, l as replayRollback, ln as CdkdError, lt as TemplateParser, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalMigrateError, mt as AssetPublisher, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as applyRoleArnIfSet, o as planFailedOps, on as resetAwsClients, ot as isRetryableTransientError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalInvokeBuildError$1, pt as shouldRetainResource, q as normalizeAwsTagsToCfn, qt as warnDeprecatedNoPrefixCliFlag, r as DeployEngine, rn as resolveBucketRegion, rt as DiffCalculator, s as planRollback, sn as setAwsClients, st as isThrottlingError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as processStackMessages, tt as requireConfigString, u as withResourceDeadline, ut as LockManager, v as isFinalSnapshotError, vn as NestedStackChildDirectDestroyError, vt as createAssetRedirectResolver, w as isStatefulRecreateTargetSync, wn as StackTerminationProtectionError, wt as getBootstrapMarkerKey, x as makeCanonicalizePropertiesFn, xn as ResourceTimeoutError, xt as AssetModeResolver, y as refusesFinalSnapshot, yn as PartialFailureError, yt as loadPublishableAssetManifest, z as CloudControlProvider, zt as resolveApp } from "./deploy-engine-Bebl98bx.js";
2
+ import { $ as requireConfigArray, $t as expectedOwnerParam, A as green, An as withErrorHandling, At as getDockerCmd, B as slowCcOperationTimeoutMs, Bt as resolveAutoAssetStorage, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackHasActiveImportsError, Ct as ensureAssetStorage, D as bold, Dt as validateContainerRepoName, E as formatResourceLine, Et as validateAssetBucketName, F as clearOnUpdateRemoval, Ft as Synthesizer, G as refStateLookupFromResource, Gt as resolveUseCdkBootstrapAssets, H as isTerminationProtectionPropagationError, Ht as resolveSkipPrefix, I as ProviderRegistry, It as synthesisStatusMessage, J as resolveExplicitPhysicalId, Jt as CFN_TEMPLATE_BODY_LIMIT, K as WAFv2WebACLProvider, Kt as stateBucketExistenceConfirmed, L as findActionableSilentDrops, Lt as getDefaultStateBucketName, M as yellow, Mt as runDockerStreaming, N as IAMRoleProvider, Nt as AssetManifestLoader, O as cyan, Ot as buildDockerImage, P as collectInlinePolicyNamesManagedBySiblings, Pt as getDockerImageBySourceHash, Q as replayWarn, Qt as uploadCfnTemplate, R as findSilentDropProperties, Rt as getLegacyStateBucketName, S as extractDeploymentEventError, Sn as ResourceUpdateNotSupportedError, St as BOOTSTRAP_MARKER_PREFIX, T as renderStatefulReason, Tt as parseBootstrapMarker, U as IntrinsicFunctionResolver, Ut as resolveStateBucketWithDefault, V as disableInstanceApiTermination, Vt as resolveCaptureObservedState, W as cfnRefValueFromPhysicalId, Wt as resolveStateBucketWithDefaultAndSource, X as configStringRefusal, Xt as MIGRATE_TMP_PREFIX, Y as assertRegionMatch, Yt as CFN_TEMPLATE_URL_LIMIT, Z as readConfigString, Zt as findLargeInlineResources, _ as createPreDeleteFinalSnapshot, _n as MissingCdkCliError, _t as buildAssetRedirectMap, a as DeploymentEventsStore, an as getAwsClients, at as withRetry, b as unsupportedFinalSnapshotError, bn as ProvisioningError, bt as rewriteTemplateAssetReferences, c as replayFailedOperations, ct as DagBuilder, d as IMPLICIT_DELETE_DEPENDENCIES, dt as S3StateBackend, en as AssemblyReader, et as requireConfigObject, f as computeImplicitDeleteEdges, fn as DeployCancelledError, ft as rebuildClientForBucketRegion, g as ccRoutedFinalSnapshotError, gt as WorkGraph, h as buildFinalSnapshotIdentifier, hn as LocalStartServiceError, ht as stringifyValue, i as DeploymentEventsReader, in as AwsClients, it as describeTypeWithThrottleRetry, j as red, jt as runDockerForeground, k as gray, kn as normalizeAwsError, kt as formatDockerLoginError, l as replayRollback, ln as CdkdError, lt as TemplateParser, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalMigrateError, mt as AssetPublisher, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as applyRoleArnIfSet, o as planFailedOps, on as resetAwsClients, ot as isRetryableTransientError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalInvokeBuildError$1, pt as shouldRetainResource, q as normalizeAwsTagsToCfn, qt as warnDeprecatedNoPrefixCliFlag, r as DeployEngine, rn as resolveBucketRegion, rt as DiffCalculator, s as planRollback, sn as setAwsClients, st as isThrottlingError, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as processStackMessages, tt as requireConfigString, u as withResourceDeadline, ut as LockManager, v as isFinalSnapshotError, vn as NestedStackChildDirectDestroyError, vt as createAssetRedirectResolver, w as isStatefulRecreateTargetSync, wn as StackTerminationProtectionError, wt as getBootstrapMarkerKey, x as makeCanonicalizePropertiesFn, xn as ResourceTimeoutError, xt as AssetModeResolver, y as refusesFinalSnapshot, yn as PartialFailureError, yt as loadPublishableAssetManifest, z as CloudControlProvider, zt as resolveApp } from "./deploy-engine-drWGPyTA.js";
3
3
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, 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-BSx4Vrth.js";
4
+ import { t as ASGProvider } from "./asg-provider-n21zWyH-.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";
@@ -54,7 +54,7 @@ import { AppSyncClient, CreateApiKeyCommand, CreateDataSourceCommand, CreateGrap
54
54
  import { parse, print } from "graphql";
55
55
  import { ConcurrentModificationException, CrawlerRunningException, CreateConnectionCommand, CreateCrawlerCommand, CreateDatabaseCommand, CreateJobCommand, CreateSecurityConfigurationCommand, CreateTableCommand as CreateTableCommand$1, CreateTriggerCommand, CreateWorkflowCommand, DeleteConnectionCommand, DeleteCrawlerCommand, DeleteDatabaseCommand, DeleteJobCommand, DeleteSecurityConfigurationCommand, DeleteTableCommand as DeleteTableCommand$1, DeleteTriggerCommand, DeleteWorkflowCommand, EntityNotFoundException, GetConnectionCommand, GetCrawlerCommand, GetDatabaseCommand, GetJobCommand, GetSecurityConfigurationCommand, GetTableCommand, GetTagsCommand, GetTriggerCommand, GetWorkflowCommand, GlueClient, StartCrawlerScheduleCommand, StartTriggerCommand, StopCrawlerCommand, StopCrawlerScheduleCommand, StopTriggerCommand, UpdateConnectionCommand, UpdateCrawlerCommand, UpdateDatabaseCommand, UpdateJobCommand, UpdateTableCommand as UpdateTableCommand$1, UpdateTriggerCommand, UpdateWorkflowCommand } from "@aws-sdk/client-glue";
56
56
  import { BudgetsClient, CreateBudgetCommand, CreateNotificationCommand, CreateSubscriberCommand, DeleteBudgetCommand, DeleteNotificationCommand, DeleteSubscriberCommand, DescribeBudgetCommand, DuplicateRecordException, NotFoundException as NotFoundException$5, TagResourceCommand as TagResourceCommand$17, UntagResourceCommand as UntagResourceCommand$17, UpdateBudgetCommand } from "@aws-sdk/client-budgets";
57
- import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, DescribeStreamSummaryCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListTagsForResourceCommand as ListTagsForResourceCommand$15, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$10, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$18, UntagResourceCommand as UntagResourceCommand$18, UpdateShardCountCommand, UpdateStreamModeCommand } from "@aws-sdk/client-kinesis";
57
+ import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, DescribeStreamSummaryCommand, DisableEnhancedMonitoringCommand, EnableEnhancedMonitoringCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListTagsForResourceCommand as ListTagsForResourceCommand$15, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$10, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$18, UntagResourceCommand as UntagResourceCommand$18, UpdateMaxRecordSizeCommand, UpdateShardCountCommand, UpdateStreamModeCommand } from "@aws-sdk/client-kinesis";
58
58
  import { CreateScheduleCommand, DeleteScheduleCommand, GetScheduleCommand, ResourceNotFoundException as ResourceNotFoundException$11, SchedulerClient, UpdateScheduleCommand } from "@aws-sdk/client-scheduler";
59
59
  import { AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, PutBackupPolicyCommand, PutFileSystemPolicyCommand, PutLifecycleConfigurationCommand, UpdateFileSystemCommand, UpdateFileSystemProtectionCommand } from "@aws-sdk/client-efs";
60
60
  import { CreateFileSystemCommand as CreateFileSystemCommand$1, CreateFileSystemFromBackupCommand, DeleteFileSystemCommand as DeleteFileSystemCommand$1, DescribeFileSystemsCommand as DescribeFileSystemsCommand$1, FSxClient, FileSystemNotFound as FileSystemNotFound$1, TagResourceCommand as TagResourceCommand$19, UntagResourceCommand as UntagResourceCommand$19, UpdateFileSystemCommand as UpdateFileSystemCommand$1 } from "@aws-sdk/client-fsx";
@@ -10727,6 +10727,7 @@ var LambdaUrlProvider = class {
10727
10727
  this.logger.debug(`Creating Lambda URL ${logicalId}`);
10728
10728
  const targetFunctionArn = properties["TargetFunctionArn"];
10729
10729
  if (!targetFunctionArn) throw new ProvisioningError(`TargetFunctionArn is required for Lambda URL ${logicalId}`, resourceType, logicalId);
10730
+ if (context?.replayingState === true && properties["AuthType"] === void 0) this.logger.warn(`Lambda URL ${logicalId} is being restored from a cdkd state record that carries no AuthType, so cdkd cannot vouch for the auth type the URL had. Creating it with the default (NONE), which makes the function URL PUBLIC. Verify the URL's auth type after the rollback completes and set 'authType' explicitly in your CDK code if it should be AWS_IAM.`);
10730
10731
  const authType = requireConfigString(properties["AuthType"], "NONE", "AWS::Lambda::Url AuthType", replayWarn(this.logger, context));
10731
10732
  try {
10732
10733
  const cors = properties["Cors"];
@@ -10776,6 +10777,12 @@ var LambdaUrlProvider = class {
10776
10777
  } });
10777
10778
  const previousAuthType = previousProperties["AuthType"];
10778
10779
  const authType = authTypeUnusable ? typeof previousAuthType === "string" && previousAuthType.trim() !== "" ? previousAuthType : void 0 : requestedAuthType;
10780
+ let effectiveProperties;
10781
+ if (authTypeUnusable) {
10782
+ effectiveProperties = { ...properties };
10783
+ if (authType === void 0) delete effectiveProperties["AuthType"];
10784
+ else effectiveProperties["AuthType"] = authType;
10785
+ }
10779
10786
  const updateParams = {
10780
10787
  FunctionName: physicalId,
10781
10788
  ...authType !== void 0 && { AuthType: authType }
@@ -10796,7 +10803,8 @@ var LambdaUrlProvider = class {
10796
10803
  attributes: {
10797
10804
  FunctionUrl: response.FunctionUrl,
10798
10805
  FunctionArn: response.FunctionArn
10799
- }
10806
+ },
10807
+ ...effectiveProperties && { effectiveProperties }
10800
10808
  };
10801
10809
  } catch (error) {
10802
10810
  const cause = error instanceof Error ? error : void 0;
@@ -13621,12 +13629,18 @@ var DynamoDBGlobalTableProvider = class {
13621
13629
  };
13622
13630
  const diagnostics = [];
13623
13631
  if (billingMode === "PROVISIONED") createParams.ProvisionedThroughput = derivePerCallProvisionedThroughput(properties, currentRegion, "min", diagnostics);
13632
+ let effectiveProperties;
13624
13633
  const streamSpecInput = properties["StreamSpecification"];
13625
13634
  const needsStream = replicas.some((r) => r["Region"] !== currentRegion) || replicas.length > 1;
13626
13635
  if (streamSpecInput != null) {
13627
13636
  let streamViewType;
13637
+ let streamSpecSubstituted = false;
13628
13638
  try {
13629
- streamViewType = readConfigString(streamSpecInput, "StreamViewType", "NEW_AND_OLD_IMAGES", "AWS::DynamoDB::GlobalTable StreamSpecification", replayWarn(this.logger, context));
13639
+ const replayDowngrade = replayWarn(this.logger, context).onUnusable;
13640
+ streamViewType = readConfigString(streamSpecInput, "StreamViewType", "NEW_AND_OLD_IMAGES", "AWS::DynamoDB::GlobalTable StreamSpecification", replayDowngrade ? { onUnusable: (message) => {
13641
+ streamSpecSubstituted = true;
13642
+ replayDowngrade(message);
13643
+ } } : {});
13630
13644
  } catch (error) {
13631
13645
  throw new ProvisioningError(error instanceof Error ? error.message : String(error), resourceType, logicalId, void 0, error instanceof Error ? error : void 0);
13632
13646
  }
@@ -13634,6 +13648,10 @@ var DynamoDBGlobalTableProvider = class {
13634
13648
  StreamEnabled: true,
13635
13649
  StreamViewType: streamViewType
13636
13650
  };
13651
+ if (streamSpecSubstituted) effectiveProperties = {
13652
+ ...properties,
13653
+ StreamSpecification: { StreamViewType: streamViewType }
13654
+ };
13637
13655
  } else if (needsStream) {
13638
13656
  this.logger.info(`Auto-enabling streams (NEW_AND_OLD_IMAGES) on ${logicalId} — required for cross-region replication`);
13639
13657
  createParams.StreamSpecification = {
@@ -13720,7 +13738,8 @@ var DynamoDBGlobalTableProvider = class {
13720
13738
  TableId: tableInfo.tableId,
13721
13739
  StreamArn: tableInfo.streamArn,
13722
13740
  TableName: tableName
13723
- }
13741
+ },
13742
+ ...effectiveProperties && { effectiveProperties }
13724
13743
  };
13725
13744
  } catch (wiringError) {
13726
13745
  this.logger.warn(`Wiring failed after CreateTable for ${tableName}; attempting best-effort cleanup`);
@@ -13844,6 +13863,7 @@ var DynamoDBGlobalTableProvider = class {
13844
13863
  const removedButStillReferenced = oldAttrs.filter((o) => !newAttrs.some((n) => n.AttributeName === o.AttributeName)).filter((a) => a.AttributeName !== void 0 && desiredKeyAttrNames.has(a.AttributeName));
13845
13864
  if (removedButStillReferenced.length > 0) throw new ProvisioningError(`AttributeDefinitions removals are immutable on AWS::DynamoDB::GlobalTable while a key schema still references them (offenders: ${removedButStillReferenced.map((a) => a.AttributeName).join(", ")}); replacement required`, resourceType, logicalId, physicalId);
13846
13865
  const currentRegion = await this.dynamoDBClient.config.region() ?? "";
13866
+ let effectiveProperties;
13847
13867
  try {
13848
13868
  await this.waitForTableActiveAfterUpdate(physicalId, logicalId);
13849
13869
  const describeResp = await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }));
@@ -13914,7 +13934,7 @@ var DynamoDBGlobalTableProvider = class {
13914
13934
  let streamSpecUnusable = false;
13915
13935
  const streamViewType = readConfigString(properties["StreamSpecification"], "StreamViewType", "NEW_AND_OLD_IMAGES", "AWS::DynamoDB::GlobalTable StreamSpecification", { onUnusable: (message) => {
13916
13936
  streamSpecUnusable = true;
13917
- this.logger.warn(`${message} The table's existing stream configuration is left untouched for this update rather than re-pointed at the default.`);
13937
+ this.logger.warn(`AWS::DynamoDB::GlobalTable ${logicalId}: ${message} The table's existing stream configuration is left untouched for this update rather than re-pointed at the default.`);
13918
13938
  } });
13919
13939
  if (!streamSpecUnusable) {
13920
13940
  flatUpdate.StreamSpecification = {
@@ -13922,6 +13942,12 @@ var DynamoDBGlobalTableProvider = class {
13922
13942
  StreamViewType: streamViewType
13923
13943
  };
13924
13944
  flatChanged = true;
13945
+ } else {
13946
+ const previousStreamSpec = previousProperties["StreamSpecification"];
13947
+ const previousStreamSpecUsable = previousStreamSpec !== void 0 && previousStreamSpec !== null && configStringRefusal(previousStreamSpec, "StreamViewType", "NEW_AND_OLD_IMAGES", "AWS::DynamoDB::GlobalTable StreamSpecification") === void 0;
13948
+ effectiveProperties = { ...properties };
13949
+ if (previousStreamSpecUsable) effectiveProperties["StreamSpecification"] = { ...previousStreamSpec };
13950
+ else delete effectiveProperties["StreamSpecification"];
13925
13951
  }
13926
13952
  }
13927
13953
  const awsOnDemand = describeResp.Table?.OnDemandThroughput;
@@ -14202,7 +14228,8 @@ var DynamoDBGlobalTableProvider = class {
14202
14228
  TableId: finalDescribe.Table?.TableId,
14203
14229
  StreamArn: finalDescribe.Table?.LatestStreamArn,
14204
14230
  TableName: physicalId
14205
- }
14231
+ },
14232
+ ...effectiveProperties && { effectiveProperties }
14206
14233
  };
14207
14234
  } catch (error) {
14208
14235
  if (error instanceof ProvisioningError) throw error;
@@ -41074,6 +41101,134 @@ function isKmsEncryption(value) {
41074
41101
  return value["EncryptionType"] === "KMS";
41075
41102
  }
41076
41103
  /**
41104
+ * The seven shard-level metrics `ALL` expands to.
41105
+ *
41106
+ * MEASURED, not copied from the docs (us-east-1, 2026-08-12): an
41107
+ * `EnableEnhancedMonitoring(ShardLevelMetrics: ['ALL'])` responds with exactly
41108
+ * these seven in `DesiredShardLevelMetrics`, and once the stream settles back
41109
+ * to ACTIVE `DescribeStream` reports the same seven — never the literal `ALL`.
41110
+ * The readback order is AWS-chosen and matched neither the input order nor
41111
+ * alphabetical, which is why the type also declares the path unordered (see
41112
+ * {@link KinesisStreamProvider.getDriftUnorderedPaths}).
41113
+ */
41114
+ const ALL_SHARD_LEVEL_METRICS = [
41115
+ "IncomingBytes",
41116
+ "IncomingRecords",
41117
+ "OutgoingBytes",
41118
+ "OutgoingRecords",
41119
+ "WriteProvisionedThroughputExceeded",
41120
+ "ReadProvisionedThroughputExceeded",
41121
+ "IteratorAgeMilliseconds"
41122
+ ];
41123
+ /**
41124
+ * Whether a value is a usable shard-level-metrics list: an array whose every
41125
+ * element is a string.
41126
+ *
41127
+ * A MIXED array (`['IncomingBytes', {Ref: 'X'}]`) is deliberately UNUSABLE
41128
+ * rather than partially usable. Filtering the unresolved element away would put
41129
+ * a list on the wire that the template never declared, while state recorded the
41130
+ * declared one — the permanent phantom drift `effectiveProperties` exists to
41131
+ * prevent, arrived at through the back door.
41132
+ */
41133
+ function isUsableMetricsList(value) {
41134
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
41135
+ }
41136
+ /**
41137
+ * Expand the `ALL` shard-level-metrics shorthand into the seven metric names
41138
+ * AWS actually stores.
41139
+ *
41140
+ * This is the ONE definition of the rule, shared by the provisioning path (what
41141
+ * goes on the wire, and therefore what `effectiveProperties` records) and by
41142
+ * {@link KinesisStreamProvider.canonicalizeDesiredProperties} (what the diff
41143
+ * compares). Deriving it twice is how state and template end up narrowed
41144
+ * differently — see the `effectiveProperties` contract in
41145
+ * `.claude/rules/providers.md`.
41146
+ *
41147
+ * Idempotent: an already-expanded list is returned with its own values (deduped
41148
+ * and otherwise untouched), so a state-borne bag that has been through this
41149
+ * before is unchanged. An UNUSABLE value is returned as-is — the callers that
41150
+ * put bytes on the wire refuse it via {@link readShardLevelMetrics} rather than
41151
+ * sending a partial list, and `canonicalizeDesiredProperties` must stay a total
41152
+ * function because the diff runs on bags no provider validated.
41153
+ */
41154
+ function expandShardLevelMetrics(value) {
41155
+ if (!isUsableMetricsList(value)) return value;
41156
+ const names = value;
41157
+ const expanded = names.includes("ALL") ? [...names.filter((n) => n !== "ALL"), ...ALL_SHARD_LEVEL_METRICS] : names;
41158
+ const seen = /* @__PURE__ */ new Set();
41159
+ const deduped = [];
41160
+ for (const name of expanded) {
41161
+ if (seen.has(name)) continue;
41162
+ seen.add(name);
41163
+ deduped.push(name);
41164
+ }
41165
+ if (deduped.length === names.length && deduped.every((n, i) => n === names[i])) return value;
41166
+ return deduped;
41167
+ }
41168
+ /**
41169
+ * Classify a declared `DesiredShardLevelMetrics` value, expanding `ALL` when it
41170
+ * is usable.
41171
+ *
41172
+ * Callers own the ACTION per the update-path rules in
41173
+ * `.claude/rules/providers.md`: a create refuses an unusable value (it is
41174
+ * template-borne), an update WARNS and skips (it may be replaying a state
41175
+ * record, where refusing would leave the resource un-rollbackable). The
41176
+ * previous side is never routed through the refusal at all — see
41177
+ * {@link previousMetricNames}.
41178
+ */
41179
+ function readShardLevelMetrics(value) {
41180
+ if (value == null) return { kind: "absent" };
41181
+ if (!isUsableMetricsList(value)) return {
41182
+ kind: "unusable",
41183
+ reason: `AWS::Kinesis::Stream DesiredShardLevelMetrics must be an array of metric-name strings, got ${JSON.stringify(value)}`
41184
+ };
41185
+ const expanded = expandShardLevelMetrics(value);
41186
+ return {
41187
+ kind: "usable",
41188
+ metrics: expanded,
41189
+ expanded
41190
+ };
41191
+ }
41192
+ /**
41193
+ * Read the PREVIOUS side leniently: it comes from cdkd state, not the user's
41194
+ * template, so an unreadable value recorded by an older binary must never
41195
+ * refuse the update (the #1471 desired-side-only rule). An unusable previous
41196
+ * side simply contributes no metrics to disable.
41197
+ */
41198
+ function previousMetricNames(value) {
41199
+ const expanded = expandShardLevelMetrics(value);
41200
+ return isUsableMetricsList(expanded) ? expanded : [];
41201
+ }
41202
+ function readMaxRecordSize(value) {
41203
+ if (value == null) return { kind: "absent" };
41204
+ if (typeof value === "number" && Number.isFinite(value)) return {
41205
+ kind: "usable",
41206
+ size: value
41207
+ };
41208
+ if (typeof value === "string" && value.trim() !== "") {
41209
+ const n = Number(value);
41210
+ if (Number.isFinite(n)) return {
41211
+ kind: "usable",
41212
+ size: n
41213
+ };
41214
+ }
41215
+ return {
41216
+ kind: "unusable",
41217
+ reason: `AWS::Kinesis::Stream MaxRecordSizeInKiB must be a number, got ${JSON.stringify(value)}`
41218
+ };
41219
+ }
41220
+ /**
41221
+ * The comparison-side read: the UPDATE path needs both sides reduced to the
41222
+ * same shape so a state record holding the number and a template holding the
41223
+ * numeric string do not read as a change and re-issue the call every deploy.
41224
+ * Unusable / absent both yield `undefined`, which the caller treats as "no
41225
+ * declared size" rather than refusing — the previous side is state-borne.
41226
+ */
41227
+ function comparableRecordSize(value) {
41228
+ const read = readMaxRecordSize(value);
41229
+ return read.kind === "usable" ? read.size : void 0;
41230
+ }
41231
+ /**
41077
41232
  * AWS Kinesis Stream Provider
41078
41233
  *
41079
41234
  * Implements resource provisioning for AWS::Kinesis::Stream using the Kinesis SDK.
@@ -41091,7 +41246,9 @@ var KinesisStreamProvider = class {
41091
41246
  "ShardCount",
41092
41247
  "Tags",
41093
41248
  "RetentionPeriodHours",
41094
- "StreamEncryption"
41249
+ "StreamEncryption",
41250
+ "DesiredShardLevelMetrics",
41251
+ "MaxRecordSizeInKiB"
41095
41252
  ])]]);
41096
41253
  getClient() {
41097
41254
  if (!this.client) this.client = new KinesisClient(this.providerRegion ? { region: this.providerRegion } : {});
@@ -41100,17 +41257,25 @@ var KinesisStreamProvider = class {
41100
41257
  /**
41101
41258
  * Create a Kinesis stream
41102
41259
  */
41103
- async create(logicalId, resourceType, properties) {
41260
+ async create(logicalId, resourceType, properties, context) {
41104
41261
  this.logger.debug(`Creating Kinesis stream ${logicalId}`);
41105
41262
  const streamName = properties["Name"] || generateResourceName(logicalId, { maxLength: 128 });
41263
+ const desiredRead = readShardLevelMetrics(properties["DesiredShardLevelMetrics"]);
41264
+ if (desiredRead.kind === "unusable") if (context?.replayingState === true) this.logger.warn(`${desiredRead.reason}. Replaying a state record, so the shard-level metrics are left unset on ${streamName} rather than refusing the restore`);
41265
+ else throw new ProvisioningError(desiredRead.reason, resourceType, logicalId, streamName);
41266
+ const maxRecordRead = readMaxRecordSize(properties["MaxRecordSizeInKiB"]);
41267
+ if (maxRecordRead.kind === "unusable") if (context?.replayingState === true) this.logger.warn(`${maxRecordRead.reason}. Replaying a state record, so ${streamName} is created with AWS's default maximum record size rather than refusing the restore`);
41268
+ else throw new ProvisioningError(maxRecordRead.reason, resourceType, logicalId, streamName);
41106
41269
  try {
41107
41270
  const streamModeDetails = properties["StreamModeDetails"];
41108
41271
  const streamMode = readConfigString(streamModeDetails, "StreamMode", "PROVISIONED", "AWS::Kinesis::Stream StreamModeDetails");
41109
41272
  const shardCount = streamMode === "PROVISIONED" ? Number(properties["ShardCount"] ?? 1) : void 0;
41273
+ const maxRecordSizeInKiB = maxRecordRead.kind === "usable" ? maxRecordRead.size : void 0;
41110
41274
  await this.getClient().send(new CreateStreamCommand({
41111
41275
  StreamName: streamName,
41112
41276
  ...shardCount !== void 0 && { ShardCount: shardCount },
41113
- StreamModeDetails: { StreamMode: streamMode }
41277
+ StreamModeDetails: { StreamMode: streamMode },
41278
+ ...maxRecordSizeInKiB !== void 0 && { MaxRecordSizeInKiB: maxRecordSizeInKiB }
41114
41279
  }));
41115
41280
  this.logger.debug(`CreateStream initiated for ${streamName}, waiting for ACTIVE status`);
41116
41281
  const streamInfo = await this.waitForStreamActive(streamName);
@@ -41147,10 +41312,21 @@ var KinesisStreamProvider = class {
41147
41312
  }));
41148
41313
  await this.waitForStreamActive(streamName);
41149
41314
  }
41315
+ const desiredMetrics = desiredRead.kind === "usable" ? desiredRead.expanded : void 0;
41316
+ const metricsToEnable = desiredRead.kind === "usable" ? desiredRead.metrics : [];
41317
+ if (metricsToEnable.length > 0) {
41318
+ this.logger.debug(`Enabling ${metricsToEnable.length} shard-level metric(s) on ${streamName}`);
41319
+ await this.getClient().send(new EnableEnhancedMonitoringCommand({
41320
+ StreamName: streamName,
41321
+ ShardLevelMetrics: metricsToEnable
41322
+ }));
41323
+ await this.waitForStreamActive(streamName);
41324
+ }
41150
41325
  this.logger.debug(`Successfully created Kinesis stream ${logicalId}: ${streamName}`);
41151
41326
  return {
41152
41327
  physicalId: streamName,
41153
- attributes: { Arn: streamInfo.streamArn }
41328
+ attributes: { Arn: streamInfo.streamArn },
41329
+ ...this.effectiveMetricsProperties(properties, desiredMetrics)
41154
41330
  };
41155
41331
  } catch (error) {
41156
41332
  if (error instanceof ProvisioningError) throw error;
@@ -41236,10 +41412,49 @@ var KinesisStreamProvider = class {
41236
41412
  await this.waitForStreamActive(physicalId);
41237
41413
  }
41238
41414
  }
41415
+ const desiredSizeRead = readMaxRecordSize(properties["MaxRecordSizeInKiB"]);
41416
+ if (desiredSizeRead.kind === "unusable") this.logger.warn(`${desiredSizeRead.reason}. Leaving the maximum record size on ${physicalId} unchanged; the same value is REFUSED on a template-path create`);
41417
+ const newMaxRecordSize = comparableRecordSize(properties["MaxRecordSizeInKiB"]);
41418
+ const oldMaxRecordSize = comparableRecordSize(previousProperties["MaxRecordSizeInKiB"]);
41419
+ if (newMaxRecordSize !== void 0 && newMaxRecordSize !== oldMaxRecordSize) {
41420
+ this.logger.debug(`Updating max record size for ${physicalId}: ${oldMaxRecordSize} -> ${newMaxRecordSize}`);
41421
+ await this.getClient().send(new UpdateMaxRecordSizeCommand({
41422
+ StreamARN: await this.resolveStreamArn(physicalId),
41423
+ MaxRecordSizeInKiB: newMaxRecordSize
41424
+ }));
41425
+ await this.waitForStreamActive(physicalId);
41426
+ }
41427
+ const desiredRead = readShardLevelMetrics(properties["DesiredShardLevelMetrics"]);
41428
+ let desiredMetrics;
41429
+ if (desiredRead.kind === "unusable") this.logger.warn(`${desiredRead.reason}. Leaving the shard-level metrics on ${physicalId} unchanged rather than disabling the live ones; the same value is REFUSED on a template-path create`);
41430
+ else {
41431
+ desiredMetrics = desiredRead.kind === "usable" ? desiredRead.expanded : void 0;
41432
+ const desiredSet = desiredRead.kind === "usable" ? desiredRead.metrics : [];
41433
+ const previousSet = previousMetricNames(previousProperties["DesiredShardLevelMetrics"]);
41434
+ const toDisable = previousSet.filter((m) => !desiredSet.includes(m));
41435
+ const toEnable = desiredSet.filter((m) => !previousSet.includes(m));
41436
+ if (toDisable.length > 0) {
41437
+ this.logger.debug(`Disabling ${toDisable.length} shard-level metric(s) on ${physicalId}`);
41438
+ await this.getClient().send(new DisableEnhancedMonitoringCommand({
41439
+ StreamName: physicalId,
41440
+ ShardLevelMetrics: toDisable
41441
+ }));
41442
+ await this.waitForStreamActive(physicalId);
41443
+ }
41444
+ if (toEnable.length > 0) {
41445
+ this.logger.debug(`Enabling ${toEnable.length} shard-level metric(s) on ${physicalId}`);
41446
+ await this.getClient().send(new EnableEnhancedMonitoringCommand({
41447
+ StreamName: physicalId,
41448
+ ShardLevelMetrics: toEnable
41449
+ }));
41450
+ await this.waitForStreamActive(physicalId);
41451
+ }
41452
+ }
41239
41453
  return {
41240
41454
  physicalId,
41241
41455
  wasReplaced: false,
41242
- attributes: { Arn: (await this.getClient().send(new DescribeStreamCommand({ StreamName: physicalId }))).StreamDescription?.StreamARN }
41456
+ attributes: { Arn: (await this.getClient().send(new DescribeStreamCommand({ StreamName: physicalId }))).StreamDescription?.StreamARN },
41457
+ ...this.effectiveMetricsProperties(properties, desiredMetrics)
41243
41458
  };
41244
41459
  } catch (error) {
41245
41460
  const cause = error instanceof Error ? error : void 0;
@@ -41268,6 +41483,52 @@ var KinesisStreamProvider = class {
41268
41483
  }
41269
41484
  }
41270
41485
  /**
41486
+ * The `effectiveProperties` half of the `ALL` expansion (issue #609).
41487
+ *
41488
+ * Returns a spreadable `{ effectiveProperties }` ONLY when the expansion
41489
+ * actually rewrote the declared value; otherwise `{}`, so the engine records
41490
+ * the desired bag verbatim (the `??` gate on the engine side treats an absent
41491
+ * field as "record the desired properties"). The returned bag is a COMPLETE
41492
+ * replacement, not a patch, per the `EffectivePropertiesResult` contract.
41493
+ */
41494
+ effectiveMetricsProperties(properties, expanded) {
41495
+ if (expanded === void 0) return {};
41496
+ if (expanded === properties["DesiredShardLevelMetrics"]) return {};
41497
+ return { effectiveProperties: {
41498
+ ...properties,
41499
+ DesiredShardLevelMetrics: expanded
41500
+ } };
41501
+ }
41502
+ /**
41503
+ * Narrow the desired bag the same way the provisioning path does, so the
41504
+ * diff compares the EXPANDED metric list on both sides.
41505
+ *
41506
+ * Required paired half of the `effectiveProperties` above: without it, state
41507
+ * holds the seven expanded names while the template still says `ALL`, and
41508
+ * every later `cdkd deploy` / `cdkd diff` reads that as a user-made change.
41509
+ * Shares {@link expandShardLevelMetrics} rather than re-deriving the rule.
41510
+ */
41511
+ canonicalizeDesiredProperties(resourceType, properties) {
41512
+ if (resourceType !== "AWS::Kinesis::Stream") return properties;
41513
+ if (!("DesiredShardLevelMetrics" in properties)) return properties;
41514
+ const expanded = expandShardLevelMetrics(properties["DesiredShardLevelMetrics"]);
41515
+ if (expanded === properties["DesiredShardLevelMetrics"]) return properties;
41516
+ return {
41517
+ ...properties,
41518
+ DesiredShardLevelMetrics: expanded
41519
+ };
41520
+ }
41521
+ /**
41522
+ * `DesiredShardLevelMetrics` is a SET: AWS returns it in an order that
41523
+ * matched neither the request order nor alphabetical when measured
41524
+ * (us-east-1, 2026-08-12), so comparing positionally would report drift on a
41525
+ * stream nobody touched.
41526
+ */
41527
+ getDriftUnorderedPaths(resourceType) {
41528
+ if (resourceType !== "AWS::Kinesis::Stream") return [];
41529
+ return ["DesiredShardLevelMetrics"];
41530
+ }
41531
+ /**
41271
41532
  * Apply a diff between old and new CFn-shape Tags arrays via Kinesis's
41272
41533
  * `AddTagsToStream` (map shape) / `RemoveTagsFromStream` (TagKeys list)
41273
41534
  * APIs.
@@ -41311,8 +41572,10 @@ var KinesisStreamProvider = class {
41311
41572
  *
41312
41573
  * Issues `DescribeStream` and surfaces the keys cdkd's `create()`
41313
41574
  * accepts: `Name`, `StreamModeDetails`, `ShardCount`, `RetentionPeriodHours`,
41314
- * and `StreamEncryption`. Tags are surfaced via a follow-up
41315
- * `ListTagsForStream` with `aws:*` filtered out.
41575
+ * `StreamEncryption`, and `DesiredShardLevelMetrics`. Tags are surfaced via a
41576
+ * follow-up `ListTagsForStream` with `aws:*` filtered out, and
41577
+ * `MaxRecordSizeInKiB` via a follow-up `DescribeStreamSummary` (the field is
41578
+ * absent from `DescribeStream`'s `StreamDescription` shape).
41316
41579
  *
41317
41580
  * `ShardCount` is reported as the count of `Shards[]` in the stream
41318
41581
  * description (only present for PROVISIONED-mode streams; ON_DEMAND
@@ -41348,6 +41611,14 @@ var KinesisStreamProvider = class {
41348
41611
  if (stream.KeyId !== void 0) encryption["KeyId"] = stream.KeyId;
41349
41612
  result["StreamEncryption"] = encryption;
41350
41613
  }
41614
+ result["DesiredShardLevelMetrics"] = (stream.EnhancedMonitoring ?? []).flatMap((entry) => entry.ShardLevelMetrics ?? []);
41615
+ try {
41616
+ const maxRecordSize = (await this.getClient().send(new DescribeStreamSummaryCommand({ StreamName: physicalId }))).StreamDescriptionSummary?.MaxRecordSizeInKiB;
41617
+ if (maxRecordSize !== void 0) result["MaxRecordSizeInKiB"] = maxRecordSize;
41618
+ } catch (err) {
41619
+ if (err instanceof ResourceNotFoundException$10) return void 0;
41620
+ throw err;
41621
+ }
41351
41622
  try {
41352
41623
  result["Tags"] = normalizeAwsTagsToCfn((await this.getClient().send(new ListTagsForStreamCommand({ StreamName: physicalId }))).Tags);
41353
41624
  } catch (err) {
@@ -72349,7 +72620,7 @@ function createMigrateCommand() {
72349
72620
  */
72350
72621
  function buildProgram() {
72351
72622
  const program = new Command();
72352
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.281.0");
72623
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.281.2");
72353
72624
  program.hook("preAction", (_thisCommand, actionCommand) => {
72354
72625
  const { profile } = actionCommand.optsWithGlobals();
72355
72626
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;