@go-to-k/cdkd 0.290.13 → 0.290.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { C as displaySafe, S as displayIdent, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, x as UNRENDERABLE, y as withoutGeneratedFallbackName } from "./logger-C17H06QA.js";
2
2
  import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
3
- import { t as getCdkdVersion } from "./version--dVnQSTI.js";
3
+ import { t as getCdkdVersion } from "./version-BnegtHzZ.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { createHash, randomUUID } from "node:crypto";
6
6
  import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -804,6 +804,96 @@ function isNameCollisionError(message) {
804
804
  return /(?<!\b(?:must|not|should|may|cannot)\s)already exists?\b/i.test(message) || message.includes("AlreadyExists");
805
805
  }
806
806
  /**
807
+ * SDK exception NAMES that mean, on their own, "a resource with this NAME
808
+ * already exists" — nothing else (issue
809
+ * [#3208](https://github.com/go-to-k/cdkd/issues/3208)).
810
+ *
811
+ * This list is the NARROW exception to the paragraph above, not a reversal of
812
+ * it. That paragraph refuses name-based classification because a name like
813
+ * `ResourceConflictException` is AMBIGUOUS — Lambda raises it for a function in
814
+ * a PENDING state too, so crediting it would delete a live function under
815
+ * `--replace`. Every name here is the opposite: the service declares it for the
816
+ * duplicate-name condition and for nothing else, so there is no second reading
817
+ * to be wrong about. A name may join this list only on that test.
818
+ *
819
+ * It exists because ELBv2 states the condition in prose that the message
820
+ * matcher above cannot see, and must not be widened to see. MEASURED against
821
+ * the real API (us-east-1, 2026-09-16, `@aws-sdk/client-elastic-load-balancing-v2`
822
+ * 3.1126.0), creating a second target group under a live name:
823
+ *
824
+ * name = 'DuplicateTargetGroupNameException'
825
+ * message = "A target group with the same name 'x' exists, but with
826
+ * different settings"
827
+ * cause = none
828
+ *
829
+ * The message carries no code and never says "already exists", so
830
+ * `isNameCollisionError` misses it — and the consequence is not cosmetic: the
831
+ * `--replace` delete-first fallback and the rollback executor's
832
+ * delete-new-first arm both gate on that predicate, so BOTH recovery paths went
833
+ * inert and a create-only change to a cdkd-named target group could not be
834
+ * deployed at all. Widening the prose matcher to a bare `exists` was rejected:
835
+ * it is substring-matched against every service's text, and the direction of a
836
+ * false positive here is a DELETE.
837
+ *
838
+ * The SET is complete rather than illustrative: `Duplicate*NameException` over
839
+ * every installed `@aws-sdk/client-*` model yields exactly these three, all
840
+ * ELBv2. Two ELBv2 siblings are deliberately EXCLUDED, and the reasons are the
841
+ * membership test in action — `DuplicateListenerException` reports a listener
842
+ * already bound to that PORT, which is not a name, and
843
+ * `DuplicateTagKeysException` reports repeated keys WITHIN one request, which
844
+ * is not an existence condition at all. Crediting either would hand a
845
+ * destructive path a collision that no delete can clear.
846
+ */
847
+ const NAME_COLLISION_ERROR_NAMES = /* @__PURE__ */ new Set([
848
+ "DuplicateTargetGroupNameException",
849
+ "DuplicateLoadBalancerNameException",
850
+ "DuplicateTrustStoreNameException"
851
+ ]);
852
+ /**
853
+ * {@link isNameCollisionError}, but reading the ERROR rather than a rendered
854
+ * message — which is the only way to see an exception NAME (issue #3208).
855
+ *
856
+ * Providers wrap an AWS failure as `Failed to create X: ${err.message}`, so the
857
+ * name is dropped before any caller could match it. This walks the bounded
858
+ * `cause` chain (the same {@link MAX_CAUSE_CHAIN_DEPTH} as every other
859
+ * classifier in this file), checking each link's `name` against
860
+ * {@link NAME_COLLISION_ERROR_NAMES} and each link's `message` through
861
+ * {@link isNameCollisionError}. A provider is required to thread the caught
862
+ * value as `cause` (`scripts/check-provider-error-cause.ts` enforces it across
863
+ * `src/provisioning/providers/**`), which is what makes the walk reach the SDK
864
+ * error at all.
865
+ *
866
+ * Prefer this at any site holding the error object. The string form stays for
867
+ * callers that genuinely have only text, and its behaviour is unchanged — this
868
+ * is strictly additive, so nothing that matched before stops matching.
869
+ */
870
+ /**
871
+ * `String(value)` that cannot itself throw — a thrown `Object.create(null)` has
872
+ * no `toString`. Preserves the call sites' pre-#3208 `String(createError)` arm
873
+ * for a non-`Error` throw, which reading `.message` alone would have dropped.
874
+ */
875
+ function stringifyForMatch(value) {
876
+ try {
877
+ return String(value);
878
+ } catch {
879
+ return "";
880
+ }
881
+ }
882
+ function isNameCollisionErrorFrom(error, logicalId) {
883
+ if (typeof error === "string") return isNameCollisionError(error);
884
+ let current = error;
885
+ for (let depth = 0; depth < MAX_CAUSE_CHAIN_DEPTH && current != null; depth++) {
886
+ const link = current;
887
+ if (typeof link.logicalId === "string" && link.logicalId !== logicalId) return false;
888
+ if (typeof link.name === "string" && NAME_COLLISION_ERROR_NAMES.has(link.name)) return true;
889
+ if (depth === 0) {
890
+ if (isNameCollisionError(error instanceof Error && typeof link.message === "string" ? link.message : stringifyForMatch(error))) return true;
891
+ }
892
+ current = link.cause;
893
+ }
894
+ return false;
895
+ }
896
+ /**
807
897
  * Match a same-name re-creation cooldown — an AWS service still holding a
808
898
  * resource's name while its asynchronous delete finishes. Every recognised
809
899
  * spelling lives in {@link NAME_COOLDOWN_ERROR_MESSAGE_PATTERNS}; add new ones
@@ -24617,6 +24707,16 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
24617
24707
  * one.
24618
24708
  */
24619
24709
  producerRegionGuest = false;
24710
+ /**
24711
+ * How a producer-region guest PRINTS its own `explicitRegion` (issue
24712
+ * [#3150](https://github.com/go-to-k/cdkd/issues/3150)): the masked log text
24713
+ * its creator held for that region, which a template can assemble around a
24714
+ * short secret, or `***` once a later spelling of the same region masks
24715
+ * differently. Display only; `undefined` on an ordinary resolver, whose
24716
+ * region its command built (the stack's synthesized or recorded region,
24717
+ * `--region`, or a region read out of a literal token).
24718
+ */
24719
+ explicitRegionLogText;
24620
24720
  strictGetAtt;
24621
24721
  cfnFallback;
24622
24722
  /**
@@ -24868,18 +24968,19 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
24868
24968
  * uppercase spelling would build a second client for the same physical
24869
24969
  * region — benign, but wasteful and confusing in a debug log.
24870
24970
  */
