@go-to-k/cdkd 0.290.22 → 0.290.23

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
- import { C as displaySafe, S as displayIdent, b as STACK_REF_MAX_CODE_POINTS, 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, w as truncateCodePoints, x as UNRENDERABLE, y as withoutGeneratedFallbackName } from "./logger-C17H06QA.js";
1
+ import { C as displaySafe, S as displayIdent, b as STACK_REF_MAX_CODE_POINTS, 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, w as truncateCodePoints, x as UNRENDERABLE, y as withoutGeneratedFallbackName } from "./logger-CkHVgzLx.js";
2
2
  import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-BoIxyCir.js";
3
- import { t as getCdkdVersion } from "./version-CpOEkAtB.js";
3
+ import { t as getCdkdVersion } from "./version-DxUVmvM5.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";
@@ -7360,7 +7360,7 @@ function repairSpawnRefusal(text, args, maskedArgs) {
7360
7360
  * error would only say "Command failed with exit code N".
7361
7361
  */
7362
7362
  function describeDockerExecFailure(error, args) {
7363
- const message = thrownMessageText(error) || safeStringify(error);
7363
+ const message = thrownMessageText(error) || safeStringify$1(error);
7364
7364
  const stderrText = capturedStreamText(error, "stderr");
7365
7365
  return redactDockerArgvInText(stderrText ? `${message}\n${stderrText}` : message, args);
7366
7366
  }
@@ -7403,7 +7403,7 @@ function thrownMessageText(error) {
7403
7403
  * two of these call sites are in `cleanupEcsRun`, where an exception aborts
7404
7404
  * the remaining volume / network teardown and leaks real Docker resources.
7405
7405
  */
7406
- function safeStringify(error) {
7406
+ function safeStringify$1(error) {
7407
7407
  try {
7408
7408
  return String(error);
7409
7409
  } catch {
@@ -7429,7 +7429,7 @@ function safeStringify(error) {
7429
7429
  * wrapper text needs the status as well.
7430
7430
  */
7431
7431
  function describeDockerFailure(error, args) {
7432
- return redactDockerArgvInText(capturedStreamText(error, "stderr") || thrownMessageText(error) || safeStringify(error), args);
7432
+ return redactDockerArgvInText(capturedStreamText(error, "stderr") || thrownMessageText(error) || safeStringify$1(error), args);
7433
7433
  }
7434
7434
  /**
7435
7435
  * A `cause` that is safe to CHAIN onto a wrapper error, for a caller that
@@ -8019,6 +8019,40 @@ function isAwsAuthoredFailure(error) {
8019
8019
  return candidate.$fault !== void 0 || typeof candidate.$metadata?.httpStatusCode === "number" || error.name === "CredentialsProviderError";
8020
8020
  }
8021
8021
  /**
8022
+ * Exactly what `String(value)` produces, without the throw.
8023
+ *
8024
+ * `String(value)` is the only spelling that carries an `Error`'s NAME as well
8025
+ * as its message (`"AccessDenied: User ... is not authorized"`), and several
8026
+ * call sites depend on that: four build a persisted `outcome: 'partial'`
8027
+ * reason where the wire code is the discriminator an operator reads first.
8028
+ * {@link describeAwsFailure}'s `detail` is the MESSAGE only, so it is NOT a
8029
+ * drop-in for the bare form -- substituting it silently deletes the code.
8030
+ * Measured, after a sweep did exactly that at nine sites.
8031
+ *
8032
+ * So this is the 1:1 replacement: same output for every value `String` can
8033
+ * convert, and a stable sentence for the ones it cannot. A null-prototype
8034
+ * object throws `TypeError: Cannot convert object to primitive value`, and an
8035
+ * object with a hostile or `null` `toString` throws whatever it likes -- inside
8036
+ * a catch, that replaces the failure being reported.
8037
+ *
8038
+ * Use `describeAwsFailure(x).detail` where the site previously read
8039
+ * `x instanceof Error ? x.message : String(x)`; use THIS where it read a bare
8040
+ * `String(x)`.
8041
+ *
8042
+ * NOT a substitute for `displaySafe` in `display-safe.ts`, which guards the
8043
+ * same coercion and answers differently on purpose -- it falls back to
8044
+ * `Object.prototype.toString` and, more importantly, SANITISES the result for a
8045
+ * terminal. Anything about to be rendered or logged goes through that one; this
8046
+ * one is for the text a catch is about to record.
8047
+ */
8048
+ function safeStringify(value) {
8049
+ try {
8050
+ return String(value);
8051
+ } catch {
8052
+ return "a value that could not be converted to text";
8053
+ }
8054
+ }
8055
+ /**
8022
8056
  * Describe a caught failure for a thrown message. See {@link AwsFailureText}.
8023
8057
  */
8024
8058
  function describeAwsFailure(error) {
@@ -11935,6 +11969,84 @@ function resolvedPlaintextOf(secrets, expression) {
11935
11969
  function resolvedExpressionsOf(secrets) {
11936
11970
  return [...resolvedPairsOf.get(secrets)?.keys() ?? []];
11937
11971
  }
11972
+ /** Poison for an intrinsic object one pass resolved two different ways. */
11973
+ const CONFLICTING_LEAF_RESOLUTION = Symbol("conflicting leaf resolution");
11974
+ /**
11975
+ * {@link IntrinsicLeafResolution}s per pass bag, keyed by the template OBJECT
11976
+ * that was resolved (issue [#3156](https://github.com/go-to-k/cdkd/issues/3156)).
11977
+ * The carry in {@link recordNestedStackParameterExpressions} reads it for the
11978
+ * very object the deploy engine handed the resolver, so its evidence is THIS
11979
+ * leaf's own resolution: no other leaf's substitution, however equal its value,
11980
+ * can answer for it, and each substitution carries its own verdict, which the
11981
+ * secret-only pair table cannot (an unclassifiable `ssm` answer recorded as a
11982
+ * pair looks the same as a later public answer with the same plaintext).
11983
+ * Both keys are weak, so a record lives as long as its bag and its template.
11984
+ */
11985
+ const intrinsicLeafResolutionsOf = /* @__PURE__ */ new WeakMap();
11986
+ /**
11987
+ * Record how the pass that owns `secrets` resolved the intrinsic object
11988
+ * `source`. A second resolution of the same object that differs in any field
11989
+ * poisons it for the pass, and the poison is never lifted; an identical one
11990
+ * changes nothing.
11991
+ */
11992
+ function recordIntrinsicLeafResolution(secrets, source, resolution) {
11993
+ let leaves = intrinsicLeafResolutionsOf.get(secrets);
11994
+ if (leaves === void 0) {
11995
+ leaves = /* @__PURE__ */ new WeakMap();
11996
+ intrinsicLeafResolutionsOf.set(secrets, leaves);
11997
+ }
11998
+ const copy = {
11999
+ input: resolution.input,
12000
+ output: resolution.output,
12001
+ substitutions: resolution.substitutions.map(({ token, value, secret }) => ({
12002
+ token,
12003
+ value,
12004
+ secret
12005
+ })),
12006
+ complete: resolution.complete
12007
+ };
12008
+ const previous = leaves.get(source);
12009
+ if (previous === void 0) leaves.set(source, copy);
12010
+ else if (previous === CONFLICTING_LEAF_RESOLUTION || !sameLeafResolution(previous, copy)) leaves.set(source, CONFLICTING_LEAF_RESOLUTION);
12011
+ }
12012
+ function sameLeafResolution(a, b) {
12013
+ return a.input === b.input && a.output === b.output && a.complete === b.complete && a.substitutions.length === b.substitutions.length && a.substitutions.every((s, i) => s.token === b.substitutions[i].token && s.value === b.substitutions[i].value && s.secret === b.substitutions[i].secret);
12014
+ }
12015
+ /**
12016
+ * The spelling `source`'s own resolution in this pass proves for
12017
+ * `resolvedValue`, or `undefined` (issue
12018
+ * [#3156](https://github.com/go-to-k/cdkd/issues/3156)). Certified only when
12019
+ * the resolution replaced every token it met, replaced exactly ONE, took a
12020
+ * SECRET verdict for it, and produced `resolvedValue` from `input` by that one
12021
+ * replacement ({@link singleSpanFrame} over `input` with the token and value
12022
+ * equal). That is the observed equation `resolvedValue = input[token := value]`;
12023
+ * it says nothing about what a later lookup of the token returns.
12024
+ *
12025
+ * The `secret` test and the COUNT are independent. The count refuses a
12026
+ * replacement listed ahead of the one the frame names that left its plaintext,
12027
+ * not its token, in `input` -- a used Sub variable holding the SAME token as
12028
+ * the template (`port:T${V}` with `V` = `T`), whose first replacement passes
12029
+ * the token and value tests while `input` keeps the variable's plaintext.
12030
+ * `complete`, `output` and the token and value tests are implied, for every
12031
+ * shape the resolver records, by the count and `singleSpanFrame` over `input`:
12032
+ * a token left unreplaced in `input` is a second span, and a frame that fits
12033
+ * `input` around the one replacement fixes the output it produces. They are
12034
+ * kept so a recorder that is not faithful refuses rather than certifies, and
12035
+ * are pinned by hand-built records only.
12036
+ */
12037
+ function substitutedSpellingOf(secrets, source, resolvedValue) {
12038
+ const resolution = intrinsicLeafResolutionsOf.get(secrets)?.get(source);
12039
+ if (resolution === void 0 || resolution === CONFLICTING_LEAF_RESOLUTION) return void 0;
12040
+ if (!resolution.complete || resolution.output !== resolvedValue) return void 0;
12041
+ if (resolution.substitutions.length !== 1) return void 0;
12042
+ const [substitution] = resolution.substitutions;
12043
+ if (!substitution.secret) return void 0;
12044
+ const frame = singleSpanFrame(resolvedValue, resolution.input);
12045
+ if (frame === void 0) return void 0;
12046
+ if (frame.token !== substitution.token || frame.middle !== substitution.value) return void 0;
12047
+ for (const plaintext of secrets.keys()) if (plaintext !== "" && (frame.prefix.includes(plaintext) || frame.suffix.includes(plaintext))) return;
12048
+ return resolution.input;
12049
+ }
11938
12050
  /**
11939
12051
  * The bag OBJECTS a deploy pass produced ITSELF and installed on a success
11940
12052
  * path — the fact the resolved-pair evidence above cannot state (issue
@@ -12886,8 +12998,9 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
12886
12998
  * literal source; pinned by the "map NO RESOLVER populated" case,
12887
12999
  * where (ii) and (iii) both pass and only the missing pair refuses.
12888
13000
  * On an OBJECT source (`Fn::Join` / `Fn::Sub`, issue #3062) there is
12889
- * no source text to compare, so the spelling is what the pass WROTE,
12890
- * admitted only when `positioned[name] !== resolvedValue`. Sound
13001
+ * no source text to compare, so the spelling-based arm takes what
13002
+ * the pass WROTE, admitted only when `positioned[name] !==
13003
+ * resolvedValue`. Sound
12891
13004
  * together with (ii), not alone: on a value the scan is silent on,
12892
13005
  * the cross-stack and skeleton arms both refuse (each requires the
12893
13006
  * WHOLE leaf to be a key of the map, which would make the scan's
@@ -12895,16 +13008,23 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
12895
13008
  * scan leaves the leaf alone -- so the frame arm is the only writer
12896
13009
  * that can have rewritten it, on its pair and the engine's mark. A
12897
13010
  * frame that is not wholly literal makes that arm refuse, the leaf
12898
- * comes back unrewritten, and (i) refuses too. The object arm
12899
- * certifies only a source whose OWN rendered token starts with a
13011
+ * comes back unrewritten, and this arm refuses too. It certifies
13012
+ * only a source whose OWN rendered token starts with a
12900
13013
  * spelled-secret prefix (`secretsmanager:` / `ssm-secure:`), read from
12901
13014
  * the source and never from what the pass wrote: the frame arm
12902
13015
  * matches among RECORDED references and a public `ssm` parameter
12903
13016
  * records none, so a public leaf whose source spells `ssm:`, or leaves
12904
13017
  * the service to an intrinsic part, can match a recorded secret
12905
- * sibling and be written as the sibling's reference. A SecureString
12906
- * spelled either way is indistinguishable here, so both are refused
12907
- * (see (e)). The STATE-derived
13018
+ * sibling and be written as the sibling's reference. Where it refuses,
13019
+ * the PROVENANCE arm (issue #3156) certifies on the leaf's own
13020
+ * resolution instead: the resolver records, per `Fn::Join` /
13021
+ * `Fn::Sub` object and pass bag, every token it replaced with the
13022
+ * verdict that replacement took, and one SECRET replacement that turns
13023
+ * the record's input into the value certifies that input as the
13024
+ * spelling -- an `ssm:` or intrinsic-service token, and a frame whose
13025
+ * non-literal part sits OUTSIDE the token, which the frame arm never
13026
+ * writes. `frameSpellingOf` states what it proves and what it does
13027
+ * not. The STATE-derived
12908
13028
  * call sites reach this arm as well: `cdkd import` can leave raw
12909
13029
  * intrinsics in a record's `properties`, which a rollback replay
12910
13030
  * passes as its source, and the frame arm does not read `rules`.
@@ -12940,10 +13060,9 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
12940
13060
  * (i)-(iii) on its own), a leaf (iii) refused under a different
12941
13061
  * frame, an object spelling the frame arm refused and a plain
12942
13062
  * literal equal to the value all fail it and would take the entry's
12943
- * frame (an object spelling the arm POSITIONED whose own source
12944
- * spells a secret service is a frame like a literal one, issue
12945
- * #3062; one whose source does not counts as unframed) -- and so
12946
- * would a
13063
+ * frame (an object spelling (i) certified is a frame like a literal
13064
+ * one, issues #3062 and #3156; one it refused counts as unframed) --
13065
+ * and so would a
12947
13066
  * same-frame sibling whose token this pass never resolved to the
12948
13067
  * middle: a PUBLIC `ssm` reference in the same `port:` frame holding
12949
13068
  * the same two characters is kept RESOLVED on the record, and the
@@ -12952,7 +13071,13 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
12952
13071
  * the row are gathered BEFORE the conditions run, a spelling that is
12953
13072
  * not a single-span literal frame with this pass's pair for its token
12954
13073
  * (`resolvedPlaintextOf`) counting as its own, and a value is
12955
- * recorded only when its certified frame is the row's only one.
13074
+ * recorded only when its certified frame is the row's only one. A
13075
+ * value one of whose leaves the position pass did NOT write (the
13076
+ * provenance arm's outside-the-token frame) also counts as unframed
13077
+ * unless every framed spelling of it carries ONE token: the frame arm
13078
+ * refuses that leaf on the parent's record, so the entry is written
13079
+ * onto it by the value scan whatever its token, and (iii)'s rescue
13080
+ * for a same-frame sibling does not reach it.
12956
13081
  * (v) No OTHER string leaf of the ROW would be rewritten by the entry,
12957
13082
  * read over every leaf of the resolved row since the bag is per
12958
13083
  * resource, not per `Parameters`. Two arms of the persist walk read
@@ -13038,16 +13163,29 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
13038
13163
  * persists the plaintext -- the same class as the nonliteral-frame deferral.
13039
13164
  * (e) CLOSED for a wholly literal frame by (i)'s object arm (issue #3062;
13040
13165
  * was: an `Fn::Join` / `Fn::Sub` source in the parent's own `Parameters`
13041
- * block was never carried). What remains of it: an object source whose frame
13042
- * is NOT wholly literal -- a region `Ref` outside the token -- is refused by
13043
- * the frame arm, so (i) refuses it and the child leaf keeps the plaintext,
13044
- * the same nonliteral-frame deferral the parent's own record has; and an
13045
- * intrinsic frame whose token spells `ssm:`, or leaves its service to an
13046
- * intrinsic part, is refused by (i) whatever the parameter's type, so a 1-3
13047
- * character SecureString spelled that way keeps the plaintext in the child
13048
- * too. That refusal is what keeps the frame arm's own wrong-reference
13049
- * residual -- a public leaf matching a recorded sibling -- on the parent's
13050
- * record instead of carrying it into the child's. (f) A child record persisted BEFORE this carry
13166
+ * block was never carried), and for the two spellings that arm refused -- a
13167
+ * token spelling `ssm:` or leaving its service to an intrinsic part, and a
13168
+ * frame whose non-literal part sits outside the token -- by its provenance
13169
+ * arm (issue #3156), which on the second also rewrites the PARENT's record of
13170
+ * the leaf through the entry. What remains of it: a leaf whose own resolution
13171
+ * does not certify -- the token spelled inside a NESTED intrinsic part (the
13172
+ * outer object's own text spells none), the token held by a used `Fn::Sub`
13173
+ * variable (the template spells a placeholder there), a leaf resolved two
13174
+ * different ways in one pass, one whose replacement took a public verdict, one
13175
+ * that replaced more than one token, one whose affix holds a plaintext the bag
13176
+ * holds (another secret a non-literal part resolved), an `Fn::If` around the
13177
+ * object (which the skeleton cannot render, and whose record is under the
13178
+ * selected branch) -- keeps the plaintext in the child, and for the
13179
+ * outside-the-token frame in the parent's record; so does an outside-the-token
13180
+ * frame sharing its value with a leaf of another token, which (iv) refuses. A
13181
+ * rollback replay records nothing here (`resolveReplayProps` resolves strings,
13182
+ * not intrinsic objects): a journal a deploy wrote holds a carried frame's
13183
+ * persisted spelling as a STRING, which the literal arm reads, while a record
13184
+ * `cdkd import` left holding the raw intrinsic stays refused on this arm
13185
+ * (go-to-k/cdkd#3306 tracks the refused shapes). Any other resolved
13186
+ * text a non-literal part contributes is carried verbatim in the spelling, as
13187
+ * the value already carries it.
13188
+ * (f) A child record persisted BEFORE this carry
13051
13189
  * keeps `port:q7` until the child is next redeployed: the parent's own row
13052
13190
  * already held the frame (the literal or frame arm), so a parent deploy whose child
13053
13191
  * row is unchanged never re-runs the child, and `cdkd scrub` cannot repair
@@ -13083,12 +13221,19 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
13083
13221
  }
13084
13222
  const framesByValue = /* @__PURE__ */ new Map();
13085
13223
  const tokensOf = /* @__PURE__ */ new Map();
13086
- const frameSpellingOf = (name, resolvedValue) => {
13224
+ const frameSpellings = /* @__PURE__ */ new Map();
13225
+ const frameSpellingOf = (name) => {
13226
+ if (!frameSpellings.has(name)) frameSpellings.set(name, computeFrameSpelling(name));
13227
+ return frameSpellings.get(name);
13228
+ };
13229
+ const computeFrameSpelling = (name) => {
13230
+ const resolvedValue = resolvedParameters[name];
13231
+ if (typeof resolvedValue !== "string") return void 0;
13087
13232
  const sourceLeaf = sourceParameters[name];
13088
13233
  if (typeof sourceLeaf === "string") return sourceLeaf;
13089
13234
  if (!isPlainObject$2(sourceLeaf)) return void 0;
13090
13235
  const written = positioned[name];
13091
- if (typeof written !== "string" || written === resolvedValue) return void 0;
13236
+ if (typeof written !== "string") return void 0;
13092
13237
  const segments = intrinsicSkeletonSegments(sourceLeaf);
13093
13238
  if (segments === void 0) return void 0;
13094
13239
  const rendered = segments.map((s) => s === UNKNOWN_PART ? UNKNOWN_PART_PLACEHOLDER : s).join("");
@@ -13096,16 +13241,20 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
13096
13241
  if (spans.length !== 1) return void 0;
13097
13242
  const [span] = spans;
13098
13243
  const ownToken = rendered.slice(span.start, span.end);
13099
- return SPELLED_SECRET_REFERENCE_PREFIXES.some((prefix) => ownToken.startsWith(prefix)) ? written : void 0;
13244
+ if (written !== resolvedValue && SPELLED_SECRET_REFERENCE_PREFIXES.some((prefix) => ownToken.startsWith(prefix))) return written;
13245
+ const substituted = substitutedSpellingOf(secrets, sourceLeaf, resolvedValue);
13246
+ if (substituted === void 0) return void 0;
13247
+ return written === resolvedValue || written === substituted ? substituted : void 0;
13100
13248
  };
13101
- const certifiedSpellingOf = (name, resolvedValue) => {
13249
+ const certifiedSpellingOf = (name) => {
13102
13250
  const sourceLeaf = sourceParameters[name];
13103
13251
  if (typeof sourceLeaf === "string") return positioned[name] === sourceLeaf ? sourceLeaf : void 0;
13104
- return frameSpellingOf(name, resolvedValue);
13252
+ return frameSpellingOf(name);
13105
13253
  };
13254
+ const unwrittenValues = /* @__PURE__ */ new Set();
13106
13255
  for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
13107
13256
  if (typeof resolvedValue !== "string") continue;
13108
- const spelling = frameSpellingOf(name, resolvedValue);
13257
+ const spelling = frameSpellingOf(name);
13109
13258
  const frame = spelling === void 0 ? void 0 : singleSpanFrame(resolvedValue, spelling);
13110
13259
  const frames = framesByValue.get(resolvedValue) ?? /* @__PURE__ */ new Set();
13111
13260
  const unframed = frame === void 0 || resolvedPlaintextOf(secrets, frame.token) !== frame.middle;
@@ -13115,8 +13264,10 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
13115
13264
  const tokens = tokensOf.get(resolvedValue) ?? /* @__PURE__ */ new Set();
13116
13265
  tokens.add(frame.token);
13117
13266
  tokensOf.set(resolvedValue, tokens);
13267
+ if (typeof sourceParameters[name] !== "string" && positioned[name] !== spelling) unwrittenValues.add(resolvedValue);
13118
13268
  }
13119
13269
  }
13270
+ for (const value of unwrittenValues) if (tokensOf.get(value)?.size !== 1) framesByValue.get(value)?.add(UNFRAMED_SPELLING);
13120
13271
  const rowWithoutParameters = {};
13121
13272
  for (const [key, value] of Object.entries(resolvedProperties)) if (key !== "Parameters") rowWithoutParameters[key] = value;
13122
13273
  const outsideLeaves = wholeStringLeavesOf(rowWithoutParameters);
@@ -13124,7 +13275,7 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
13124
13275
  const framedByName = [];
13125
13276
  for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
13126
13277
  if (typeof resolvedValue !== "string") continue;
13127
- const spelling = certifiedSpellingOf(name, resolvedValue);
13278
+ const spelling = certifiedSpellingOf(name);
13128
13279
  if (spelling === void 0) continue;
13129
13280
  if (redactSecretsForState(resolvedValue, secrets) !== resolvedValue) continue;
13130
13281
  const frame = singleSpanFrame(resolvedValue, spelling);
@@ -17884,7 +18035,7 @@ function getCreateOnlyPropertyPaths(resourceType) {
17884
18035
  if (cached) return cached;
17885
18036
  const entry = fetchCreateOnlyPropertyPaths(resourceType).catch((error) => {
17886
18037
  createOnlyPropertiesCache.delete(resourceType);
17887
- const message = error instanceof Error ? error.message : String(error);
18038
+ const message = describeAwsFailure(error).detail;
17888
18039
  getLogger().child("CreateOnlyProperties").warn(`Failed to resolve create-only properties for ${resourceType} via cloudformation:DescribeType (${message}). Falling back to the registry-only replacement classification for this resource — an immutable-property change may be mis-classified as an in-place update. Grant cloudformation:DescribeType to enable schema-driven replacement detection.`);
17889
18040
  return [];
17890
18041
  });
@@ -24743,7 +24894,7 @@ var WAFv2WebACLProvider = class {
24743
24894
  const tagsResp = await this.getClient().send(new ListTagsForResourceCommand$11({ ResourceARN: physicalId }));
24744
24895
  result["Tags"] = normalizeAwsTagsToCfn(tagsResp.TagInfoForResource?.TagList);
24745
24896
  } catch (err) {
24746
- this.logger.debug(`WAFv2 ListTagsForResource(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`);
24897
+ this.logger.debug(`WAFv2 ListTagsForResource(${physicalId}) failed: ${describeAwsFailure(err).detail}`);
24747
24898
  }
24748
24899
  return result;
24749
24900
  }
@@ -26967,8 +27118,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
26967
27118
  const obj = value;
26968
27119
  if ("Ref" in obj) return await this.resolveRef(obj["Ref"], context);
26969
27120
  if ("Fn::GetAtt" in obj) return await this.resolveGetAtt(obj["Fn::GetAtt"], context);
26970
- if ("Fn::Join" in obj) return await this.resolveJoin(obj["Fn::Join"], context);
26971
- if ("Fn::Sub" in obj) return await this.resolveSub(obj["Fn::Sub"], context);
27121
+ if ("Fn::Join" in obj) return await this.resolveJoin(obj["Fn::Join"], context, obj);
27122
+ if ("Fn::Sub" in obj) return await this.resolveSub(obj["Fn::Sub"], context, obj);
26972
27123
  if ("Fn::Select" in obj) return await this.resolveSelect(obj["Fn::Select"], context);
26973
27124
  if ("Fn::Split" in obj) return await this.resolveSplit(obj["Fn::Split"], context);
26974
27125
  if ("Fn::If" in obj) return await this.resolveIf(obj["Fn::If"], context);
@@ -28064,32 +28215,45 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28064
28215
  *
28065
28216
  * Fn::Join: [delimiter, [value1, value2, ...]]
28066
28217
  */
28067
- async resolveJoin(joinArgs, context) {
28218
+ async resolveJoin(joinArgs, context, source) {
28068
28219
  const [delimiter, rawValues] = joinArgs;
28069
28220
  let values = rawValues;
28070
28221
  if (!Array.isArray(values)) values = await this.resolveValue(values, context);
28071
28222
  if (!Array.isArray(values)) throw new Error(`Fn::Join's second argument must be a list (an array literal or a list-returning intrinsic such as Fn::Cidr / Fn::GetAZs / Fn::Split / a Ref to a list-typed parameter — any List<...> type or CommaDelimitedList), but resolved to ${typeof values}`);
28072
28223
  const literalList = Array.isArray(rawValues);
28073
- const parts = (await allSettledKeepingFirstRejection(values.map(async (v) => {
28074
- if (typeof v === "string") return {
28075
- ...v.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(v, this.logTwinOfProduct({
28224
+ const resolvedParts = await allSettledKeepingFirstRejection(values.map(async (v) => {
28225
+ if (typeof v === "string") {
28226
+ const part = v.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(v, this.logTwinOfProduct({
28076
28227
  result: v,
28077
28228
  twin: v
28078
28229
  }, context).twin, context) : {
28079
28230
  result: v,
28080
- twin: v
28081
- },
28082
- product: !literalList
28083
- };
28231
+ twin: v,
28232
+ substitutions: [],
28233
+ complete: true
28234
+ };
28235
+ return {
28236
+ result: part.result,
28237
+ twin: part.twin,
28238
+ product: !literalList,
28239
+ input: v,
28240
+ substitutions: part.substitutions,
28241
+ complete: part.complete
28242
+ };
28243
+ }
28084
28244
  const raw = await this.resolveValue(v, context);
28085
28245
  const resolved = String(raw);
28086
28246
  return {
28087
28247
  result: resolved,
28088
28248
  twin: resolved,
28089
28249
  product: true,
28090
- raw: { value: raw }
28250
+ raw: { value: raw },
28251
+ input: resolved,
28252
+ substitutions: [],
28253
+ complete: true
28091
28254
  };
28092
- }), (pending) => this.warnAbandonedParts(pending))).map((part) => {
28255
+ }), (pending) => this.warnAbandonedParts(pending));
28256
+ const parts = resolvedParts.map((part) => {
28093
28257
  if (!part.product) return part;
28094
28258
  if (part.raw) return {
28095
28259
  result: part.result,
@@ -28099,7 +28263,20 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28099
28263
  });
28100
28264
  let result = parts.map((part) => part.result).join(delimiter);
28101
28265
  let twin = parts.map((part) => part.twin).join(delimiter);
28102
- if (result.includes("{{resolve:")) ({result, twin} = await this.resolveDynamicReferencesWithLogTwin(result, twin, context));
28266
+ const substitutions = resolvedParts.flatMap((part) => part.substitutions);
28267
+ let complete = resolvedParts.every((part) => part.complete);
28268
+ if (result.includes("{{resolve:")) {
28269
+ const joined = await this.resolveDynamicReferencesWithLogTwin(result, twin, context);
28270
+ ({result, twin} = joined);
28271
+ substitutions.push(...joined.substitutions);
28272
+ complete &&= joined.complete;
28273
+ }
28274
+ this.recordLeafResolution(context, source, {
28275
+ input: resolvedParts.map((part) => part.input).join(delimiter),
28276
+ output: result,
28277
+ substitutions,
28278
+ complete
28279
+ });
28103
28280
  this.rememberLogTwin(context, result, twin);
28104
28281
  this.logger.debug(`Resolved Fn::Join: ${this.maskSecretsForLog(this.logTwinText(result, twin, context), context)}`);
28105
28282
  return result;
@@ -28241,10 +28418,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28241
28418
  * inside replace(). For full async support, we'd need to collect all replacements
28242
28419
  * first, then do them synchronously.
28243
28420
  */
28244
- async resolveSub(subArgs, context) {
28421
+ async resolveSub(subArgs, context, source) {
28245
28422
  let template;
28246
28423
  const variables = Object.create(null);
28247
28424
  const variableTwins = Object.create(null);
28425
+ const variablePasses = Object.create(null);
28248
28426
  if (Array.isArray(subArgs)) {
28249
28427
  const [templateString, variableMap] = subArgs;
28250
28428
  template = templateString;
@@ -28252,10 +28430,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28252
28430
  for (const [key, val] of Object.entries(variableMap)) if (typeof val === "string") {
28253
28431
  const resolved = val.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(val, val, context) : {
28254
28432
  result: val,
28255
- twin: val
28433
+ twin: val,
28434
+ substitutions: [],
28435
+ complete: true
28256
28436
  };
28257
28437
  variables[key] = resolved.result;
28258
28438
  variableTwins[key] = resolved.twin;
28439
+ variablePasses[key] = resolved;
28259
28440
  } else variables[key] = context.abandonedResolutions === void 0 ? await this.resolveValue(val, context) : await this.resolveKeyUnit(key, val, context, context.abandonedResolutions);
28260
28441
  } else template = subArgs;
28261
28442
  const replacements = [];
@@ -28282,9 +28463,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28282
28463
  }
28283
28464
  let replacement;
28284
28465
  let twinReplacement;
28466
+ let pass;
28285
28467
  if (varNameStr in variables) {
28286
28468
  replacement = String(variables[varNameStr]);
28287
28469
  twinReplacement = varNameStr in variableTwins ? variableTwins[varNameStr] : this.productLogTwin(variables[varNameStr], context);
28470
+ if (varNameStr in variablePasses) pass = variablePasses[varNameStr];
28288
28471
  } else {
28289
28472
  const pseudoValue = await this.resolvePseudoParameter(varNameStr, context);
28290
28473
  if (pseudoValue !== void 0) replacement = String(pseudoValue);
@@ -28314,7 +28497,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28314
28497
  replacements.push({
28315
28498
  match: match[0],
28316
28499
  replacement,
28317
- twin: twinReplacement ?? replacement
28500
+ twin: twinReplacement ?? replacement,
28501
+ ...pass ? { pass } : {}
28318
28502
  });
28319
28503
  }
28320
28504
  let cursor = 0;
@@ -28327,7 +28511,21 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
28327
28511
  const entry = replacements[twinCursor++];
28328
28512
  return entry ? entry.twin : whole;
28329
28513
  });
28330
- if (result.includes("{{resolve:")) ({result, twin} = await this.resolveDynamicReferencesWithLogTwin(result, twin, context));
28514
+ const input = result;
28515
+ const substitutions = replacements.flatMap((entry) => entry.pass?.substitutions ?? []);
28516
+ let complete = replacements.every((entry) => entry.pass?.complete ?? true);
28517
+ if (result.includes("{{resolve:")) {
28518
+ const substituted = await this.resolveDynamicReferencesWithLogTwin(result, twin, context);
28519
+ ({result, twin} = substituted);
28520
+ substitutions.push(...substituted.substitutions);
28521
+ complete &&= substituted.complete;
28522
+ }
28523
+ this.recordLeafResolution(context, source, {
28524
+ input,
28525
+ output: result,
28526
+ substitutions,
28527
+ complete
28528
+ });
28331
28529
  this.rememberLogTwin(context, result, twin);
28332
28530
  this.logger.debug(`Resolved Fn::Sub: ${this.maskSecretsForLog(this.logTwinText(result, twin, context), context)}`);
28333
28531
  return result;
@@ -29717,7 +29915,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29717
29915
  * not the bag holds pairs. Where the middle RE-WRAPS it (an `Fn::Join` around
29718
29916
  * the `Ref`) the middle registers its own twin, and the hand-off still drops
29719
29917
  * a bag holding no pairs (it passes `inheritedSecrets` only when `size` is
29720
- * nonzero). Both are issue #3156.
29918
+ * nonzero). What reaches a grandchild instead is the parent's WHOLE-VALUE
29919
+ * entry: the middle's `{ Ref }` copies it into the middle's bag, which is then
29920
+ * non-empty and handed down. Issue #3156 made the carry record that entry for
29921
+ * the intrinsic frames it used to refuse; a frame it still refuses (listed on
29922
+ * `recordNestedStackParameterExpressions`) keeps both gaps.
29721
29923
  *
29722
29924
  * The registry is keyed by VALUE, and `splitLogTwins`' unaligned arm
29723
29925
  * registers every piece, public ones included. So a child `Fn::Base64` over a
@@ -29767,6 +29969,17 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29767
29969
  };
29768
29970
  }
29769
29971
  /**
29972
+ * Record the `Fn::Join` / `Fn::Sub` object `source`'s own resolution under
29973
+ * the pass bag the nested-stack carry reads (issue
29974
+ * [#3156](https://github.com/go-to-k/cdkd/issues/3156)). The key is the
29975
+ * object `resolveValue` dispatched on, and a context with no bag has no pass
29976
+ * to scope it to.
29977
+ */
29978
+ recordLeafResolution(context, source, resolution) {
29979
+ if (context.recordedSecretValues === void 0) return;
29980
+ recordIntrinsicLeafResolution(context.recordedSecretValues, source, resolution);
29981
+ }
29982
+ /**
29770
29983
  * Register a MASKED `twin` as the log twin of `result` for this pass (issue
29771
29984
  * #3100). An unmasked twin is not registered, so a later literal that
29772
29985
  * resolves to the same string cannot replace an earlier write's mask, and
@@ -29904,6 +30117,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29904
30117
  const pattern = /\{\{resolve:([^}]+)\}\}/g;
29905
30118
  let result = value;
29906
30119
  let twin = logTwin;
30120
+ const substitutions = [];
30121
+ let complete = true;
29907
30122
  let match;
29908
30123
  const matches = [];
29909
30124
  while ((match = pattern.exec(value)) !== null) matches.push({
@@ -29919,7 +30134,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29919
30134
  const nameLogText = inherited?.nameLogText ?? (pairedTwin === void 0 ? () => "***" : this.dynamicReferenceNameLogText(inner, pairedTwin, context));
29920
30135
  try {
29921
30136
  const isKnownSecret = service === "secretsmanager" || service === "ssm-secure" || recordedSecretExpressions.has(fullMatch);
29922
- if (isKnownSecret && context?.skipDynamicReferences) continue;
30137
+ if (isKnownSecret && context?.skipDynamicReferences) {
30138
+ complete = false;
30139
+ continue;
30140
+ }
29923
30141
  const regionVerdict = classifyReplaySecretRegion(fullMatch, this.explicitRegion ?? this.resolverRegion, context?.producerRegions);
29924
30142
  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.`));
29925
30143
  if (regionVerdict.kind === "named-region") {
@@ -29929,6 +30147,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29929
30147
  });
29930
30148
  result = result.replace(fullMatch, () => foreign.result);
29931
30149
  twin = twin.replace(fullMatch, () => foreign.twin);
30150
+ const [delegated] = foreign.substitutions;
30151
+ substitutions.push({
30152
+ token: fullMatch,
30153
+ value: foreign.result,
30154
+ secret: foreign.substitutions.length === 1 && delegated.secret
30155
+ });
30156
+ if (!foreign.complete || foreign.substitutions.length !== 1) complete = false;
29932
30157
  continue;
29933
30158
  }
29934
30159
  const cached = this.cachedDynamicReferences.get(fullMatch);
@@ -29939,6 +30164,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29939
30164
  }
29940
30165
  result = result.replace(fullMatch, () => cached.value);
29941
30166
  twin = twin.replace(fullMatch, () => cached.secret && cached.value ? "***" : cached.value);
30167
+ substitutions.push({
30168
+ token: fullMatch,
30169
+ value: cached.value,
30170
+ secret: cached.secret
30171
+ });
29942
30172
  continue;
29943
30173
  }
29944
30174
  const parts = inner.split(":");
@@ -29966,7 +30196,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29966
30196
  else cacheable = false;
29967
30197
  isSecret = param.secure;
29968
30198
  if (param.secure) {
29969
- if (!decrypt) continue;
30199
+ if (!decrypt) {
30200
+ complete = false;
30201
+ continue;
30202
+ }
29970
30203
  }
29971
30204
  resolved = param.value;
29972
30205
  } else if (service === "ssm-secure") {
@@ -29976,6 +30209,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29976
30209
  resolved = param.value;
29977
30210
  } else {
29978
30211
  this.logger.warn(this.maskSecretsForLog(`Unsupported dynamic reference service: ${this.maskSecretsForLog(nameLogText(String(service)), context)}`, context));
30212
+ complete = false;
29979
30213
  continue;
29980
30214
  }
29981
30215
  if (cacheable) this.cachedDynamicReferences.set(fullMatch, {
@@ -29989,6 +30223,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
29989
30223
  }
29990
30224
  result = result.replace(fullMatch, () => resolved);
29991
30225
  twin = twin.replace(fullMatch, () => isSecret && resolved ? "***" : resolved);
30226
+ substitutions.push({
30227
+ token: fullMatch,
30228
+ value: resolved,
30229
+ secret: isSecret
30230
+ });
29992
30231
  } catch (err) {
29993
30232
  if (context?.abandonedResolutions === void 0) throw err;
29994
30233
  if (isDeliberateResolutionRefusal(err)) throw err;
@@ -30001,13 +30240,16 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
30001
30240
  }
30002
30241
  return out;
30003
30242
  }));
30243
+ complete = false;
30004
30244
  continue;
30005
30245
  }
30006
30246
  }
30007
30247
  if (context) this.rememberLogTwin(context, result, twin);
30008
30248
  return {
30009
30249
  result,
30010
- twin
30250
+ twin,
30251
+ substitutions,
30252
+ complete
30011
30253
  };
30012
30254
  }
30013
30255
  /**
@@ -30262,7 +30504,7 @@ async function disableInstanceApiTermination(client, instanceId, logger) {
30262
30504
  }));
30263
30505
  logger.debug(`Disabled DisableApiTermination on EC2 Instance ${instanceId} before deletion`);
30264
30506
  } catch (flipError) {
30265
- logger.debug(`Could not disable DisableApiTermination on ${instanceId}: ${flipError instanceof Error ? flipError.message : String(flipError)}`);
30507
+ logger.debug(`Could not disable DisableApiTermination on ${instanceId}: ${describeAwsFailure(flipError).detail}`);
30266
30508
  }
30267
30509
  }
30268
30510
  /**
@@ -30574,7 +30816,7 @@ function getTopLevelWriteOnlyProperties(resourceType) {
30574
30816
  if (cached) return cached;
30575
30817
  const entry = fetchTopLevelWriteOnlyProperties(resourceType).catch((error) => {
30576
30818
  writeOnlyPropertiesCache.delete(resourceType);
30577
- const message = error instanceof Error ? error.message : String(error);
30819
+ const message = describeAwsFailure(error).detail;
30578
30820
  getLogger().child("WriteOnlyProperties").warn(`Failed to resolve write-only properties for ${resourceType} via cloudformation:DescribeType (${message}). Falling back to a minimal update patch — write-only properties (if any) may be dropped by the Cloud Control read-modify-write update. Grant cloudformation:DescribeType to enable write-only property re-inclusion.`);
30579
30821
  return /* @__PURE__ */ new Set();
30580
30822
  });
@@ -30700,7 +30942,7 @@ function getTopLevelReadOnlyProperties(resourceType) {
30700
30942
  if (cached) return cached;
30701
30943
  const entry = fetchTopLevelReadOnlyProperties(resourceType).catch((error) => {
30702
30944
  readOnlyPropertiesCache.delete(resourceType);
30703
- const message = error instanceof Error ? error.message : String(error);
30945
+ const message = describeAwsFailure(error).detail;
30704
30946
  getLogger().child("ReadOnlyProperties").debug(`Failed to resolve read-only properties for ${displaySafe(resourceType, { asciiOnly: true })} via cloudformation:DescribeType (${message}).`);
30705
30947
  });
30706
30948
  readOnlyPropertiesCache.set(resourceType, entry);
@@ -31918,7 +32160,7 @@ var CloudControlProvider = class {
31918
32160
  const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
31919
32161
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
31920
32162
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
31921
- const { ASGProvider } = await import("./asg-provider-DTzndMHB.js").then((n) => n.n);
32163
+ const { ASGProvider } = await import("./asg-provider-BOYln2Tw.js").then((n) => n.n);
31922
32164
  const asgProvider = new ASGProvider();
31923
32165
  return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
31924
32166
  }
@@ -34585,7 +34827,7 @@ var CustomResourceProvider = class CustomResourceProvider {
34585
34827
  }
34586
34828
  this.logger.debug(`Successfully deleted custom resource ${logicalId}`);
34587
34829
  } catch (error) {
34588
- this.logger.warn(`Failed to delete custom resource ${logicalId}, but continuing: ${error instanceof Error ? error.message : String(error)}. The Delete handler did not complete, so anything this custom resource manages may still be LIVE — cdkd is KEEPING the state record and the run exits non-zero. ${CR_SKIP_NOT_A_RETRY_CAVEAT} ${DEPLOY_SKIP_CAVEAT}`);
34830
+ this.logger.warn(`Failed to delete custom resource ${logicalId}, but continuing: ${describeAwsFailure(error).detail}. The Delete handler did not complete, so anything this custom resource manages may still be LIVE — cdkd is KEEPING the state record and the run exits non-zero. ${CR_SKIP_NOT_A_RETRY_CAVEAT} ${DEPLOY_SKIP_CAVEAT}`);
34589
34831
  return {
34590
34832
  outcome: "skipped",
34591
34833
  reason: CR_DELETE_INVOKE_FAILED_SKIP_REASON
@@ -34622,7 +34864,7 @@ var CustomResourceProvider = class CustomResourceProvider {
34622
34864
  return false;
34623
34865
  } catch (error) {
34624
34866
  if (error.name === "ResourceNotFoundException") return true;
34625
- this.logger.debug(`GetFunction pre-check for ${serviceToken} failed inconclusively (${error instanceof Error ? error.message : String(error)}); proceeding with the normal delete invoke`);
34867
+ this.logger.debug(`GetFunction pre-check for ${serviceToken} failed inconclusively (${describeAwsFailure(error).detail}); proceeding with the normal delete invoke`);
34626
34868
  return false;
34627
34869
  }
34628
34870
  }
@@ -34699,7 +34941,7 @@ var CustomResourceProvider = class CustomResourceProvider {
34699
34941
  } catch (error) {
34700
34942
  if (delivered || preDeliveryRetries >= this.preDeliveryAuthzMaxRetries || !this.isTransientAuthzThrow(error)) throw error;
34701
34943
  const delayMs = Math.min(250 * Math.pow(2, preDeliveryRetries), IAM_PROPAGATION_MAX_DELAY_MS);
34702
- this.logger.warn(`Custom resource ${operation} for ${logicalId} hit a transient IAM-authorization error before the request was delivered (attempt ${attempt + 1}/${this.preDeliveryAuthzMaxRetries + 1}): ${this.truncateReason(error instanceof Error ? error.message : String(error))}. Retrying in ${delayMs / 1e3}s with a fresh response URL and RequestId.`);
34944
+ this.logger.warn(`Custom resource ${operation} for ${logicalId} hit a transient IAM-authorization error before the request was delivered (attempt ${attempt + 1}/${this.preDeliveryAuthzMaxRetries + 1}): ${this.truncateReason(describeAwsFailure(error).detail)}. Retrying in ${delayMs / 1e3}s with a fresh response URL and RequestId.`);
34703
34945
  if (invocation !== void 0) await this.cleanupResponseObject(invocation.responseKey);
34704
34946
  preDeliveryRetries += 1;
34705
34947
  await this.sleepInterruptibly(delayMs, watch);
@@ -34901,7 +35143,7 @@ var CustomResourceProvider = class CustomResourceProvider {
34901
35143
  maxDelay: 5
34902
35144
  }, { FunctionName: serviceToken });
34903
35145
  } catch (error) {
34904
- this.logger.debug(`Could not recycle backing function for ${logicalId} (${error instanceof Error ? error.message : String(error)}); retrying invoke without a forced cold start`);
35146
+ this.logger.debug(`Could not recycle backing function for ${logicalId} (${describeAwsFailure(error).detail}); retrying invoke without a forced cold start`);
34905
35147
  }
34906
35148
  }
34907
35149
  /**
@@ -35250,7 +35492,7 @@ var CustomResourceProvider = class CustomResourceProvider {
35250
35492
  Key: responseKey
35251
35493
  }));
35252
35494
  } catch (error) {
35253
- this.logger.debug(`Failed to delete custom-resource response object s3://${displaySafe(bucket, { asciiOnly: true }) || "<unrenderable>"}/${displaySafe(responseKey)}; it remains as a current object. Underlying error: ${displaySafe(error instanceof Error ? error.message : String(error)) || "<unrenderable>"}`);
35495
+ this.logger.debug(`Failed to delete custom-resource response object s3://${displaySafe(bucket, { asciiOnly: true }) || "<unrenderable>"}/${displaySafe(responseKey)}; it remains as a current object. Underlying error: ${displaySafe(describeAwsFailure(error).detail) || "<unrenderable>"}`);
35254
35496
  }
35255
35497
  await purgeNoncurrentKeyVersions(this.s3Client, bucket, [responseKey], {
35256
35498
  logger: this.logger,
@@ -36029,7 +36271,7 @@ var IAMRoleProvider = class {
36029
36271
  await this.iamClient.send(new DeleteRoleCommand({ RoleName: roleName }));
36030
36272
  this.logger.debug(`Cleaned up partially-created IAM role ${logicalId} (${roleName}) after wiring failure`);
36031
36273
  } catch (cleanupError) {
36032
- this.logger.warn(`Failed to clean up partially-created IAM role ${logicalId} (${roleName}): ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}. Manual deletion may be required before the next deploy: detach managed policies (aws iam list-attached-role-policies --role-name ${roleName} then aws iam detach-role-policy --role-name ${roleName} --policy-arn <arn>), delete inline policies (aws iam list-role-policies --role-name ${roleName} then aws iam delete-role-policy --role-name ${roleName} --policy-name <name>), then aws iam delete-role --role-name ${roleName}`);
36274
+ this.logger.warn(`Failed to clean up partially-created IAM role ${logicalId} (${roleName}): ${describeAwsFailure(cleanupError).detail}. Manual deletion may be required before the next deploy: detach managed policies (aws iam list-attached-role-policies --role-name ${roleName} then aws iam detach-role-policy --role-name ${roleName} --policy-arn <arn>), delete inline policies (aws iam list-role-policies --role-name ${roleName} then aws iam delete-role-policy --role-name ${roleName} --policy-name <name>), then aws iam delete-role --role-name ${roleName}`);
36033
36275
  }
36034
36276
  throw innerError;
36035
36277
  }
@@ -36066,8 +36308,8 @@ var IAMRoleProvider = class {
36066
36308
  this.logger.warn(`Skipped deleting old role ${physicalId} during replacement: ${deleteResult.reason}. The old role may be orphaned and require manual cleanup.`);
36067
36309
  }
36068
36310
  } catch (error) {
36069
- orphanReason = `old role ${physicalId} could not be deleted: ${String(error)}`;
36070
- this.logger.warn(`Failed to delete old role ${physicalId} during replacement: ${String(error)}. The old role may be orphaned and require manual cleanup.`);
36311
+ orphanReason = `old role ${physicalId} could not be deleted: ${safeStringify(error)}`;
36312
+ this.logger.warn(`Failed to delete old role ${physicalId} during replacement: ${safeStringify(error)}. The old role may be orphaned and require manual cleanup.`);
36071
36313
  }
36072
36314
  const base = {
36073
36315
  physicalId: createResult.physicalId,
@@ -38336,7 +38578,7 @@ function makeCanonicalizePropertiesFn(registry) {
38336
38578
  if (!registry.hasProvider(resourceType)) return properties;
38337
38579
  return registry.getProvider(resourceType).canonicalizeDesiredProperties?.(resourceType, properties) ?? properties;
38338
38580
  } catch (error) {
38339
- logger.debug(`canonicalizeDesiredProperties failed for ${resourceType}: ${error instanceof Error ? error.message : String(error)}`);
38581
+ logger.debug(`canonicalizeDesiredProperties failed for ${resourceType}: ${describeAwsFailure(error).detail}`);
38340
38582
  return properties;
38341
38583
  }
38342
38584
  };
@@ -44912,5 +45154,5 @@ var DeployEngine = class DeployEngine {
44912
45154
  };
44913
45155
 
44914
45156
  //#endregion
44915
- export { secretBearing as $, normalizeAwsError as $i, scrubResourceRecord as $n, synthesisStatusMessage as $r, s3BucketArn as $t, extractDeploymentEventError as A, AssetError as Ai, repairMalformedResourcesForReadOnly as An, isCrossRegionRedirect as Ar, isImpossibleEmptyStoredAttribute as At, toCfnInteger as B, LockError as Bi, TEMPLATE_SOURCED_RULES as Bn, describeDockerFailure as Br, coerceCfnBoolean as Bt, buildFinalSnapshotIdentifier as C, processStackMessages as Ci, refuseMalformedOutputs as Cn, loadPublishableAssetManifest as Cr, isTerminationProtectionPropagationError as Ct, refusesFinalSnapshot as D, getAwsClients as Di, refuseMalformedState as Dn, assertAssetBucketRegion as Dr, cfnRefValueFromPhysicalId as Dt, isFinalSnapshotError as E, AwsClients as Ei, refuseMalformedResourcesForDestroy as En, BOOTSTRAP_MARKER_PREFIX as Er, carriesFetchableDynamicReference as Et, isStatefulRecreateTargetSync as F, DeployCancelledError as Fi, DagBuilder as Fn, buildDenyExternalAccessPolicy as Fr, isSettledInstanceState as Ft, gray as G, ResourceTimeoutError as Gi, identityKeyFor as Gn, redactDockerArgvValues as Gr, readConfigString as Gt, formatResourceLine as H, NestedStackChildDirectDestroyError as Hi, createSecretMasker as Hn, formatDockerLoginError as Hr, configBooleanRefusal as Ht, renderStatefulReason as I, DynamicReferenceRegionAmbiguousError as Ii, TemplateParser as In, describeAwsFailure as Ir, WAFv2WebACLProvider as It, yellow as J, StackTerminationProtectionError as Ji, maskSecretsInError as Jn, escapeRegExp$1 as Jr, requireConfigObject as Jt, green as K, ResourceUpdateNotSupportedError as Ki, isSingleDynamicReferenceToken as Kn, runDockerForeground as Kr, replayWarn as Kt, WARM_THROUGHPUT_MEMBERS as L, IntrinsicResolutionRefusalError as Li, STATE_SOURCED_BASELINE_RULES as Ln, buildDockerImage as Lr, normalizeAwsTagsToCfn as Lt, planOrphanAdoption as M, ConfigError as Mi, findSilentDropProperties as Mn, readBootstrapMarkerBody as Mr, isUnboundTemplateParameter as Mt, MULTI_REGION_RECREATE_BLOCKED_TYPES as N, CrossAccountSecretRefusalError as Ni, describeTypeWithThrottleRetry as Nn, validateAssetBucketName as Nr, parameterTypeMayLoseSecretIdentity as Nt, unsupportedFinalSnapshotError as O, resetAwsClients as Oi, repairMalformedOutputsForReadOnly as On, ensureAssetStorage as Or, coerceParameterTypedValue as Ot, isStatefulRecreateTargetForReplace as P, DependencyError as Pi, withRetry as Pn, validateContainerRepoName as Pr, refStateLookupFromResource as Pt, isExportAliasCollision as Q, isCdkdError as Qi, redactSecretsForState as Qn, Synthesizer as Qr, withSharedDrainBudget as Qt, coerceWarmThroughput as R, LocalInvokeBuildError as Ri, STATE_SOURCED_CROSS_GENERATION_RULES as Rn, describeDockerCapturedOutput as Rr, resolveExplicitPhysicalId as Rt, PRE_DELETE_SNAPSHOT_TYPES as S, AssemblyReader as Si, refuseMalformedNestedChildOutputs as Sn, createAssetRedirectResolver as Sr, disableInstanceApiTermination as St, createPreDeleteFinalSnapshot as T, resolveBucketRegion as Ti, refuseMalformedResourcePropertiesForOrphan as Tn, AssetModeResolver as Tr, carriesDynamicReference as Tt, bold as U, PartialFailureError as Ui, dynamicReferenceTokens as Un, getDockerCmd as Ur, configIntegerRefusal as Ut, toFiniteNumber as V, MalformedProducerRecordRefusalError as Vi, carriesSecretMask as Vn, dockerSpawnEnvWithSensitive as Vr, coerceCfnInteger as Vt, cyan as W, ProvisioningError as Wi, errorCauseChain as Wn, partitionSensitiveEnv as Wr, configStringRefusal as Wt, collectPublishedOutputNames as X, SynthesisError as Xi, recordMaskOnlyValue as Xn, AssetManifestLoader as Xr, classifyReplaySecretRegion as Xt, collectDeclaredOutputNames as Y, StateError as Yi, maskSecretsInText as Yn, stripControlChars as Yr, requireConfigString as Yt, exportAliasCollisionScrubWarning as Z, formatError as Zi, recoverMaskedOutput as Zn, getDockerImageBySourceHash as Zr, producerRegionsFromState as Zt, isSecretBearingReferenceString as _, decodeListingKey as _i, malformedRenderedContainersWarning as _n, shouldRetainResource as _r, isWaitAbandonedError as _t, DeploymentEventsStore as a, markNonRetryable as aa, resolveSkipPrefix as ai, applyCallerIdentityCredentials as an, forceQuitRecoveryClause as ar, clearOnUpdateRemoval as at, bindingSkippedOutputs as b, canonicalizeRegion as bi, malformedStateRefusalMessage as bn, WorkGraph as br, deleteIndeterminateGuards as bt, replayFailedOperations as c, __exportAll as ca, resolveUseCdkBootstrapAssets as ci, INTRINSIC_KEYS as cn, CUSTOM_RESOURCE_RESPONSE_PREFIX as cr, createMaskedRetryLogger as ct, updatePartialReason as d, CFN_TEMPLATE_BODY_LIMIT as di, hasReadableResources as dn, hasReadableExportSet as dr, beginCommandInterruptScope as dt, withErrorHandling as ea, getDefaultStateBucketName as ei, s3BucketDomainName as en, LockManager as er, secretBearingStateKeyWarning as et, withResourceDeadline as f, CFN_TEMPLATE_URL_LIMIT as fi, malformedExportNamesWarning as fn, importableOutputKeys as fr, endCommandInterruptScope as ft, bagHoldsSecretExpression as g, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as gi, malformedOutputsWarning as gn, orphansCarriedFrom as gr, CloudControlProvider as gt, computeImplicitDeleteEdges as h, uploadCfnTemplate as hi, malformedOutputsRefusalMessage as hn, orphansAfterRollback as hr, startInterruptWatch as ht, DeploymentEventsReader as i, isTransientServerError as ia, resolveCaptureObservedState as ii, applyRoleArnIfSet as in, buildLockContentionMessage as ir, collectInlinePolicyNamesManagedBySiblings as it, makeSiblingClaimReader as j, CdkdError as ji, findActionableSilentDrops as jn, parseBootstrapMarker as jr, isNamelessDynamicReferenceError as jt, makeCanonicalizePropertiesFn as k, setAwsClients as ki, repairMalformedResourcePropertiesForReadOnly as kn, getBootstrapMarkerKey as kr, getAccountInfo as kt, replayRollback as l, stateBucketExistenceConfirmed as li, STATE_RESOURCES_MALFORMED as ln, DEFAULT_STATE_PREFIX as lr, maskDeep as lt, IMPLICIT_DELETE_DEPENDENCIES as m, findLargeInlineResources as mi, malformedLocalOutputsWarning as mn, isReadableBag as mr, isInterruptedWaitError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, isRetryableTransientError as na, resolveApp as ni, s3BucketRegionalDomainName as nn, rebuildClientForBucketRegion as nr, getCurrentResourceSecrets as nt, planFailedOps as o, markRedactedCause as oa, resolveStateBucketWithDefault as oi, callerEnvCredentials as on, formatLockExpiry as or, ProviderRegistry as ot, maskingRetryLogger as p, MIGRATE_TMP_PREFIX as pi, malformedExportSourceWarning as pn, importableOutputs as pr, interruptWatchListenerCount as pt, red as q, StackHasActiveImportsError as qi, markSameGenerationBag as qn, runDockerStreaming as qr, requireConfigArray as qt, DeployEngine as r, isThrottlingError as ra, resolveAutoAssetStorage as ri, s3BucketWebsiteUrl as rn, buildForceUnlockCommand as rr, IAMRoleProvider as rt, planRollback as s, retryClassificationText as sa, resolveStateBucketWithDefaultAndSource as si, DiffCalculator as sn, shellQuote as sr, wouldReturnToSdkProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, isMarkedNonRetryable as ta, getLegacyStateBucketName as ti, s3BucketDualStackDomainName as tn, S3StateBackend as tr, secretSafeKeyDisplay as tt, updatePartialMessage as u, warnDeprecatedNoPrefixCliFlag as ui, hasReadableOutputs as un, exportNamesCarriedFrom as ur, maskerOrIdentity as ut, keptWholeReasonText as v, expectedOwnerParam as vi, malformedResourcePropertiesWarning as vn, AssetPublisher as vr, slowCcOperationTimeoutMs as vt, ccRoutedFinalSnapshotError as w, clearBucketRegionCache as wi, refuseMalformedOutputsForDestroy as wn, rewriteTemplateAssetReferences as wr, IntrinsicFunctionResolver as wt, ATOMIC_FINAL_SNAPSHOT_TYPES as x, derivePartitionAndUrlSuffix as xi, producerRecordKey as xn, buildAssetRedirectMap as xr, deleteSkipReason as xt, mergeNoChangeOutputs as y, PARTITION_TABLE as yi, malformedResourcesWarning as yn, stringifyValue as yr, UNSPECIFIED_SKIP_REASON as yt, isWarmThroughputDecrease as z, LocalStartServiceError as zi, STATE_SOURCED_READBACK_RULES as zn, describeDockerExecFailure as zr, assertRegionMatch as zt };
44916
- //# sourceMappingURL=deploy-engine-Dbmoo4FQ.js.map
45157
+ export { secretBearing as $, isCdkdError as $i, scrubResourceRecord as $n, Synthesizer as $r, s3BucketArn as $t, extractDeploymentEventError as A, setAwsClients as Ai, repairMalformedResourcesForReadOnly as An, isCrossRegionRedirect as Ar, isImpossibleEmptyStoredAttribute as At, toCfnInteger as B, LocalStartServiceError as Bi, TEMPLATE_SOURCED_RULES as Bn, describeDockerExecFailure as Br, coerceCfnBoolean as Bt, buildFinalSnapshotIdentifier as C, AssemblyReader as Ci, refuseMalformedOutputs as Cn, loadPublishableAssetManifest as Cr, isTerminationProtectionPropagationError as Ct, refusesFinalSnapshot as D, AwsClients as Di, refuseMalformedState as Dn, assertAssetBucketRegion as Dr, cfnRefValueFromPhysicalId as Dt, isFinalSnapshotError as E, resolveBucketRegion as Ei, refuseMalformedResourcesForDestroy as En, BOOTSTRAP_MARKER_PREFIX as Er, carriesFetchableDynamicReference as Et, isStatefulRecreateTargetSync as F, DependencyError as Fi, DagBuilder as Fn, buildDenyExternalAccessPolicy as Fr, isSettledInstanceState as Ft, gray as G, ProvisioningError as Gi, identityKeyFor as Gn, partitionSensitiveEnv as Gr, readConfigString as Gt, formatResourceLine as H, MalformedProducerRecordRefusalError as Hi, createSecretMasker as Hn, dockerSpawnEnvWithSensitive as Hr, configBooleanRefusal as Ht, renderStatefulReason as I, DeployCancelledError as Ii, TemplateParser as In, describeAwsFailure as Ir, WAFv2WebACLProvider as It, yellow as J, StackHasActiveImportsError as Ji, maskSecretsInError as Jn, runDockerStreaming as Jr, requireConfigObject as Jt, green as K, ResourceTimeoutError as Ki, isSingleDynamicReferenceToken as Kn, redactDockerArgvValues as Kr, replayWarn as Kt, WARM_THROUGHPUT_MEMBERS as L, DynamicReferenceRegionAmbiguousError as Li, STATE_SOURCED_BASELINE_RULES as Ln, safeStringify as Lr, normalizeAwsTagsToCfn as Lt, planOrphanAdoption as M, CdkdError as Mi, findSilentDropProperties as Mn, readBootstrapMarkerBody as Mr, isUnboundTemplateParameter as Mt, MULTI_REGION_RECREATE_BLOCKED_TYPES as N, ConfigError as Ni, describeTypeWithThrottleRetry as Nn, validateAssetBucketName as Nr, parameterTypeMayLoseSecretIdentity as Nt, unsupportedFinalSnapshotError as O, getAwsClients as Oi, repairMalformedOutputsForReadOnly as On, ensureAssetStorage as Or, coerceParameterTypedValue as Ot, isStatefulRecreateTargetForReplace as P, CrossAccountSecretRefusalError as Pi, withRetry as Pn, validateContainerRepoName as Pr, refStateLookupFromResource as Pt, isExportAliasCollision as Q, formatError as Qi, redactSecretsForState as Qn, getDockerImageBySourceHash as Qr, withSharedDrainBudget as Qt, coerceWarmThroughput as R, IntrinsicResolutionRefusalError as Ri, STATE_SOURCED_CROSS_GENERATION_RULES as Rn, buildDockerImage as Rr, resolveExplicitPhysicalId as Rt, PRE_DELETE_SNAPSHOT_TYPES as S, derivePartitionAndUrlSuffix as Si, refuseMalformedNestedChildOutputs as Sn, createAssetRedirectResolver as Sr, disableInstanceApiTermination as St, createPreDeleteFinalSnapshot as T, clearBucketRegionCache as Ti, refuseMalformedResourcePropertiesForOrphan as Tn, AssetModeResolver as Tr, carriesDynamicReference as Tt, bold as U, NestedStackChildDirectDestroyError as Ui, dynamicReferenceTokens as Un, formatDockerLoginError as Ur, configIntegerRefusal as Ut, toFiniteNumber as V, LockError as Vi, carriesSecretMask as Vn, describeDockerFailure as Vr, coerceCfnInteger as Vt, cyan as W, PartialFailureError as Wi, errorCauseChain as Wn, getDockerCmd as Wr, configStringRefusal as Wt, collectPublishedOutputNames as X, StateError as Xi, recordMaskOnlyValue as Xn, stripControlChars as Xr, classifyReplaySecretRegion as Xt, collectDeclaredOutputNames as Y, StackTerminationProtectionError as Yi, maskSecretsInText as Yn, escapeRegExp$1 as Yr, requireConfigString as Yt, exportAliasCollisionScrubWarning as Z, SynthesisError as Zi, recoverMaskedOutput as Zn, AssetManifestLoader as Zr, producerRegionsFromState as Zt, isSecretBearingReferenceString as _, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as _i, malformedRenderedContainersWarning as _n, shouldRetainResource as _r, isWaitAbandonedError as _t, DeploymentEventsStore as a, isTransientServerError as aa, resolveCaptureObservedState as ai, applyCallerIdentityCredentials as an, forceQuitRecoveryClause as ar, clearOnUpdateRemoval as at, bindingSkippedOutputs as b, PARTITION_TABLE as bi, malformedStateRefusalMessage as bn, WorkGraph as br, deleteIndeterminateGuards as bt, replayFailedOperations as c, retryClassificationText as ca, resolveStateBucketWithDefaultAndSource as ci, INTRINSIC_KEYS as cn, CUSTOM_RESOURCE_RESPONSE_PREFIX as cr, createMaskedRetryLogger as ct, updatePartialReason as d, warnDeprecatedNoPrefixCliFlag as di, hasReadableResources as dn, hasReadableExportSet as dr, beginCommandInterruptScope as dt, normalizeAwsError as ea, synthesisStatusMessage as ei, s3BucketDomainName as en, LockManager as er, secretBearingStateKeyWarning as et, withResourceDeadline as f, CFN_TEMPLATE_BODY_LIMIT as fi, malformedExportNamesWarning as fn, importableOutputKeys as fr, endCommandInterruptScope as ft, bagHoldsSecretExpression as g, uploadCfnTemplate as gi, malformedOutputsWarning as gn, orphansCarriedFrom as gr, CloudControlProvider as gt, computeImplicitDeleteEdges as h, findLargeInlineResources as hi, malformedOutputsRefusalMessage as hn, orphansAfterRollback as hr, startInterruptWatch as ht, DeploymentEventsReader as i, isThrottlingError as ia, resolveAutoAssetStorage as ii, applyRoleArnIfSet as in, buildLockContentionMessage as ir, collectInlinePolicyNamesManagedBySiblings as it, makeSiblingClaimReader as j, AssetError as ji, findActionableSilentDrops as jn, parseBootstrapMarker as jr, isNamelessDynamicReferenceError as jt, makeCanonicalizePropertiesFn as k, resetAwsClients as ki, repairMalformedResourcePropertiesForReadOnly as kn, getBootstrapMarkerKey as kr, getAccountInfo as kt, replayRollback as l, __exportAll as la, resolveUseCdkBootstrapAssets as li, STATE_RESOURCES_MALFORMED as ln, DEFAULT_STATE_PREFIX as lr, maskDeep as lt, IMPLICIT_DELETE_DEPENDENCIES as m, MIGRATE_TMP_PREFIX as mi, malformedLocalOutputsWarning as mn, isReadableBag as mr, isInterruptedWaitError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, isMarkedNonRetryable as na, getLegacyStateBucketName as ni, s3BucketRegionalDomainName as nn, rebuildClientForBucketRegion as nr, getCurrentResourceSecrets as nt, planFailedOps as o, markNonRetryable as oa, resolveSkipPrefix as oi, callerEnvCredentials as on, formatLockExpiry as or, ProviderRegistry as ot, maskingRetryLogger as p, CFN_TEMPLATE_URL_LIMIT as pi, malformedExportSourceWarning as pn, importableOutputs as pr, interruptWatchListenerCount as pt, red as q, ResourceUpdateNotSupportedError as qi, markSameGenerationBag as qn, runDockerForeground as qr, requireConfigArray as qt, DeployEngine as r, isRetryableTransientError as ra, resolveApp as ri, s3BucketWebsiteUrl as rn, buildForceUnlockCommand as rr, IAMRoleProvider as rt, planRollback as s, markRedactedCause as sa, resolveStateBucketWithDefault as si, DiffCalculator as sn, shellQuote as sr, wouldReturnToSdkProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, withErrorHandling as ta, getDefaultStateBucketName as ti, s3BucketDualStackDomainName as tn, S3StateBackend as tr, secretSafeKeyDisplay as tt, updatePartialMessage as u, stateBucketExistenceConfirmed as ui, hasReadableOutputs as un, exportNamesCarriedFrom as ur, maskerOrIdentity as ut, keptWholeReasonText as v, decodeListingKey as vi, malformedResourcePropertiesWarning as vn, AssetPublisher as vr, slowCcOperationTimeoutMs as vt, ccRoutedFinalSnapshotError as w, processStackMessages as wi, refuseMalformedOutputsForDestroy as wn, rewriteTemplateAssetReferences as wr, IntrinsicFunctionResolver as wt, ATOMIC_FINAL_SNAPSHOT_TYPES as x, canonicalizeRegion as xi, producerRecordKey as xn, buildAssetRedirectMap as xr, deleteSkipReason as xt, mergeNoChangeOutputs as y, expectedOwnerParam as yi, malformedResourcesWarning as yn, stringifyValue as yr, UNSPECIFIED_SKIP_REASON as yt, isWarmThroughputDecrease as z, LocalInvokeBuildError as zi, STATE_SOURCED_READBACK_RULES as zn, describeDockerCapturedOutput as zr, assertRegionMatch as zt };
45158
+ //# sourceMappingURL=deploy-engine-CBzq85r6.js.map