24871
- clientsForRegion(targetRegion) {
24971
+ clientsForRegion(targetRegion, targetLogText) {
24872
24972
  const ambient = getAwsClients();
24873
24973
  if (!targetRegion) return ambient;
24874
24974
  const target = canonicalizeRegion(targetRegion);
24875
- if (!isClientSafeRegion(target)) throw new Error(`Refusing to build AWS clients for the region '${stripControlChars(target).slice(0, 64)}': it is not a valid AWS region name, and a region is substituted into the AWS service hostname.`);
24975
+ const loggedTarget = targetLogText ?? (targetRegion === this.explicitRegion ? this.explicitRegionLogText : void 0) ?? target;
24976
+ if (!isClientSafeRegion(target)) throw new Error(`Refusing to build AWS clients for the region '${stripControlChars(loggedTarget).slice(0, 64)}': it is not a valid AWS region name, and a region is substituted into the AWS service hostname.`);
24876
24977
  if (typeof ambient.withRegion !== "function") return ambient;
24877
24978
  const cached = this.regionScopedClients.get(target);
24878
24979
  if (cached) return cached;
24879
24980
  if (canonicalizeRegion(ambient.configuredRegion) === target) return ambient;
24880
24981
  const scoped = ambient.withRegion(target);
24881
24982
  this.regionScopedClients.set(target, scoped);
24882
- this.logger.debug(`Using region-scoped AWS clients for ${target}`);
24983
+ this.logger.debug(`Using region-scoped AWS clients for ${loggedTarget}`);
24883
24984
  return scoped;
24884
24985
  }
24885
24986
  /**
@@ -25469,7 +25570,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25469
25570
  return this.noteAttributeSecrecy(logicalId, attributeName, nameServers, context);
25470
25571
  }
25471
25572
  this.logger.debug(`Resolved Fn::GetAtt from attributes: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, this.maskValueLeaves(flatValue, context)), context)}`);
25472
- if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX) && carriesDynamicReference(flatValue)) return await this.reresolveCrossStackValue(flatValue, nestedStackChildRegionFromLocalArn(resource.physicalId), context, `nested stack ${logicalId} ${attributeName}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
25573
+ if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX) && carriesDynamicReference(flatValue)) return await this.reresolveCrossStackValue(flatValue, nestedStackChildRegionFromLocalArn(resource.physicalId), context, `nested stack ${logicalId} ${this.logTextOfLeaf(attributeName, context)}`, crossStackSourceKey({ "Fn::GetAtt": getAtt }));
25473
25574
  return this.noteAttributeSecrecy(logicalId, attributeName, flatValue, context);
25474
25575
  }
25475
25576
  if (attributeName.includes(".")) {
@@ -25487,8 +25588,9 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
25487
25588
  }
25488
25589
  }
25489
25590
  if (resource.resourceType === NESTED_STACK_RESOURCE_TYPE$1 && attributeName.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX)) {
25490
- const declared = Object.keys(resource.attributes ?? {}).filter((k) => k.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX)).map((k) => k.slice(8)).sort();
25491
- throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.maskSecretsForLog(attributeName, context)}]: the nested stack '${logicalId}' declares no output named '${this.maskSecretsForLog(attributeName.slice(8), context)}'. Its outputs are ${declared.length > 0 ? declared.join(", ") : "(none)"}. Check the output name in the nested stack's template, and deploy the child stack again if you have just added it.`));
25591
+ const declared = Object.keys(resource.attributes ?? {}).filter((k) => k.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX)).sort().map((k) => this.maskSecretsForLog(this.outputNameLogText(k, context), context));
25592
+ const declaredText = declared.length > 0 ? declared.join(", ") : "(none)";
25593
+ throw markNonRetryable(new IntrinsicResolutionRefusalError(`Cannot resolve Fn::GetAtt [${logicalId}, ${this.maskSecretsForLog(attributeName, context)}]: the nested stack '${logicalId}' declares no output named '${this.maskSecretsForLog(this.outputNameLogText(attributeName, context), context)}'. Its outputs are ${this.maskSecretsForLog(declaredText, context)}. Check the output name in the nested stack's template, and deploy the child stack again if you have just added it.`));
25492
25594
  }
25493
25595
  const value = await this.constructGuardedAttribute(resource, attributeName, context, logicalId);
25494
25596
  this.logger.debug(`Resolved Fn::GetAtt: ${logicalId}.${this.maskSecretsForLog(attributeName, context)} -> ${this.maskSecretsForLog(stringifyAttributeForLog(attributeName, this.maskValueLeaves(value, context)), context)}`);
@@ -26775,7 +26877,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26775
26877
  * the producer's rather than the caller's — which is exactly what issue #2057
26776
26878
  * says the other two copies get wrong.
26777
26879
  */
26778
- async reresolveCrossStackValue(value, producerRegion, context, origin, sourceKey, producerOutput) {
26880
+ async reresolveCrossStackValue(value, producerRegion, context, origin, sourceKey, producerOutput, producerRegionLogText) {
26779
26881
  if (carriesSecretMask(value)) {
26780
26882
  const recovered = producerOutput === void 0 || producerOutput.crossAccount === true ? void 0 : recoverMaskedOutput(producerOutput.stackName, producerOutput.region, producerOutput.outputKey);
26781
26883
  if (recovered !== void 0) {
@@ -26791,7 +26893,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26791
26893
  }
26792
26894
  }
26793
26895
  if (!carriesDynamicReference(value)) return value;
26794
- const resolver = this.resolverForProducerRegion(producerRegion);
26896
+ const resolver = this.resolverForProducerRegion(producerRegion, context, producerRegionLogText);
26795
26897
  const pinnedContext = producerRegion ? withoutProducerRegions(context) : context;
26796
26898
  const walk = async (v) => {
26797
26899
  if (typeof v === "string") return v.includes("{{resolve:") ? await resolver.resolveDynamicReferences(v, pinnedContext) : v;
@@ -26872,19 +26974,25 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26872
26974
  if (secret) recordedSecretExpressions.add(expression);
26873
26975
  else recordedSecretExpressions.delete(expression);
26874
26976
  }
26875
- resolverForProducerRegion(producerRegion) {
26977
+ resolverForProducerRegion(producerRegion, context, producerRegionLogText) {
26876
26978
  if (!producerRegion) return this;
26877
26979
  const target = canonicalizeRegion(producerRegion);
26878
26980
  if (target === canonicalizeRegion(this.explicitRegion)) return this;
26981
+ const regionText = producerRegionLogText !== void 0 ? canonicalizeRegion(producerRegionLogText) : this.regionLogText(producerRegion, context);
26982
+ const guestRegionText = this.maskThenStripThenMask(regionText, context);
26879
26983
  const cached = this.producerRegionResolvers.get(target);
26880
- if (cached) return cached;
26984
+ if (cached) {
26985
+ if (cached.explicitRegionLogText !== guestRegionText) cached.explicitRegionLogText = "***";
26986
+ return cached;
26987
+ }
26881
26988
  const scoped = new IntrinsicFunctionResolver(target, {
26882
26989
  strictGetAtt: this.strictGetAtt,
26883
26990
  cfnFallback: this.cfnFallback
26884
26991
  });
26885
26992
  scoped.producerRegionGuest = true;
26993
+ scoped.explicitRegionLogText = guestRegionText;
26886
26994
  this.producerRegionResolvers.set(target, scoped);
26887
- this.logger.debug(`Using a producer-region resolver for ${target}`);
26995
+ this.logger.debug(`Using a producer-region resolver for ${guestRegionText}`);
26888
26996
  return scoped;
26889
26997
  }
26890
26998
  /**
@@ -26909,8 +27017,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26909
27017
  }
26910
27018
  if (entry && (!context.stackName || entry.producerStack !== context.stackName)) {
26911
27019
  this.recordImport(context, exportName, entry.producerStack, entry.producerRegion);
26912
- this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from index: ${this.maskSecretsForLog(entry.producerStack, context)} / ${entry.producerRegion}; ${carriesDynamicReference(entry.value) ? "redacted dynamic reference" : "literal value"})`);
26913
- return await this.reresolveCrossStackValue(entry.value, entry.producerRegion, context, `Fn::ImportValue '${exportName}' (producer ${entry.producerStack} / ${entry.producerRegion})`, sourceKey, {
27020
+ this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from index: ${this.maskSecretsForLog(entry.producerStack, context)} / ${this.maskSecretsForLog(entry.producerRegion, context)}; ${carriesDynamicReference(entry.value) ? "redacted dynamic reference" : "literal value"})`);
27021
+ return await this.reresolveCrossStackValue(entry.value, entry.producerRegion, context, `Fn::ImportValue '${this.logTextOfLeaf(exportName, context)}' (producer ${this.logTextOfLeaf(entry.producerStack, context)} / ${this.logTextOfLeaf(entry.producerRegion, context)})`, sourceKey, {
26914
27022
  stackName: entry.producerStack,
26915
27023
  region: entry.producerRegion,
26916
27024
  outputKey: exportName
@@ -26934,13 +27042,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26934
27042
  }
26935
27043
  const stateData = await context.stateBackend.getState(refStack, lookupRegion);
26936
27044
  if (!stateData) {
26937
- this.logger.debug(`No state found for stack: ${this.maskSecretsForLog(refStack, context)} (${lookupRegion})`);
27045
+ this.logger.debug(`No state found for stack: ${this.maskSecretsForLog(refStack, context)} (${this.maskSecretsForLog(lookupRegion, context)})`);
26938
27046
  continue;
26939
27047
  }
26940
27048
  const { state } = stateData;
26941
27049
  if (importableOutputKeys(state).includes(exportName)) {
26942
27050
  const value = state.outputs[exportName];
26943
- this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from stack: ${this.maskSecretsForLog(refStack, context)} / ${lookupRegion}; ${carriesDynamicReference(value) ? "redacted dynamic reference" : "literal value"})`);
27051
+ this.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from stack: ${this.maskSecretsForLog(refStack, context)} / ${this.maskSecretsForLog(lookupRegion, context)}; ${carriesDynamicReference(value) ? "redacted dynamic reference" : "literal value"})`);
26944
27052
  if (context.exportIndex) context.exportIndex.patchEntry(exportName, {
26945
27053
  value,
26946
27054
  producerStack: refStack,
@@ -26961,7 +27069,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26961
27069
  continue;
26962
27070
  }
26963
27071
  }
26964
- if (found) return await this.reresolveCrossStackValue(found.value, found.lookupRegion, context, `Fn::ImportValue '${exportName}' (producer ${found.refStack} / ${found.lookupRegion})`, sourceKey, {
27072
+ if (found) return await this.reresolveCrossStackValue(found.value, found.lookupRegion, context, `Fn::ImportValue '${this.logTextOfLeaf(exportName, context)}' (producer ${this.logTextOfLeaf(found.refStack, context)} / ${this.logTextOfLeaf(found.lookupRegion, context)})`, sourceKey, {
26965
27073
  stackName: found.refStack,
26966
27074
  region: found.lookupRegion,
26967
27075
  outputKey: exportName
@@ -27026,9 +27134,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27026
27134
  * `OutputName` is the overwhelmingly common cause, and the list is what makes
27027
27135
  * the error actionable.
27028
27136
  *
27029
- * Residual, stated rather than hidden: the needles belong to the CONSUMER's
27030
- * resolution, so a plaintext sitting in a PRODUCER key that this consumer
27031
- * never resolved is not maskable from here. The cap is what bounds that case;
27137
+ * `maskSecretsForLog` reads the consumer pass's log twin first (issue #3150),
27138
+ * so a key equal to a name this pass assembled around a short secret is
27139
+ * masked. Residual, stated rather than hidden: the needles and twins belong to the
27140
+ * CONSUMER's resolution, so a plaintext sitting in a PRODUCER key that this
27141
+ * consumer never resolved is not maskable from here. The cap is what bounds that case;
27032
27142
  * `cdkd scrub` reporting the producer's own `secretBearingKeys` is the remedy.
27033
27143
  */
27034
27144
  describeAvailableOutputs(keys, context) {
@@ -27060,7 +27170,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27060
27170
  * logged for non-not-found failures). Same graceful-degradation
27061
27171
  * contract as {@link lookupCfnExport}.
27062
27172
  */
27063
- async lookupCfnStackOutputs(stackName, region, context) {
27173
+ async lookupCfnStackOutputs(stackName, region, context, loggedRegionText) {
27064
27174
  const cacheKey = `${region}\0${stackName}`;
27065
27175
  let fetch = this.cfnStackOutputsCache.get(cacheKey);
27066
27176
  if (!fetch) {
@@ -27074,7 +27184,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27074
27184
  return await fetch;
27075
27185
  } catch (error) {
27076
27186
  const message = error instanceof Error ? error.message : String(error);
27077
- this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${this.maskSecretsForLog(stackName, context)}' (${this.maskSecretsForLog(region, context)}): ${this.maskSecretsForLog(message, context)}. Grant cloudformation:DescribeStacks to resolve outputs from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
27187
+ this.logger.warn(`Fn::GetStackOutput: CloudFormation DescribeStacks fallback failed for stack '${this.maskSecretsForLog(stackName, context)}' (${this.maskSecretsForLog(loggedRegionText, context)}): ${this.maskSecretsForLog(message, context)}. Grant cloudformation:DescribeStacks to resolve outputs from CloudFormation-managed stacks, or pass --no-cfn-fallback to disable the fallback.`);
27078
27188
  return;
27079
27189
  }
27080
27190
  }
@@ -27179,12 +27289,14 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27179
27289
  const outputName = await this.resolveValue(args["OutputName"], context);
27180
27290
  if (typeof outputName !== "string" || outputName === "") throw new Error(`Fn::GetStackOutput: OutputName must resolve to a non-empty string, got ${typeof outputName}`);
27181
27291
  let region = this.resolverRegion;
27292
+ let loggedRegionText = this.logTextOfLeaf(region, context);
27182
27293
  if ("Region" in args && args["Region"] !== void 0 && args["Region"] !== null) {
27183
27294
  const resolvedRegion = await this.resolveValue(args["Region"], context);
27184
27295
  if (typeof resolvedRegion !== "string" || resolvedRegion === "") throw new Error(`Fn::GetStackOutput: Region must resolve to a non-empty string, got ${typeof resolvedRegion}`);
27185
27296
  const requestedRegion = canonicalizeRegion(resolvedRegion);
27186
- if (!isClientSafeRegion(requestedRegion)) throw new Error(`Fn::GetStackOutput: '${this.maskThenStripThenMask(resolvedRegion, context).slice(0, 64)}' is not a valid AWS region name. The region selects both the AWS endpoint and the state-file key, so cdkd will not use it.`);
27297
+ if (!isClientSafeRegion(requestedRegion)) throw new Error(`Fn::GetStackOutput: '${this.maskThenStripThenMask(this.logTextOfLeaf(resolvedRegion, context) !== resolvedRegion ? "***" : resolvedRegion, context).slice(0, 64)}' is not a valid AWS region name. The region selects both the AWS endpoint and the state-file key, so cdkd will not use it.`);
27187
27298
  region = requestedRegion;
27299
+ loggedRegionText = this.regionLogText(resolvedRegion, context);
27188
27300
  }
27189
27301
  let roleArn;
27190
27302
  if ("RoleArn" in args && args["RoleArn"] !== void 0 && args["RoleArn"] !== null) {
@@ -27192,15 +27304,15 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27192
27304
  if (typeof raw !== "string" || raw === "") throw new Error(`Fn::GetStackOutput: RoleArn must be a literal string in the template (no Ref / Fn::GetAtt / Fn::Sub allowed for cross-account references). Got ${raw === null ? "null" : Array.isArray(raw) ? "array" : typeof raw}${typeof raw === "object" ? ` (intrinsic shape: ${JSON.stringify(raw).slice(0, 80)})` : ""}.`);
27193
27305
  roleArn = raw;
27194
27306
  }
27195
- if (!roleArn && context.stackName && context.stackName === stackName && canonicalizeRegion(region) === canonicalizeRegion(this.resolverRegion)) throw new Error(`Fn::GetStackOutput: cannot reference own stack '${this.maskSecretsForLog(stackName, context)}' in the same region '${this.maskSecretsForLog(region, context)}'`);
27307
+ if (!roleArn && context.stackName && context.stackName === stackName && canonicalizeRegion(region) === canonicalizeRegion(this.resolverRegion)) throw new Error(`Fn::GetStackOutput: cannot reference own stack '${this.maskSecretsForLog(stackName, context)}' in the same region '${this.maskSecretsForLog(loggedRegionText, context)}'`);
27196
27308
  const loggedStackName = this.maskSecretsForLog(stackName, context);
27197
27309
  const loggedOutputName = this.maskSecretsForLog(outputName, context);
27198
- const loggedRegion = this.maskSecretsForLog(region, context);
27310
+ const loggedRegion = this.maskSecretsForLog(loggedRegionText, context);
27199
27311
  this.logger.debug(`Resolving Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${roleArn}` : ""}`);
27200
27312
  const stateData = roleArn ? await this.getCrossAccountStackState(roleArn, stackName, region, context) : await this.getSameAccountStackState(stackName, region, context);
27201
27313
  if (!stateData) {
27202
27314
  if (!roleArn && this.cfnFallback) {
27203
- const cfnOutputs = await this.lookupCfnStackOutputs(stackName, region, context);
27315
+ const cfnOutputs = await this.lookupCfnStackOutputs(stackName, region, context, loggedRegionText);
27204
27316
  if (cfnOutputs) {
27205
27317
  if (!Object.hasOwn(cfnOutputs, outputName)) {
27206
27318
  const available = this.describeAvailableOutputs(Object.keys(cfnOutputs), context);
@@ -27222,12 +27334,12 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27222
27334
  this.logger.info(`Resolved Fn::GetStackOutput: StackName=${loggedStackName}, Region=${loggedRegion}, OutputName=${loggedOutputName}${roleArn ? `, RoleArn=${roleArn}` : ""} (${carriesDynamicReference(value) ? "redacted dynamic reference" : "literal value"})`);
27223
27335
  if (!roleArn) this.recordOutputRead(context, stackName, region, outputName);
27224
27336
  if (roleArn && !context.skipDynamicReferences && carriesDynamicReference(value)) throw markNonRetryable(new CrossAccountSecretRefusalError(`Fn::GetStackOutput: output '${loggedOutputName}' of stack '${loggedStackName}' (${loggedRegion}) is a redacted dynamic reference, and this is a CROSS-ACCOUNT reference (RoleArn ${roleArn}). cdkd will not resolve a producer account's secret with the consumer's credentials — a same-named secret in the consumer account would answer instead. Export a non-secret value (e.g. the secret's ARN) and resolve it in the consumer stack, or reference the producer stack from within its own account.`));
27225
- return await this.reresolveCrossStackValue(value, region, context, `Fn::GetStackOutput '${outputName}' (producer ${stackName} / ${region})`, sourceKey, {
27337
+ return await this.reresolveCrossStackValue(value, region, context, `Fn::GetStackOutput '${this.logTextOfLeaf(outputName, context)}' (producer ${this.logTextOfLeaf(stackName, context)} / ${loggedRegionText})`, sourceKey, {
27226
27338
  stackName,
27227
27339
  region,
27228
27340
  outputKey: outputName,
27229
27341
  ...roleArn ? { crossAccount: true } : {}
27230
- });
27342
+ }, loggedRegionText);
27231
27343
  }
27232
27344
  /**
27233
27345
  * Push a resolved `Fn::GetStackOutput` into the consumer's
@@ -27365,7 +27477,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27365
27477
  if (typeof resolvedValue !== "string") throw new Error(`Fn::Base64: value must resolve to a string, got ${typeof resolvedValue}`);
27366
27478
  const result = Buffer.from(resolvedValue).toString("base64");
27367
27479
  const inputLogText = this.logTextOfLeaf(resolvedValue, context);
27368
- if (context.recordedSecretValues && (inputLogText !== resolvedValue || this.maskSecretsForLog(resolvedValue, context) !== resolvedValue)) recordMaskOnlyValue(context.recordedSecretValues, result);
27480
+ if (context.recordedSecretValues && (inputLogText !== resolvedValue || this.maskNeedlesForLog(resolvedValue, context) !== resolvedValue)) recordMaskOnlyValue(context.recordedSecretValues, result);
27369
27481
  this.logger.debug(`Resolved Fn::Base64: ${this.maskSecretsForLog(inputLogText, context)} -> ${this.maskSecretsForLog(inputLogText !== resolvedValue ? "***" : result, context)}`);
27370
27482
  return result;
27371
27483
  }
@@ -27395,21 +27507,23 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27395
27507
  * given explicitly (see {@link explicitRegion}).
27396
27508
  */
27397
27509
  let clientRegion;
27510
+ let loggedRegionText;
27398
27511
  if (typeof resolvedValue === "string" && resolvedValue !== "") {
27399
27512
  const requested = canonicalizeRegion(resolvedValue);
27400
- if (!isClientSafeRegion(requested)) throw new Error(`Fn::GetAZs: '${this.maskThenStripThenMask(resolvedValue, context).slice(0, 64)}' is not a valid AWS region name. A region is substituted into the AWS service hostname, so cdkd will not build a client from it.`);
27513
+ if (!isClientSafeRegion(requested)) throw new Error(`Fn::GetAZs: '${this.maskThenStripThenMask(this.logTextOfLeaf(resolvedValue, context) !== resolvedValue ? "***" : resolvedValue, context).slice(0, 64)}' is not a valid AWS region name. A region is substituted into the AWS service hostname, so cdkd will not build a client from it.`);
27401
27514
  region = requested;
27402
27515
  clientRegion = requested;
27516
+ loggedRegionText = this.regionLogText(resolvedValue, context);
27403
27517
  } else {
27404
27518
  region = (await getAccountInfo(this.resolverRegion)).region;
27405
27519
  clientRegion = this.explicitRegion;
27406
27520
  }
27407
27521
  const cached = cachedAvailabilityZones[region];
27408
27522
  if (cached) {
27409
- this.logger.debug(`Resolved Fn::GetAZs from cache: ${this.maskSecretsForLog(region, context)} -> ${JSON.stringify(this.maskValueLeaves(cached, context))}`);
27523
+ this.logger.debug(`Resolved Fn::GetAZs from cache: ${this.maskSecretsForLog(loggedRegionText ?? region, context)} -> ${JSON.stringify(this.maskValueLeaves(cached, context))}`);
27410
27524
  return cached;
27411
27525
  }
27412
- const ec2Client = this.clientsForRegion(clientRegion).ec2;
27526
+ const ec2Client = this.clientsForRegion(clientRegion, loggedRegionText === void 0 ? void 0 : this.maskSecretsForLog(loggedRegionText, context)).ec2;
27413
27527
  let azNames;
27414
27528
  try {
27415
27529
  azNames = ((await ec2Client.send(new DescribeAvailabilityZonesCommand({ Filters: [{
@@ -27420,11 +27534,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27420
27534
  Values: ["available"]
27421
27535
  }] }))).AvailabilityZones || []).map((az) => az.ZoneName).filter((name) => name !== void 0).sort();
27422
27536
  } catch (error) {
27423
- throw new Error(`Fn::GetAZs: failed to describe availability zones for region '${this.maskSecretsForLog(region, context)}': ${this.maskSecretsForLog(error instanceof Error ? error.message : String(error), context)}`);
27537
+ throw new Error(`Fn::GetAZs: failed to describe availability zones for region '${this.maskSecretsForLog(loggedRegionText ?? region, context)}': ${this.maskSecretsForLog(error instanceof Error ? error.message : String(error), context)}`);
27424
27538
  }
27425
- if (azNames.length === 0) throw new Error(`Fn::GetAZs: no availability zones returned for region '${this.maskSecretsForLog(region, context)}'. Either the region is not enabled on this account (opt-in regions must be enabled before use), or the request was answered by a different region's endpoint.`);
27539
+ if (azNames.length === 0) throw new Error(`Fn::GetAZs: no availability zones returned for region '${this.maskSecretsForLog(loggedRegionText ?? region, context)}'. Either the region is not enabled on this account (opt-in regions must be enabled before use), or the request was answered by a different region's endpoint.`);
27426
27540
  cachedAvailabilityZones[region] = azNames;
27427
- this.logger.debug(`Resolved Fn::GetAZs: ${this.maskSecretsForLog(region, context)} -> ${JSON.stringify(this.maskValueLeaves(azNames, context))}`);
27541
+ this.logger.debug(`Resolved Fn::GetAZs: ${this.maskSecretsForLog(loggedRegionText ?? region, context)} -> ${JSON.stringify(this.maskValueLeaves(azNames, context))}`);
27428
27542
  return azNames;
27429
27543
  }
27430
27544
  /**
@@ -27461,8 +27575,37 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27461
27575
  * Mask any resolved secret value out of a string bound for a log line, using
27462
27576
  * the secrets recorded on the resolution pass (GHSA fix). No-op when the pass
27463
27577
  * recorded no secrets.
27578
+ *
27579
+ * A value with a registered LOG TWIN prints as its twin first (issue
27580
+ * [#3150](https://github.com/go-to-k/cdkd/issues/3150)). The needle mask
27581
+ * matches a secret under {@link MIN_NEEDLE_LENGTH} only as the whole text,
27582
+ * so a name an `Fn::Sub` assembled around a 1-3 character secret (a map key,
27583
+ * a stack or output name, an attribute name, the secret id of a dynamic
27584
+ * reference) printed in the clear at every site that handed its RAW value
27585
+ * here, although the pass had registered where the secret sits. Looking the
27586
+ * twin up HERE, rather than at each such site, is what makes the class
27587
+ * closed for raw values: every one of those sites already calls this method.
27588
+ * The twin prints as it is: it is the raw text with masked spans, so it
27589
+ * holds no recorded needle the raw text lacks. When the needle mask ALSO
27590
+ * changes the raw text the whole text is masked instead, the rule
27591
+ * `logTwinText` applies to a Join / Sub line, since the two masks' spans
27592
+ * cannot be merged. What this cannot see is a value TRANSFORMED before it
27593
+ * arrives (a lowercased region, a sliced output name, an assembled
27594
+ * sentence); those sites derive their text from the twin themselves.
27464
27595
  */
27465
27596
  maskSecretsForLog(text, context) {
27597
+ const registered = this.registeredLogTwin(text, context);
27598
+ if (registered === void 0) return this.maskNeedlesForLog(text, context);
27599
+ return this.maskNeedlesForLog(text, context) !== text ? "***" : registered;
27600
+ }
27601
+ /**
27602
+ * The needle mask alone: {@link maskSecretsForLog} without the log-twin
27603
+ * lookup. For the two DETECTORS that must ask the needle mask apart from the
27604
+ * position mask: `logTwinText`, which asks it of a value that already has a
27605
+ * twin, and `resolveBase64`, whose other operand is the position mask. A
27606
+ * message masks through `maskSecretsForLog`.
27607
+ */
27608
+ maskNeedlesForLog(text, context) {
27466
27609
  let masked = text;
27467
27610
  const inherited = context?.inheritedSecrets;
27468
27611
  if (inherited && inherited.size > 0) masked = maskSecretsInText(masked, inherited);
@@ -27492,7 +27635,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27492
27635
  * resolver's mask-coverage checker sees a masker at the site.
27493
27636
  */
27494
27637
  logTwinText(result, twin, context) {
27495
- return twin !== result && this.maskSecretsForLog(result, context) !== result ? "***" : twin;
27638
+ return twin !== result && this.maskNeedlesForLog(result, context) !== result ? "***" : twin;
27496
27639
  }
27497
27640
  /**
27498
27641
  * The log twins of `Fn::Split`'s pieces (issue #3100), each registered for
@@ -27540,16 +27683,15 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27540
27683
  * the leaf treated as a resolution product — masked whole when it is a
27541
27684
  * recorded secret, otherwise the masked twin this pass registered for it —
27542
27685
  * and then `logTwinText`'s whole-line guard. The caller still wraps the
27543
- * result in `maskSecretsForLog`. Shared by every caller of `maskValueLeaves`
27544
- * (the `Fn::Select`, `Fn::Split`, `Fn::Equals`, `Fn::FindInMap`,
27545
- * `Fn::GetAZs` and `Fn::Cidr` lines and the VPC `Ipv6CidrBlocks` line among
27546
- * them) and by the `Fn::Base64` line, so a string one
27547
- * write already masked by position is not printed in the clear by the next
27548
- * intrinsic that logs it. `maskValueLeaves` also masks values interpolated
27549
- * into THROWN messages (the `Fn::Cidr` argument refusals, for one), so those
27550
- * messages take the same position mask: a short secret an earlier write put
27551
- * into the value is `***` there too, the direction the mask at the throw
27552
- * already takes for a whole secret.
27686
+ * result in `maskSecretsForLog`. Used where the text is needed BEFORE that
27687
+ * masker, or apart from it: the `Fn::Base64` line and its detector, and the
27688
+ * names issue [#3150](https://github.com/go-to-k/cdkd/issues/3150)
27689
+ * transforms or composes before printing (`regionLogText`,
27690
+ * `outputNameLogText`, the invalid-region refusals, the cross-stack `origin`
27691
+ * strings). A leaf printed as it is needs none of it: `maskSecretsForLog`
27692
+ * looks the twin up itself, which is how `maskValueLeaves` gives its lines
27693
+ * and the THROWN messages it masks (the `Fn::Cidr` argument refusals, for
27694
+ * one) the same position mask.
27553
27695
  */
27554
27696
  logTextOfLeaf(value, context) {
27555
27697
  return this.logTwinText(value, this.logTwinOfProduct({
@@ -27557,6 +27699,85 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27557
27699
  twin: value
27558
27700
  }, context).twin, context);
27559
27701
  }
27702
+ /**
27703
+ * The log text of a nested stack's OUTPUT name, the part of `attributeName`
27704
+ * after `Outputs.` (issue [#3150](https://github.com/go-to-k/cdkd/issues/3150)).
27705
+ * The twin registry is keyed by the exact string, so the suffix has no twin
27706
+ * of its own: it is sliced from the twin of the WHOLE attribute name. A twin
27707
+ * that no longer starts with the literal prefix has a mask over part of it
27708
+ * (a secret was written into the prefix), so the slice offset no longer
27709
+ * lines up and the suffix prints as `***`.
27710
+ */
27711
+ outputNameLogText(attributeName, context) {
27712
+ const twin = this.logTextOfLeaf(attributeName, context);
27713
+ return twin.startsWith(NESTED_STACK_OUTPUT_ATTRIBUTE_PREFIX) ? twin.slice(8) : "***";
27714
+ }
27715
+ /**
27716
+ * The log text of a template-supplied REGION as the resolver uses it, i.e.
27717
+ * after `canonicalizeRegion` (issue #3150). The twin is taken from the RAW
27718
+ * value, the string a write registered, and lowercased the same way: a
27719
+ * lookup of the canonical form finds no twin once the raw value had an
27720
+ * upper-case part, and lowercasing leaves every `***` span where it was.
27721
+ */
27722
+ regionLogText(rawRegion, context) {
27723
+ const canonical = canonicalizeRegion(rawRegion);
27724
+ const text = canonicalizeRegion(this.logTextOfLeaf(rawRegion, context));
27725
+ return text !== canonical && this.maskNeedlesForLog(canonical, context) !== canonical ? "***" : text;
27726
+ }
27727
+ /**
27728
+ * The log text of a name or token whose `twin` masks spans of `raw` (issue
27729
+ * [#3150](https://github.com/go-to-k/cdkd/issues/3150)). The twin prints
27730
+ * unless the needle mask ALSO changes `raw`; then the two must agree. When
27731
+ * the needle-masked `raw` IS the twin, both masked the same spans and the
27732
+ * twin is safe (`/probe/***` for a 4+ character secret the name holds
27733
+ * whole). When they differ, a recorded secret straddles a masked span
27734
+ * (`q7ab` across `id-***ab`), no text can honour both, and the name prints
27735
+ * as `***`. Coarser `logTwinText` gives up whenever both masks fire.
27736
+ */
27737
+ straddleSafeTwin(raw, twin, context) {
27738
+ if (twin === raw) return twin;
27739
+ const needled = this.maskNeedlesForLog(raw, context);
27740
+ if (needled === raw) return twin;
27741
+ return needled === twin ? twin : "***";
27742
+ }
27743
+ /**
27744
+ * The log text of a name parsed out of a dynamic-reference token (issue
27745
+ * [#3150](https://github.com/go-to-k/cdkd/issues/3150)). `resolveSub` /
27746
+ * `resolveJoin` re-enter the dynamic-reference loop with the ASSEMBLED string
27747
+ * and its twin, so a secret id, JSON key, version stage or id, SSM parameter
27748
+ * name, service or ARN region assembled around a short secret has its masked
27749
+ * spelling in `tokenTwin` only. Every such name is a run of the token's
27750
+ * `:`-separated pieces, so its log text is the twin's run over the same
27751
+ * pieces. Nothing is registered: the pass's log-twin registry also decides
27752
+ * what `Fn::Base64` persists, so the mapping lives in the returned function.
27753
+ *
27754
+ * `tokenTwin` is the twin's own `{{resolve:...}}` token paired with this one.
27755
+ * Each run's text goes through `straddleSafeTwin`, so a name whose needle
27756
+ * mask disagrees with its twin prints as `***`. A name whose runs carry different
27757
+ * twins, or a token whose pieces do not pair with the twin's (a mask
27758
+ * covering a `:`), prints as `***` too.
27759
+ *
27760
+ * A name that is no run of the token is a default the caller synthesized
27761
+ * (`AWSCURRENT` for an empty version stage, `''` for an absent version id),
27762
+ * printed as it is. Should the token spell such a non-empty name inside a longer
27763
+ * piece, it prints as `***`: the run rule says nothing about that text.
27764
+ */
27765
+ dynamicReferenceNameLogText(inner, tokenTwin, context) {
27766
+ const twinPieces = tokenTwin.slice(10, -2).split(":");
27767
+ const pieces = inner.split(":");
27768
+ if (twinPieces.length !== pieces.length) return () => "***";
27769
+ return (name) => {
27770
+ let text;
27771
+ for (let start = 0; start < pieces.length; start++) for (let end = start + 1; end <= pieces.length; end++) {
27772
+ if (pieces.slice(start, end).join(":") !== name) continue;
27773
+ const twin = this.straddleSafeTwin(name, twinPieces.slice(start, end).join(":"), context);
27774
+ if (text !== void 0 && text !== twin) return "***";
27775
+ text = twin;
27776
+ break;
27777
+ }
27778
+ return text ?? (name !== "" && inner.includes(name) ? "***" : name);
27779
+ };
27780
+ }
27560
27781
  /** The bag a pass's log twins are keyed by (issue #3100): the recorded one, else the inherited one. */
27561
27782
  logTwinBag(context) {
27562
27783
  return context?.recordedSecretValues ?? context?.inheritedSecrets;
@@ -27692,7 +27913,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27692
27913
  maskValueLeaves(value, context) {
27693
27914
  const done = /* @__PURE__ */ new Map();
27694
27915
  const walk = (node) => {
27695
- if (typeof node === "string") return this.maskSecretsForLog(this.logTextOfLeaf(node, context), context);
27916
+ if (typeof node === "string") return this.maskSecretsForLog(node, context);
27696
27917
  if (node === null || typeof node !== "object") return node;
27697
27918
  const memo = done.get(node);
27698
27919
  if (memo !== void 0) return memo;
@@ -27704,7 +27925,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27704
27925
  }
27705
27926
  const out = Object.create(null);
27706
27927
  done.set(node, out);
27707
- for (const [key, child] of Object.entries(node)) out[this.maskSecretsForLog(this.logTextOfLeaf(key, context), context)] = walk(child);
27928
+ for (const [key, child] of Object.entries(node)) out[this.maskSecretsForLog(key, context)] = walk(child);
27708
27929
  return out;
27709
27930
  };
27710
27931
  return walk(value);
@@ -27731,14 +27952,14 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27731
27952
  * visible. The FIRST mask is demonstrated by a test: deleting it (masking
27732
27953
  * only after the strip) reds the split-needle case, because the recorded
27733
27954
  * needle is then the split form and the strip has destroyed it. The SECOND
27734
- * mask is NOT reached by any test here and is defence in depth: it earns its
27735
- * place only when the bag holds a needle that is the STRIPPED form of the
27736
- * value in hand, and every route through THIS resolver records the value it
27737
- * actually resolved — so the split copy is itself a needle and the first
27738
- * mask already catches it. The shape was measured against a hand-built bag
27739
- * during review, not produced by the resolver. Kept anyway: it is one
27740
- * idempotent call, and the alternative is re-deciding per future caller
27741
- * whether the bag and the value can disagree.
27955
+ * mask earns its place when the bag holds a needle that is the STRIPPED form
27956
+ * of the text in hand. A value this resolver resolved cannot be that text
27957
+ * (the split copy is itself recorded, so the first mask catches it), but a
27958
+ * template LITERAL can: issue #3150's region-scoped clients refusal prints
27959
+ * a producer-region guest's region through this helper, and a literal ARN
27960
+ * region spelling a recorded `st-1` as `s` + U+0001 + `t-1` is masked only
27961
+ * by the second pass (`intrinsic-resolver-name-argument-log-twin.test.ts`
27962
+ * pins both halves on that route).
27742
27963
  *
27743
27964
  * THE BOUND, since this file's job is to state them: this covers a needle
27744
27965
  * split by a character `stripControlChars` removes. A needle split by
@@ -27772,7 +27993,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27772
27993
  * NEEDLE match that straddles a masked span, which is why the log lines go
27773
27994
  * through `logTwinText` rather than masking the twin alone.
27774
27995
  */
27775
- async resolveDynamicReferencesWithLogTwin(value, logTwin, context) {
27996
+ async resolveDynamicReferencesWithLogTwin(value, logTwin, context, inherited) {
27776
27997
  const pattern = /\{\{resolve:([^}]+)\}\}/g;
27777
27998
  let result = value;
27778
27999
  let twin = logTwin;
@@ -27782,14 +28003,22 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27782
28003
  fullMatch: match[0],
27783
28004
  inner: match[1]
27784
28005
  });
27785
- for (const { fullMatch, inner } of matches) {
28006
+ const twinTokens = dynamicReferenceTokens(logTwin);
28007
+ const tokensAligned = twinTokens.length === matches.length;
28008
+ for (const [index, { fullMatch, inner }] of matches.entries()) {
27786
28009
  const service = inner.split(":")[0];
28010
+ const pairedTwin = tokensAligned ? twinTokens[index] : void 0;
28011
+ const tokenLogText = inherited?.tokenLogText ?? (pairedTwin === void 0 ? "***" : this.straddleSafeTwin(fullMatch, pairedTwin, context));
28012
+ const nameLogText = inherited?.nameLogText ?? (pairedTwin === void 0 ? () => "***" : this.dynamicReferenceNameLogText(inner, pairedTwin, context));
27787
28013
  const isKnownSecret = service === "secretsmanager" || service === "ssm-secure" || recordedSecretExpressions.has(fullMatch);
27788
28014
  if (isKnownSecret && context?.skipDynamicReferences) continue;
27789
28015
  const regionVerdict = classifyReplaySecretRegion(fullMatch, this.explicitRegion ?? this.resolverRegion, context?.producerRegions);
27790
- if (regionVerdict.kind === "ambiguous") throw markNonRetryable(new DynamicReferenceRegionAmbiguousError(`Refusing to resolve the secret reference ${this.maskSecretsForLog(fullMatch, context)}: it names '${this.maskSecretsForLog(regionVerdict.secretName, context)}' without a region, and this stack reads from ${regionVerdict.foreignProducerRegions.join(", ")} as well as its own region. cdkd cannot tell which one must answer, and resolving against the wrong one yields a different secret. Spell the reference as a full ARN to say which region owns it.`));
28016
+ if (regionVerdict.kind === "ambiguous") throw markNonRetryable(new DynamicReferenceRegionAmbiguousError(`Refusing to resolve the secret reference ${this.maskSecretsForLog(tokenLogText, context)}: it names '${this.maskSecretsForLog(nameLogText(regionVerdict.secretName), context)}' without a region, and this stack reads from ${this.maskSecretsForLog(regionVerdict.foreignProducerRegions.map((r) => this.maskSecretsForLog(r, context)).join(", "), context)} as well as its own region. cdkd cannot tell which one must answer, and resolving against the wrong one yields a different secret. Spell the reference as a full ARN to say which region owns it.`));
27791
28017
  if (regionVerdict.kind === "named-region") {
27792
- const foreign = await this.resolverForProducerRegion(regionVerdict.region).resolveDynamicReferencesWithLogTwin(fullMatch, fullMatch, withoutProducerRegions(context));
28018
+ const foreign = await this.resolverForProducerRegion(regionVerdict.region, context, nameLogText(regionVerdict.region)).resolveDynamicReferencesWithLogTwin(fullMatch, fullMatch, withoutProducerRegions(context), {
28019
+ tokenLogText,
28020
+ nameLogText
28021
+ });
27793
28022
  result = result.replace(fullMatch, () => foreign.result);
27794
28023
  twin = twin.replace(fullMatch, () => foreign.twin);
27795
28024
  continue;
@@ -27820,10 +28049,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27820
28049
  * which caches nothing (issue #1933).
27821
28050
  */
27822
28051
  let cacheable = true;
27823
- if (service === "secretsmanager") resolved = await this.resolveSecretsManagerReference(inner, context);
28052
+ if (service === "secretsmanager") resolved = await this.resolveSecretsManagerReference(inner, context, nameLogText);
27824
28053
  else if (service === "ssm") {
27825
28054
  const decrypt = context?.skipDynamicReferences !== true;
27826
- const param = await this.resolveSSMReference(parts, decrypt, "ssm", context);
28055
+ const param = await this.resolveSSMReference(parts, decrypt, "ssm", context, nameLogText);
27827
28056
  if (param.type === "SecureString") this.pinSecretVerdict(fullMatch, true);
27828
28057
  else if (!param.secure) this.pinSecretVerdict(fullMatch, false);
27829
28058
  else cacheable = false;
@@ -27833,12 +28062,12 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27833
28062
  }
27834
28063
  resolved = param.value;
27835
28064
  } else if (service === "ssm-secure") {
27836
- const param = await this.resolveSSMReference(parts, true, "ssm-secure", context);
27837
- if (!param.secure) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Refusing to resolve ${this.maskSecretsForLog(fullMatch, context)}: the parameter is a ${param.type} parameter, and the ssm-secure spelling is defined for SecureString parameters only. Reference it as {{resolve:ssm:...}} if it is public configuration.`));
28065
+ const param = await this.resolveSSMReference(parts, true, "ssm-secure", context, nameLogText);
28066
+ if (!param.secure) throw markNonRetryable(new IntrinsicResolutionRefusalError(`Refusing to resolve ${this.maskSecretsForLog(tokenLogText, context)}: the parameter is a ${param.type} parameter, and the ssm-secure spelling is defined for SecureString parameters only. Reference it as {{resolve:ssm:...}} if it is public configuration.`));
27838
28067
  isSecret = true;
27839
28068
  resolved = param.value;
27840
28069
  } else {
27841
- this.logger.warn(this.maskSecretsForLog(`Unsupported dynamic reference service: ${service}`, context));
28070
+ this.logger.warn(this.maskSecretsForLog(`Unsupported dynamic reference service: ${this.maskSecretsForLog(nameLogText(String(service)), context)}`, context));
27842
28071
  continue;
27843
28072
  }
27844
28073
  if (cacheable) this.cachedDynamicReferences.set(fullMatch, {
@@ -27874,7 +28103,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27874
28103
  * runs when no mid-string ":SecretString:" delimiter is present, so the json-key / version
27875
28104
  * forms are unaffected.)
27876
28105
  */
27877
- async resolveSecretsManagerReference(inner, context) {
28106
+ async resolveSecretsManagerReference(inner, context, nameLogText) {
27878
28107
  const afterService = inner.substring(15);
27879
28108
  let secretId;
27880
28109
  let jsonKey = "";
@@ -27903,9 +28132,9 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
27903
28132
  } else secretId = afterService;
27904
28133
  if (!versionStage) versionStage = "AWSCURRENT";
27905
28134
  if (!secretId) throw new Error("Dynamic reference: secretsmanager SECRET_ID is required");
27906
- const loggedSecretId = this.maskSecretsForLog(secretId, context);
27907
- const loggedJsonKey = this.maskSecretsForLog(jsonKey, context);
27908
- this.logger.debug(`Resolving dynamic reference: secretsmanager:${loggedSecretId}:SecretString:${loggedJsonKey}:${this.maskSecretsForLog(versionStage, context)}:${this.maskSecretsForLog(versionId, context)}`);
28135
+ const loggedSecretId = this.maskSecretsForLog(nameLogText(secretId), context);
28136
+ const loggedJsonKey = this.maskSecretsForLog(nameLogText(jsonKey), context);
28137
+ this.logger.debug(`Resolving dynamic reference: secretsmanager:${loggedSecretId}:SecretString:${loggedJsonKey}:${this.maskSecretsForLog(nameLogText(versionStage), context)}:${this.maskSecretsForLog(nameLogText(versionId), context)}`);
27909
28138
  const client = this.clientsForRegion(this.explicitRegion).secretsManager;
27910
28139
  const command = new GetSecretValueCommand({
27911
28140
  SecretId: secretId,
@@ -28066,10 +28295,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28066
28295
  * discard the value when `secure` is set — it is ciphertext, not the resolved
28067
28296
  * reference.
28068
28297
  */
28069
- async resolveSSMReference(parts, decrypt = true, service = "ssm", context) {
28298
+ async resolveSSMReference(parts, decrypt, service, context, nameLogText) {
28070
28299
  const parameterName = parts.slice(1).join(":");
28071
28300
  if (!parameterName) throw new Error(`Dynamic reference: ${service} PARAMETER_NAME is required`);
28072
- const loggedParameterName = this.maskSecretsForLog(parameterName, context);
28301
+ const loggedParameterName = this.maskSecretsForLog(nameLogText(parameterName), context);
28073
28302
  this.logger.debug(`Resolving dynamic reference: ${service}:${loggedParameterName}`);
28074
28303
  const client = this.clientsForRegion(this.explicitRegion).ssm;
28075
28304
  const command = new GetParameterCommand({
@@ -29421,7 +29650,7 @@ var CloudControlProvider = class {
29421
29650
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
29422
29651
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
29423
29652
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
29424
- const { ASGProvider } = await import("./asg-provider-CpUSth0q.js").then((n) => n.n);
29653
+ const { ASGProvider } = await import("./asg-provider-D5-3SGmd.js").then((n) => n.n);
29425
29654
  const asgProvider = new ASGProvider();
29426
29655
  return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
29427
29656
  }
@@ -36996,12 +37225,18 @@ const SKIP_FINAL_SNAPSHOT_FLAG = "--skip-final-snapshot";
36996
37225
  * `update()` (`this.create(...)` in ACM certificate / IAM managed policy / IAM
36997
37226
  * role / Lambda permission / SNS subscription). Those are NOT template-driven
36998
37227
  * — this executor's `revert` arm calls `provider.update(...)` with
36999
- * `previousState.properties`, so they forward a STATE record on a replay — but
37000
- * they CANNOT receive a `CreateContext`: `update()`'s own context is an
37001
- * `UpdateContext`, which carries no `replayingState` to forward.
37002
- * The constraint that follows is on providers, not on this constant: a
37003
- * provider with a create-side pre-flight refusal must not re-create inside
37004
- * `update()`. See `CreateContext` in `src/types/resource.ts`.
37228
+ * `previousState.properties`, so they forward a STATE record on a replay — and
37229
+ * they still pass NO `CreateContext`, so a create-side pre-flight refusal
37230
+ * would still fire there. The constraint that follows is on providers, not on
37231
+ * this constant: a provider with a create-side pre-flight refusal must not
37232
+ * re-create inside `update()`. See `CreateContext` in `src/types/resource.ts`.
37233
+ *
37234
+ * What issue [#3141](https://github.com/go-to-k/cdkd/issues/3141) changed is
37235
+ * that the INFORMATION now exists on that path — `UpdateContext` carries its
37236
+ * own `replayingState`, set by both revert arms below — so such a provider
37237
+ * could build a `CreateContext` from it instead of relying on the constraint.
37238
+ * None does today; the five sites are untouched. Read that as a route that
37239
+ * opened, not as a constraint that lifted.
37005
37240
  */
37006
37241
  const REPLAYING_STATE_CREATE_CONTEXT = { replayingState: true };
37007
37242
  /**
@@ -38122,7 +38357,7 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
38122
38357
  });
38123
38358
  } catch (createError) {
38124
38359
  const msg = createError instanceof Error ? createError.message : String(createError);
38125
- if (!isNameCollisionError(msg)) throw createError;
38360
+ if (!isNameCollisionErrorFrom(createError, op.logicalId)) throw createError;
38126
38361
  if (rollbackRetainsNewResource(current)) throw markNonRetryable(new CdkdError(maskSecretsInText(`Cannot reverse the replacement of ${safe(op.logicalId)} (${safe(op.resourceType)}): the re-create of the old resource (${safe(prev.physicalId)}) collided with the name still held by the new one (${safe(current.physicalId)}), and UpdateReplacePolicy: Retain pins that new resource in place, so cdkd will not delete it to free the name. Delete the new resource yourself, or remove UpdateReplacePolicy: Retain, then re-run \`cdkd rollback\` — the journal is kept, so the revert resumes from here. To leave THIS resource alone and let the rest of the rollback proceed, re-run with ` + (typeof op.logicalId === "string" && PASTEABLE_LOGICAL_ID.test(op.logicalId) ? `\`cdkd rollback --orphan ${op.logicalId}\`: one op failure stops the ` : "`cdkd rollback --orphan <id>` (the id is withheld: it is not a plain CloudFormation logical id, so a pasted command could be reshaped by the shell or name a different resource -- read it from `cdkd events`): one op failure stops the ") + `segment loop, so a single pinned resource otherwise halts every OLDER segment too. Underlying collision: ${displaySafe(msg)}`, secrets), "NAMED_REPLACEMENT_COLLISION", maskSecretsInError(createError instanceof Error ? createError : void 0, secrets)));
38127
38362
  logger.info(` Rollback: re-create collided with the new resource's name — deleting the new resource (${displaySafe(current.physicalId)}) first...`);
38128
38363
  {
@@ -38221,7 +38456,8 @@ async function replaySingle(op, stateResources, stackName, ctx, resolver, orphan
38221
38456
  currentProps ?? {},
38222
38457
  {
38223
38458
  maskSecrets: createSecretMasker(secrets),
38224
- expectedRegion: ctx.region
38459
+ expectedRegion: ctx.region,
38460
+ replayingState: true
38225
38461
  }
38226
38462
  ], op.logicalId, logger, isInterrupted, secrets);
38227
38463
  stateResources[op.logicalId] = redactRollbackRecord(recordAfterRollbackUpdate(previousState, revertResult), secrets, previousState.properties);
@@ -38389,7 +38625,8 @@ async function replayFailedOperations(failedOps, stateResources, stackName, ctx,
38389
38625
  attemptedProps ?? {},
38390
38626
  {
38391
38627
  maskSecrets: createSecretMasker(secrets),
38392
- expectedRegion: ctx.region
38628
+ expectedRegion: ctx.region,
38629
+ replayingState: true
38393
38630
  }
38394
38631
  ], op.logicalId, logger, options.isInterrupted, secrets);
38395
38632
  stateResources[op.logicalId] = redactRollbackRecord(recordAfterRollbackUpdate(prev, revertFailedResult), secrets, prev.properties);
@@ -41259,7 +41496,7 @@ var DeployEngine = class DeployEngine {
41259
41496
  createResult = await this.withRetry(() => withCurrentResourceSecrets(updateSecrets, () => replaceProvider.create(logicalId, resourceType, replaceProps, { maskSecrets: createSecretMasker(updateSecrets) })), logicalId, void 0, void 0, replaceProvider);
41260
41497
  } catch (createError) {
41261
41498
  const createMsg = createError instanceof Error ? createError.message : String(createError);
41262
- if (!isNameCollisionError(createMsg)) throw createError;
41499
+ if (!isNameCollisionErrorFrom(createError, logicalId)) throw createError;
41263
41500
  const nameOrigin = this.replacementNameOrigin(logicalId, currentResource.physicalId);
41264
41501
  if (updateReplacePolicy === "Retain") throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but its physical name is still held by the existing resource AND UpdateReplacePolicy: Retain pins that resource in place. ${nameOrigin.descriptor}. ${nameOrigin.remedy} — with Retain, the old resource keeps the name, so a same-name replacement can never proceed.`, "NAMED_REPLACEMENT_COLLISION");
41265
41502
  if (this.options.replace !== true) throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but the create-first attempt collided with the existing resource: ${createMsg}. ${nameOrigin.descriptor}, so the CloudFormation-style safe replacement order (create the new resource before deleting the old) cannot reuse the occupied name — CloudFormation refuses this shape with "cannot update a stack when a custom-named resource requires replacing". ${nameOrigin.remedy}, or re-run with \`cdkd deploy --replace\` to delete the old resource FIRST and recreate it under the same name (the resource is briefly unavailable while it is recreated).`, "NAMED_REPLACEMENT_COLLISION");
@@ -41395,8 +41632,7 @@ var DeployEngine = class DeployEngine {
41395
41632
  createResult = await this.withRetry(() => withCurrentResourceSecrets(updateSecrets, () => replProvider.create(logicalId, resourceType, replProps, { maskSecrets: createSecretMasker(updateSecrets) })), logicalId, void 0, void 0, replProvider);
41396
41633
  } catch (createError) {
41397
41634
  if (!retainOldOnReplace) throw new Error(maskSecretsInText(`Failed to create ${logicalId} after the UPDATE-not-supported replacement: the old resource (${currentResource.physicalId}) is now gone. Cause: ${createError instanceof Error ? createError.message : String(createError)}. Re-run the deploy to create it fresh.`, updateSecrets), { cause: createError instanceof Error ? createError : void 0 });
41398
- const createMsg = createError instanceof Error ? createError.message : String(createError);
41399
- if (!isNameCollisionError(createMsg)) throw createError;
41635
+ if (!isNameCollisionErrorFrom(createError, logicalId)) throw createError;
41400
41636
  const nameOrigin = this.replacementNameOrigin(logicalId, currentResource.physicalId);
41401
41637
  throw markNonRetryable(new CdkdError(`${logicalId} (${resourceType}) requires replacement because the provisioning layer cannot update it in place — but its physical name is still held by the existing resource AND UpdateReplacePolicy: Retain pins that resource in place. ${nameOrigin.descriptor}. ${nameOrigin.remedy} — with Retain, the old resource keeps the name, so a same-name replacement can never proceed. Removing UpdateReplacePolicy: Retain lets cdkd delete the old resource first, which destroys it and any data it holds.`, "NAMED_REPLACEMENT_COLLISION", createError instanceof Error ? createError : void 0));
41402
41638
  }
@@ -41680,7 +41916,7 @@ var DeployEngine = class DeployEngine {
41680
41916
  if (!(error instanceof ProvisioningError)) return void 0;
41681
41917
  const physicalId = error.physicalId;
41682
41918
  if (!physicalId) return void 0;
41683
- if (!isNameCollisionError(error.message)) return void 0;
41919
+ if (!isNameCollisionErrorFrom(error, logicalId)) return void 0;
41684
41920
  const stackName = getCurrentStackName();
41685
41921
  if (!looksLikeCdkdGeneratedName(physicalId, logicalId, stackName)) return void 0;
41686
41922
  if (!stackName) return void 0;
@@ -42151,4 +42387,4 @@ var DeployEngine = class DeployEngine {
42151
42387
 
42152
42388
  //#endregion
42153
42389
  export { secretBearing as $, BOOTSTRAP_MARKER_PREFIX as $n, getAwsClients as $r, s3BucketRegionalDomainName as $t, extractDeploymentEventError as A, markNonRetryable as Ai, buildForceUnlockCommand as An, resolveAutoAssetStorage as Ar, parameterTypeMayLoseSecretIdentity as At, toCfnInteger as B, importableOutputs as Bn, MIGRATE_TMP_PREFIX as Br, configIntegerRefusal as Bt, buildFinalSnapshotIdentifier as C, isCdkdError as Ci, recordMaskOnlyValue as Cn, AssetManifestLoader as Cr, IntrinsicFunctionResolver as Ct, refusesFinalSnapshot as D, isRetryableTransientError as Di, LockManager as Dn, getDefaultStateBucketName as Dr, getAccountInfo as Dt, isFinalSnapshotError as E, isMarkedNonRetryable as Ei, scrubResourceRecord as En, synthesisStatusMessage as Er, coerceParameterTypedValue as Et, isStatefulRecreateTargetSync as F, CUSTOM_RESOURCE_RESPONSE_PREFIX as Fn, resolveUseCdkBootstrapAssets as Fr, resolveExplicitPhysicalId as Ft, gray as G, AssetPublisher as Gn, PARTITION_TABLE as Gr, requireConfigObject as Gt, formatResourceLine as H, orphansAfterRollback as Hn, uploadCfnTemplate as Hr, readConfigString as Ht, renderStatefulReason as I, DEFAULT_STATE_PREFIX as In, stateBucketExistenceConfirmed as Ir, assertRegionMatch as It, yellow as J, buildAssetRedirectMap as Jn, AssemblyReader as Jr, producerRegionsFromState as Jt, green as K, stringifyValue as Kn, canonicalizeRegion as Kr, requireConfigString as Kt, WARM_THROUGHPUT_MEMBERS as L, exportNamesCarriedFrom as Ln, warnDeprecatedNoPrefixCliFlag as Lr, coerceCfnBoolean as Lt, planOrphanAdoption as M, retryClassificationText as Mi, forceQuitRecoveryClause as Mn, resolveSkipPrefix as Mr, isSettledInstanceState as Mt, MULTI_REGION_RECREATE_BLOCKED_TYPES as N, __exportAll as Ni, formatLockExpiry as Nn, resolveStateBucketWithDefault as Nr, WAFv2WebACLProvider as Nt, unsupportedFinalSnapshotError as O, isThrottlingError as Oi, S3StateBackend as On, getLegacyStateBucketName as Or, isImpossibleEmptyStoredAttribute as Ot, isStatefulRecreateTargetForReplace as P, shellQuote as Pn, resolveStateBucketWithDefaultAndSource as Pr, normalizeAwsTagsToCfn as Pt, isExportAliasCollision as Q, AssetModeResolver as Qn, AwsClients as Qr, s3BucketDualStackDomainName as Qt, coerceWarmThroughput as R, hasReadableExportSet as Rn, CFN_TEMPLATE_BODY_LIMIT as Rr, coerceCfnInteger as Rt, PRE_DELETE_SNAPSHOT_TYPES as S, formatError as Si, maskSecretsInText as Sn, stripControlChars as Sr, isTerminationProtectionPropagationError as St, createPreDeleteFinalSnapshot as T, withErrorHandling as Ti, redactSecretsForState as Tn, Synthesizer as Tr, cfnRefValueFromPhysicalId as Tt, bold as U, orphansCarriedFrom as Un, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Ur, replayWarn as Ut, toFiniteNumber as V, isReadableBag as Vn, findLargeInlineResources as Vr, configStringRefusal as Vt, cyan as W, shouldRetainResource as Wn, expectedOwnerParam as Wr, requireConfigArray as Wt, collectPublishedOutputNames as X, loadPublishableAssetManifest as Xn, clearBucketRegionCache as Xr, s3BucketArn as Xt, collectDeclaredOutputNames as Y, createAssetRedirectResolver as Yn, processStackMessages as Yr, withSharedDrainBudget as Yt, exportAliasCollisionScrubWarning as Z, rewriteTemplateAssetReferences as Zn, resolveBucketRegion as Zr, s3BucketDomainName as Zt, isSecretBearingReferenceString as _, ResourceUpdateNotSupportedError as _i, errorCauseChain as _n, partitionSensitiveEnv as _r, slowCcOperationTimeoutMs as _t, DeploymentEventsStore as a, CrossAccountSecretRefusalError as ai, findSilentDropProperties as an, readBootstrapMarkerBody as ar, clearOnUpdateRemoval as at, bindingSkippedOutputs as b, StateError as bi, markSameGenerationBag as bn, runDockerStreaming as br, deleteSkipReason as bt, replayFailedOperations as c, DynamicReferenceRegionAmbiguousError as ci, DagBuilder as cn, buildDenyExternalAccessPolicy as cr, createMaskedRetryLogger as ct, updatePartialReason as d, LocalStartServiceError as di, STATE_SOURCED_CROSS_GENERATION_RULES as dn, describeDockerCapturedOutput as dr, beginCommandInterruptScope as dt, resetAwsClients as ei, s3BucketWebsiteUrl as en, assertAssetBucketRegion as er, secretBearingStateKeyWarning as et, withResourceDeadline as f, LockError as fi, STATE_SOURCED_READBACK_RULES as fn, describeDockerExecFailure as fr, endCommandInterruptScope as ft, bagHoldsSecretExpression as g, ResourceTimeoutError as gi, dynamicReferenceTokens as gn, getDockerCmd as gr, CloudControlProvider as gt, computeImplicitDeleteEdges as h, ProvisioningError as hi, createSecretMasker as hn, formatDockerLoginError as hr, startInterruptWatch as ht, DeploymentEventsReader as i, ConfigError as ii, findActionableSilentDrops as in, parseBootstrapMarker as ir, collectInlinePolicyNamesManagedBySiblings as it, makeSiblingClaimReader as j, markRedactedCause as ji, buildLockContentionMessage as jn, resolveCaptureObservedState as jr, refStateLookupFromResource as jt, makeCanonicalizePropertiesFn as k, isTransientServerError as ki, rebuildClientForBucketRegion as kn, resolveApp as kr, isUnboundTemplateParameter as kt, replayRollback as l, IntrinsicResolutionRefusalError as li, TemplateParser as ln, describeAwsFailure as lr, maskDeep as lt, IMPLICIT_DELETE_DEPENDENCIES as m, PartialFailureError as mi, carriesSecretMask as mn, dockerSpawnEnvWithSensitive as mr, isInterruptedWaitError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, AssetError as ni, DiffCalculator as nn, getBootstrapMarkerKey as nr, getCurrentResourceSecrets as nt, planFailedOps as o, DependencyError as oi, describeTypeWithThrottleRetry as on, validateAssetBucketName as or, ProviderRegistry as ot, maskingRetryLogger as p, NestedStackChildDirectDestroyError as pi, TEMPLATE_SOURCED_RULES as pn, describeDockerFailure as pr, interruptWatchListenerCount as pt, red as q, WorkGraph as qn, derivePartitionAndUrlSuffix as qr, classifyReplaySecretRegion as qt, DeployEngine as r, CdkdError as ri, INTRINSIC_KEYS as rn, isCrossRegionRedirect as rr, IAMRoleProvider as rt, planRollback as s, DeployCancelledError as si, withRetry as sn, validateContainerRepoName as sr, wouldReturnToSdkProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, setAwsClients as ti, applyRoleArnIfSet as tn, ensureAssetStorage as tr, secretSafeKeyDisplay as tt, updatePartialMessage as u, LocalInvokeBuildError as ui, STATE_SOURCED_BASELINE_RULES as un, buildDockerImage as ur, maskerOrIdentity as ut, keptWholeReasonText as v, StackHasActiveImportsError as vi, identityKeyFor as vn, redactDockerArgvValues as vr, UNSPECIFIED_SKIP_REASON as vt, ccRoutedFinalSnapshotError as w, normalizeAwsError as wi, recoverMaskedOutput as wn, getDockerImageBySourceHash as wr, carriesDynamicReference as wt, ATOMIC_FINAL_SNAPSHOT_TYPES as x, SynthesisError as xi, maskSecretsInError as xn, escapeRegExp$1 as xr, disableInstanceApiTermination as xt, mergeNoChangeOutputs as y, StackTerminationProtectionError as yi, isSingleDynamicReferenceToken as yn, runDockerForeground as yr, deleteIndeterminateGuards as yt, isWarmThroughputDecrease as z, importableOutputKeys as zn, CFN_TEMPLATE_URL_LIMIT as zr, configBooleanRefusal as zt };
42154
- //# sourceMappingURL=deploy-engine-omGpC16W.js.map
42390
+ //# sourceMappingURL=deploy-engine-C2qLzc-5.js.map